# Пользовательские скрипты и задачи pfSense

> Выполнение команд в pfSense, пакеты Shellcmd и Cron, PHP-скрипты, автозагрузочные скрипты rc.d, devd-правила и автоматизация рутинных задач

Source: https://opennix.org/docs/pfsense/development/pfsense-custom-scripts/


pfSense построен на FreeBSD и предоставляет полноценную командную строку, PHP-интерпретатор и механизмы автозагрузки. Это позволяет создавать пользовательские скрипты для задач, которые не покрываются веб-интерфейсом: автоматическое резервное копирование на удаленный сервер, ротация логов, мониторинговые проверки и обновление сертификатов. Для управления скриптами и задачами по расписанию в pfSense доступны пакеты Shellcmd и Cron.

## Выполнение команд через веб-интерфейс

pfSense предоставляет два инструмента для работы с системой через браузер без SSH-доступа.

### Diagnostics - Command Prompt

Страница **Diagnostics > Command Prompt** позволяет выполнять shell-команды и PHP-код непосредственно из веб-интерфейса.

**Execute Shell Command** - выполняет произвольную команду FreeBSD:

```bash
# Проверка дискового пространства
df -h

# Просмотр запущенных процессов
ps aux | grep openvpn

# Проверка сетевых соединений
netstat -an | grep ESTABLISHED | wc -l
```

**Execute PHP Command** - выполняет PHP-код с доступом к функциям pfSense:

```php
require_once("config.inc");
require_once("interfaces.inc");

// Вывод имени хоста
echo $config['system']['hostname'] . "." . $config['system']['domain'];
```

### Diagnostics - Edit File

Страница **Diagnostics > Edit File** предоставляет текстовый редактор для просмотра и изменения файлов на файловой системе. Полезна для редактирования конфигурационных файлов без SSH-доступа.

## Пакет Shellcmd - команды при загрузке

Пакет Shellcmd позволяет задавать команды, которые выполняются при загрузке pfSense. Это замена ручному редактированию config.xml для добавления тегов `<shellcmd>`.

### Установка

**System > Package Manager > Available Packages** - найти и установить **Shellcmd**.

После установки настройка доступна через **Services > Shellcmd**.

### Типы команд

| Тип | Момент выполнения | Использование |
|---|---|---|
| **shellcmd** | Конец процесса загрузки | Основные задачи при старте |
| **earlyshellcmd** | Начало процесса загрузки (до запуска сервисов) | Загрузка модулей ядра, монтирование файловых систем |
| **afterfilterchangeshellcmd** | После каждого изменения правил файрвола | Динамические правила, интеграции |

### Пример конфигурации

```text
Command: /usr/local/bin/custom-startup.sh
Type: shellcmd
Description: Custom startup script
```

Команды также можно добавлять напрямую в config.xml:

```xml
<shellcmd>/usr/local/bin/custom-startup.sh</shellcmd>
<earlyshellcmd>kldload if_tap</earlyshellcmd>
```

### Рекомендации

- Используйте абсолютные пути к исполняемым файлам
- Скрипты должны быть исполняемыми (`chmod +x`)
- Длительные операции запускайте в фоне с `&`
- Перенаправляйте вывод в лог для отладки: `/usr/local/bin/script.sh > /var/log/custom-startup.log 2>&1 &`

## Пакет Cron - задачи по расписанию

Пакет Cron предоставляет веб-интерфейс для управления cron-задачами. pfSense использует стандартный FreeBSD cron, но пакет добавляет графическое управление через **Services > Cron**.

### Установка

**System > Package Manager > Available Packages** - найти и установить **Cron**.

### Формат расписания

```text
*    *    *    *    *    command
|    |    |    |    |
|    |    |    |    +--- День недели (0-7, 0 и 7 = воскресенье)
|    |    |    +-------- Месяц (1-12)
|    |    +------------- День месяца (1-31)
|    +------------------ Час (0-23)
+----------------------- Минута (0-59)
```

### Примеры задач

| Задача | Расписание | Команда |
|---|---|---|
| Бэкап конфигурации ежедневно в 2:00 | `0 2 * * *` | `/usr/local/bin/backup-config.sh` |
| Перезапуск OpenVPN каждые 6 часов | `0 */6 * * *` | `/usr/local/sbin/pfSsh.php playback svc restart openvpn` |
| Очистка tmp каждое воскресенье | `0 3 * * 0` | `/usr/bin/find /tmp -type f -mtime +7 -delete` |
| Проверка дискового пространства каждый час | `0 * * * *` | `/usr/local/bin/check-disk.sh` |

## Пользовательские PHP-скрипты

PHP-скрипты имеют полный доступ к конфигурации и функциям pfSense. Интерпретатор находится по пути `/usr/local/bin/php`.

### Структура скрипта

```php
#!/usr/local/bin/php
<?php
require_once("config.inc");
require_once("functions.inc");
require_once("filter.inc");

// Доступ к конфигурации
$hostname = $config['system']['hostname'];
$interfaces = $config['interfaces'];

// Пример: подсчет активных правил файрвола
$rules = $config['filter']['rule'];
$active_rules = array_filter($rules, function($rule) {
    return !isset($rule['disabled']);
});

echo "Active firewall rules: " . count($active_rules) . "\n";
```

### Полезные include-файлы

| Файл | Назначение |
|---|---|
| `config.inc` | Загрузка массива `$config` |
| `functions.inc` | Общие вспомогательные функции |
| `filter.inc` | Управление правилами файрвола |
| `interfaces.inc` | Функции работы с интерфейсами |
| `openvpn.inc` | Функции управления OpenVPN |
| `certs.inc` | Функции работы с сертификатами |
| `notices.inc` | Система уведомлений |

