Ipfrewall псевдоним ipfw - это системное устройство, которое позволяет выполнять фильтрацию, переадресацию и другие операции с IP-пакетами, проходящими через системный интерфейс. Выбор пакетов производится путем применения упорядоченного списка правил образцов к кажому пакету до тех пор, пока не будет найден подходящий, после чего выполняются соответствующие действия по передаче этого пакета. Привила нумеруются от 1 до 65534, а составные правила могут иметь (разделять) один и тот же номер.
Одно правило - оно имеет номер 65535 - существует всегда. Правило 65535 обычно действует для пакетов, которые должны быть отброшены. Следовательно, любой пакет, который не удовлетворяет какому-либо из правил с меньшим номером, будет отброшен. Однако опция IPFIREWALL_DEFAULT_TO_ACCEPT - она устанавливается во время компиляции ядра - позволяет администратору изменять эти постоянные правила - можно наоборот - разрешить все.
Значение, переданное в setsockopt() - это просто структура ip_fw, описывающая правило (см. ниже). В исключительных случаях, таких как IP_FW_DEL, имеет значение только номер правила (см. syslog(3)) для дальнейшей регистрации посредством syslogd(8); IP_FIREWALL_VERBOSE_LIMIT ограничивает максимальное количество порождаемых правилом сообщений о регистрации. Эти переменные можно изменять при помощи sysctl
.Для управления списком правил используются следующие опции сокета.
IP_FW_ADD | добавляет правило в список |
IP_FW_DEL | удаляет все правила, имеющие соответствующий номер |
IP_FW_GET | возвращает (первое) правило, имеющее соответствующий номер |
IP_FW_ZERO | обнуляет статистику по всем правилам с соответсвующими номерами; если номер правила 0, то обнуляются всеправила. |
IP_FW_FLUSH | удаляет все правила, за исключением 65535. |
Если уровень безопасности ядра (см. init) больше 2, разрешена только команда IP_FW_GET.
Правила описываются следующей структурой.
/*Определяет интерфейс */union ip_fw_if { | ||
struct in_addr fu_via_ip; | /* Определение по IP-адресу */ | |
struct { | /* Определение имени интерфейса */ | |
#define FW_IFNLEN 6 | /*Для сохранения размера структуры с границах 2-х */ | |
char name [FW_IFNLEN]; } fu_via_if; }; |
/* -1 означает соответствие любой единице */ | |
union ip_fw_if fw_in_if, fw_out_if; | /* Входящие/исходящие итерфейсы */ | |
union { | ||
u_short fu_divert_port; | /*Перенаправляющий/копирующий порт */ | |
u_short fu_skip_to_rule; | /*Команда пропустить правило */ | |
u_short fu_reject_code; } fw_un; |
/*Код ответа "отвергнуть" */ | |
u_char fw_prot; | /* IP-протокол */ | |
u_char fw_nports | /*Номера src-портов и номера dst-портов */ | |
/*В массиве портов )dst-порты следуют */ | ||
/*за src-портами;
максимум 10 портов ао всех; 0 означает соотствие всем портам */ |
||
/* Кодирование номеров портов источников/приемников из ipfw_nports */ | ||
#define IP_FW_GETNSRCP(rule) | ((rule)->fw_nports & 0x0f) | |
#define IP_FW_SETNSRCP(rule, n) | do
{
\ (rule)->fw_nports &= ~0x0f; \ (rule)->fw_nports |= (n); \ } while (0) |
|
#define IP_FW_GETNDSTP(rule) | ((rule)->fw_nports >> 4) | |
#define IP_FW_SETNDSTP(rule, n) | do
{
\ (rule)->fw_nports &= ~0xf0; \ (rule)->fw_nports |= (n) << 4; \ } while (0) |
|
/* Значения флагов для поля "flags" */ | ||
#define IP_FW_F_IN | 0x0001 | /* Проверить входящие пакеты */ |
#define IP_FW_F_OUT | 0x0002 | /* Проверить исходящие пакеты */ |
#define IP_FW_F_IIFACE | 0x0004 | /* Применить "входящий" тест интерфейса */ |
#define IP_FW_F_OIFACE | 0x0008 | /* Применить исходящий тест интерфейса */ |
#define IP_FW_F_COMMAND | 0x0070 | /* Маска для типа последовательного входа */ |
#define IP_FW_F_DENY | 0x0000 | /*Это запрещающее правило */ |
#define IP_FW_F_REJECT | 0x0010 | /*Запретить и сообщить об этом, послав ответный пакет */ |
#define IP_FW_F_ACCEPT | 0x0020 | /*Разрешающее правило */ |
#define IP_FW_F_COUNT | 0x0030 | /*Правило счета */ |
#define IP_FW_F_DIVERT | 0x0040 | /*Правило перенаправления */ |
#define IP_FW_F_TEE | 0x0050 | /* Правило дублирования */ |
#define IP_FW_F_SKIPTO | 0x0060 | /* Правило "пропустить" */ |
#define IP_FW_F_PRN | 0x0080 | /* Вывод на печать в случае соответствия правилу */ |
#define IP_FW_F_SRNG | 0x0100 | /* Первые два src-порта - это диапазон минимума и максимума (хранимые в порядке главного байта), |
#define IP_FW_F_DRNG | 0x0200 | /* Первые два dst-порта - диапазон минимума и максимума, хранимые в порядке глаавного байта */ |
Слово флагов |
||
IP_FW_F_DENY | Отбросить пакет | |
IP_FW_F_REJECT | Отбросить пакет и послать сообщение об отказе по протоколу ipmp или tcp | |
IP_FW_F_ACCEPT | Принять пакет | |
IP_FW_F_COUNT | Инкрементный счетчик; продолжать поиск | |
IP_FW_F_DIVERT | Перенаправить пакет в сокет divert(4) | |
IP_FW_F_TEE | Копировать пакет в сокет divert(4) | |
IP_FW_F_SKIPTO | Пропустить до правила fu_skipto_rule |
В случае команды IP_FW_F_REJECT, если fu_reject_code - это число от 0 до 255, тогда пакет icmp, сигнализирующий "сеть недоступна", отправляется обратно по первоначальному IP-адресу источника с соответствующим ответным кодом. В противном случае значение должно быть 256 и протокол IPPROTO_TCP, в этом случае взамен посылается переадресующий пакет tcp.
C IP_FW_F_SKIPTO все успешные правила имеют номер меньший, чем пропущенные fu_skipto_rule.
Опции файла конфигурации ядра:
options IPFIREWALL | IPFIREWALL разрешен |
options IPFIREWALL_VERBOSE | Разрешить записть событий firewall в журнал |
options IPFIREWALL_VERBOSE_LIMIT | ограничить журанал firewall'a |
options IPDIVERT | Разрешить сокет divert |
Если пакеты соответствуют правилу с установленным битом IP_FW_F_PRN и если разрешена регистрация пакетов (IPFIREWALL_VERBOSE), сообщение записывается в /dev/klog с установкой LOG_SECURITY для дальнейшего протоколирования посредством syslogd(8); IPFIREWALL_VERBOSE_LIMIT ограничивает максимальное количество порождаемых правилом сообщений протоколирования. Эти переменные доступны через sysctl.
Функция syssockopt() возвращает 0 в случае успеха. В противном случае возвращается "-1". Для индикации ошибки устанавливается глобальная переменная errno.
Функция setsockopt() не будет выплнена, если:
[EINVAL] | поле опции IP было сформировано неправильно; поле опции было короче минимального значения или длиннее максимального. |
Правило "tee" еще не выполнено - на данный момент не имеет эффекта.