## Автозагрузочные скрипты rc.d

Скрипты в каталоге `/usr/local/etc/rc.d/` автоматически запускаются при загрузке системы в стиле FreeBSD rc.d.

### Пример rc.d-скрипта

```sh
#!/bin/sh

# PROVIDE: custom_monitor
# REQUIRE: NETWORKING
# BEFORE: LOGIN

. /etc/rc.subr

name="custom_monitor"
rcvar="${name}_enable"
command="/usr/local/bin/custom-monitor.sh"
command_args="&"

load_rc_config $name
run_rc_command "$1"
```

Для активации добавьте в `/etc/rc.conf.local`:

```sh
custom_monitor_enable="YES"
```

## Правила devd

devd (device daemon) реагирует на системные события - подключение устройств, изменение сетевых интерфейсов. Пользовательские правила devd размещаются в `/etc/devd/`.

```text
notify 0 {
    match "system"    "IFNET";
    match "subsystem" "igb0";
    match "type"      "LINK_UP";
    action "/usr/local/bin/link-up-handler.sh";
};
```

После изменения правил перезапустите devd:

```bash
service devd restart
```

## Типовые задачи автоматизации

### Автоматический бэкап на удаленный сервер

```sh
#!/bin/sh
# /usr/local/bin/backup-config.sh
# Резервное копирование config.xml на удаленный сервер по SCP

REMOTE_USER="backup"
REMOTE_HOST="backup.example.com"
REMOTE_DIR="/backups/pfsense"
DATE=$(date +%Y%m%d-%H%M)

cp /cf/conf/config.xml /tmp/config-${DATE}.xml
scp -i /root/.ssh/backup_key /tmp/config-${DATE}.xml \
  ${REMOTE_USER}@${REMOTE_HOST}:${REMOTE_DIR}/
rm /tmp/config-${DATE}.xml

logger -t backup "Configuration backed up to ${REMOTE_HOST}"
```

### Ротация логов

```sh
#!/bin/sh
# /usr/local/bin/rotate-custom-logs.sh
# Ротация пользовательских логов

LOG_DIR="/var/log/custom"
MAX_FILES=7

for logfile in ${LOG_DIR}/*.log; do
    if [ -f "${logfile}" ]; then
        cp "${logfile}" "${logfile}.$(date +%Y%m%d)"
        : > "${logfile}"
    fi
done

# Удаление старых файлов
find ${LOG_DIR} -name "*.log.*" -mtime +${MAX_FILES} -delete
```

### Мониторинговая проверка шлюза

```sh
#!/bin/sh
# /usr/local/bin/check-gateway.sh
# Проверка доступности шлюза и уведомление

GATEWAY="10.0.0.1"
ALERT_EMAIL="admin@example.com"

if ! ping -c 3 -W 5 ${GATEWAY} > /dev/null 2>&1; then
    echo "Gateway ${GATEWAY} unreachable at $(date)" | \
      mail -s "pfSense: Gateway Down" ${ALERT_EMAIL}
    logger -t gateway-check "Gateway ${GATEWAY} is unreachable"
fi
```

### Скрипт обновления сертификатов

```php
#!/usr/local/bin/php
<?php
// /usr/local/bin/check-cert-expiry.php
// Проверка срока действия сертификатов

require_once("config.inc");
require_once("certs.inc");

$warning_days = 30;

foreach ($config['cert'] as $cert) {
    $info = openssl_x509_parse(base64_decode($cert['crt']));
    if ($info === false) continue;

    $expires = $info['validTo_time_t'];
    $days_left = floor(($expires - time()) / 86400);

    if ($days_left < $warning_days) {
        $msg = "Certificate '{$cert['descr']}' expires in {$days_left} days";
        log_error($msg);
        // Можно добавить отправку уведомления
    }
}
```

## Предупреждения о пользовательских модификациях

Пользовательские изменения в pfSense сопряжены с определенными рисками. Несоблюдение следующих правил может привести к неработоспособности системы после обновления.

| Риск | Описание | Рекомендация |
|---|---|---|
| Потеря при обновлении | Файлы вне `/usr/local/` и `/root/` перезаписываются при обновлении pfSense | Размещайте скрипты в `/usr/local/bin/` или `/root/` |
| Несовместимость API | PHP-функции pfSense могут измениться между версиями | Проверяйте работу скриптов после каждого обновления |
| Безопасность | Скрипты выполняются с правами root | Минимизируйте привилегии, проверяйте ввод |
| config.xml | Прямое редактирование config.xml может нарушить структуру | Используйте PHP API (`write_config()`) вместо прямого редактирования |
| Пакеты Shellcmd/Cron | Неработающий скрипт в shellcmd может задержать загрузку | Тестируйте скрипты перед добавлением в автозагрузку |

Перед каждым обновлением pfSense создайте полную резервную копию и составьте список всех пользовательских модификаций.

## Связанные разделы

- [API и автоматизация pfSense](/docs/pfsense/development/pfsense-api-automation/) - REST API, Ansible, Terraform и программное управление через HTTP
- [Резервное копирование pfSense](/docs/pfsense/backup/pfsense-backup-recovery/) - штатные средства резервного копирования и восстановления конфигурации
- [Пакеты pfSense](/docs/pfsense/packages/) - установка и управление пакетами Shellcmd, Cron и другими расширениями

