aboutsummaryrefslogtreecommitdiff
path: root/documentation/content/ru/books/handbook/firewalls/_index.adoc
diff options
context:
space:
mode:
Diffstat (limited to 'documentation/content/ru/books/handbook/firewalls/_index.adoc')
-rw-r--r--documentation/content/ru/books/handbook/firewalls/_index.adoc2464
1 files changed, 1655 insertions, 809 deletions
diff --git a/documentation/content/ru/books/handbook/firewalls/_index.adoc b/documentation/content/ru/books/handbook/firewalls/_index.adoc
index 9e9714ec44..fb6638f307 100644
--- a/documentation/content/ru/books/handbook/firewalls/_index.adoc
+++ b/documentation/content/ru/books/handbook/firewalls/_index.adoc
@@ -1,12 +1,14 @@
---
-title: Глава 26. Межсетевые экраны
-part: Часть IV. Сетевые коммуникации
-prev: books/handbook/network-servers
+description: 'В базовой системе FreeBSD встроено три межсетевых экрана: PF, IPFW и IPFILTER. В этой главе рассматривается, как определять правила фильтрации пакетов, различия между встроенными в FreeBSD межсетевыми экранами и способы их использования'
next: books/handbook/advanced-networking
-showBookMenu: true
-weight: 31
params:
- path: "/books/handbook/firewalls/"
+ path: /books/handbook/firewalls/
+part: 'IV. Сетевое взаимодействие'
+prev: books/handbook/network-servers
+showBookMenu: true
+tags: ["firewall", "pf", "ipfw", "ipfilter", "blacklistd", "filtering"]
+title: 'Глава 33. Межсетевые экраны'
+weight: 38
---
[[firewalls]]
@@ -17,7 +19,7 @@ params:
:icons: font
:sectnums:
:sectnumlevels: 6
-:sectnumoffset: 26
+:sectnumoffset: 33
:partnums:
:source-highlighter: rouge
:experimental:
@@ -48,1340 +50,2184 @@ include::../../../../../shared/asciidoctor.adoc[]
endif::[]
[[firewalls-intro]]
-== Введение
+== Обзор
+
+Межсетевые экраны позволяют фильтровать входящий и исходящий трафик, проходящий через систему. Межсетевой экран может использовать один или несколько наборов "правил" для проверки сетевых пакетов при их поступлении или выходе из сетевых соединений и либо пропускает трафик, либо блокирует его. Правила межсетевого экрана могут проверять одну или несколько характеристик пакетов, таких как тип протокола, адрес исходного или целевого хоста, а также исходный или целевой порт.
+
+Межсетевые экраны могут повысить безопасность узла или сети. Они могут использоваться для выполнения одной или нескольких следующих функций:
+
+* Защищать и изолировать приложения, сервисы и машины внутренней сети от нежелательного трафика из общедоступного Интернета.
+* Ограничивать или отключать доступ с хостов внутренней сети к сервисам публичного Интернета.
+* Поддерживать преобразования сетевых адресов (NAT), что позволяет внутренней сети использовать частные IP-адреса и совместно использовать одно подключение к публичному интернету с помощью одного IP-адреса или общего пула автоматически назначаемых публичных адресов.
-Межсетевые экраны (firewall, брандмауэр) делают возможной фильтрацию входящего и исходящего трафика, идущего через вашу систему. Межсетевой экран использует один или более наборов "правил" для проверки сетевых пакетов при их входе или выходе через сетевое соединение, он или позволяет прохождение трафика или блокирует его. Правила межсетевого экрана могут проверять одну или более характеристик пакетов, включая но не ограничиваясь типом протокола, адресом хоста источника или назначения и портом источника или назначения.
+В базовой системе FreeBSD встроено три межсетевых экрана: PF, IPFW и IPFILTER, также известный как IPF. FreeBSD также предоставляет два инструмента для управления использованием пропускной способности: man:altq[4] и man:dummynet[4]. ALTQ традиционно тесно связан с PF, а dummynet — с IPFW. Каждый межсетевой экран использует правила для контроля доступа пакетов к системе FreeBSD и из неё, хотя подходы у них различаются, и каждый имеет свой собственный синтаксис правил.
-Межсетевые экраны могут серьезно повысить уровень безопасности хоста или сети. Они могут быть использованы для выполнения одной или более нижеперечисленных задач:
+FreeBSD предоставляет несколько межсетевых экранов для удовлетворения различных требований и предпочтений широкого круга пользователей. Каждый пользователь должен оценить, какой межсетевой экран лучше всего соответствует его потребностям.
-* Для защиты и изоляции приложений, сервисов и машин во внутренней сети от нежелательного трафика, приходящего из внешней сети интернет.
-* Для ограничения или запрещения доступа хостов внутренней сети к сервисам внешней сети интернет.
-* Для поддержки преобразования сетевых адресов (network address translation, NAT), что дает возможность задействовать во внутренней сети приватные IP адреса и совместно использовать одно подключение к сети Интернет (либо через один выделенный IP адрес, либо через адрес из пула автоматически присваиваемых публичных адресов).
+Прочитав эту главу, вы будете знать:
-После прочтения этой главы вы узнаете:
+* Как определить правила фильтрации пакетов.
+* Различия между межсетевыми экранами, встроенными в FreeBSD.
+* Как использовать и настроить межсетевой экран PF.
+* Как использовать и настроить межсетевой экран IPFW.
+* Как использовать и настроить межсетевой экран IPFILTER.
-* Как правильно задать правила фильтрации пакетов.
-* Разницу между межсетевыми экранами, встроенными в FreeBSD
-* Как использовать и настраивать межсетевой экран OpenBSD PF.
-* Как использовать и настраивать IPFILTER.
-* Как использовать и настраивать IPFW.
+Прежде чем читать эту главу, вы должны:
-Перед прочтением этой главы вам потребуется:
+* Понимать основы FreeBSD и принципы работы Интернета.
-* Ознакомиться с основами FreeBSD и интернет.
+[NOTE]
+====
+Поскольку все межсетевые экраны основаны на проверке значений выбранных управляющих полей пакетов, создатель набора правил межсетевого экрана должен понимать, как работает TCP/IP, какие значения содержатся в управляющих полях пакетов и как эти значения используются в обычном сеансе связи. Хорошее введение можно найти в http://www.ipprimer.com[TCP/IP Primer от Daryl].
+====
[[firewalls-concepts]]
-== Принципы работы межсетевых экранов
+== Концепции межсетевого экрана
+
+Набор правил содержит группу правил, которые пропускают или блокируют пакеты на основе значений, содержащихся в пакете. Двунаправленный обмен пакетами между хостами составляет сеанс взаимодействия. Межсетевой экран обрабатывает как пакеты, поступающие из общедоступного Интернета, так и пакеты, генерируемые системой в ответ на них. Каждая служба TCP/IP имеет свой протокол и порт прослушивания. Пакеты, предназначенные для конкретной службы, идут из исходного адреса с использованием непривилегированного порта и направляются на конкретный порт службы на адресе назначения. Все вышеуказанные параметры могут быть использованы в качестве критериев выбора для создания правил, которые будут пропускать или блокировать службы.
+
+Для поиска неизвестных номеров портов обратитесь к [.filename]#/etc/services#. Или посетите https://en.wikipedia.org/wiki/List_of_TCP_and_UDP_port_numbers[https://en.wikipedia.org/wiki/List_of_TCP_and_UDP_port_numbers] и выполните поиск по номеру порта, чтобы узнать его назначение.
+
+Ознакомьтесь с этой ссылкой для http://web.archive.org/web/20150803024617/http://www.sans.org/security-resources/idfaq/oddports.php[номеров портов, используемых троянами].
+
+FTP имеет два режима: активный режим и пассивный режим. Разница заключается в том, как устанавливается канал передачи данных. Пассивный режим более безопасен, так как канал передачи данных устанавливается инициатором сессии FTP. Для подробного объяснения работы FTP и различных режимов см. http://www.slacksite.com/other/ftp.html[http://www.slacksite.com/other/ftp.html].
-Существует два основных способа создания наборов правил межсетевого экрана: "включающий" и "исключающий". Исключающий межсетевой экран позволяет прохождение всего трафика, за исключением трафика, соответствующего набору правил. Включающий межсетевой экран действует прямо противоположным образом. Он пропускает только трафик, соответствующий правилам и блокирует все остальное.
+Набор правил межсетевого экрана может быть "исключающим" или "включающим". Исключающий межсетевой экран пропускает весь трафик, кроме трафика, соответствующего набору правил. Включающий межсетевой экран действует наоборот, пропуская только трафик, соответствующий правилам, и блокируя всё остальное.
-Включающий межсетевой экран обеспечивает гораздо большую степень контроля исходящего трафика. Поэтому включающий межсетевой экран является лучшим выбором для систем, предоставляющих сервисы в сети Интернет. Он также контролирует тип трафика, порождаемого вне и направляющегося в вашу приватную сеть. Трафик, не попавший в правила, блокируется, а в файл протокола вносятся соответствующие записи. Включающие межсетевые экраны обычно более безопасны, чем исключающие, поскольку они существенно уменьшают риск пропуска межсетевым экраном нежелательного трафика.
+Включающий межсетевой экран обеспечивает лучший контроль исходящего трафика, что делает его предпочтительным выбором для систем, предоставляющих услуги в публичном Интернете. Он также контролирует тип трафика, исходящего из публичного Интернета, который может получить доступ к частной сети. Весь трафик, не соответствующий правилам, блокируется и регистрируется. Включающие межсетевые экраны, как правило, безопаснее исключающих, поскольку они значительно снижают риск пропуска нежелательного трафика.
[NOTE]
====
-Если не указано иначе, то все приведенные в этом разделе примеры наборов правил и конфигураций относятся к типу включающего межсетевого экрана.
+Если не указано иное, все конфигурации и примеры наборов правил в этой главе создают включающие наборы правил для межсетевого экрана.
====
-Безопасность может быть дополнительно повышена с использованием "межсетевого экрана с сохранением состояния". Такой межсетевой экран сохраняет информацию об открытых соединениях и разрешает только трафик через открытые соединения или открытие новых соединений. Недостаток межсетевого экрана с сохранением состояния в том, что он может быть уязвим для атак DoS (Denial of Service, отказ в обслуживании), если множество новых соединений открывается очень быстро. Большинство межсетевых экранов позволяют комбинировать поведение с сохранением состояния и без сохранения состояния, что позволяет создавать оптимальную конфигурацию для каждой конкретной системы.
+Безопасность можно дополнительно усилить с помощью "межсетевого экрана с отслеживанием состояния". Такой тип межсетевого экрана отслеживает активные соединения и разрешает только трафик, который соответствует существующему соединению или открывает новое, разрешённое соединение.
-[[firewalls-apps]]
-== Пакеты межсетевых экранов
+Фильтрация с отслеживанием состояния рассматривает трафик как двусторонний обмен пакетами, составляющими сеанс. Когда для соответствующего правила указано состояние, межсетевой экран динамически создает внутренние правила для каждого ожидаемого пакета, обмениваемого во время сеанса. Он обладает достаточными возможностями сопоставления, чтобы определить, является ли пакет допустимым для сеанса. Любые пакеты, которые не соответствуют шаблону сеанса, автоматически отклоняются.
-В базовую систему FreeBSD встроено три программных межсетевых экрана. Это _IPFILTER_ (известный также как IPF), _IPFIREWALL_ (известный также как IPFW) и _OpenBSD PacketFilter_ (также известный как PF). Помимо этого, FreeBSD содержит два пакета ограничения трафика (по существу, предназначенных для контроля пропускной способности сетевого соединения): man:altq[4] и man:dummynet[4]. Dummynet традиционно сильно связан с IPFW, а ALTQ с PF. В настоящее время IPFILTER не поддерживает ограничение пропускной способности сетевого соединения. Для реализации этой функции предлагается использовать IPFILTER совместно с одним из двух существующих пакетов ограничения трафика. Конфигурация следующая: IPFILTER задействуется для фильтрации и трансляции трафика, а IPFW с man:dummynet[4] _или_PF с ALTQ - для контроля пропускной способности сетевого соединения. IPFW и PF для контроля исходящих и входящих пакетов используют наборы правил, хотя и разными способами с разным синтаксисом правил.
+Когда сеанс завершается, он удаляется из динамической таблицы состояний.
-Причина, по которой в FreeBSD включено более одного пакета межсетевых экранов, заключается в том, что разные пользователи выдвигают к ним различные требования и используют разные предпочтения. Нет одного пакета, который был бы очевидно лучше других.
+Фильтрация с сохранением состояния позволяет сосредоточиться на блокировке/пропускании новых сеансов. Если новый сеанс пропущен, все последующие его пакеты автоматически разрешаются, а любые поддельные пакеты автоматически отвергаются. Если новый сеанс заблокирован, ни один из его последующих пакетов не разрешается. Фильтрация с сохранением состояния предоставляет расширенные возможности сопоставления, способные защитить от потока различных методов атак, используемых злоумышленниками.
-Автор предпочитает IPFILTER, поскольку его правила с сохранением состояния гораздо проще использовать совместно с NAT; кроме того, в него встроен ftp прокси, что упрощает правила для фильтрации исходящих FTP соединений.
+NAT означает _Network Address Translation_ (Преобразование сетевых адресов). Функция NAT позволяет частной локальной сети за межсетевым экраном использовать один IP-адрес, назначенный провайдером, даже если этот адрес динамический. NAT даёт возможность каждому компьютеру в локальной сети выходить в Интернет без необходимости оплачивать провайдеру несколько интернет-аккаунтов или IP-адресов.
-Поскольку все межсетевые экраны основаны на анализе значений выбранных полей заголовка пакета, для создания правил межсетевого экрана необходимо понимание принципов TCP/IP, того, что означают различные поля заголовка пакета, и как эти поля используются в обычной сессии. Хорошим примером является: http://www.ipprimer.com/overview.cfm[http://www.ipprimer.com/overview.cfm].
+NAT автоматически преобразует частный IP-адрес LAN для каждой системы в локальной сети в единственный публичный IP-адрес, когда пакеты выходят за пределы межсетевого экрана, направляясь в публичный Интернет. Он также выполняет обратное преобразование для возвращающихся пакетов.
+
+Согласно RFC 1918, следующие диапазоны IP-адресов зарезервированы для частных сетей, которые никогда не маршрутизируются напрямую в публичный Интернет и, следовательно, могут использоваться с NAT:
+
+* `10.0.0.0/8`.
+* `172.16.0.0/12`.
+* `192.168.0.0/16`.
+
+[WARNING]
+====
+При работе с правилами межсетевого экрана будьте _очень осторожны_. Некоторые конфигурации _могут заблокировать администратора_ на сервере. Для безопасности рекомендуется выполнять первоначальную настройку межсетевого экрана с локальной консоли, а не удалённо через ssh.
+====
[[firewalls-pf]]
-== Packet Filter (PF, межсетевой экран OpenBSD) и ALTQ
+== PF
-В июле 2003 программный межсетевой экран OpenBSD, известный как PF, был портирован в FreeBSD и стал доступен из коллекции портов FreeBSD; первым релизом, где PF был интегрирован в основную систему, стала FreeBSD 5.3 в ноябре 2004. PF это полноценный межсетевой экран с широким набором возможностей, в котором есть опциональная поддержка ALTQ (Alternate Queuing). ALTQ предоставляет управление пропускной способностью Quality of Service (QoS).
+Начиная с FreeBSD 5.3, портированная версия межсетевого экрана PF из OpenBSD включена в базовую систему как её неотъемлемая часть. PF — это полноценный и многофункциональный межсетевой экран с опциональной поддержкой ALTQ (Alternate Queuing), которая обеспечивает качество обслуживания (QoS).
-Проект OpenBSD осуществляет замечательную работу по поддержке http://www.openbsd.org/faq/pf/[PF FAQ]. Этот раздел руководства фокусируется на взаимосвязи PF и FreeBSD, предоставляя лишь общую информацию по его использованию. За более подробной информацией по использованию PF обратитесь к http://www.openbsd.org/faq/pf/[PF FAQ].
+Проект OpenBSD содержит каноническое справочное издание по PF в http://www.openbsd.org/faq/pf/[FAQ по PF]. Питер Ханстин ведет подробный учебник по PF на http://home.nuug.no/\~peter/pf/[http://home.nuug.no/~peter/pf/].
-Дополнительные сведения о PF для FreeBSD можно получить с веб сайта: http://pf4freebsd.love2party.net/[http://pf4freebsd.love2party.net/].
+[WARNING]
+====
+При чтении http://www.openbsd.org/faq/pf/[FAQ по PF] учитывайте, что версия PF в FreeBSD значительно отличается от оригинальной версии OpenBSD за прошедшие годы. Не все функции работают одинаково в FreeBSD и OpenBSD, и наоборот.
+====
-=== Использование модуля ядра PF
+`{freebsd-pf}` — хорошее место для вопросов о настройке и работе PF межсетевого экрана. Перед тем как задать вопрос, проверьте архивы списка рассылки — возможно, ответ уже был дан.
-Чтобы загрузить PF как модуль ядра, добавьте следующую строку в [.filename]#/etc/rc.conf#:
+Эта часть Руководства посвящена PF в контексте FreeBSD. В ней показано, как включить PF и ALTQ, а также приведены несколько примеров создания наборов правил в системе FreeBSD.
-[.programlisting]
+=== Включение PF
+
+Для использования PF необходимо сначала загрузить его модуль ядра. В этом разделе описаны записи, которые можно добавить в [.filename]#/etc/rc.conf# для включения PF.
+
+Начните с добавления `pf_enable=yes` в [.filename]#/etc/rc.conf#:
+
+[source, shell]
....
-pf_enable="YES"
+# sysrc pf_enable=yes
....
-Далее, выполните стартовый скрипт:
+Дополнительные параметры, описанные в man:pfctl[8], могут быть переданы в PF при его запуске. Добавьте или измените эту запись в [.filename]#/etc/rc.conf# и укажите необходимые флаги между кавычками (`""`):
-[source,shell]
+[.programlisting]
....
-# /etc/rc.d/pf start
+pf_flags="" # additional flags for pfctl startup
....
-Учтите, модуль PF не загрузится, если он не сможет найти конфигурационный файл с набором правил. По умолчанию размещение файла с правилами следующее: [.filename]#/etc/pf.conf#. Если путь к файлу отличается от вышеприведённого, то внесите в [.filename]#/etc/rc.conf# строку вида:
+PF не запустится, если не сможет найти файл конфигурации набора правил. По умолчанию FreeBSD не поставляется с готовым набором правил, и файл [.filename]#/etc/pf.conf# отсутствует. Примеры наборов правил можно найти в [.filename]#/usr/share/examples/pf/#. Если пользовательский набор правил был сохранён в другом месте, добавьте строку в [.filename]#/etc/rc.conf#, указывающую полный путь к файлу:
[.programlisting]
....
pf_rules="/path/to/pf.conf"
....
-Файл с примерами конфигураций [.filename]#pf.conf# находится в каталоге [.filename]#/usr/shared/examples/pf/#.
+Поддержка журналирования для PF предоставляется man:pflog[4]. Для включения поддержки журналирования добавьте `pflog_enable=yes` в [.filename]#/etc/rc.conf#:
+
+[source, shell]
+....
+# sysrc pflog_enable=yes
+....
-Модуль PF можно также загрузить вручную:
+Следующие строки также могут быть добавлены для изменения расположения файла журнала по умолчанию или для указания дополнительных флагов, передаваемых в man:pflog[4] при его запуске:
-[source,shell]
+[.programlisting]
....
-# kldload pf.ko
+pflog_logfile="/var/log/pflog" # where pflogd should store the logfile
+pflog_flags="" # additional flags for pflogd startup
....
-Поддержка ведения логов для PF обеспечивается модулем `pflog.ko`, для загрузки которого добавьте следующую строку в [.filename]#/etc/rc.conf#:
+Наконец, если за межсетевым экраном есть локальная сеть (LAN) и пакеты необходимо перенаправлять для компьютеров в этой сети, или требуется NAT, включите следующую опцию:
[.programlisting]
....
-pflog_enable="YES"
+gateway_enable="YES" # Enable as LAN gateway
....
-и запустите на выполнение скрипт:
+После сохранения необходимых изменений, PF можно запустить с поддержкой журналирования, набрав:
-[source,shell]
+[source, shell]
....
-# /etc/rc.d/pflog start
+# service pf start
+# service pflog start
....
-Если вам необходимы другие функциональные возможности PF, то придется добавить поддержку PF в ядро.
+По умолчанию PF читает свои правила конфигурации из [.filename]#/etc/pf.conf# и изменяет, отбрасывает или пропускает пакеты в соответствии с правилами или определениями, указанными в этом файле. Установка FreeBSD включает несколько примеров файлов, расположенных в [.filename]#/usr/share/examples/pf/#. Полное описание наборов правил PF можно найти в http://www.openbsd.org/faq/pf/[PF FAQ].
+
+Для управления PF используйте `pfctl`. crossref:firewalls[pfctl,Полезные опции `pfctl`] содержит сводку полезных опций этой команды. За подробным описанием всех доступных опций обратитесь к man:pfctl[8]:
+[[pfctl]]
+.Полезные параметры `pfctl`
+[cols="1,1", frame="none", options="header"]
+|===
+| Команда
+| Назначение
+
+|`pfctl -e`
+|Включить PF.
-=== Параметры ядра
+|`pfctl -d`
+|Отключить PF.
-Включение PF путем компиляции с ядром FreeBSD не является обязательным требованием, однако вам может понадобиться одна из функциональных возможностей, которая не включена в загружаемый модуль. Например, man:pfsync[4] являет собой псевдоустройство, которое вносит определенные изменения в таблицу состояний, используемую PF. В дальнейшем, это псевдоустройство может быть скомпоновано с man:carp[4] чтобы создать отказоустойчивую систему межсетевых экранов на основе PF.
+|`pfctl -F all -f /etc/pf.conf`
+|Очистить все правила NAT, фильтрации, состояний и таблиц и перезагрузить [.filename]#/etc/pf.conf#.
-Пример параметров конфигурации ядра для включения PF находится в [.filename]#/usr/src/sys/conf/NOTES# и показан здесь:
+|`pfctl -s [ rules \| nat \| states ]`
+|Отчет о правилах фильтрации, правилах NAT или таблице состояний.
+
+|`pfctl -vnf /etc/pf.conf`
+|Проверить [.filename]#/etc/pf.conf# на ошибки, но не загружать набор правил.
+|===
+
+[TIP]
+====
+Пакет package:security/sudo[] полезен для выполнения команд, таких как `pfctl`, которые требуют повышенных привилегий. Он может быть установлен из Коллекции портов.
+====
+
+Для наблюдения за трафиком, проходящим через межсетевой экран PF, рекомендуется установить пакет package:sysutils/pftop[] или порт. После установки можно запустить pftop для просмотра текущего снимка трафика в формате, аналогичном man:top[1].
+
+[[pf-tutorial]]
+=== Наборы правил PF
+
+Этот раздел демонстрирует, как создать настраиваемый набор правил. Он начинается с простейшего набора правил и развивает его концепции, используя несколько примеров для демонстрации практического применения множества возможностей PF.
+
+Самый простой возможный набор правил предназначен для одиночной машины, которая не запускает никаких сервисов и которой требуется доступ к одной сети, возможно, к Интернету. Чтобы создать этот минимальный набор правил, отредактируйте файл [.filename]#/etc/pf.conf#, чтобы он выглядел следующим образом:
[.programlisting]
....
-device pf
-device pflog
-device pfsync
+block in all
+pass out all keep state
....
-`device pf` включает поддержку межсетевого экрана "Packet Filter" (man:pf[4]).
+Первое правило по умолчанию запрещает весь входящий трафик. Второе правило разрешает исходящие соединения, созданные этой системой, сохраняя информацию о состоянии этих соединений. Эта информация о состоянии позволяет возвратному трафику для этих соединений проходить обратно и должна использоваться только на машинах, которым можно доверять. Набор правил можно загрузить с помощью:
-`device pflog` включает необязательное сетевое псевдоустройство man:pflog[4], которое может использоваться для протоколирования трафика через man:bpf[4]. Даемон man:pflogd[8] может использоваться для сохранения протоколируемой информации на диск.
+[source, shell]
+....
+# pfctl -e ; pfctl -f /etc/pf.conf
+....
-`device pfsync` включает необязательное сетевое псевдоустройство man:pfsync[4], используемое для отслеживания "изменений состояния".
+В дополнение к отслеживанию состояний, PF предоставляет _списки_ и _макросы_, которые можно определить для использования при создании правил. Макросы могут включать списки и должны быть определены до их использования. В качестве примера вставьте следующие строки в самое начало набора правил:
-=== Доступные параметры rc.conf
+[.programlisting]
+....
+tcp_services = "{ ssh, smtp, domain, www, pop3, auth, pop3s }"
+udp_services = "{ domain }"
+....
-Для активации PF и man:pflog[4] во время загрузки в man:rc.conf[5] должны быть включены следующие переменные:
+PF понимает как имена портов, так и их номера, при условии, что имена перечислены в [.filename]#/etc/services#. В этом примере создаются два макроса. Первый — это список из семи имён TCP-портов, а второй — одно имя UDP-порта. После определения макросы можно использовать в правилах. В данном примере весь трафик блокируется, за исключением соединений, инициированных этой системой для семи указанных TCP-сервисов и одного указанного UDP-сервиса:
[.programlisting]
....
-pf_enable="YES" # Включить PF (загрузить модуль если необходимо)
-pf_rules="/etc/pf.conf" # определение правил для pf
-pf_flags="" # дополнительные флаги для запуска pfctl
-pflog_enable="YES" # запустить pflogd(8)
-pflog_logfile="/var/log/pflog" # где pflogd должен сохранять протокол
-pflog_flags="" # дополнительные флаги для запуска pflogd
+tcp_services = "{ ssh, smtp, domain, www, pop3, auth, pop3s }"
+udp_services = "{ domain }"
+block all
+pass out proto tcp to any port $tcp_services keep state
+pass proto udp to any port $udp_services keep state
....
-Если за межсетевым экраном находится локальная сеть и необходимо передавать пакеты для компьютеров этой сети, или использовать NAT, включите также следующий параметр:
+Хотя UDP считается протоколом без сохранения состояния, PF способен отслеживать некоторую информацию о состоянии. Например, когда передается UDP-запрос к серверу имен с вопросом о доменном имени, PF будет ожидать ответ, чтобы пропустить его обратно.
-[.programlisting]
+Всякий раз при внесении изменений в набор правил, новые правила должны быть загружены для их использования:
+
+[source, shell]
....
-gateway_enable="YES" # Включить сетевой шлюз
+# pfctl -f /etc/pf.conf
....
-=== Создание правил фильтрации
+Если нет синтаксических ошибок, `pfctl` не выводит сообщений во время загрузки правил. Правила также можно проверить перед попыткой их загрузки:
-Пакет PF читает конфигурацию из файла man:pf.conf[5] (полный путь: [.filename]#/etc/pf.conf#); пакеты отвергаются, пропускаются или модифицируются в соответствии с правилами и определениями из этого файла. В стандартную поставку FreeBSD входят несколько файлов с примерами конфигураций, которые находятся в каталоге [.filename]#/usr/shared/examples/pf/#. За исчерпывающим описанием правил PF обратитесь к http://www.openbsd.org/faq/pf/[PF FAQ].
+[source, shell]
+....
+# pfctl -nf /etc/pf.conf
+....
-[WARNING]
-====
+Включение опции `-n` приводит к тому, что правила только интерпретируются, но не загружаются. Это даёт возможность исправить любые ошибки. В любое время будет применяться последний загруженный корректный набор правил, пока либо PF не будет отключён, либо не будет загружен новый набор правил.
-Изучая http://www.openbsd.org/faq/pf/[PF FAQ], имейте в виду, что различные версии FreeBSD могут содержать разные версии pf. В настоящий момент FreeBSD использует ту же версию PF, которая включена в OpenBSD 4.1.
+[TIP]
+====
+Добавление `-v` к проверке или загрузке набора правил `pfctl` отобразит полностью разобранные правила именно так, как они будут загружены. Это крайне полезно при отладке правил межсетевого экрана.
====
-{freebsd-pf} является хорошим местом, чтобы задавать вопросы по конфигурации и использованию пакета PF. Не забудьте проверить архивы списка рассылки перед тем, как задавать вопрос.
+[[pftut-gateway]]
+==== Простой шлюз с NAT
-=== Работа с PF
+В этом разделе показано, как настроить систему FreeBSD с PF для работы в качестве шлюза как минимум для одного другого компьютера. Шлюзу требуется как минимум два сетевых интерфейса, каждый из которых подключен к отдельной сети. В этом примере [.filename]#xl0# подключен к Интернету, а [.filename]#xl1# подключен к внутренней сети.
-Для управления PF используйте утилиту man:pfctl[8]. Ниже приведено несколько полезных команд (все возможные команды и опции приведены на странице справочника man:pfctl[8]):
+Включите шлюз, чтобы позволить машине перенаправлять сетевой трафик, полученный на одном интерфейсе, на другой интерфейс. Этот параметр sysctl перенаправляет IPv4-пакеты:
-[.informaltable]
-[cols="1,1", frame="none", options="header"]
-|===
-| Команда
-| Действие
+[source, shell]
+....
+# sysctl net.inet.ip.forwarding=1
+....
-|`pfctl -e`
-|Включить PF
+Для переадресации IPv6-трафика используйте:
-|`pfctl -d`
-|Выключить PF
+[source, shell]
+....
+# sysctl net.inet6.ip6.forwarding=1
+....
-|`pfctl -F all -f /etc/pf.conf`
-|Сбросить все правила (NAT, правила фильтрации, состояния соединений, таблицы и т.д.) и загрузить новые с файла [.filename]#/etc/pf.conf#
+Чтобы включить эти настройки при загрузке системы, используйте man:sysrc[8] для их добавления в [.filename]#/etc/rc.conf#:
-|`pfctl -s [ rules \| nat \| state ]`
-|Отобразить правила фильтрации, правила NAT или таблицу состояний соединений
+[source, shell]
+....
+# sysrc gateway_enable=yes
+# sysrc ipv6_gateway_enable=yes
+....
-|`pfctl -vnf /etc/pf.conf`
-|Проверить [.filename]#/etc/pf.conf# на наличие ошибок, но сами наборы правил не загружать
-|===
+Проверьте с помощью `ifconfig`, что оба интерфейса активны и работают.
-=== Включение ALTQ
+Далее создайте правила PF, чтобы позволить шлюзу передавать трафик. Хотя следующее правило разрешает трафик с сохранением статуса от хостов внутренней сети проходить к шлюзу, ключевое слово `to` не гарантирует прохождение всего пути от источника до назначения:
-ALTQ может быть включен только путем компилирования ядра FreeBSD с соответствующими параметрами. ALTQ поддерживается не всеми существующими драйверами сетевых карт. Для просмотра списка поддерживаемых устройств в вашем релизе FreeBSD обратитесь к странице справочника man:altq[4].
+[.programlisting]
+....
+pass in on xl1 from xl1:network to xl0:network port $ports keep state
+....
-Следующие параметры включат ALTQ и добавят дополнительную функциональность.
+Это правило разрешает прохождение трафика только внутрь шлюза на внутреннем интерфейсе. Чтобы пакеты могли идти дальше, требуется соответствующее правило:
[.programlisting]
....
-options ALTQ
-options ALTQ_CBQ # Class Bases Queuing (CBQ)
-options ALTQ_RED # Random Early Detection (RED)
-options ALTQ_RIO # RED In/Out
-options ALTQ_HFSC # Hierarchical Packet Scheduler (HFSC)
-options ALTQ_PRIQ # Priority Queuing (PRIQ)
-options ALTQ_NOPCC # Required for SMP build
+pass out on xl0 from xl1:network to xl0:network port $ports keep state
....
-`options ALTQ` включает подсистему ALTQ.
+Хотя эти два правила будут работать, столь специфичные правила редко требуются. Для занятого сетевого администратора читаемый набор правил — это более безопасный набор правил. В оставшейся части этого раздела показано, как сохранять правила максимально простыми для удобочитаемости. Например, эти два правила можно заменить одним:
-`options ALTQ_CBQ` включает _Class Based Queuing_ (CBQ). CBQ позволяет распределять пропускную способность соединений по классам или очередям для выставления приоритетов трафика на основе правил фильтрации.
+[.programlisting]
+....
+pass from xl1:network to any port $ports keep state
+....
-`options ALTQ_RED` включает _Random Early Detection_ (RED). RED используется для предотвращения перегрузки сети. RED вычисляет длину очереди и сравнивает ее с минимальным и максимальным значением длины очереди. Если очередь превышает максимум, все новые пакеты будут отброшены. В соответствии со своим названием, RED отбрасывает пакеты из различных соединений в произвольном порядке.
+Обозначение `interface:network` может быть заменено макросом для повышения читаемости набора правил. Например, можно определить макрос `$localnet` как сеть, непосредственно подключённую к внутреннему интерфейсу (`$xl1:network`). Или определение `$localnet` может быть изменено на _IP-адрес/маску сети_ для обозначения сети, например `192.168.100.1/24` для подсети частных адресов.
-`options ALTQ_RIO` включает _Random Early Detection In and Out_.
+Если требуется, `$localnet` можно определить даже как список сетей. Независимо от конкретных потребностей, разумное определение `$localnet` может быть использовано в типичном правиле пропуска следующим образом:
-`options ALTQ_HFSC` включает _Hierarchical Fair Service Curve Packet Scheduler_. Дополнительная информация о HFSC находится по адресу: http://www-2.cs.cmu.edu/\~hzhang/HFSC/main.html[http://www-2.cs.cmu.edu/~hzhang/HFSC/main.html].
+[.programlisting]
+....
+pass from $localnet to any port $ports keep state
+....
-`options ALTQ_PRIQ` включает _Priority Queuing_ (PRIQ). PRIQ всегда первым пропускает трафик из очереди c более высоким приоритетом.
+Следующий пример набора правил разрешает весь трафик, инициированный машинами во внутренней сети. Сначала определяются два макроса для представления внешнего и внутреннего интерфейсов 3COM настраиваемого шлюза.
-`options ALTQ_NOPCC` включает поддержку SMP для ALTQ. Эта опция необходима для SMP систем.
+[NOTE]
+====
+Для пользователей коммутируемого доступа внешний интерфейс будет использовать [.filename]#tun0#. Для ADSL-подключения, особенно тех, которые используют PPP через Ethernet (PPPoE), правильный внешний интерфейс — это [.filename]#tun0#, а не физический Ethernet-интерфейс.
+====
-[[firewalls-ipf]]
-== * IPFILTER (IPF)
+[.programlisting]
+....
+ext_if = "xl0" # macro for external interface - use tun0 for PPPoE
+int_if = "xl1" # macro for internal interface
+localnet = $int_if:network
+# ext_if IP address could be dynamic, hence ($ext_if)
+nat on $ext_if from $localnet to any -> ($ext_if)
+block all
+pass from { lo0, $localnet } to any keep state
+....
-[WARNING]
-====
+Этот набор правил вводит правило `nat`, которое используется для обработки преобразования сетевых адресов из не маршрутизируемых адресов внутри внутренней сети в IP-адрес, назначенный внешнему интерфейсу. Скобки вокруг последней части правила nat `($ext_if)` включаются, когда IP-адрес внешнего интерфейса назначается динамически. Это гарантирует, что сетевой трафик будет работать без серьёзных перебоев, даже если внешний IP-адрес изменится.
-Перевод раздела не завершен.
-====
+Обратите внимание, что этот набор правил, вероятно, разрешает больше трафика для выхода из сети, чем необходимо. Один из разумных вариантов настройки может создать этот макрос:
-[NOTE]
-====
-Этот раздел находится в процессе написания; содержание может не вполне соответствовать действительности.
-====
+[.programlisting]
+....
+client_out = "{ ftp-data, ftp, ssh, domain, pop3, auth, nntp, http, \
+ https, cvspserver, 2628, 5999, 8000, 8080 }"
+....
-Автором IPFILTER является Darren Reed. IPFILTER не зависит от операционной системы: это приложение с открытыми исходными текстами, которое было портировано на операционные системы FreeBSD, NetBSD, OpenBSD, SunOS(TM), HP/UX, и Solaris(TM). IPFILTER активно разрабатывается и поддерживается, регулярно выпускаются обновленные версии.
+для использования в основном правиле пропуска:
-IPFILTER основан на межсетевом экране и механизме NAT уровня ядра, которые управляются и контролируются утилитами уровня пользовательских процессов. Правила межсетевого экрана могут устанавливаться или удаляться утилитой man:ipf[8]. Правила NAT могут устанавливаться или удаляться утилитой man:ipnat[1]. Утилита man:ipfstat[8] выводит статистику IPFILTER для ядра. Программа man:ipmon[8] может заносить действия IPFILTER в файлы системных протоколов.
+[.programlisting]
+....
+pass inet proto tcp from $localnet to any port $client_out \
+ flags S/SA keep state
+....
+
+Еще могут понадобиться несколько других правил пропуска . Это правило включает SSH на внешнем интерфейсе:
-IPF был первоначально написан с использованием правила "последнее совпадение применяется" и только с правилами без сохранения состояния. Со временем IPF был расширен и включает параметры "quick" и "keep state" (сохранение состояния), которые кардинальным образом изменяют логику обработки пакетов. Официальная документация IPF включает традиционные параметры правил с традиционной последовательностью обработки пакетов. Измененные функции включены в виде дополнительных параметров, они необходимы для создания эффективного межсетевого экрана.
+[.programlisting]
+....
+pass in inet proto tcp to $ext_if port ssh
+....
-Инструкции этого раздела подразумевают использование параметра "quick" и параметра сохранения состояния "keep state". Это основа для создания включающего межсетевого экрана.
+Это определение макроса и правило разрешают DNS и NTP для внутренних клиентов:
-Детальное описание традиционных методов обработки правил: http://www.obfuscation.org/ipf/ipf-howto.html#TOC_1[http://www.obfuscation.org/ipf/ipf-howto.html#TOC_1] и http://coombs.anu.edu.au/\~avalon/ip-filter.html[http://coombs.anu.edu.au/~avalon/ip-filter.html].
+[.programlisting]
+....
+udp_services = "{ domain, ntp }"
+pass quick inet proto { tcp, udp } to any port $udp_services keep state
+....
-IPF FAQ находится по адресу http://www.phildev.net/ipf/index.html[http://www.phildev.net/ipf/index.html].
+Обратите внимание на ключевое слово `quick` в этом правиле. Поскольку набор правил состоит из нескольких правил, важно понимать взаимосвязи между ними. Правила обрабатываются сверху вниз, в порядке их написания. Для каждого пакета или соединения, оцениваемого PF, _последнее совпадающее правило_ в наборе является тем, которое применяется. Однако, когда пакет совпадает с правилом, содержащим ключевое слово `quick`, обработка правил прекращается, и пакет обрабатывается в соответствии с этим правилом. Это очень полезно, когда требуется исключение из общих правил.
-Архив списка рассылки по IPFilter с возможностью поиска доступен по адресу http://marc.theaimsgroup.com/?l=ipfilter[http://marc.theaimsgroup.com/?l=ipfilter].
+[[pftut-ftp]]
+==== Создание FTP-прокси
-=== Включение IPF
+Настройка рабочих правил FTP может быть проблематичной из-за особенностей протокола FTP. Протокол FTP появился на несколько десятилетий раньше межсетевых экранов и небезопасен по своей конструкции. Наиболее распространённые аргументы против использования FTP включают:
-IPF включен в базовую систему FreeBSD в качестве отдельного загружаемого модуля. Система динамически загрузит модуль IPF, если в [.filename]#rc.conf# указана переменная `ipfilter_enable="YES"`. Модуль создается с включенным протоколированием и правилом по умолчанию `pass all` (пропускать все). Для изменения правила по умолчанию не обязательно собирать ядро с новыми параметрами. Просто добавьте в конец набора правило, блокирующее все пакеты.
+* Пароли передаются в открытом виде.
+* Протокол требует использования как минимум двух TCP-соединений (управляющего канала и канала данных) на отдельных портах.
+* Когда сеанс установлен, данные передаются с использованием случайно выбранных портов.
-=== Параметры ядра
+Все эти моменты представляют собой проблемы безопасности, даже без учёта потенциальных уязвимостей в клиентском или серверном программном обеспечении. Более безопасные альтернативы для передачи файлов существуют, например, man:sftp[1] или man:scp[1], которые обеспечивают аутентификацию и передачу данных через зашифрованные соединения.
-Включение IPF в ядро FreeBSD не является обязательным требованием. Эта процедура представлена здесь в качестве дополнительной информации. При включении IPF в ядро загружаемый модуль не используется.
+Для случаев, когда требуется FTP, PF предоставляет возможность перенаправления FTP-трафика на небольшую прокси-программу под названием man:ftp-proxy[8], которая включена в базовую систему FreeBSD. Роль прокси заключается в динамическом добавлении и удалении правил в наборе правил, используя набор якорей, для корректной обработки FTP-трафика.
-Пример параметров настройки ядра для IPF находится в [.filename]#/usr/src/sys/conf/NOTES# и воспроизведен здесь:
+Чтобы включить FTP-прокси, добавьте следующую строку в [.filename]#/etc/rc.conf#:
[.programlisting]
....
-options IPFILTER
-options IPFILTER_LOG
-options IPFILTER_DEFAULT_BLOCK
+ftpproxy_enable="YES"
....
-`options IPFILTER` включает поддержку межсетевого экрана "IPFILTER".
+Затем запустите прокси, выполнив:
-`options IPFILTER_LOG` включает протоколирование трафика через IPF путем записи его в псевдо-устройство протоколирования пакетов [.filename]#ipl# для каждого правила, содержащего ключевое слово `log`.
+[source, bash]
+....
+# service ftp-proxy start
+....
-`options IPFILTER_DEFAULT_BLOCK` изменяет поведение по умолчанию так, что блокируется каждый пакет, не соответствующий правилу `pass`.
+Для базовой конфигурации необходимо добавить три элемента в [.filename]#/etc/pf.conf#. Во-первых, якоря, которые прокси будет использовать для вставки правил, генерируемых для FTP-сессий:
-Эти настройки будут работать только после сборки и установки нового ядра.
+[.programlisting]
+....
+nat-anchor "ftp-proxy/*"
+rdr-anchor "ftp-proxy/*"
+....
-=== Доступные параметры rc.conf
+Во-вторых, необходимо правило pass, чтобы разрешить FTP-трафик к прокси.
-Для активации IPF во время загрузки в [.filename]#/etc/rc.conf# потребуется добавить следующие переменные:
+Третье, правила перенаправления и NAT должны быть определены до правил фильтрации. Вставьте это правило `rdr` сразу после правила `nat`:
[.programlisting]
....
-ipfilter_enable="YES" # Запуск межсетевого экрана ipf
-ipfilter_rules="/etc/ipf.rules" # Загрузка файла с правилами
-ipmon_enable="YES" # Включение протоколирования IP monitor
-ipmon_flags="-Ds" # D = запуск в виде даемона
- # s = протоколирование в syslog
- # v = протоколирование tcp window, ack, seq
- # n = отображение имен IP и портов
+rdr pass on $int_if proto tcp from any to any port ftp -> 127.0.0.1 port 8021
....
-Если за межсетевым экраном находится локальная сеть, использующая приватные IP адреса, для включения NAT потребуется добавить следующие переменные:
+Наконец, разрешите перенаправленному трафику проходить:
[.programlisting]
....
-gateway_enable="YES" # Включение шлюза для локальной сети
-ipnat_enable="YES" # Запуск функции ipnat
-ipnat_rules="/etc/ipnat.rules" # Определение файла правил для ipnat
+pass out proto tcp from $proxy to any port ftp
....
-=== IPF
+где `$proxy` раскрывается в адрес, к которому привязан демон прокси.
-Команда man:ipf[8] используется для загрузки файла с правилами. Обычно создается файл, содержащий подготовленный набор правил, который полностью замещает набор, используемый на данный момент:
+Сохраните [.filename]#/etc/pf.conf#, загрузите новые правила и проверьте с клиента, что FTP-подключения работают:
-[source,shell]
+[source, shell]
....
-# ipf -Fa -f /etc/ipf.rules
+# pfctl -f /etc/pf.conf
....
-`-Fa` означает сброс всех внутренних таблиц правил.
+Этот пример описывает базовую настройку, когда клиенты в локальной сети должны обращаться к FTP-серверам в других местах. Данная базовая конфигурация должна хорошо работать с большинством комбинаций FTP-клиентов и серверов. Как показано в man:ftp-proxy[8], поведение прокси можно изменить различными способами, добавляя параметры в строку `ftpproxy_flags=`. Некоторые клиенты или серверы могут иметь специфические особенности, которые необходимо учитывать в конфигурации, или может возникнуть необходимость интегрировать прокси определённым образом, например, назначить FTP-трафик в определённую очередь.
-`-f` указывает файл с правилами, который необходимо загрузить.
+Для способов запуска FTP-сервера, защищённого PF и man:ftp-proxy[8], настройте отдельный `ftp-proxy` в обратном режиме с использованием `-R` на отдельном порту с собственным правилом перенаправления pass.
-Это дает вам возможность отредактировать файл с правилами, запустить вышеприведенную команду IPF, тем самым обновить набор правил работающего межсетевого экрана без перезагрузки системы. Для обновления правил такой подход очень удобен, поскольку команду можно выполнять столько раз, сколько нужно.
+[[pftut-icmp]]
+==== Управление ICMP
-На странице справочной системы man:ipf[8] находится подробная информация по всем флагам этой команды.
+Многие инструменты, используемые для отладки или устранения неполадок в сети TCP/IP, основаны на протоколе ICMP (Internet Control Message Protocol), который был специально разработан для целей отладки.
-Набор правил для команды man:ipf[8] должен быть в виде стандартного текстового файла. Правила, написанные в виде скрипта с символами подстановки, не принимаются.
+Протокол ICMP отправляет и получает _управляющие сообщения_ между хостами и шлюзами, в основном для предоставления отправителю обратной связи о любых необычных или сложных условиях на пути к целевому хосту. Маршрутизаторы используют ICMP для согласования размеров пакетов и других параметров передачи в процессе, часто называемом _обнаружением MTU пути_.
-Есть способ составления правил IPF, использующих символы подстановки. Обратитесь к <<firewalls-ipf-rules-script>>.
+С точки зрения межсетевого экрана, некоторые управляющие ICMP-сообщения уязвимы к известным векторам атак. Кроме того, безусловный пропуск всего диагностического трафика упрощает отладку, но также облегчает для других получение информации о сети. По этим причинам следующее правило может быть неоптимальным:
-=== IPFSTAT
+[.programlisting]
+....
+pass inet proto icmp from any to any
+....
-По умолчанию man:ipfstat[8] получает и отображает суммарную статистику, полученную в результате применения действующих правил к пакетам, проходящим через межсетевой экран с момента его последнего запуска, или с того момента, когда статистика была последний раз обнулена командой `ipf -Z`.
+Одно из решений — пропускать весь ICMP-трафик из локальной сети, блокируя все запросы извне:
-Детальная информация приводится на странице справочника man:ipfstat[8].
+[.programlisting]
+....
+pass inet proto icmp from $localnet to any keep state
+pass inet proto icmp from any to $ext_if keep state
+....
-Вывод команды man:ipfstat[8] по умолчанию выглядит примерно так:
+Дополнительные параметры демонстрируют гибкость PF. Например, вместо разрешения всех ICMP-сообщений можно указать сообщения, используемые man:ping[8] и man:traceroute[8]. Начните с определения макроса для этого типа сообщения:
-[source,shell]
+[.programlisting]
....
-input packets: blocked 99286 passed 1255609 nomatch 14686 counted 0
- output packets: blocked 4200 passed 1284345 nomatch 14687 counted 0
- input packets logged: blocked 99286 passed 0
- output packets logged: blocked 0 passed 0
- packets logged: input 0 output 0
- log failures: input 3898 output 0
- fragment state(in): kept 0 lost 0
- fragment state(out): kept 0 lost 0
- packet state(in): kept 169364 lost 0
- packet state(out): kept 431395 lost 0
- ICMP replies: 0 TCP RSTs sent: 0
- Result cache hits(in): 1215208 (out): 1098963
- IN Pullups succeeded: 2 failed: 0
- OUT Pullups succeeded: 0 failed: 0
- Fastroute successes: 0 failures: 0
- TCP cksum fails(in): 0 (out): 0
- Packet log flags set: (0)
+icmp_types = "echoreq"
....
-При задании флага `-i` или `-o` соответственно для входящих или исходящих пакетов, команда извлечет и отобразит соответствующий список правил, установленных и используемых на данный момент.
+и правила, которое использует макрос:
-`ipfstat -in` отображает правила, применяемые к входящим пакетам, вместе с номерами этих правил.
+[.programlisting]
+....
+pass inet proto icmp all icmp-type $icmp_types keep state
+....
-`ipfstat -on` отображает правила, применяемые к исходящим пакетам, вместе с номерами этих правил.
+Если требуются другие типы ICMP-пакетов, расширьте `icmp_types` до списка этих типов пакетов. Введите `more /usr/src/sbin/pfctl/pfctl_parser.c`, чтобы увидеть список типов ICMP-сообщений, поддерживаемых PF. Дополнительные сведения о каждом типе сообщения можно найти по ссылке http://www.iana.org/assignments/icmp-parameters/icmp-parameters.xhtml[http://www.iana.org/assignments/icmp-parameters/icmp-parameters.xhtml].
-Вывод команды будет выглядеть примерно так:
+Поскольку Unix `traceroute` по умолчанию использует UDP, требуется дополнительное правило для разрешения Unix `traceroute`:
-[source,shell]
+[.programlisting]
....
-@1 pass out on xl0 from any to any
-@2 block out on dc0 from any to any
-@3 pass out quick on dc0 proto tcp/udp from any to any keep state
+# allow out the default range for traceroute(8):
+pass out on $ext_if inet proto udp from any to any port 33433 >< 33626 keep state
....
-`ipfstat -ih` отображает правила, применяемые к входящим пакетам, со счетчиком количества совпадений для каждого правила.
+Поскольку `TRACERT.EXE` в системах Microsoft Windows использует сообщения запроса эхо-ответа ICMP, достаточно только первого правила, чтобы разрешить трассировку сети с этих систем. В Unix `traceroute` можно настроить на использование других протоколов, и он будет использовать сообщения запроса эхо-ответа ICMP, если указан параметр `-I`. Подробности смотрите на man:traceroute[8].
-`ipfstat -oh` отображает правила, применяемые к исходящим пакетам, со счетчиком количества совпадений для каждого правила.
+[[pftut-pathmtudisc]]
+===== Обнаружение MTU пути
-Вывод команды будет выглядеть примерно так:
+Протоколы Интернета разработаны так, чтобы быть независимыми от устройств, и одним из следствий этой независимости является то, что оптимальный размер пакета для данного соединения не всегда может быть надежно предсказан. Основное ограничение на размер пакета — это _Maximum Transmission Unit_ (MTU), который устанавливает верхний предел размера пакета для интерфейса. Введите `ifconfig`, чтобы просмотреть MTU для сетевых интерфейсов системы.
-[source,shell]
+TCP/IP использует процесс, известный как обнаружение MTU пути, для определения правильного размера пакета для соединения. Этот процесс отправляет пакеты различного размера с установленным флагом "Не фрагментировать", ожидая возврата ICMP-пакета с "типом 3, кодом 4", когда достигнут верхний предел. Тип 3 означает "адресат недостижим", а код 4 является сокращением для "требуется фрагментация, но установлен флаг 'не фрагментировать'". Чтобы разрешить обнаружение MTU пути для поддержки соединений с другими MTU, добавьте тип `destination unreachable` в макрос `icmp_types`:
+
+[.programlisting]
....
-2451423 pass out on xl0 from any to any
-354727 block out on dc0 from any to any
-430918 pass out quick on dc0 proto tcp/udp from any to any keep state
+icmp_types = "{ echoreq, unreach }"
....
-Одна из наиболее важных функций команды `ipfstat` активируется флагом `-t`, правила отображаются подобно тому, как man:top[1] показывает таблицу запущенных процессов FreeBSD. Когда межсетевой экран подвергается атаке, эта функция позволяет обнаружить соответствующие пакеты. Дополнительные флаги дают возможность выбирать IP адрес назначения или источника, порт или протокол, которые будут отслеживаться в реальном времени. Подробная информация приведена на странице man:ipfstat[8].
+Поскольку правило `pass` уже использует этот макрос, его не нужно изменять для поддержки нового типа ICMP:
-=== IPMON
+[.programlisting]
+....
+pass inet proto icmp all icmp-type $icmp_types keep state
+....
+
+PF позволяет фильтрацию по всем вариантам типов и кодов ICMP. Список возможных типов и кодов документирован в man:icmp[4] и man:icmp6[4].
-Для того, чтобы стало возможно использование команды `ipmon`, необходимо включить параметр ядра `IPFILTER_LOG`. Эта команда может использоваться в двух различных режимах. В основном режиме, который используется по умолчанию, она используется без флага `-D`.
+[[pftut-tables]]
+==== Использование таблиц
-В режиме даемона создается непрерывный протокол, и возможен просмотр предыдущих событий. В этом режиме IPFILTER работает в FreeBSD. Поскольку в FreeBSD встроена функция ротации файлов протокола, лучше использовать man:syslogd[8], чем используемый по умолчанию вывод в обычный файл. В [.filename]#rc.conf# по умолчанию `ipmon_flags` имеет значение `-Ds`:
+Некоторые типы данных важны для фильтрации и перенаправления в определенный момент времени, но их определение слишком длинное, чтобы включать его в файл набора правил. PF поддерживает использование таблиц — это определенные списки, которыми можно управлять без необходимости перезагружать весь набор правил, и которые обеспечивают быстрый поиск. Имена таблиц всегда заключаются в `< >`, например:
[.programlisting]
....
-ipmon_flags="-Ds" # D = start as daemon
- # s = log to syslog
- # v = log tcp window, ack, seq
- # n = map IP & port to names
+table <clients> { 192.168.2.0/24, !192.168.2.5 }
....
-Описывать преимущества протоколирования излишне. Например, оно дает возможность отложенного просмотра информации об отброшенных пакетах, откуда они пришли и куда направлялись. Эта информация существенно помогает при отслеживании атак.
+В этом примере сеть `192.168.2.0/24` является частью таблицы, за исключением адреса `192.168.2.5`, который исключен с помощью оператора `!`. Также можно загружать таблицы из файлов, где каждый элемент находится на отдельной строке, как показано в этом примере [.filename]#/etc/clients#:
-Даже с включенным протоколированием, IPF не ведет протокол для каждого правила. Администратор межсетевого экран должен решить, по каким правилам набора нужно вести протокол и добавить ключевое слово log к этим правилам. Обычно протоколируются только правила, отбрасывающие пакеты.
+[.programlisting]
+....
+192.168.2.0/24
+!192.168.2.5
+....
-Включение в набор последнего правила, запрещающего прохождение пакетов, в сочетании с ключевым словом `log` является довольно распространённой практикой. Так вы можете увидеть все пакеты, не попадающие ни под одно правило набора.
+Для обращения к файлу определите таблицу следующим образом:
-=== Протоколирование IPMON
+[.programlisting]
+....
+table <clients> persist file "/etc/clients"
+....
-Для разделения собираемых данных syslogd использует свой собственный специальный метод. Он использует группировку по категории ("facility") и уровню ("level"). IPMON в режиме `-Ds` использует `local0` в качестве имени "категории". Для дальнейшего разделения протоколируемых данных, если такое необходимо, могут быть использованы следующие уровни:
+После определения таблицы на неё можно ссылаться в правиле:
-[source,shell]
+[.programlisting]
....
-LOG_INFO - packets logged using the "log" keyword as the action rather than pass or block.
-LOG_NOTICE - packets logged which are also passed
-LOG_WARNING - packets logged which are also blocked
-LOG_ERR - packets which have been logged and which can be considered short
+pass inet proto tcp from <clients> to any port $client_out flags S/SA keep state
....
-Для указания IPFILTER протоколировать все данные в [.filename]#/var/log/ipfilter.log#, создайте этот файл заранее, выполнив следующую команду:
+Содержимое таблицы можно изменять в реальном времени с помощью `pfctl`. В этом примере добавляется ещё одна сеть в таблицу:
-[source,shell]
+[source, shell]
....
-# touch /var/log/ipfilter.log
+# pfctl -t clients -T add 192.168.1.0/16
....
-Функционирование man:syslogd[8] управляется настройками в файле [.filename]#/etc/syslog.conf#. Файл [.filename]#syslog.conf# позволяет достаточно гибко настроить обработку системных сообщений, выдаваемых программами, такими как IPF.
+Обратите внимание, что любые изменения, внесенные таким образом, вступят в силу немедленно, что делает их идеальными для тестирования, но они не сохранятся после отключения питания или перезагрузки. Чтобы сделать изменения постоянными, необходимо изменить определение таблицы в наборе правил или отредактировать файл, на который ссылается таблица. Можно поддерживать копию таблицы на диске с помощью задания man:cron[8], которое периодически сохраняет содержимое таблицы на диск, используя команду вида `pfctl -t clients -T show >/etc/clients`. Или [.filename]#/etc/clients# можно обновить содержимым таблицы из памяти:
-Добавьте в [.filename]#/etc/syslog.conf# следующую запись:
+[source, shell]
+....
+# pfctl -t clients -T replace -f /etc/clients
+....
+
+[[pftut-overload]]
+==== Использование таблиц превышения нагрузки для защиты SSH
+
+Те, кто запускает SSH на внешнем интерфейсе, вероятно, видели что-то подобное в журналах аутентификации:
[.programlisting]
....
-local0.* /var/log/ipfilter.log
+Sep 26 03:12:34 skapet sshd[25771]: Failed password for root from 200.72.41.31 port 40992 ssh2
+Sep 26 03:12:34 skapet sshd[5279]: Failed password for root from 200.72.41.31 port 40992 ssh2
+Sep 26 03:12:35 skapet sshd[5279]: Received disconnect from 200.72.41.31: 11: Bye Bye
+Sep 26 03:12:44 skapet sshd[29635]: Invalid user admin from 200.72.41.31
+Sep 26 03:12:44 skapet sshd[24703]: input_userauth_request: invalid user admin
+Sep 26 03:12:44 skapet sshd[24703]: Failed password for invalid user admin from 200.72.41.31 port 41484 ssh2
....
-`local0.*` означает запись всех протоколируемых сообщений в указанный файл.
+Это указывает на атаку методом грубой силы, когда кто-то или какая-то программа пытается подобрать имя пользователя и пароль, чтобы получить доступ к системе.
-Для применения внесенных в [.filename]#/etc/syslog.conf# изменений вы можете перезагрузиться или заставить man:syslogd[8] перечитать [.filename]#/etc/syslog.conf#, выполнив команду `/etc/rc.d/syslogd reload`.
+Если необходим внешний доступ по SSH для законных пользователей, изменение порта по умолчанию, используемого SSH, может обеспечить некоторую защиту. Однако PF предоставляет более элегантное решение. Правила `pass` могут содержать ограничения на действия подключающихся хостов, а нарушители могут быть заблокированы в таблице адресов, которым запрещён частичный или полный доступ. Также возможно разорвать все существующие соединения с машинами, которые превышают установленные ограничения.
-Не забудьте отредактировать [.filename]#/etc/newsyslog.conf# для ротации только что созданного лог файла.
+Для настройки создайте следующую таблицу в разделе tables набора правил:
-=== Формат протоколируемых сообщений
+[.programlisting]
+....
+table <bruteforce> persist
+....
+
+Затем, где-то в начале набора правил добавьте правила для блокировки перебора, разрешая при этом законный доступ:
+
+[.programlisting]
+....
+block quick from <bruteforce>
+pass inet proto tcp from any to $localnet port $tcp_services \
+ flags S/SA keep state \
+ (max-src-conn 100, max-src-conn-rate 15/5, \
+ overload <bruteforce> flush global)
+....
-Сообщения, генерируемые `ipmon`, состоят из полей данных, разделенных пробелами. Поля, общие для всех сообщений:
+Часть в скобках определяет ограничения, и числа должны быть изменены в соответствии с местными требованиями. Это можно прочитать следующим образом:
-. Дата получения пакета.
-. Время получения пакета. Формат времени HH:MM:SS.F для часов, минут, секунд и долей секунд (последнее поле может состоять из нескольких цифр).
-. Имя интерфейса, через который прошел пакет, например [.filename]#dc0#.
-. Группа и номер правила, например `@0:17`.
+`max-src-conn` — это количество одновременных подключений, разрешённых с одного хоста.
-Эти сообщения могут быть просмотрены командой `ipfstat -in`.
+`max-src-conn-rate` — это частота новых соединений, разрешённых с любого отдельного хоста (_15_) за указанное количество секунд (_5_).
+
+`overload <bruteforce>` означает, что любой хост, превышающий эти ограничения, добавляет свой адрес в таблицу `bruteforce`. Набор правил блокирует весь трафик с адресов, находящихся в таблице `bruteforce`.
+
+Наконец, `flush global` означает, что когда хост достигает лимита, все (`global`) соединения этого хоста будут разорваны (`flush`).
+
+[NOTE]
+====
+Эти правила _не_ заблокируют медленные брутфорсеры, как описано в http://home.nuug.no/\~peter/hailmary2013/[http://home.nuug.no/~peter/hailmary2013/].
+====
-. Действие: p для пропущенных, b для заблокированных, S для пакетов с неполным заголовком (short packet), n для пакетов, не соответствующих какому-либо правилу, L для соответствующих правилу протоколирования. Порядок следования по флагам: S, p, b, n, L. Знаки P или B в верхнем регистре означают, что пакет был протоколирован в соответствии с общими настройками, а не каким-то конкретным правилом.
-. Адреса. Всего три поля: адрес и порт источника (разделенные запятой), ->, адрес и порт назначения. 209.53.17.22,80 -> 198.73.220.17,1722.
-. `PR`, с последующим именем или номером протокола, например `PR tcp`.
-. `len`, с последующей длиной заголовка и общей длиной пакета, например `len 20 40`.
+Этот пример набора правил предназначен в основном для иллюстрации. Например, если требуется разрешить большое количество соединений в целом, но необходимо быть более строгим в отношении ssh, дополните приведенное выше правило чем-то вроде следующего, в начале набора правил:
-Для TCP пакетов добавляется дополнительное поле, начинающееся с дефиса, за которым следуют буквы, соответствующие установленным флагам. На странице справочника man:ipf[5] находится список букв и флагов.
+[.programlisting]
+....
+pass quick proto { tcp, udp } from any to any port ssh \
+ flags S/SA keep state \
+ (max-src-conn 15, max-src-conn-rate 5/3, \
+ overload <bruteforce> flush global)
+....
-Для пакетов ICMP, в конце находятся два поля, одно всегда "ICMP", а второе содержит тип и подтип ICMP сообщения (message и sub-message), разделенные символом косой черты, например ICMP 3/3 для сообщения "port unreachable".
+[NOTE]
+====
+*It May Not be Necessary to Block All Overloaders:* +
-[[firewalls-ipf-rules-script]]
-=== Создание набора правил с использованием символьной подстановки
+Стоит отметить, что механизм превышения нагрузки — это общий метод, который применяется не только к SSH, и не всегда оптимально полностью блокировать весь трафик от нарушителей.
-Некоторые опытные пользователи IPF создают файл правил, поддерживающий использование символьной подстановки. Основное преимущество использования такого подхода заключается в возможности изменения значения, присваиваемого символьному имени, в результате чего во всех правилах, содержащих эту символьную подстановку, будет использоваться новое значение. В начале скрипта вы можете поместить часто используемые переменные, а затем использовать их сразу в нескольких правилах. Ниже дан пример такого использования.
+Например, правило превышения нагрузки может использоваться для защиты почтовой службы или веб-сервиса, а таблица превышения нагрузки может применяться в правиле для назначения нарушителей в очередь с минимальным выделением пропускной способности или для перенаправления на определённую веб-страницу.
+====
-Синтаксис скрипта совместим с man:sh[1], man:csh[1], и man:tcsh[1].
+Со временем таблицы будут заполняться правилами превышения нагрузки, и их размер будет постепенно увеличиваться, занимая больше памяти. Иногда заблокированный IP-адрес оказывается динамически назначенным, который с тех пор был выделен хосту, имеющему законные основания для взаимодействия с хостами в локальной сети.
-Символьная подстановка предваряется знаком доллара: `$`.
+Для подобных ситуаций `pfctl` предоставляет возможность удалять записи из таблиц. Например, следующая команда удалит записи из таблицы `<bruteforce>`, к которым не было обращений в течение `86400` секунд:
-Для присвоения значения символьным переменным знак $ не используется.
+[source, shell]
+....
+# pfctl -t bruteforce -T expire 86400
+....
-Присваиваемое символической переменной значение должно быть заключено в двойные кавычки (`"`).
+Аналогичную функциональность предоставляет пакет package:security/expiretable[], который удаляет записи таблицы, к которым не было обращений в течение указанного периода времени.
-Начните файл правил примерно так:
+После установки `expiretable` можно запустить для удаления записей из таблицы `<bruteforce>`, которые старше указанного времени. В этом примере удаляются все записи старше 24 часов:
[.programlisting]
....
-############# Start of IPF rules script ########################
+/usr/local/sbin/expiretable -v -d -t 24h bruteforce
+....
-oif="dc0" # name of the outbound interface
-odns="192.0.2.11" # ISP's DNS server IP address
-myip="192.0.2.7" # my static IP address from ISP
-ks="keep state"
-fks="flags S keep state"
+[[pftut-spamd]]
+==== Защита от SPAM
-# You can choose between building /etc/ipf.rules file
-# from this script or running this script "as is".
-#
-# Uncomment only one line and comment out another.
-#
-# 1) This can be used for building /etc/ipf.rules:
-#cat > /etc/ipf.rules << EOF
-#
-# 2) This can be used to run script "as is":
-/sbin/ipf -Fa -f - << EOF
+package:mail/spamd[] можно настроить совместно с PF для обеспечения внешней защиты от SPAM (Не путайте его с демоном spamd, который поставляется вместе с spamassassin). Этот spamd интегрируется в конфигурацию PF с помощью набора перенаправлений.
+
+Спамеры обычно рассылают большое количество сообщений, и СПАМ в основном отправляется из нескольких дружественных к спамерам сетей и множества взломанных машин, которые быстро попадают в _списки блокировки_.
-# Allow out access to my ISP's Domain name server.
-pass out quick on $oif proto tcp from any to $odns port = 53 $fks
-pass out quick on $oif proto udp from any to $odns port = 53 $ks
+Когда SMTP-соединение с адреса из блок-листа получено, spamd отображает свой баннер и немедленно переключается в режим, где он отвечает на SMTP-трафик по одному байту за раз. Эта техника, предназначенная для максимально возможной потери времени на стороне спамера, называется _тарпиттинг_ (tarpitting, намеренное замедление). Конкретная реализация, использующая однобайтовые SMTP-ответы, часто упоминается как _прерывистые ответы_ (stuttering, метод заикания).
-# Allow out non-secure standard www function
-pass out quick on $oif proto tcp from $myip to any port = 80 $fks
+В этом примере показана базовая процедура настройки spamd с автоматически обновляемыми списками блокировки. Для получения дополнительной информации обратитесь к руководствам, которые устанавливаются вместе с пакетом package:mail/spamd[].
-# Allow out secure www function https over TLS SSL
-pass out quick on $oif proto tcp from $myip to any port = 443 $fks
-EOF
-################## End of IPF rules script ########################
+[.procedure]
+****
+.Процедура: Настройка spamd
+. Установите пакет package:mail/spamd[] или порт. Для использования функции серого списка (greylisting) в spamd, необходимо подключить man:fdescfs[5] в [.filename]#/dev/fd#. Добавьте следующую строку в [.filename]#/etc/fstab#:
++
+[.programlisting]
+....
+ fdescfs /dev/fd fdescfs rw 0 0
+....
++
+Затем смонтируйте файловую систему:
++
+[.programlisting]
+....
+# mount fdescfs
....
-Это все, что требовалось сделать. В данном примере сами правила не важны; важно то, как используется символьная подстановка. Если вышеприведенный пример помещен в файл [.filename]#/etc/ipf.rules.script#, то набор правил можно перезагрузить, введя следующую команду:
+. Далее отредактируйте набор правил PF, включив:
++
+[.programlisting]
+....
+table <spamd> persist
+table <spamd-white> persist
+rdr pass on $ext_if inet proto tcp from <spamd> to \
+ { $ext_if, $localnet } port smtp -> 127.0.0.1 port 8025
+rdr pass on $ext_if inet proto tcp from !<spamd-white> to \
+ { $ext_if, $localnet } port smtp -> 127.0.0.1 port 8025
+....
++
+Две таблицы `<spamd>` и `<spamd-white>` являются обязательными. SMTP-трафик с адреса, указанного в `<spamd>`, но отсутствующего в `<spamd-white>`, перенаправляется к демону spamd, ожидающему на порту 8025.
+. Следующий шаг — настроить spamd в [.filename]#/usr/local/etc/spamd.conf# и добавить параметры в [.filename]#rc.conf#.
++
+Установка пакета package:mail/spamd[] включает образец файла конфигурации ([.filename]#/usr/local/etc/spamd.conf.sample#) и man-страницу для [.filename]#spamd.conf#. Обратитесь к ним для получения дополнительных параметров конфигурации, помимо показанных в этом примере.
++
+Одна из первых строк в файле конфигурации, которая не начинается с символа комментария `+#+`, содержит блок, определяющий список `all`, который указывает списки для использования:
++
+[.programlisting]
+....
+all:\
+ :traplist:allowlist:
+....
++
+Эта запись добавляет желаемые списки блокировок, разделённые двоеточиями (`:`). Чтобы использовать список разрешений для исключения адресов из списка блокировок, добавьте имя списка разрешений _непосредственно_ после имени этого списка блокировок. Например: `:blocklist:allowlist:`.
++
+За этим следует определение указанного списка блокировки:
++
+[.programlisting]
+....
+traplist:\
+ :black:\
+ :msg="SPAM. Your address %A has sent spam within the last 24 hours":\
+ :method=http:\
+ :file=www.openbsd.org/spamd/traplist.gz
+....
++
+где первая строка — это имя списка блокировки, а вторая строка определяет тип списка. Поле `msg` содержит сообщение, которое будет отображаться заблокированным отправителям во время SMTP-диалога. Поле `method` указывает, каким образом spamd-setup получает данные списка; поддерживаемые методы — `http`, `ftp`, из `file` в смонтированной файловой системе и через `exec` внешней программы. Наконец, поле `file` определяет имя файла, который ожидает получить spamd.
++
+Определение указанного разрешенного списка аналогично, но опускает поле `msg`, так как сообщение не требуется:
++
+[.programlisting]
+....
+allowlist:\
+ :white:\
+ :method=file:\
+ :file=/var/mail/allowlist.txt
+....
++
+[TIP]
+====
+*Choose Data Sources with Care:* +
-[source,shell]
+Использование всех блокирующих списков в примере [.filename]#spamd.conf# приведет к блокировке больших сегментов Интернета. Администраторам необходимо отредактировать файл, чтобы создать оптимальную конфигурацию, которая использует подходящие источники данных и, при необходимости, пользовательские списки.
+====
++
+Далее добавьте эту запись в [.filename]#/etc/rc.conf#. Дополнительные флаги описаны в man-странице, указанной в комментарии:
++
+[.programlisting]
....
-# sh /etc/ipf.rules.script
+spamd_flags="-v" # use "" and see spamd-setup(8) for flags
....
++
+После завершения перезагрузите набор правил, запустите spamd командой `service obspamd start` и завершите настройку с помощью `spamd-setup`. Наконец, создайте задание в man:cron[8], которое будет вызывать `spamd-setup` для обновления таблиц через разумные промежутки времени.
+****
-С использованием в правилах символьной подстановки связана одна проблема: IPF не понимает символьную подстановку и не может обработать такой скрипт непосредственно.
+На типичном шлюзе перед почтовым сервером узлы начнут попадать в ловушку в течение от нескольких секунд до нескольких минут.
-Скрипт может использоваться одним из следующих двух способов:
+PF также поддерживает _greylisting_, который временно отклоняет сообщения от неизвестных хостов с кодами _45n_. Сообщения от хостов, находящихся в greylisting, которые повторяют попытку в разумные сроки, пропускаются. Трафик от отправителей, настроенных на работу в пределах, установленных RFC 1123 и RFC 2821, пропускается сразу.
-* Уберите комментарий перед строкой, начинающейся с `cat`, и закомментируйте строку, начинающуюся с `/sbin/ipf`. Поместите строку `ipfilter_enable="YES"` в файл [.filename]#/etc/rc.conf# как обычно, и запускайте скрипт после каждого его обновления для создания или обновления файла [.filename]#/etc/ipf.rules#.
-* Отключите IPFILTER в стартовых скриптах системы, поместив строку `ipfilter_enable="NO"` (это значение по умолчанию) в файл [.filename]#/etc/rc.conf#.
-+
-Поместите скрипт, подобный нижеприведенному, в каталог [.filename]#/usr/local/etc/rc.d/#. У него должно быть однозначно говорящее о его назначении имя, например [.filename]#ipf.loadrules.sh#. Расширение [.filename]#.sh# обязательно.
+Дополнительная информация о методе серых списков (greylisting) доступна на сайте http://www.greylisting.org/[greylisting.org]. Самое удивительное в серых списках, помимо их простоты, это то, что они до сих пор работают. Спамеры и авторы вредоносного ПО очень медленно адаптируются, чтобы обойти этот метод.
+
+Основная процедура настройки серого списка выглядит следующим образом:
+
+[.procedure]
+.Процедура: Настройка серого списка
+. Убедитесь, что man:fdescfs[5] смонтирован, как описано в Шаге 1 предыдущей процедуры.
+. Для запуска spamd в режиме серого списка добавьте следующую строку в [.filename]#/etc/rc.conf#:
+
[.programlisting]
....
-#!/bin/sh
-sh /etc/ipf.rules.script
+spamd_grey="YES" # use spamd greylisting if YES
....
-
-+
-Права, установленные на этот файл, должны разрешать чтение, запись и выполнение владельцу `root`.
+
+Обратитесь к man-странице spamd для описания дополнительных параметров, относящихся к серым спискам.
+. Для завершения настройки серого списка:
++
+[.programlisting]
+....
+# service obspamd restart
+# service obspamlogd start
+....
+
+За кулисами инструмент базы данных spamdb и обновляющий белый список spamlogd выполняют важные функции для механизма отложенной доставки. spamdb — это основной интерфейс администратора для управления списками блокировки, серого списка и списка с разрешениями через содержимое базы данных [.filename]#/var/db/spamdb#.
+
+[[pftut-hygiene]]
+==== Сетевая гигиена
-[source,shell]
+В этом разделе описывается, как `block-policy`, `scrub` и `antispoof` могут быть использованы для обеспечения разумного поведения набора правил.
+
+`block-policy` — это опция, которую можно установить в разделе `options` набора правил, предшествующем правилам перенаправления и фильтрации. Эта опция определяет, какую обратную связь (если таковая имеется) PF отправляет хостам, заблокированным правилом. Опция имеет два возможных значения: `drop` отбрасывает заблокированные пакеты без ответа, а `return` возвращает код состояния, например `Connection refused`.
+
+Если не задано, политика по умолчанию — `drop`. Чтобы изменить `block-policy`, укажите желаемое значение:
+
+[.programlisting]
....
-# chmod 700 /usr/local/etc/rc.d/ipf.loadrules.sh
+set block-policy return
....
-Теперь, правила IPF будут загружаться при загрузке системы.
+В PF `scrub` — это ключевое слово, которое включает нормализацию сетевых пакетов. Этот процесс пересобирает фрагментированные пакеты и отбрасывает TCP-пакеты с недопустимыми комбинациями флагов. Включение `scrub` обеспечивает защиту от определённых видов атак, основанных на некорректной обработке фрагментов пакетов. Доступно несколько опций, но простейшая форма подходит для большинства конфигураций:
-=== Наборы правил IPF
+[.programlisting]
+....
+scrub in all
+....
-Набор правил ipf это группа правил, составленных для пропускания или блокирования пакетов на основе их содержимого. Двусторонний обмен пакетами между хостами составляет сессию. Межсетевой экран обрабатывает как входящие из Интернет пакеты, так и исходящие пакеты, которые сгенерированы самой системой в ответ на входящий трафик. Для каждой службы TCP/IP (например, telnet, www, mail, и т.п.) назначен протокол и номер привилегированного (прослушиваемого) порта. Пакеты, предназначенные для определенного сервиса, порождаются с некоторым исходящим адресом и портом из непривилегированного диапазона и направляются на определенный адрес и определенный порт назначения. Все упомянутые параметры (номера портов и адреса) могут использоваться как критерии выбора в правилах, пропускающих или блокирующих доступ к службам TCP/IP.
+Некоторые службы, такие как NFS, требуют специальных параметров обработки фрагментов. Дополнительную информацию можно найти по ссылке https://home.nuug.no/~peter/pf/en/scrub.html[https://home.nuug.no/~peter/pf/en/scrub.html].
-IPF был первоначально написан с использованием логики "последнее совпадающее правило побеждает" и только с правилами без сохранения состояния. Со временем в IPF был включен параметр "quick" и параметр сохранения состояния "keep state", что существенно улучшило логику обработки правил.
+Этот пример собирает фрагменты, сбрасывает бит "не фрагментировать" и устанавливает максимальный размер сегмента в 1440 байт:
-Инструкции, помещенные в эту главу, созданы с использованием параметров "quick" и "keep state". Это основа для создания набора правил включающего межсетевого экрана.
+[.programlisting]
+....
+scrub in all fragment reassemble no-df max-mss 1440
+....
-[WARNING]
-====
+Механизм `antispoof` защищает от активности с подделанных или фальсифицированных IP-адресов, в основном блокируя пакеты, появляющиеся на интерфейсах и в направлениях, которые логически невозможны.
-При работе с правилами межсетевого экрана, будьте _очень осторожны_. Некоторые конфигурации _могут заблокировать вам доступ_ к серверу. В целях предосторожности, первоначальную настройку межсетевого экрана вы можете выполнить с локальной консоли, а не через удаленное подключение, такое как ssh.
-====
+Эти правила отсеивают поддельный трафик, поступающий из остального мира, а также любые поддельные пакеты, исходящие из локальной сети:
+
+[.programlisting]
+....
+antispoof for $ext_if
+antispoof for $int_if
+....
+
+[[pftut-unrouteables]]
+==== Обработка Немаршрутизируемых Адресов
+
+Даже при правильно настроенном шлюзе для обработки преобразования сетевых адресов может потребоваться компенсировать ошибки в конфигурации, сделанные другими людьми. Распространённой ошибкой является пропуск трафика с не маршрутизируемыми адресами в Интернет. Поскольку трафик с не маршрутизируемых адресов может использоваться в нескольких методах DoS-атак, рекомендуется явно блокировать такой трафик от попадания в сеть через внешний интерфейс.
+
+В этом примере определяется макрос, содержащий не маршрутизируемые адреса, который затем используется в правилах блокировки. Трафик на эти адреса и с этих адресов тихо отбрасывается на внешнем интерфейсе шлюза.
+
+[.programlisting]
+....
+martians = "{ 127.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12, \
+ 10.0.0.0/8, 169.254.0.0/16, 192.0.2.0/24, \
+ 0.0.0.0/8, 240.0.0.0/4 }"
+
+block drop in quick on $ext_if from $martians to any
+block drop out quick on $ext_if from any to $martians
+....
+
+=== Включение ALTQ
+
+На FreeBSD ALTQ можно использовать с PF для обеспечения качества обслуживания (QOS — Quality of Service). После включения ALTQ в наборе правил можно определить очереди, которые определяют приоритет обработки исходящих пакетов.
+
+Прежде чем включить ALTQ, обратитесь к man:altq[4], чтобы определить, поддерживают ли его драйверы сетевых карт, установленных в системе.
+
+ALTQ недоступен в виде загружаемого модуля ядра. Если интерфейсы системы поддерживают ALTQ, создайте собственное ядро, следуя инструкциям в crossref:kernelconfig[kernelconfig,Настройка ядра FreeBSD]. Доступны следующие параметры ядра. Первый необходим для включения ALTQ. Хотя бы один из остальных параметров требуется для указания алгоритма планирования очередей:
+
+[.programlisting]
+....
+options ALTQ
+options ALTQ_CBQ # Class Based Queuing (CBQ)
+options ALTQ_RED # Random Early Detection (RED)
+options ALTQ_RIO # RED In/Out
+options ALTQ_HFSC # Hierarchical Packet Scheduler (HFSC)
+options ALTQ_PRIQ # Priority Queuing (PRIQ)
+....
+
+Доступны следующие алгоритмы планировщика:
+
+CBQ::
+Очереди на основе классов (CBQ — Class Based Queuing) используется для разделения пропускной способности соединения на различные классы или очереди с целью приоритизации трафика на основе правил фильтрации.
+
+RED::
+Случайное раннее обнаружение (RED — Random Early Detection) используется для предотвращения перегрузки сети путем измерения длины очереди и сравнения ее с минимальным и максимальным порогами для очереди. Когда очередь превышает максимальный порог, все новые пакеты случайным образом отбрасываются.
+
+RIO::
+В режиме Случайного раннего обнаружения для входящего и исходящего трафика (RIO) RED поддерживает несколько средних длин очередей и несколько пороговых значений, по одному для каждого уровня QOS.
+
+HFSC::
+Иерархический планировщик пакетов с гарантированной справедливой кривой обслуживания (HFSC) описан на http://www-2.cs.cmu.edu/\~hzhang/HFSC/main.html[http://www-2.cs.cmu.edu/~hzhang/HFSC/main.html].
+
+PRIQ::
+Очереди с приоритетом (PRIQ) всегда пропускают трафик из более высокоуровневой очереди первым.
+
+Дополнительная информация о алгоритмах планирования и примеры наборов правил доступны на https://web.archive.org/web/20151109213426/http://www.openbsd.org/faq/pf/queueing.html[архивированной странице OpenBSD].
[[firewalls-ipfw]]
== IPFW
-IPFIREWALL (IPFW) - представляет собой межсетевой экран, написанный и поддерживаемый добровольными участниками проекта FreeBSD. Он использует stateless правила, т.е. правила без учета состояния, и наследование техники кодирования правил для получения того, что называется простой логикой с сохранением состояния (stateful).
+IPFW — это межсетевой экран с отслеживанием состояний, разработанный для FreeBSD, который поддерживает как IPv4, так и IPv6. Он состоит из нескольких компонентов: процессора правил фильтрации межсетевого экрана в ядре и встроенного механизма учёта пакетов, механизма журналирования, NAT, механизма управления трафиком man:dummynet[4], механизма переадресации, механизма моста и механизма ipstealth.
-Пример простейшего набора правил IPFW (находится в [.filename]#/etc/rc.firewall# и [.filename]#/etc/rc.firewall6#) в стандартной установке FreeBSD достаточно прост и не рассчитан на непосредственное использование без изменений. В нём не используется фильтрация с сохранением состояния, которая даёт преимущества во многих конфигурациях, поэтому он не может быть взят за основу для этого раздела.
+FreeBSD предоставляет пример набора правил в [.filename]#/etc/rc.firewall#, который определяет несколько типов межсетевых экранов для распространённых сценариев, чтобы помочь новичкам в создании подходящего набора правил. IPFW предлагает мощный синтаксис, с помощью которого опытные пользователи могут создавать настраиваемые наборы правил, соответствующие требованиям безопасности заданного окружения.
-Синтаксис правил IPFW без сохранения состояния обеспечивает расширенные возможности фильтрации, которые намного превосходят уровень знаний обычного пользователя межсетевого экрана. IPFW рассчитан на профессиональных пользователей или технически продвинутых любителей, которые предъявляют повышенные требования к фильтрации пакетов. Чтобы использовать возможности IPFW в полную силу, необходимы углубленные знания того, как в различных протоколах формируются и используются заголовки пакетов. Углубленное изучение работы протоколов выходит за рамки этого раздела Руководства.
-
-IPFW состоит из семи компонентов, главный из которых - процессор правил фильтрации уровня ядра и интегрированный в него механизм учета пакетов, а также средства протоколирования пакетов, правило `divert`, посредством которых вызывается функция NAT и другие возможности специального назначения, средства для ограничения скорости (шейпинга) трафика (dummynet), средства перенаправления `fwd`, средства организации сетевого моста bridge и механизм ipstealth. IPFW поддерживает протоколы IPv4 и IPv6.
+Этот раздел описывает, как включить IPFW, предоставляет обзор синтаксиса его правил и демонстрирует несколько наборов правил для распространённых сценариев настройки.
[[firewalls-ipfw-enable]]
=== Включение IPFW
-IPFW включён в базовую установку FreeBSD в виде отдельного подгружаемого модуля. Система динамически загружает модуль ядра, когда в [.filename]#rc.conf# присутствует строка `firewall_enable="YES"`. Если использовать функциональность NAT не планируется, то в этом случае дополнительно компилировать IPFW в состав ядра FreeBSD не требуется.
+IPFW включён в базовую установку FreeBSD в виде загружаемого модуля ядра, что означает, что для его включения не требуется собирать собственное ядро.
+
+Для пользователей, которые хотят статически скомпилировать поддержку IPFW в собственном ядре, см. crossref:firewalls[firewalls-ipfw-kernelconfig, Параметры ядра IPFW].
+
+Для настройки системы для включения IPFW при загрузке добавьте `firewall_enable="YES"` в файл [.filename]#/etc/rc.conf#:
+
+[source, shell]
+....
+# sysrc firewall_enable="YES"
+....
+
+Чтобы использовать один из типов межсетевых экранов, предоставляемых FreeBSD, добавьте строку с указанием типа:
+
+[source, shell]
+....
+# sysrc firewall_type="open"
+....
+
+Доступные типы:
+
+* `open`: пропускает весь трафик.
+* `client`: защищает только эту машину.
+* `simple`: защищает всю сеть.
+* `closed`: полностью отключает IP-трафик, за исключением интерфейса loopback.
+* `workstation`: защищает только эту машину с использованием правил с отслеживанием состояния.
+* `UNKNOWN`: отключает загрузку правил межсетевого экрана.
+* [.filename]#filename#: полный путь к файлу, содержащему набор правил межсетевого экрана.
+
+Если `firewall_type` установлен в значение `client` или `simple`, измените правила по умолчанию, указанные в [.filename]#/etc/rc.firewall#, чтобы они соответствовали конфигурации системы.
-После перезагрузки системы с `firewall_enable="YES"` в [.filename]#rc.conf# на экране в процессе загрузки отобразится выделенное белым сообщение:
+Обратите внимание, что тип `filename` используется для загрузки пользовательского набора правил.
-[source,shell]
+Альтернативный способ загрузки пользовательского набора правил — присвойте переменной `firewall_script` значение, равное абсолютному пути к _исполняемому скрипту_, который включает команды IPFW. Примеры, используемые в этом разделе, предполагают, что `firewall_script` установлен в [.filename]#/etc/ipfw.rules#:
+
+[source, shell]
+....
+# sysrc firewall_script="/etc/ipfw.rules"
+....
+
+Чтобы включить ведение журнала через man:syslogd[8], добавьте следующую строку:
+
+[source, shell]
+....
+# sysrc firewall_logging="YES"
+....
+
+[WARNING]
+====
+В журнал будут записываться только правила межсетевого экрана с опцией `log`. Правила по умолчанию не включают эту опцию, и её необходимо добавить вручную. Поэтому рекомендуется отредактировать набор правил по умолчанию для ведения журнала. Кроме того, может потребоваться ротация журналов, если они сохраняются в отдельный файл.
+====
+
+В файле [.filename]#/etc/rc.conf# нет переменной для установки ограничений журналирования. Чтобы ограничить количество записей в журнале для каждого правила на одну попытку соединения, укажите число с помощью следующей строки в [.filename]#/etc/sysctl.conf#:
+
+[source, shell]
+....
+# echo "net.inet.ip.fw.verbose_limit=5" >> /etc/sysctl.conf
+....
+
+Для включения журналирования через выделенный интерфейс с именем `ipfw0`, добавьте следующую строку в [.filename]#/etc/rc.conf# вместо этого:
+
+[source, shell]
+....
+# sysrc firewall_logif="YES"
+....
+
+Затем используйте tcpdump для просмотра записываемых данных:
+
+[source, shell]
+....
+# tcpdump -t -n -i ipfw0
+....
+
+[TIP]
+====
+
+Нет накладных расходов из-за ведения журнала, если не подключен tcpdump.
+====
+
+После сохранения необходимых изменений запустите межсетевой экран. Чтобы сразу включить ограничения журналирования, также установите указанное выше значение `sysctl`:
+
+[source, shell]
....
-ipfw2 initialized, divert disabled, rule-based forwarding disabled, default to deny, logging disabled
+# service ipfw start
+# sysctl net.inet.ip.fw.verbose_limit=5
....
-Загружаемый модуль скомпилирован с возможностью протоколирования информации о трафике. Для включения протоколирования и установки уровня его детализации имеется переключатель, значение которого можно установить в конфигурационном файле [.filename]#/etc/sysctl.conf#. При добавлении следующих двух строк протоколирование будет включено при следующей загрузке системы:
+[[firewalls-ipfw-rules]]
+=== Синтаксис правил IPFW
+
+Когда пакет попадает в межсетевой экран IPFW, он сравнивается с первым правилом в наборе правил и последовательно обрабатывается сверху вниз, правило за правилом. Если пакет соответствует параметрам выбора правила, выполняется действие этого правила, и поиск в наборе правил для данного пакета прекращается. Это называется «первое совпадение побеждает». Если пакет не соответствует ни одному из правил, он попадает под действие обязательного правила IPFW с номером 65535, которое запрещает все пакеты и тихо их отбрасывает. Однако, если пакет соответствует правилу, содержащему ключевые слова `count`, `skipto` или `tee`, поиск продолжается. Подробнее о том, как эти ключевые слова влияют на обработку правил, см. в man:ipfw[8].
+
+При создании правила IPFW ключевые слова должны быть записаны в следующем порядке. Некоторые ключевые слова являются обязательными, а другие — опциональными. Слова, написанные в верхнем регистре, обозначают переменную, а слова в нижнем регистре должны предшествовать следующей за ними переменной. Символ `+#+` используется для обозначения начала комментария и может находиться в конце правила или на отдельной строке. Пустые строки игнорируются.
+
+`_CMD RULE_NUMBER set SET_NUMBER ACTION log LOG_AMOUNT PROTO from SRC SRC_PORT to DST DST_PORT OPTIONS_`
+
+В этом разделе представлен обзор этих ключевых слов и их параметров. Это не исчерпывающий список всех возможных вариантов. Для полного описания синтаксиса правил, которые можно использовать при создании правил IPFW, обратитесь к man:ipfw[8].
+
+CMD::
+Каждое правило должно начинаться с `ipfw add`.
+
+RULE_NUMBER::
+Каждое правило связано с числом от `1` до `65534`. Этот номер используется для указания порядка обработки правил. Несколько правил могут иметь одинаковый номер, в таком случае они применяются в порядке их добавления.
+
+SET_NUMBER::
+Каждое правило связано с номером набора от `0` до `31`. Наборы можно отключать или включать по отдельности, что позволяет быстро добавлять или удалять набор правил. Если `SET_NUMBER` не указан, правило будет добавлено в набор `0`.
+
+ACTION::
+Правило может быть связано с одним из следующих действий. Указанное действие будет выполнено, когда пакет соответствует критерию выбора правила.
++
+`allow | accept | pass | permit`: эти ключевые слова эквивалентны и разрешают пакеты, соответствующие правилу.
++
+`check-state`: проверяет пакет по таблице динамических состояний. Если совпадение найдено, выполняется действие, связанное с правилом, которое создало это динамическое правило, в противном случае осуществляется переход к следующему правилу. Правило `check-state` не имеет критериев выбора. Если правило `check-state` отсутствует в наборе правил, таблица динамических правил проверяется при первом правиле `keep-state` или `limit`.
++
+`count`: обновляет счетчики для всех пакетов, соответствующих правилу. Поиск продолжается со следующего правила.
++
+`deny | drop`: любое из этих слов тихо отбрасывает пакеты, соответствующие этому правилу.
++
+Доступны дополнительные действия. Подробности смотрите в man:ipfw[8].
+
+LOG_AMOUNT::
+Когда пакет соответствует правилу с ключевым словом `log`, сообщение будет записано в man:syslogd[8] с именем средства `SECURITY`. Запись в журнал происходит только в том случае, если количество пакетов, зарегистрированных для этого конкретного правила, не превышает указанного LOG_AMOUNT. Если LOG_AMOUNT не указан, лимит берется из значения `net.inet.ip.fw.verbose_limit`. Значение нуля снимает ограничение на запись в журнал. Как только лимит достигнут, запись в журнал можно снова включить, сбросив счетчик журналирования или счетчик пакетов для этого правила с помощью `ipfw resetlog`.
++
+[NOTE]
+====
+Журналирование выполняется после того, как все остальные условия сопоставления пакета выполнены, и перед выполнением конечного действия с пакетом. Администратор решает, для каких правил включить журналирование.
+====
+
+PROTO::
+Это необязательное значение может использоваться для указания любого имени протокола или номера, найденного в [.filename]#/etc/protocols#.
+
+SRC::
+Ключевое слово `from` должно сопровождаться исходным адресом или ключевым словом, представляющим исходный адрес. Адрес может быть представлен как `any`, `me` (любой адрес, настроенный на интерфейсе этой системы), `me6` (любой IPv6-адрес, настроенный на интерфейсе этой системы) или `table`, за которым следует номер таблицы поиска, содержащей список адресов. При указании IP-адреса, он может быть дополнительно указан с маской CIDR или маской подсети. Например, `1.2.3.4/25` или `1.2.3.4:255.255.255.128`.
+
+SRC_PORT::
+Необязательный порт источника может быть указан с использованием номера порта или имени из [.filename]#/etc/services#.
+
+DST::
+Ключевое слово `to` должно сопровождаться адресом назначения или ключевым словом, представляющим адрес назначения. Те же ключевые слова и адреса, которые описаны в разделе SRC, могут быть использованы для описания назначения.
+
+DST_PORT::
+Необязательный порт назначения может быть указан с использованием номера порта или имени из [.filename]#/etc/services#.
+
+OPTIONS::
+Несколько ключевых слов могут следовать за источником и назначением. Как следует из названия, OPTIONS являются необязательными. Часто используемые опции включают `in` или `out`, которые указывают направление потока пакетов, `icmptypes` с указанием типа ICMP-сообщения и `keep-state`.
++
+Когда правило `keep-state` совпадает, межсетевой экран создаст динамическое правило, которое соответствует двунаправленному трафику между исходным и целевым адресами и портами, используя тот же протокол.
++
+Функция динамических правил уязвима к истощению ресурсов из-за SYN-флуда, который может создать огромное количество динамических правил. Для защиты от такого типа атак в IPFW используйте параметр `limit`. Этот параметр ограничивает количество одновременных сессий, проверяя открытые динамические правила и подсчитывая, сколько раз встречалось сочетание данного правила и IP-адреса. Если это количество превышает значение, указанное в `limit`, пакет отбрасывается.
++
+Доступны десятки параметров `OPTIONS`. Описание каждого доступного параметра можно найти в man:ipfw[8].
+
+=== Пример набора правил
+
+В этом разделе показано, как создать пример набора правил для статического межсетевого экрана в виде скрипта с именем [.filename]#/etc/ipfw.rules#. В данном примере все правила соединений используют `in` или `out` для указания направления. Они также используют `via` _имя-интерфейса_ для указания интерфейса, через который проходит пакет.
+
+[NOTE]
+====
+При первоначальном создании или тестировании набора правил межсетевого экрана рекомендуется временно установить этот параметр:
[.programlisting]
....
-net.inet.ip.fw.verbose=1
-net.inet.ip.fw.verbose_limit=5
+net.inet.ip.fw.default_to_accept="1"
....
-[[firewalls-ipfw-kernel]]
-=== Параметры ядра
+Это устанавливает политику по умолчанию для man:ipfw[8] более разрешительной, чем стандартная `deny ip from any to any`, что немного снижает вероятность блокировки системы сразу после перезагрузки.
+====
-Включение следующих параметров в ядро FreeBSD не является обязательным, если дополнительно не требуется функциональность NAT. Эти параметры представлены здесь в качестве справочной информации для дальнейших примеров.
+Скрипт межсетевого экрана начинается с указания, что это скрипт Bourne shell, и очищает все существующие правила. Затем он создает переменную `cmd`, чтобы не приходилось вводить `ipfw add` в начале каждого правила. Также определяется переменная `pif`, которая представляет имя интерфейса, подключенного к Интернету.
[.programlisting]
....
-options IPFIREWALL
+#!/bin/sh
+# Flush out the list before we begin.
+ipfw -q -f flush
+
+# Set rules command prefix
+cmd="ipfw -q add"
+pif="dc0" # interface name of NIC attached to Internet
....
-Этот параметр включает IPFW в состав ядра.
+Первые два правила разрешают весь трафик на доверенном внутреннем интерфейсе и на loopback-интерфейсе:
[.programlisting]
....
-options IPFIREWALL_VERBOSE
+# Change xl0 to LAN NIC interface name
+$cmd 00005 allow all from any to any via xl0
+
+# No restrictions on Loopback Interface
+$cmd 00010 allow all from any to any via lo0
....
-Этот параметр включает протоколирование пакетов, которые проходят через IPFW по правилам с ключевым словом `log`.
+Следующее правило пропускает пакет, если он соответствует существующей записи в таблице динамических правил:
[.programlisting]
....
-options IPFIREWALL_VERBOSE_LIMIT=5
+$cmd 00101 check-state
....
-Ограничение числа пакетов, прошедших через man:syslogd[8], отдельно для каждого правила. Этот параметр имеет смысл использовать в недружественной среде, когда необходимо отслеживать активность межсетевого экрана. Это закрывает возможность атак типа "отказ в обслуживании" через флуд сообщениями syslog.
+Следующий набор правил определяет, какие состояния соединений внутренние системы могут устанавливать с узлами в Интернете:
[.programlisting]
....
-options IPFIREWALL_DEFAULT_TO_ACCEPT
+# Allow access to public DNS
+# Replace x.x.x.x with the IP address of a public DNS server
+# and repeat for each DNS server in /etc/resolv.conf
+$cmd 00110 allow tcp from any to x.x.x.x 53 out via $pif setup keep-state
+$cmd 00111 allow udp from any to x.x.x.x 53 out via $pif keep-state
+
+# Allow access to ISP's DHCP server for cable/DSL configurations.
+# Use the first rule and check log for IP address.
+# Then, uncomment the second rule, input the IP address, and delete the first rule
+$cmd 00120 allow log udp from any to any 67 out via $pif keep-state
+#$cmd 00120 allow udp from any to x.x.x.x 67 out via $pif keep-state
+
+# Allow outbound HTTP and HTTPS connections
+$cmd 00200 allow tcp from any to any 80 out via $pif setup keep-state
+$cmd 00220 allow tcp from any to any 443 out via $pif setup keep-state
+
+# Allow outbound email connections
+$cmd 00230 allow tcp from any to any 25 out via $pif setup keep-state
+$cmd 00231 allow tcp from any to any 110 out via $pif setup keep-state
+
+# Allow outbound ping
+$cmd 00250 allow icmp from any to any out via $pif keep-state
+
+# Allow outbound NTP
+$cmd 00260 allow udp from any to any 123 out via $pif keep-state
+
+# Allow outbound SSH
+$cmd 00280 allow tcp from any to any 22 out via $pif setup keep-state
+
+# deny and log all other outbound connections
+$cmd 00299 deny log all from any to any out via $pif
....
-Этот параметр включает для IPFW разрешающую политику по умолчанию. Это удобно на первых этапах настройки IPFW.
+Следующий набор правил управляет соединениями от хостов Интернета к внутренней сети. Он начинается с запрета пакетов, обычно связанных с атаками, а затем явно разрешает определённые типы соединений. Все авторизованные сервисы, поступающие из Интернета, используют `limit` для предотвращения перегрузки.
[.programlisting]
....
-options IPDIVERT
+# Deny all inbound traffic from non-routable reserved address spaces
+$cmd 00300 deny all from 192.168.0.0/16 to any in via $pif #RFC 1918 private IP
+$cmd 00301 deny all from 172.16.0.0/12 to any in via $pif #RFC 1918 private IP
+$cmd 00302 deny all from 10.0.0.0/8 to any in via $pif #RFC 1918 private IP
+$cmd 00303 deny all from 127.0.0.0/8 to any in via $pif #loopback
+$cmd 00304 deny all from 0.0.0.0/8 to any in via $pif #loopback
+$cmd 00305 deny all from 169.254.0.0/16 to any in via $pif #DHCP auto-config
+$cmd 00306 deny all from 192.0.2.0/24 to any in via $pif #reserved for docs
+$cmd 00307 deny all from 204.152.64.0/23 to any in via $pif #Sun cluster interconnect
+$cmd 00308 deny all from 224.0.0.0/3 to any in via $pif #Class D & E multicast
+
+# Deny public pings
+$cmd 00310 deny icmp from any to any in via $pif
+
+# Deny ident
+$cmd 00315 deny tcp from any to any 113 in via $pif
+
+# Deny all Netbios services.
+$cmd 00320 deny tcp from any to any 137 in via $pif
+$cmd 00321 deny tcp from any to any 138 in via $pif
+$cmd 00322 deny tcp from any to any 139 in via $pif
+$cmd 00323 deny tcp from any to any 81 in via $pif
+
+# Deny fragments
+$cmd 00330 deny all from any to any frag in via $pif
+
+# Deny ACK packets that did not match the dynamic rule table
+$cmd 00332 deny tcp from any to any established in via $pif
+
+# Allow traffic from ISP's DHCP server.
+# Replace x.x.x.x with the same IP address used in rule 00120.
+#$cmd 00360 allow udp from any to x.x.x.x 67 in via $pif keep-state
+
+# Allow HTTP connections to internal web server
+$cmd 00400 allow tcp from any to me 80 in via $pif setup limit src-addr 2
+
+# Allow inbound SSH connections
+$cmd 00410 allow tcp from any to me 22 in via $pif setup limit src-addr 2
+
+# Reject and log all other incoming connections
+$cmd 00499 deny log all from any to any in via $pif
+....
+
+Последнее правило записывает в журнал информацию о всех пакетах, которые не соответствуют ни одному из правил в наборе правил:
+
+[.programlisting]
....
+# Everything else is denied and logged
+$cmd 00999 deny log all from any to any
+....
+
+[[in-kernel-nat]]
+=== NAT в ядре системы
+
+Межсетевой экран IPFW в FreeBSD имеет две реализации NAT: реализацию в пользовательском пространстве man:natd[8] и более новую реализацию NAT в ядре. Обе работают совместно с IPFW для преобразования сетевых адресов. Это можно использовать для организации общего доступа в Интернет, чтобы несколько внутренних компьютеров могли подключаться к Интернету, используя один публичный IP-адрес.
-Включение функциональности NAT.
+Для этого машина FreeBSD, подключённая к Интернету, должна выступать в роли шлюза. Эта система должна иметь две сетевые карты (NIC), где одна подключена к Интернету, а другая — к внутренней локальной сети (LAN). Каждой машине в LAN должен быть назначен IP-адрес из частного адресного пространства, как определено в https://www.ietf.org/rfc/rfc1918.txt[RFC 1918].
+
+Для включения встроенной в ядро функции NAT в IPFW требуется дополнительная настройка. Чтобы поддержка NAT на уровне ядра включалась при загрузке, необходимо добавить следующие параметры в [.filename]#/etc/rc.conf#:
+
+[.programlisting]
+....
+gateway_enable="YES"
+firewall_enable="YES"
+firewall_nat_enable="YES"
+....
[NOTE]
====
-Межсетевой экран будет блокировать все входящие и исходящие пакеты, если отсутствует параметр ядра `IPFIREWALL_DEFAULT_TO_ACCEPT` или правило, явно разрешающее эти соединения.
+Когда `firewall_nat_enable` установлен, но `firewall_enable` нет, это не будет иметь эффекта и ничего не сделает. Это связано с тем, что реализация NAT в ядре совместима только с IPFW.
====
-[[firewalls-ipfw-rc]]
-=== Параметры [.filename]#/etc/rc.conf#
+Когда набор правил содержит правила с отслеживанием состояния, позиционирование правила NAT критически важно, и используется действие `skipto`. Действие `skipto` требует указания номера правила, чтобы знать, к какому правилу перейти. В приведённом ниже примере расширяется набор правил межсетевого экрана, показанный в предыдущем разделе. В него добавлены некоторые новые записи и изменены существующие правила для настройки межсетевого экрана с поддержкой NAT, встроенного в ядро. Начинается он с добавления дополнительных переменных, представляющих номер правила для перехода, опцию `keep-state` и список TCP-портов, который будет использоваться для сокращения количества правил.
-Включение межсетевого экрана:
+[.programlisting]
+....
+#!/bin/sh
+ipfw -q -f flush
+cmd="ipfw -q add"
+skip="skipto 1000"
+pif=dc0
+ks="keep-state"
+good_tcpo="22,25,37,53,80,443,110"
+....
+
+При использовании NAT в ядре необходимо отключить аппаратную сегментацию TCP (TSO) из-за архитектуры man:libalias[3] — библиотеки, реализованной в виде модуля ядра для обеспечения функциональности NAT в IPFW. TSO можно отключить для каждого сетевого интерфейса с помощью man:ifconfig[8] или для всей системы с помощью man:sysctl[8]. Чтобы отключить TSO для всей системы, необходимо добавить следующие настройки в [.filename]#/etc/sysctl.conf#:
[.programlisting]
....
-firewall_enable="YES"
+net.inet.tcp.tso="0"
....
-Для выбора одного из стандартных режимов работы межсетевого экрана, предоставляемых FreeBSD, выберите наиболее подходящий в файле [.filename]#/etc/rc.firewall# и разместите так, как указано ниже:
+Будет также настроен экземпляр NAT. Возможно иметь несколько экземпляров NAT, каждый со своей конфигурацией. Для этого примера нужен только один экземпляр NAT — экземпляр NAT номер 1. Конфигурация может принимать несколько опций, таких как: `if`, указывающий публичный интерфейс, `same_ports`, обеспечивающий одинаковое отображение алиасов портов и локальных номеров портов, `unreg_only`, приводящий к обработке только незарегистрированных (частных) адресных пространств экземпляром NAT, и `reset`, который помогает поддерживать работоспособность экземпляра NAT даже при изменении публичного IP-адреса машины с IPFW. Для всех возможных опций, которые могут быть переданы в конфигурацию отдельного экземпляра NAT, обратитесь к man:ipfw[8]. При настройке межсетевого экрана с NAT и отслеживанием состояний необходимо разрешить повторное внедрение преобразованных пакетов в межсетевой экран для дальнейшей обработки. Это можно достичь, отключив поведение `one_pass` в начале скрипта межсетевого экрана.
[.programlisting]
....
-firewall_type="open"
+ipfw disable one_pass
+ipfw -q nat 1 config if $pif same_ports unreg_only reset
....
-Возможны следующие значения для этого параметра:
+Правило входящего NAT вставляется _после_ двух правил, которые разрешают весь трафик на доверенных интерфейсах и интерфейсе loopback, а также после правила пересборки, но _до_ правила `check-state`. Важно, чтобы номер правила, выбранный для этого NAT-правила (в данном примере `100`), был больше, чем первые три правила, и меньше, чем правило `check-state`. Кроме того, из-за особенностей работы встроенного NAT рекомендуется размещать правило пересборки непосредственно перед первым NAT-правилом и после правил, разрешающих трафик на доверенных интерфейсах. Обычно фрагментация IP-пакетов не должна происходить, но при работе с туннелированным трафиком IPSEC/ESP/GRE это возможно, и пересборка фрагментов необходима перед передачей полного пакета встроенному механизму NAT.
-* `open` - пропускать весь трафик.
-* `client` - защищать только эту машину.
-* `simple` - защищать всю сеть.
-* `closed` - полностью запретить IP трафик, за исключением loopback интерфейса.
-* `UNKNOWN` - отключить загрузку правил межсетевого экрана.
-* [.filename]#filename# - абсолютный путь к файлу, содержащему правила межсетевого экрана.
+[NOTE]
+====
+Правило пересборки не требовалось при использовании пользовательского демона man:natd[8], поскольку внутренняя работа действия `divert` в man:ipfw[8] уже обеспечивает пересборку пакетов перед их передачей в сокет, как также указано в man:ipfw[8].
-Есть два варианта загрузки собственных правил в межсетевой экран ipfw. Первый способ - задать переменную `firewall_type` в виде абсолютного пути файла, содержащего _правила межсетевого экрана_ без каких-либо параметров командной строки для самого man:ipfw[8]. Ниже приведён простой пример набора правил, который блокирует весь входящий и исходящий трафик:
+Экземпляр NAT и номер правила, используемые в этом примере, не совпадают с экземпляром NAT и номером правила, созданными по умолчанию в [.filename]#rc.firewall#. [.filename]#rc.firewall# — это скрипт, который настраивает правила межсетевого экрана по умолчанию в FreeBSD.
+====
[.programlisting]
....
-add deny in
-add deny out
+$cmd 005 allow all from any to any via xl0 # exclude LAN traffic
+$cmd 010 allow all from any to any via lo0 # exclude loopback traffic
+$cmd 099 reass all from any to any in # reassemble inbound packets
+$cmd 100 nat 1 ip from any to any in via $pif # NAT any inbound packets
+# Allow the packet through if it has an existing entry in the dynamic rules table
+$cmd 101 check-state
....
-Второй способ - установить значение переменной `firewall_script` в виде абсолютного пути исполняемого скрипта, содержащего команды `ipfw`, которые будут выполнены во время загрузки операционной системы. Правильный формат правил исполняемого скрипта должен соответствовать формату файла, приведённому ниже:
+Правила для исходящего трафика изменены, чтобы заменить действие `allow` на переменную `$skip`, указывая, что обработка правил продолжится с правила `1000`. Семь правил для `tcp` заменены правилом `125`, так как переменная `$good_tcpo` содержит семь разрешённых исходящих портов.
+
+[NOTE]
+====
+Помните, что производительность IPFW в значительной степени определяется количеством правил в наборе правил межсетевого экрана.
+====
[.programlisting]
....
-#!/bin/sh
+# Authorized outbound packets
+$cmd 120 $skip udp from any to x.x.x.x 53 out via $pif $ks
+$cmd 121 $skip udp from any to x.x.x.x 67 out via $pif $ks
+$cmd 125 $skip tcp from any to any $good_tcpo out via $pif setup $ks
+$cmd 130 $skip icmp from any to any out via $pif $ks
+....
-ipfw -q flush
+Правила для входящего трафика остаются такими же, за исключением самого последнего правила, в котором удаляется `via $pif`, чтобы охватить как входящие, так и исходящие правила. Правило NAT должно следовать за этим последним исходящим правилом, иметь номер выше, чем у последнего правила, и номер правила должен быть указан в действии `skipto`. В этом наборе правил правило номер `1000` обрабатывает передачу всех пакетов в настроенный экземпляр для обработки NAT. Следующее правило разрешает прохождение любого пакета, прошедшего обработку NAT.
-ipfw add deny in
-ipfw add deny out
+[.programlisting]
+....
+$cmd 999 deny log all from any to any
+$cmd 1000 nat 1 ip from any to any out via $pif # skipto location for outbound stateful rules
+$cmd 1001 allow ip from any to any
....
+В этом примере правила `100`, `101`, `125`, `1000` и `1001` управляют преобразованием адресов исходящих и входящих пакетов, чтобы записи в таблице динамического состояния всегда указывали на частный LANIP-адрес.
+
+Рассмотрим внутренний веб-браузер, который инициирует новый исходящий HTTP-сеанс через порт 80. Когда первый исходящий пакет попадает в межсетевой экран, он не соответствует правилу `100`, так как направлен наружу, а не внутрь. Он проходит правило `101`, так как это первый пакет и он ещё не был добавлен в таблицу динамического состояния. В итоге пакет соответствует правилу `125`, так как он исходящий на разрешённом порту и имеет исходный IP-адрес из внутренней LAN. При соответствии этому правилу выполняются два действия. Во-первых, действие `keep-state` добавляет запись в таблицу динамического состояния, и выполняется указанное действие `skipto rule 1000`. Затем пакет проходит NAT и отправляется в Интернет. Этот пакет достигает целевого веб-сервера, где генерируется и отправляется обратно ответный пакет. Этот новый пакет попадает в начало набора правил. Он соответствует правилу `100`, и его IP-адрес назначения преобразуется обратно в исходный внутренний адрес. Затем он обрабатывается правилом `check-state`, обнаруживается в таблице как существующий сеанс и передаётся в LAN.
+
+На входящей стороне набор правил должен блокировать плохие пакеты и разрешать только авторизованные сервисы. Пакет, соответствующий входящему правилу, помещается в таблицу динамического состояния и выпускается в локальную сеть. Пакет, сгенерированный в ответ, распознаётся правилом `check-state` как принадлежащий существующему сеансу. Затем он отправляется к правилу `1000` для выполнения NAT перед выпуском на исходящий интерфейс.
+
[NOTE]
====
-Если переменной `firewall_type` присвоено значение `client` или `simple`, то правила, расположенные по умолчанию в [.filename]#/etc/rc.firewall#, должны быть приведены в соответствие с конфигурацией данной машины. Также заметим, что для используемых в этой главе примеров в качестве значения переменной `firewall_script` используется [.filename]#/etc/ipfw.rules#.
+Переход от пользовательской реализации man:natd[8] к NAT в ядре может сначала показаться простым, но есть небольшой нюанс. При использовании GENERIC ядра IPFW загрузит модуль ядра [.filename]#libalias.ko#, когда в [.filename]#/etc/rc.conf# включена опция `firewall_nat_enable`. Модуль ядра [.filename]#libalias.ko# предоставляет только базовую функциональность NAT, в то время как пользовательская реализация man:natd[8] имеет все функции NAT в своей пользовательской библиотеке без дополнительной настройки. Под всей функциональностью подразумеваются следующие модули ядра, которые могут быть дополнительно загружены при необходимости, помимо стандартного модуля [.filename]#libalias.ko#: [.filename]#alias_ftp.ko#, [.filename]#alias_bbt.ko#, [.filename]#skinny.ko#, [.filename]#irc.ko#, [.filename]#alias_pptp.ko# и [.filename]#alias_smedia.ko# с использованием директивы `kld_list` в [.filename]#/etc/rc.conf#. Если используется собственное ядро, полная функциональность пользовательской библиотеки может быть встроена в ядро с помощью опции `options LIBALIAS`.
====
-Включение протоколирования:
+==== Перенаправление портов
+
+Недостаток NAT в целом заключается в том, что клиенты в локальной сети недоступны из Интернета. Клиенты в локальной сети могут устанавливать исходящие соединения с внешним миром, но не могут принимать входящие. Это создаёт проблему, если необходимо запустить интернет-сервисы на одной из машин-клиентов локальной сети. Простое решение этой проблемы — перенаправление определённых портов из Интернета на машине, предоставляющей NAT, к клиенту в локальной сети.
+
+Например, сервер IRC работает на клиенте `A`, а веб-сервер — на клиенте `B`. Для правильной работы соединения, полученные на портах 6667 (IRC) и 80 (HTTP), должны быть перенаправлены на соответствующие машины.
+
+С встроенным в ядро NAT вся конфигурация выполняется в настройках экземпляра NAT. Полный список параметров, которые может использовать экземпляр встроенного в ядро NAT, приведен в man:ipfw[8]. Синтаксис IPFW соответствует синтаксису natd. Синтаксис для `redirect_port` выглядит следующим образом:
[.programlisting]
....
-firewall_logging="YES"
+redirect_port proto targetIP:targetPORT[-targetPORT]
+ [aliasIP:]aliasPORT[-aliasPORT]
+ [remoteIP[:remotePORT[-remotePORT]]]
....
-[WARNING]
-====
+Для настройки приведённой выше конфигурации аргументы должны быть:
+
+[.programlisting]
+....
+redirect_port tcp 192.168.0.2:6667 6667
+redirect_port tcp 192.168.0.3:80 80
+....
-Единственное, что делает параметр `firewall_logging`, - присвоение логической единицы (`1`) переменной sysctl `net.inet.ip.fw.verbose` (смотрите <<firewalls-ipfw-enable>>). В [.filename]#rc.conf# нет переменной для ограничения протоколирования, но это можно сделать через переменную sysctl вручную либо используя файл [.filename]#/etc/sysctl.conf#:
+После добавления этих аргументов в конфигурацию NAT-экземпляра 1 в приведенном выше наборе правил, TCP-порты будут проброшены на клиентские машины в локальной сети, на которых работают службы IRC и HTTP.
[.programlisting]
....
-net.inet.ip.fw.verbose_limit=5
+ipfw -q nat 1 config if $pif same_ports unreg_only reset \
+ redirect_port tcp 192.168.0.2:6667 6667 \
+ redirect_port tcp 192.168.0.3:80 80
....
+Диапазоны портов вместо отдельных портов могут быть указаны с помощью `redirect_port`. Например, _tcp 192.168.0.2:2000-3000 2000-3000_ перенаправит все соединения, полученные на портах с 2000 по 3000, на порты с 2000 по 3000 клиента `A`.
+
+==== Перенаправление адресов
+
+Перенаправление адресов полезно, если доступно более одного IP-адреса. Каждому клиенту в локальной сети может быть назначен собственный внешний IP-адрес с помощью man:ipfw[8], который затем перезаписывает исходящие пакеты от клиентов локальной сети с соответствующим внешним IP-адресом и перенаправляет весь входящий трафик для этого конкретного IP-адреса обратно к определённому клиенту локальной сети. Это также известно как статический NAT. Например, если доступны IP-адреса `128.1.1.1`, `128.1.1.2` и `128.1.1.3`, то `128.1.1.1` может использоваться как внешний IP-адрес машины с man:ipfw[8], а `128.1.1.2` и `128.1.1.3` перенаправляются обратно клиентам `A` и `B` локальной сети.
+
+Синтаксис `redirect_addr` приведён ниже, где `localIP` — это внутренний IP-адрес клиента в локальной сети, а `publicIP` — внешний IP-адрес, соответствующий клиенту в локальной сети.
+
+[.programlisting]
+....
+redirect_addr localIP publicIP
+....
+
+В этом примере аргументы выглядели бы следующим образом:
+
+[.programlisting]
+....
+redirect_addr 192.168.0.2 128.1.1.2
+redirect_addr 192.168.0.3 128.1.1.3
+....
+
+Как и `redirect_port`, эти аргументы размещаются в конфигурации экземпляра NAT. При перенаправлении адреса нет необходимости в перенаправлении портов, так как перенаправляются все данные, полученные на определённый IP-адрес.
+
+Внешние IP-адреса на машине с man:ipfw[8] должны быть активны и назначены как псевдонимы внешнему интерфейсу. Подробности см. в man:rc.conf[5].
+
+==== Пользовательский NAT
+
+Начнем с утверждения: реализация NAT в пользовательском пространстве: man:natd[8], имеет больше накладных расходов, чем NAT в ядре. Для работы man:natd[8] по преобразованию пакетов, пакеты должны копироваться из ядра в пользовательское пространство и обратно, что создает дополнительные накладные расходы, отсутствующие при использовании NAT в ядре.
+
+Для включения демона NAT в пользовательском пространстве man:natd[8] при загрузке, следующая минимальная конфигурация должна быть добавлена в [.filename]#/etc/rc.conf#. Параметр `natd_interface` должен быть установлен равным имени сетевого интерфейса, подключенного к Интернету. Скрипт man:rc[8] для man:natd[8] автоматически проверит, используется ли динамический IP-адрес, и настроит себя соответствующим образом.
+
+[.programlisting]
+....
+gateway_enable="YES"
+natd_enable="YES"
+natd_interface="rl0"
+....
+
+В общем случае, приведённый выше набор правил, описанный для NAT в ядре, также может использоваться совместно с man:natd[8]. Исключениями являются настройка экземпляра NAT в ядре `(ipfw -q nat 1 config ...)`, которая не требуется вместе с правилом пересборки 99, так как его функциональность включена в действие `divert`. Правила 100 и 1000 необходимо немного изменить, как показано ниже.
+
+[.programlisting]
+....
+$cmd 100 divert natd ip from any to any in via $pif
+$cmd 1000 divert natd ip from any to any out via $pif
+....
+
+Для настройки перенаправления портов или адресов используется синтаксис, аналогичный NAT в ядре. Однако, в отличие от настройки в скрипте набора правил, как в случае с NAT в ядре, конфигурацию man:natd[8] лучше выполнять в конфигурационном файле. Для этого необходимо передать дополнительный флаг через [.filename]#/etc/rc.conf#, который указывает путь к конфигурационному файлу.
+
+[.programlisting]
+....
+natd_flags="-f /etc/natd.conf"
+....
+
+[NOTE]
====
+Указанный файл должен содержать список параметров конфигурации, по одному на строку. Для получения дополнительной информации о файле конфигурации и возможных переменных обратитесь к man:natd[8]. Ниже приведены два примера записей, по одному на строку:
-Если ваша машина выполняет роль шлюза, т.е. обеспечивает трансляцию сетевых адресов (NAT) с помощью man:natd[8], имеет смысл сразу перейти к чтению crossref:advanced-networking[network-natd,Даемон преобразования сетевых адресов (natd)] для уточнения информации относительно параметров [.filename]#/etc/rc.conf#.
+[.programlisting]
+....
+redirect_port tcp 192.168.0.2:6667 6667
+redirect_addr 192.168.0.3 128.1.1.3
+....
+
+====
[[firewalls-ipfw-cmd]]
=== Команда IPFW
-Команда `ipfw` - это стандартный механизм для ручного добавления/удаления отдельных правил в активной цепочке правил межсетевого экрана. Основная проблема при использовании этого метода состоит в том, что при перезагрузке операционной системы все изменения, сделанные с помощью данной команды, будут утеряны. Вместо этого рекомендуется записать все правила в файл, из которого они будут считываться во время загрузки операционной системы, а также для полной замены текущего набора правил на содержимое из файла.
+`ipfw` можно использовать для ручного добавления или удаления отдельных правил в активный межсетевой экран во время его работы. Проблема этого метода в том, что все изменения теряются при перезагрузке системы. Рекомендуется вместо этого записывать все правила в файл и использовать его для загрузки правил при запуске системы, а также для замены текущих правил межсетевого экрана при изменении этого файла.
-Тем не менее, команду `ipfw` удобно использовать для отображения текущей конфигурации правил на экране консоли. Учетный модуль IPFW динамически создаёт счётчики для каждого правила, которые подсчитывают количество пакетов, соответствующих условиям срабатывания правила. В процессе тестирования отображение правила со своим счётчиком является одним из способов проверки, срабатывает ли правило при прохождении через него пакета или нет.
+`ipfw` — это полезный способ отображения текущих правил межсетевого экрана на экране консоли. Возможность учёта IPFW динамически создаёт счётчик для каждого правила, который подсчитывает каждый пакет, соответствующий правилу. В процессе тестирования правила, вывод правила с его счётчиком — это один из способов определить, работает ли правило так, как ожидается.
-Вывод полного списка правил:
+Чтобы вывести список всех активных правил в порядке их применения:
-[source,shell]
+[source, shell]
....
# ipfw list
....
-Вывод полного списка правил с маркером времени последнего срабатывания правила:
+Для вывода всех активных правил с отметкой времени последнего совпадения правила:
-[source,shell]
+[source, shell]
....
# ipfw -t list
....
-Следующий пример выводит учетную информацию, количество совпавших пакетов и сами правила. Первым столбцом идет номер правила, за ним следует число совпавших исходящих пакетов, третий столбец - число соответствующих входящих пакетов, и затем само правило.
+Следующий пример выводит информацию о сборе статистики и количество пакетов для совпавших правил вместе с самими правилами. Первый столбец — это номер правила, за которым следует количество совпавших пакетов и байтов, а затем само правило.
-[source,shell]
+[source, shell]
....
# ipfw -a list
....
-Вывод динамических правил вместе со статическими:
+Для отображения динамических правил вместе со статическими:
-[source,shell]
+[source, shell]
....
# ipfw -d list
....
-Отобразить статические и динамические правила, в т.ч. с истекшим временем действия:
+Чтобы также показать истекшие динамические правила:
-[source,shell]
+[source, shell]
....
# ipfw -d -e list
....
-Обнуление счетчиков:
+Для обнуления счетчиков:
-[source,shell]
+[source, shell]
....
# ipfw zero
....
-Обнулить счетчики для правила под номером _NUM_:
+Обнулить счетчики только для правила с номером _NUM_:
-[source,shell]
+[source, shell]
....
# ipfw zero NUM
....
-[[firewalls-ipfw-rules]]
-=== Набор правил IPFW
+==== Журналирование сообщений межсетевого экрана
+
+Даже при включенной функции журналирования, IPFW не будет самостоятельно генерировать записи о правилах. Администратор межсетевого экрана решает, какие правила в наборе правил будут записываться в журнал, и добавляет ключевое слово `log` к этим правилам. Обычно журналируются только правила с действием deny. Принято дублировать правило "ipfw default deny everything" с включенным ключевым словом `log` в качестве последнего правила в наборе. Таким образом, можно увидеть все пакеты, которые не соответствуют ни одному из правил в наборе.
+
+Журналирование — это обоюдоострый меч. Если не быть осторожным, переизбыток данных журналирования или атака типа DoS могут заполнить диск файлами журналов. Сообщения журнала записываются не только в syslogd, но и выводятся на корневую консоль, что быстро становится раздражающим.
+
+Опция ядра `IPFIREWALL_VERBOSE_LIMIT=5` ограничивает количество последовательных сообщений, отправляемых в man:syslogd[8], касающихся совпадения пакетов с заданным правилом. Когда эта опция включена в ядре, количество последовательных сообщений, касающихся определённого правила, ограничивается указанным числом. Нет никакой пользы от 200 одинаковых сообщений в журнале. При установке этого параметра в пять, пять последовательных сообщений, касающихся определённого правила, будут записаны в syslogd, а оставшиеся идентичные последовательные сообщения будут подсчитаны и отправлены в syslogd с фразой, подобной следующей:
+
+[.programlisting]
+....
+last message repeated 45 times
+....
+
+Все сообщения о зарегистрированных пакетах по умолчанию записываются в [.filename]#/var/log/security#, что определено в [.filename]#/etc/syslog.conf#.
+
+[[firewalls-ipfw-rules-script]]
+==== Построение скрипта правил
+
+Большинство опытных пользователей IPFW создают файл, содержащий правила, и оформляют их таким образом, чтобы их можно было запускать как скрипт. Основное преимущество этого подхода заключается в том, что правила межсетевого экрана можно обновлять массово без необходимости перезагрузки системы для их активации. Этот метод удобен при тестировании новых правил, так как процедуру можно выполнять столько раз, сколько потребуется. Будучи скриптом, можно использовать символические подстановки для часто используемых значений, которые будут заменяться в нескольких правилах.
+
+Синтаксис примера, приведенного ниже, совместим с синтаксисом, используемым оболочками man:sh[1], man:csh[1] и man:tcsh[1]. Поля символьной подстановки (переменные — один из видов полей подстановки, прим. перев.) начинаются со знака доллара ($). Символьные поля не имеют префикса $. Значение для заполнения символьного поля должно быть заключено в двойные кавычки ("").
+
+Начните файл правил следующим образом:
-Набор правил (ruleset) представляет собой группу правил IPFW, которые разрешают или запрещают прохождение пакета через межсетевой экран на основании значений, содержащихся в пакете. Двунаправленный обмен пакетов между машинами является сессией. Набор правил межсетевого экрана анализирует как пакеты, приходящие из глобальной сети, так и ответные пакеты, исходящие из системы. Каждый TCP/IP сервис (такой как telnet, www, mail, и т.д.) принадлежит определенному протоколу и привилегированному (прослушиваемому) порту. Пакеты, предназначенные для конкретного сервиса, передаются с непривилегированного (с высоким значением) порта по адресу назначения на указанный порт сервиса. Все эти параметры (т.е. порты и адреса) могут быть использованы в качестве критериев фильтрации при создании правил, которые пропускают или блокируют сервисы.
+[.programlisting]
+....
+############### start of example ipfw rules script #############
+#
+ipfw -q -f flush # Delete all rules
+# Set defaults
+oif="tun0" # out interface
+odns="192.0.2.11" # ISP's DNS server IP address
+cmd="ipfw -q add " # build rule prefix
+ks="keep-state" # just too lazy to key this each time
+$cmd 00500 check-state
+$cmd 00502 deny all from any to any frag
+$cmd 00501 deny tcp from any to any established
+$cmd 00600 allow tcp from any to any 80 out via $oif setup $ks
+$cmd 00610 allow tcp from any to $odns 53 out via $oif setup $ks
+$cmd 00611 allow udp from any to $odns 53 out via $oif $ks
+################### End of example ipfw rules script ############
+....
+
+Правила не важны, так как цель этого примера — показать, как заполняются поля символьной подстановки.
+
+Если приведённый выше пример находится в [.filename]#/etc/ipfw.rules#, правила можно перезагрузить следующей командой:
+
+[source, shell]
+....
+# sh /etc/ipfw.rules
+....
+
+[.filename]#/etc/ipfw.rules# может находиться в любом месте, и файл может иметь любое имя.
+
+То же самое можно выполнить вручную, запустив следующие команды:
+
+[source, shell]
+....
+# ipfw -q -f flush
+# ipfw -q add check-state
+# ipfw -q add deny all from any to any frag
+# ipfw -q add deny tcp from any to any established
+# ipfw -q add allow tcp from any to any 80 out via tun0 setup keep-state
+# ipfw -q add allow tcp from any to 192.0.2.11 53 out via tun0 setup keep-state
+# ipfw -q add 00611 allow udp from any to 192.0.2.11 53 out via tun0 keep-state
+....
+
+[[firewalls-ipfw-kernelconfig]]
+=== Опции ядра для IPFW
-Когда пакет попадает в межсетевой экран, он сравнивается с каждым правилом, начиная с первого, двигаясь по множеству правил верху вниз в порядке увеличения номера правил. Когда пакет совпадает с критерием выбора правила, выполняется действие, указанное в правиле, и на этом поиск правил прекращается. Такой метод поиска известен как "выигрыш первого совпадения", т.е. после срабатывания правила оставшиеся не просматриваются. Если содержимое пакета не соответствует ни одному из правил, он принудительно попадает на встроенное правило по умолчанию, заданное под номером 65535, которое запрещает и отбрасывает все пакеты без какого-либо отклика в сторону отправителя.
+Для статической компиляции поддержки IPFW в собственное ядро обратитесь к инструкциям в crossref:kernelconfig[kernelconfig,Настройка ядра FreeBSD]. В файле конфигурации собственного ядра доступны следующие параметры:
+
+[.programlisting]
+....
+options IPFIREWALL # enables IPFW
+options IPFIREWALL_VERBOSE # enables logging for rules with log keyword to syslogd(8)
+options IPFIREWALL_VERBOSE_LIMIT=5 # limits number of logged packets per-entry
+options IPFIREWALL_DEFAULT_TO_ACCEPT # sets default policy to pass what is not explicitly denied
+options IPFIREWALL_NAT # enables basic in-kernel NAT support
+options LIBALIAS # enables full in-kernel NAT support
+options IPFIREWALL_NAT64 # enables in-kernel NAT64 support
+options IPFIREWALL_NPTV6 # enables in-kernel IPv6 NPT support
+options IPFIREWALL_PMOD # enables protocols modification module support
+options IPDIVERT # enables NAT through natd(8)
+....
[NOTE]
====
-Поиск продолжается после правил `count`, `skipto` и `tee`.
+IPFW может быть загружен как модуль ядра: указанные выше параметры по умолчанию собираются как модули или могут быть установлены во время выполнения с помощью tunables.
====
-Упомянутые здесь инструкции основаны на использовании правил, содержащих параметры с сохранением состояния `keep state`, `limit`, `in`, `out` и `via`. Это основной механизм для кодирования набора правил межсетевого экрана закрытого типа.
+[[firewalls-ipf]]
+== IPFILTER (IPF)
-[WARNING]
-====
+IPFILTER, также известный как IPF, представляет собой кроссплатформенный межсетевой экран с открытым исходным кодом, который был портирован на несколько операционных систем, включая FreeBSD, NetBSD, OpenBSD и Solaris(TM).
-Будьте осторожны, когда работаете с правилами межсетевого экрана, так как вы можете легко заблокировать самого себя.
-====
+IPFILTER — это механизм межсетевого экрана и NAT на уровне ядра, которым можно управлять и отслеживать его работу с помощью пользовательских программ. Правила межсетевого экрана можно устанавливать или удалять с помощью `ipf`, правила NAT — с помощью `ipnat`, статистику работы ядерной части IPFILTER в реальном времени можно выводить с помощью `ipfstat`, а `ipmon` позволяет записывать действия IPFILTER в системные журналы.
-[[firewalls-ipfw-rules-syntax]]
-==== Синтаксис правил
+IPF изначально был написан с использованием логики обработки правил "последнее совпавшее правило побеждает" и использовал только правила без состояния. С тех пор IPF был улучшен и теперь включает опции `quick` и `keep state`.
-Представленный здесь синтаксис правил был упрощен для создания стандартного набора правил межсетевого экрана закрытого типа. Для полного описания синтаксиса правил смотрите страницу Справочника man:ipfw[8].
+Часто задаваемые вопросы по IPF находятся на сайте http://www.phildev.net/ipf/index.html[http://www.phildev.net/ipf/index.html]. Доступен поисковый архив списка рассылки IPFilter по адресу http://marc.info/?l=ipfilter[http://marc.info/?l=ipfilter].
-Правила содержат ключевые слова: эти ключевые слова записываются в строке в определенном порядке слева направо. Ключевые слова выделены полужирным шрифтом. Некоторые ключевые слова имеют дополнительные параметры, которые могут являться ключевыми словами для них самих и также содержать вложенные дополнительные параметры.
+Этот раздел Руководства посвящен IPF в контексте FreeBSD. В нем приведены примеры правил, содержащих опции `quick` и `keep state`.
-Символ `#` используется для обозначения начала комментария и может быть расположен в конце строки с правилом или в начале строки над правилом. Пустые строки игнорируются.
+=== Включение IPF
-_CMD RULE_NUMBER ACTION LOGGING SELECTION STATEFUL_
+IPF включён в базовую установку FreeBSD в виде загружаемого модуля ядра, что означает, что для включения IPF не требуется создавать собственное ядро.
-===== CMD
+Для пользователей, которые предпочитают статически компилировать поддержку IPF в пользовательское ядро, обратитесь к инструкциям в crossref:kernelconfig[kernelconfig,Настройка ядра FreeBSD]. Доступны следующие параметры ядра:
-Каждое новое правило должно начинаться с префикса [parameter]#add# для добавления во внутреннюю таблицу.
+[.programlisting]
+....
+options IPFILTER
+options IPFILTER_LOG
+options IPFILTER_LOOKUP
+options IPFILTER_DEFAULT_BLOCK
+....
-===== RULE_NUMBER
+где `options IPFILTER` включает поддержку IPFILTER, `options IPFILTER_LOG` включает журналирование IPF с использованием псевдоустройства [.filename]#ipl# для записи пакетов для каждого правила, содержащего ключевое слово `log`, `IPFILTER_LOOKUP` включает пулы IP для ускорения поиска IP, а `options IPFILTER_DEFAULT_BLOCK` изменяет поведение по умолчанию так, что любой пакет, не соответствующий правилу `pass` межсетевого экрана, блокируется.
-Каждое правило обозначено номером в диапазоне 1..65535.
+Для настройки системы на включение IPF при загрузке добавьте следующие записи в [.filename]#/etc/rc.conf#. Эти записи также включат журналирование и политику `default pass all`. Чтобы изменить политику по умолчанию на `block all` без компиляции пользовательского ядра, не забудьте добавить правило `block all` в конец набора правил.
-===== ACTION
+[.programlisting]
+....
+ipfilter_enable="YES" # Start ipf firewall
+ipfilter_rules="/etc/ipf.rules" # loads rules definition text file
+ipv6_ipfilter_rules="/etc/ipf6.rules" # loads rules definition text file for IPv6
+ipmon_enable="YES" # Start IP monitor log
+ipmon_flags="-Ds" # D = start as daemon
+ # s = log to syslog
+ # v = log tcp window, ack, seq
+ # n = map IP & port to names
+....
-При соответствии пакета описанным в правиле критериям фильтрации будет выполнено одно из следующих действий.
+Если требуется функциональность NAT, также добавьте следующие строки:
-[parameter]#allow | accept | pass | permit#
+[.programlisting]
+....
+gateway_enable="YES" # Enable as LAN gateway
+ipnat_enable="YES" # Start ipnat function
+ipnat_rules="/etc/ipnat.rules" # rules definition file for ipnat
+....
-Все эти действия означают одно и то же - пакеты, совпадающие с правилом, могут покинуть обработку правил межсетевого экрана. На этом поиск прекращается.
+Затем, чтобы запустить IPF сейчас:
-[parameter]#check-state#
+[.programlisting]
+....
+# service ipfilter start
+....
-Проверяет пакет на соответствие динамической таблице правил. Если совпадение найдено, выполняется действие, содержащееся в правиле, породившем данное динамическое правило, иначе выполняется переход к следующему правилу. Правило check-state не имеет критериев фильтрации. При отсутствии правила check-state в наборе правил проверка по динамической таблице происходит на первом правиле keep-state или limit.
+Для загрузки правил межсетевого экрана укажите имя файла набора правил, используя `ipf`. Следующая команда может быть использована для замены текущих работающих правил межсетевого экрана:
-[parameter]#deny | drop#
+[source, shell]
+....
+# ipf -Fa -f /etc/ipf.rules
+....
-Оба слова означают отбрасывание пакетов, совпавших с правилом. Поиск прекращается.
+где `-Fa` очищает все внутренние таблицы правил, а `-f` указывает файл, содержащий правила для загрузки.
-===== Протоколирование
+Это предоставляет возможность вносить изменения в пользовательский набор правил и обновлять работающий межсетевой экран новой копией правил без необходимости перезагрузки системы. Этот метод удобен для тестирования новых правил, так как процедуру можно выполнять столько раз, сколько потребуется.
-[parameter]#log# или [parameter]#logamount#
+Обратитесь к man:ipf[8] для получения подробностей о других флагах, доступных с этой командой.
-Когда пакет совпадает с правилом, содержащим ключевое слово `log`, информация об этом событии записывается в man:syslogd[8] с пометкой SECURITY. Запись в журнал происходит только в том случае, если число срабатываний для данного правила не превышает значения параметра `logamount`. Если значение `logamount` не объявлено, то ограничение берется из значения переменной sysctl `net.inet.ip.fw.verbose_limit`. В обоих случаях обнуление значения отменяет ограничение. По достижению установленного лимита запись в журнал может быть повторно включена путем сброса счетчика срабатываний или счетчика пакетов для этого правила; смотрите описание команды `ipfw reset log`.
+=== Синтаксис правил IPF
-[NOTE]
-====
-Протоколирование осуществляется после проверки на соответствие всем условиям в правиле и перед выполнением окончательного действия (accept, deny) над пакетом. Вы должны выбрать сами, какие действия правил вы хотите включить в журнал.
-====
+В этом разделе описывается синтаксис правил IPF, используемый для создания правил с состояниями. При создании правил следует помнить, что если в правиле не указано ключевое слово `quick`, каждое правило обрабатывается по порядку, и _последнее совпавшее правило_ будет применено. Это означает, что даже если первое совпавшее правило разрешает (`pass`), но далее есть совпадающее правило, которое запрещает (`block`), пакет будет отброшен. Примеры наборов правил можно найти в [.filename]#/usr/share/examples/ipfilter#.
-===== Условия отбора
+При создании правил символ `+#+` используется для обозначения начала комментария и может находиться в конце правила, чтобы пояснить его функцию, или на отдельной строке. Пустые строки игнорируются.
-Ключевые слова, представленные в этом разделе, используются для описания атрибутов пакета, по которым проверяется условие срабатывания того или иного правила. Для совпадения используется следующая последовательность атрибутов общего назначения:
+Ключевые слова, используемые в правилах, должны быть записаны в определенном порядке, слева направо. Некоторые ключевые слова являются обязательными, а другие — опциональными. Некоторые ключевые слова имеют подопции, которые могут сами быть ключевыми словами и включать дополнительные подопции. Порядок ключевых слов следующий, где слова, написанные в ВЕРХНЕМ РЕГИСТРЕ, представляют переменную, а слова, написанные в нижнем регистре, должны предшествовать следующей за ними переменной:
-[parameter]#udp | tcp | icmp#
+`_ACTION DIRECTION OPTIONS proto PROTO_TYPE from SRC_ADDR SRC_PORT to DST_ADDR DST_PORT TCP_FLAG|ICMP_TYPE keep state STATE_`
-Также могут быть использованы имена протоколов, описанные в [.filename]#/etc/protocols#. Указанное значение обозначает протокол для совпадения. Это является обязательным требованием.
+В этом разделе описываются ключевые слова и их параметры. Это не исчерпывающий список всех возможных параметров. Полное описание синтаксиса правил, который можно использовать при создании правил IPF, а также примеры использования каждого ключевого слова приведены в man:ipf[5].
-[parameter]#from src to dst#
+ACTION::
+Ключевое слово `action` указывает действие — что делать с пакетом, если он соответствует данному правилу. Каждое правило _должно_ иметь действие. Поддерживаются следующие действия:
++
+`block`: отбрасывает пакет.
++
+`pass`: разрешает пакет.
++
+`log`: создает запись в журнале.
++
+`count`: подсчитывает количество пакетов и байтов, что может дать представление о том, как часто используется правило.
++
+`auth`: ставит пакет в очередь для дальнейшей обработки другой программой.
++
+`call`: предоставляет доступ к функциям, встроенным в IPF, которые позволяют выполнять более сложные действия.
++
+`decapsulate`: удаляет любые заголовки для обработки содержимого пакета.
-Ключевые слова `from` и `to` служат для фильтрации по IP адресам. Обязательно должны быть указаны и источник, и получатель. `any` - это специальное ключевое слово, которое соответствует любому IP адресу. `me` - это специальное ключевое слово, которое соответствует любому из IP адресов, сконфигурированных на интерфейсе вашей системы FreeBSD, и служит для указания компьютера, на котором работает межсетевой экран (т.е. этот компьютер), как показано на примерах `from me to any`, `from any to me`, `from 0.0.0.0/0 to any`, `from any to 0.0.0.0/0`, `from 0.0.0.0 to any`, `from any to 0.0.0.0` и `from me to 0.0.0.0`. IP адрес указывается в виде четырёх чисел, разделённых точками, или дополнительно с префиксом сети (нотация CIDR). Это является обязательным требованием. Для упрощения вычислений, связанных с IP адресами, используйте порт package:net-mgmt/ipcalc[]. Более подробную информацию можно посмотреть на странице программы: http://jodies.de/ipcalc[http://jodies.de/ipcalc].
+DIRECTION::
+Далее, каждое правило должно явно указывать `direction ` — направление трафика с использованием одного из следующих ключевых слов:
++
+`in`: правило применяется к входящему пакету.
++
+`out`: правило применяется к исходящему пакету.
++
+`all`: правило применяется в обоих направлениях.
++
+Если в системе несколько интерфейсов, можно указать интерфейс вместе с направлением. Примером может быть `in on fxp0`.
-[parameter]#port number#
+OPTIONS::
+`options` — параметры необязательны. Однако, если указано несколько параметров, они должны использоваться в порядке, указанном здесь.
++
+`log`: при выполнении указанного ДЕЙСТВИЯ содержимое заголовков пакета будет записано в псевдоустройство журнала пакетов man:ipl[4].
++
+`quick`: если пакет соответствует этому правилу, происходит ДЕЙСТВИЕ, указанное в правиле, и дальнейшая обработка последующих правил для этого пакета не выполняется.
++
+`on`: должен сопровождаться именем интерфейса, как отображается в man:ifconfig[8]. Правило будет применяться только в том случае, если пакет проходит через указанный интерфейс в указанном направлении.
++
+При использовании ключевого слова `log` следующие квалификаторы могут быть указаны в таком порядке:
++
+`body`: указывает, что первые 128 байт содержимого пакета будут записаны в журнал после заголовков.
++
+`first`: если ключевое слово `log` используется вместе с опцией `keep state`, рекомендуется использовать эту опцию, чтобы регистрировался только инициирующий пакет, а не каждый пакет, соответствующий соединению с отслеживанием состояний.
++
+Дополнительные параметры доступны для указания сообщений об ошибках. Подробности смотрите в man:ipf[5].
-Для протоколов, работающих с портами (такие как TCP и UDP), обязательным требованием является указание номера порта соответствующего сервиса. Вместо номера порта можно использовать имя сервиса (из [.filename]#/etc/services#).
+PROTO_TYPE::
+Тип протокола является необязательным. Однако он обязателен, если в правиле необходимо указать SRC_PORT или DST_PORT, так как он определяет тип протокола. При указании типа протокола используйте ключевое слово `proto`, за которым следует номер протокола или его имя из [.filename]#/etc/protocols#. Примеры названий протоколов: `tcp`, `udp` или `icmp`. Если указан PROTO_TYPE, но не указаны SRC_PORT или DST_PORT, все номера портов для этого протокола будут соответствовать этому правилу.
-[parameter]#in | out#
+SRC_ADDR::
+Ключевое слово `from` является обязательным и сопровождается ключевым словом, обозначающим источник пакета. Источником может быть имя хоста, IP-адрес с указанием маски CIDR, пул адресов или ключевое слово `all`. Примеры можно найти в man:ipf[5].
++
+Единственный способ задать диапазоны IP-адресов, это представить их в нотации — числа, разделенные точками / длина маски. Пакет или порт package:net-mgmt/ipcalc[] может быть использован для упрощения расчета маски CIDR. Дополнительная информация доступна на веб-странице утилиты: http://jodies.de/ipcalc[http://jodies.de/ipcalc].
-Отбор соответственно по входящим и исходящим пакетам. Присутствие одного из этих ключевым слов в правиле обязательно для формирования критерия фильтрации.
+SRC_PORT::
+Номер порта источника является необязательным. Однако, если он используется, требуется, чтобы PROTO_TYPE был сначала определён в правиле. Номер порта также должен предваряться ключевым словом `proto`.
++
+Поддерживается несколько различных операторов сравнения: `=` (равно), `!=` (не равно), `<` (меньше), `>` (больше), `<=` (меньше или равно) и `>=` (больше или равно).
++
+Для указания диапазона портов поместите два номера порта между `<>` (меньше и больше), `><` (больше и меньше) или `:` (больше или равно и меньше или равно).
-[parameter]#via IF#
+DST_ADDR::
+Ключевое слово `to` является обязательным и за ним следует ключевое слово, обозначающее назначение пакета. Аналогично SRC_ADDR, это может быть имя хоста, IP-адрес с маской CIDR, пул адресов или ключевое слово `all`.
-Совпадает с пакетами, проходящими через указанный интерфейс. Ключевое слово `via` включает обязательную проверку на указанном интерфейсе в общий процесс поиска совпадений.
+DST_PORT::
+Аналогично SRC_PORT, номер порта назначения является необязательным. Однако, если он используется, требуется, чтобы PROTO_TYPE был сначала определён в правиле. Номер порта также должен предваряться ключевым словом `proto`.
-[parameter]#setup#
+TCP_FLAG|ICMP_TYPE::
+Если в качестве `PROTO_TYPE` указан `tcp`, флаги могут быть заданы в виде букв, где каждая буква представляет один из возможных флагов TCP, используемых для определения состояния соединения. Возможные значения: `S` (SYN), `A` (ACK), `P` (PSH), `F` (FIN), `U` (URG), `R` (RST), `C` (CWN) и `E` (ECN).
++
+Если указан `icmp` в качестве PROTO_TYPE, можно указать тип ICMP для сопоставления. Допустимые типы приведены в man:ipf[5].
-Это обязательное ключевое слово определяет начало запроса сессии для TCP пакетов.
+STATE::
+Если правило `pass` содержит `keep state`, IPF добавит запись в свою таблицу динамического состояния и разрешит последующие пакеты, соответствующие соединению. IPF может отслеживать состояние сеансов TCP, UDP и ICMP. Любой пакет, который IPF может однозначно идентифицировать как часть активного сеанса, даже если это другой протокол, будет разрешён.
++
+В IPF пакеты, предназначенные для выхода через интерфейс, подключенный к публичному интернету, сначала проверяются в динамической таблице состояний. Если пакет соответствует следующему ожидаемому пакету активного сеанса связи, он проходит через межсетевой экран, и состояние потока сеанса обновляется в динамической таблице состояний. Пакеты, не принадлежащие к уже активному сеансу, проверяются в соответствии с набором правил для исходящего трафика. Пакеты, поступающие через интерфейс, подключенный к публичному интернету, сначала проверяются в динамической таблице состояний. Если пакет соответствует следующему ожидаемому пакету активного сеанса, он проходит через межсетевой экран, и состояние потока сеанса обновляется в динамической таблице состояний. Пакеты, не принадлежащие к уже активному сеансу, проверяются в соответствии с набором правил для входящего трафика.
++
+Несколько ключевых слов могут быть добавлены после `keep state`. Если они используются, эти ключевые слова устанавливают различные параметры, управляющие фильтрацией с отслеживанием статуса, такие как установка ограничений на соединения или времени жизни соединения. Подробный список доступных параметров и их описания можно найти в man:ipf[5].
-[parameter]#keep-state#
+=== Пример набора правил
-Это обязательное ключевое слово. При совпадении межсетевой экран создает динамическое правило, которое по умолчанию будет совпадать с двунаправленным трафиком между отправителем и получателем для данной пары IP/порт по указанному протоколу.
+Этот раздел демонстрирует, как создать пример набора правил, который разрешает только сервисы, соответствующие правилам `pass`, и блокирует все остальные.
-[parameter]#limit {src-addr | src-port | dst-addr | dst-port}#
+FreeBSD использует loopback-интерфейс (интерфейс обратной петли) ([.filename]#lo0#) и IP-адрес `127.0.0.1` для внутреннего взаимодействия. Набор правил межсетевого экрана должен включать правила, разрешающие свободное перемещение этих внутренних пакетов:
-Межсетевой экран разрешит только _N_ соединений с одинаковым набором параметров, указанных в правиле. Можно задавать один или несколько адресов и портов отправителя и получателя. В одном и том же правиле использование `limit` и `keep-state` не допускается. Параметр `limit` предоставляет такую же функцию с сохранением состояний, что и `keep-state`, плюс свои собственные.
+[.programlisting]
+....
+# no restrictions on loopback interface
+pass in quick on lo0 all
+pass out quick on lo0 all
+....
-==== Параметры для правил с сохранением состояния
+Публичный интерфейс, подключенный к Интернету, используется для авторизации и контроля доступа всех исходящих и входящих соединений. Если один или несколько интерфейсов подключены к частным сетям, этим внутренним интерфейсам могут потребоваться правила, разрешающие передачу пакетов, исходящих из локальной сети, между внутренними сетями или к интерфейсу, подключенному к Интернету. Набор правил должен быть организован в три основных раздела: доверенные внутренние интерфейсы, исходящие соединения через публичный интерфейс и входящие соединения через публичный интерфейс.
-С точки зрения фильтрации по правилам с сохранением состояния весь трафик выглядит как двусторонний обмен пакетами, включая данные о сессиях. При такой фильтрации у нас есть средства сопоставления и определения корректности процедуры двустороннего обмена пакетами между стороной, породившей пакет, и стороной-получателем. Любые пакеты, которые не подходят под шаблон сессии, автоматически отбрасываются как злонамеренные.
+Эти два правила разрешают весь трафик через доверенный интерфейс LAN с именем [.filename]#xl0#:
-Параметр `check-state` служит для указания места в наборе правил IPFW, в котором пакет будет передан на поиск соответствий динамическим правилам. В случае совпадения пакет пропускается, при этом создается новое динамическое правило для следующего пакета, принадлежащего данной двусторонней сессии. В противном случае пакет движется по обычным правилам, начиная со следующей позиции.
+[.programlisting]
+....
+# no restrictions on inside LAN interface for private network
+pass out quick on xl0 all
+pass in quick on xl0 all
+....
+
+Правила для исходящего и входящего разделов публичного интерфейса должны иметь наиболее часто совпадающие правила, расположенные перед менее часто совпадающими, а последнее правило в разделе должно блокировать и журналировать все пакеты для этого интерфейса и направления.
+
+Этот набор правил определяет исходящий раздел общедоступного интерфейса с именем [.filename]#dc0#. Эти правила сохраняют состояние и определяют конкретные службы, для которых внутренние системы авторизованы для доступа к общедоступному Интернету. Все правила используют `quick` и указывают соответствующие номера портов и, где применимо, адреса назначения.
-Динамические правила уязвимы к атаке SYN-пакетами, которые могут породить гигантское количество динамических правил. Для предотвращения такого рода атак во FreeBSD предусмотрен еще один параметр - `limit`. Этот параметр служит для ограничения количества одновременно установленных сессий путём проверки полей отправителя и получателя, в зависимости от параметра `limit`, с использованием IP адреса пакета для поиска открытых динамических правил, которые представляют собой счетчик количества совпадений для данного IP адреса и этого правила. Если это количество превышает значение, указанное в параметре `limit`, то такой пакет отбрасывается.
+[.programlisting]
+....
+# interface facing Internet (outbound)
+# Matches session start requests originating from or behind the
+# firewall, destined for the Internet.
-==== Протоколирование сообщений межсетевого экрана
+# Allow outbound access to public DNS servers.
+# Replace x.x.x.x with address listed in /etc/resolv.conf.
+# Repeat for each DNS server.
+pass out quick on dc0 proto tcp from any to x.x.x.x port = 53 flags S keep state
+pass out quick on dc0 proto udp from any to x.x.x.x port = 53 keep state
-Преимущества протоколирования очевидны: это предоставляет возможность отслеживать постфактум, прохождение каких пакетов было отклонено, откуда эти пакеты пришли и куда они назначались для тех правил, в которых включена функция записи в журнал. Это замечательный инструмент для отслеживания атак на вашу систему.
+# Allow access to ISP's specified DHCP server for cable or DSL networks.
+# Use the first rule, then check log for the IP address of DHCP server.
+# Then, uncomment the second rule, replace z.z.z.z with the IP address,
+# and comment out the first rule
+pass out log quick on dc0 proto udp from any to any port = 67 keep state
+#pass out quick on dc0 proto udp from any to z.z.z.z port = 67 keep state
-Даже при включенной функции ведения журнала само по себе оно производиться не будет. Администратор межсетевого экрана определяет, для каких правил будет включена функция ведения журнала, и добавляет к этим правилам `log`. Обычно в журнал пишутся только запрещающие правила, такие как правила deny для входящего ICMP ping. Довольно часто конец списка добавляют дублирующее правило вида "ipfw default deny everything" с приставкой `log`. Это позволяет отслеживать все пакеты, не совпадающие ни с одним из правил в вашем наборе.
+# Allow HTTP and HTTPS
+pass out quick on dc0 proto tcp from any to any port = 80 flags S keep state
+pass out quick on dc0 proto tcp from any to any port = 443 flags S keep state
-Будьте крайне осмотрительны при использовании функции ведения журнала, так как это чревато несоразмерным разрастанием файла журнала, вплоть до полного заполнения им места на жестком диске. DoS атаки, направленные на переполнение свободного пространства жесткого диска, являются одними из самых старейших. Помимо заполнения жесткого диска это неприятно еще и тем, что сообщения журнала пишутся не только в syslogd, но также отображаются на экране системной консоли, и это вскоре начинает сильно раздражать.
+# Allow email
+pass out quick on dc0 proto tcp from any to any port = 110 flags S keep state
+pass out quick on dc0 proto tcp from any to any port = 25 flags S keep state
-Параметр ядра `IPFIREWALL_VERBOSE_LIMIT=5` ограничивает число идущих подряд сообщений в системный регистратор man:syslogd[8], касающихся пакетов, совпавших с правилом. Когда этот параметр включен в ядро, число последовательно идущих сообщений для определенного правила обрезается указанным числом. От записи 200 идентичных сообщений особого прока нет. В данном случае для сработавшего правила в журнале syslogd будут зафиксированы 5 сообщений подряд, остальные идентичные сообщения будут подсчитаны и отправлены в syslogd как одно сообщение такого вида:
+# Allow NTP
+pass out quick on dc0 proto tcp from any to any port = 37 flags S keep state
-[.programlisting]
+# Allow FTP
+pass out quick on dc0 proto tcp from any to any port = 21 flags S keep state
+
+# Allow SSH
+pass out quick on dc0 proto tcp from any to any port = 22 flags S keep state
+
+# Allow ping
+pass out quick on dc0 proto icmp from any to any icmp-type 8 keep state
+
+# Block and log everything else
+block out log first quick on dc0 all
....
-last message repeated 45 times
+
+Этот пример правил в разделе входящего трафика публичного интерфейса сначала блокирует все нежелательные пакеты. Это уменьшает количество пакетов, регистрируемых последним правилом.
+
+[.programlisting]
....
+# interface facing Internet (inbound)
+# Block all inbound traffic from non-routable or reserved address spaces
+block in quick on dc0 from 192.168.0.0/16 to any #RFC 1918 private IP
+block in quick on dc0 from 172.16.0.0/12 to any #RFC 1918 private IP
+block in quick on dc0 from 10.0.0.0/8 to any #RFC 1918 private IP
+block in quick on dc0 from 127.0.0.0/8 to any #loopback
+block in quick on dc0 from 0.0.0.0/8 to any #loopback
+block in quick on dc0 from 169.254.0.0/16 to any #DHCP auto-config
+block in quick on dc0 from 192.0.2.0/24 to any #reserved for docs
+block in quick on dc0 from 204.152.64.0/23 to any #Sun cluster interconnect
+block in quick on dc0 from 224.0.0.0/3 to any #Class D & E multicast
-Путь к файлу, в который пишутся сообщения, задается в файле [.filename]#/etc/syslog.conf#. По умолчанию это файл [.filename]#/var/log/security#.
+# Block fragments and too short tcp packets
+block in quick on dc0 all with frags
+block in quick on dc0 proto tcp all with short
-[[firewalls-ipfw-rules-script]]
-==== Написание скрипта правил
+# block source routed packets
+block in quick on dc0 all with opt lsrr
+block in quick on dc0 all with opt ssrr
+
+# Block OS fingerprint attempts and log first occurrence
+block in log first quick on dc0 proto tcp from any to any flags FUP
+
+# Block anything with special options
+block in quick on dc0 all with ipopts
-Наиболее опытные пользователи IPFW создают скрипт, содержащий в себе правила, оформленные таким образом, что они могут быть исполнены как обыкновенный sh-скрипт. Основное преимущество такого подхода в том, что правила можно полностью заменить на новые без необходимости в перезагрузке системы для их активации. Это крайне удобно на этапе разработки и тестирования набора правил, т.к. перезагружать весь список правил можно сколь угодно часто. Помимо того, поскольку это скрипт, то здесь можно объявить некие часто используемые значения в виде переменной, и использовать её во множестве правил, как показано в примере ниже.
+# Block public pings and ident
+block in quick on dc0 proto icmp all icmp-type 8
+block in quick on dc0 proto tcp from any to any port = 113
-Синтаксис примера, приведенного ниже, совместим с тремя командными оболочками: man:sh[1], man:csh[1], man:tcsh[1]. Для использования значения ранее объявленной переменной имя переменной предваряется символом $. Во время присвоения имя переменной не имеет префикса $, присваиваемое значение должно быть заключено в "двойные кавычки".
+# Block incoming Netbios services
+block in log first quick on dc0 proto tcp/udp from any to any port = 137
+block in log first quick on dc0 proto tcp/udp from any to any port = 138
+block in log first quick on dc0 proto tcp/udp from any to any port = 139
+block in log first quick on dc0 proto tcp/udp from any to any port = 81
+....
+
+Всякий раз, когда регистрируются сообщения о правиле с опцией `log first`, выполните команду `ipfstat -hio`, чтобы оценить, сколько раз правило сработало. Большое количество срабатываний может указывать на то, что система подвергается атаке.
-Так выглядит файл с правилами, с которого вы можете начать:
+Остальные правила в разделе входящего трафика определяют, какие соединения могут быть инициированы из Интернета. Последнее правило запрещает все соединения, которые не были явно разрешены предыдущими правилами в этом разделе.
[.programlisting]
....
-############### начало примера скрипта с правилами ipfw #############
-#
-ipfw -q -f flush # Сброс всех правил.
-# Установки по умолчанию
-oif="tun0" # наш интерфейс
-odns="192.0.2.11" # IP DNS сервера провайдера
-cmd="ipfw -q add " # префикс для создания правил
-ks="keep-state" # просто лень вводить каждый раз
-$cmd 00500 check-state
-$cmd 00502 deny all from any to any frag
-$cmd 00501 deny tcp from any to any established
-$cmd 00600 allow tcp from any to any 80 out via $oif setup $ks
-$cmd 00610 allow tcp from any to $odns 53 out via $oif setup $ks
-$cmd 00611 allow udp from any to $odns 53 out via $oif $ks
-################### конец примера скрипта с правилами ipfw ############
+# Allow traffic in from ISP's DHCP server. Replace z.z.z.z with
+# the same IP address used in the outbound section.
+pass in quick on dc0 proto udp from z.z.z.z to any port = 68 keep state
+
+# Allow public connections to specified internal web server
+pass in quick on dc0 proto tcp from any to x.x.x.x port = 80 flags S keep state
+
+# Block and log only first occurrence of all remaining traffic.
+block in log first quick on dc0 all
....
-Вот и все, что нужно сделать. Сами правила в этом примере не столь важны, они написаны ради того, чтобы продемонстрировать использование подстановки значения переменной по ее имени.
+=== Настройка NAT
-Если бы этот скрипт находился в файле [.filename]#/etc/ipfw.rules#, то правила можно было бы перезагрузить следующей командой.
+Чтобы включить NAT, добавьте следующие выражения в [.filename]#/etc/rc.conf# и укажите имя файла, содержащего правила NAT:
-[source,shell]
+[.programlisting]
....
-# sh /etc/ipfw.rules
+gateway_enable="YES"
+ipnat_enable="YES"
+ipnat_rules="/etc/ipnat.rules"
....
-Имя и расположение файла [.filename]#/etc/ipfw.rules# могут быть какими угодно.
+Правила NAT гибки и могут выполнять множество различных задач, подходящих как для коммерческих, так и для домашних пользователей. Синтаксис правил, представленный здесь, упрощен для демонстрации типичного использования. Полное описание синтаксиса правил можно найти в man:ipnat[5].
-Такой же результат можно получить, выполнив вручную следующие команды:
+Базовая синтаксическая структура правила NAT выглядит следующим образом, где `map` начинает правило, а _IF_ следует заменить на имя внешнего интерфейса:
-[source,shell]
+[.programlisting]
....
-# ipfw -q -f flush
-# ipfw -q add check-state
-# ipfw -q add deny all from any to any frag
-# ipfw -q add deny tcp from any to any established
-# ipfw -q add allow tcp from any to any 80 out via tun0 setup keep-state
-# ipfw -q add allow tcp from any to 192.0.2.11 53 out via tun0 setup keep-state
-# ipfw -q add 00611 allow udp from any to 192.0.2.11 53 out via tun0 keep-state
+map IF LAN_IP_RANGE -> PUBLIC_ADDRESS
....
-==== Набор правил с сохранением состояния
+_LAN_IP_RANGE_ — это диапазон IP-адресов, используемых внутренними клиентами. Обычно это частный диапазон адресов, например `192.168.1.0/24`. _PUBLIC_ADDRESS_ может быть либо статическим внешним IP-адресом, либо ключевым словом `0/32`, которое представляет IP-адрес, назначенный _IF_.
-Следующий набор правил, не включающий в себя правила трансляции адресов NAT, является примером того, как создавать правила для межсетевого экрана закрытого типа высокого уровня защиты. Закрытый межсетевой экран разрешает трафик, описанный в разрешающих правилах, и по умолчанию блокирует всё остальное. Межсетевой экран, предназначенный для защиты сегментов сети, имеет как минимум два интерфейса, для которых должны быть написаны правила для работы межсетевого экрана.
+В IPF, когда пакет прибывает на межсетевой экран из локальной сети с публичным адресом назначения, он сначала проходит через исходящие правила набора правил межсетевого экрана. Затем пакет передается в набор правил NAT, который читается сверху вниз, и первое совпадающее правило применяется. IPF проверяет каждое правило NAT на соответствие имени интерфейса и исходному IP-адресу пакета. Когда имя интерфейса пакета совпадает с правилом NAT, исходный IP-адрес пакета в частной локальной сети проверяется на вхождение в диапазон IP-адресов, указанный в _LAN_IP_RANGE_. При совпадении исходный IP-адрес пакета перезаписывается публичным IP-адресом, указанным в _PUBLIC_ADDRESS_. IPF добавляет запись в свою внутреннюю таблицу NAT, чтобы при возврате пакета из Интернета он мог быть сопоставлен с исходным частным IP-адресом перед передачей в набор правил межсетевого экрана для дальнейшей обработки.
-Все разновидности операционных систем UNIX(R), включая FreeBSD, используют интерфейс [.filename]#lo0# и IP адрес `127.0.0.1` для передачи данных внутри операционной системы. Правила межсетевого экрана должны содержать в своем составе правила, разрешающие беспрепятственное прохождение трафика по этому интерфейсу.
+Для сетей с большим количеством внутренних систем или несколькими подсетями процесс перенаправления каждого частного IP-адреса в один публичный IP-адрес становится проблемой с точки зрения ресурсов. Доступны два метода для решения этой проблемы.
-Интерфейс, подключенный к Интернет, является местом для размещения правил авторизации и контроля доступа исходящих и входящих соединений. Это может быть туннельный интерфейс PPP [.filename]#tun0# или сетевой адаптер, подключенный к DSL или кабельному модему.
+Первый метод заключается в назначении диапазона портов для использования в качестве исходных портов. Добавление ключевого слова `portmap` позволяет указать NAT использовать только исходные порты из заданного диапазона:
-В случае, когда за межсетевым экраном один и более интерфейсов подсоединён к локальной сети, должны присутствовать правила для беспрепятственного прохождения исходящих пакетов с этих интерфейсов LAN.
+[.programlisting]
+....
+map dc0 192.168.1.0/24 -> 0/32 portmap tcp/udp 20000:60000
+....
-Правила изначально разделяются на три основных раздела: интерфейсы, не ограниченные правилами, правила для исходящего трафика на внешнем интерфейсе и правила для входящего трафика на внешнем интерфейсе.
+Или используйте ключевое слово `auto`, которое указывает NAT определить порты, доступные для использования:
-В каждом из разделов, относящихся к внешнему интерфейсу, правила должны быть упорядоченны по следующему принципу: наиболее используемые расположены в начале, наименее используемые - в конце. Последним должно идти правило блокирования и занесения в журнал информации о пакетах на этом интерфейсе, не попавших под предыдущие правила.
+[.programlisting]
+....
+map dc0 192.168.1.0/24 -> 0/32 portmap tcp/udp auto
+....
-Раздел, описывающий правила для исходящего трафика на внешнем интерфейсе, содержит только разрешающие правила `allow`, состоящие из значений фильтрации, которые однозначно определяют сервис, которому разрешен доступ в Интернет. Все правила включают в себя поля `proto`, `port`, `in/out`, `via` и `keep state`. Правила, содержащие `proto tcp`, имеют также параметр `setup`, который служит для определения начала сессии, которое в дальнейшем передается как условие срабатывания в динамическую таблицу.
+Второй метод заключается в использовании пула публичных адресов. Это полезно, когда количество локальных адресов слишком велико, чтобы уместиться в один публичный адрес, и доступен блок публичных IP-адресов. Эти публичные адреса могут использоваться как пул, из которого NAT выбирает IP-адрес для отображения адреса пакета при его выходе.
-В разделе, описывающем правила для входящего трафика на внешнем интерфейсе, в самом начале должны стоять правила, блокирующие нежелательные пакеты. Так должно быть по двум причинам. Первая состоит в том, что пакеты, сформированные злоумышленником, могут частично или полностью соответствовать разрешающим правилам `allow`. Вторая причина состоит в том, что заведомо не интересующие нас пакеты могут быть просто отклонены, вместо того, чтобы быть перехваченными и записанными в файл журнала по последнему правилу. Последнее правило в каждом разделе блокирует и регистрирует в журнале все пакеты и может быть использовано для юридических обоснований в ходе разбирательств против злоумышленников, атаковавших вашу систему.
+Диапазон публичных IP-адресов может быть указан с использованием маски сети или нотации CIDR. Эти два правила эквивалентны:
+
+[.programlisting]
+....
+map dc0 192.168.1.0/24 -> 204.134.75.0/255.255.255.0
+map dc0 192.168.1.0/24 -> 204.134.75.0/24
+....
-Также следует убедиться в том, что ваш сервер не отвечает ни на какие другие формы непредусмотренного трафика. Некорректные пакеты должны быть просто отброшены. В результате атакующие не получат информацию о том, достиг ли его пакет вашего сервера. Чем меньше атакующие будут знать о вашей системе, тем более она защищена. Назначение нераспознанного номера порта можно посмотреть в файле [.filename]#/etc/services/# или по адресу http://en.wikipedia.org/wiki/List_of_TCP_and_UDP_port_numbers[http://en.wikipedia.org/wiki/List_of_TCP_and_UDP_port_numbers]. Рекомендуем ознакомиться с содержимым ссылки относительно номеров портов, используемых троянами: http://www.sans.org/security-resources/idfaq/oddports.php[http://www.sans.org/security-resources/idfaq/oddports.php].
+Распространённой практикой является размещение общедоступного веб-сервера или почтового сервера в изолированном сегменте внутренней сети. Трафик с этих серверов всё равно проходит через NAT, но требуется перенаправление портов для направления входящего трафика на нужный сервер. Например, чтобы сопоставить веб-сервер с внутренним адресом `10.0.10.25` с его публичным IP-адресом `20.20.20.5`, используйте следующее правило:
-==== Пример правил для межсетевого экрана закрытого типа.
+[.programlisting]
+....
+rdr dc0 20.20.20.5/32 port 80 -> 10.0.10.25 port 80
+....
-Следующие правила, не включающие поддержку NAT, являются логически полным набором правил для межсетевого экрана закрытого типа. При использовании этого набора правил вы вполне можете быть уверены в безопасности вашей системы. Просто закомментируйте некоторые из правил `pass` для тех служб, которые вам не требуются. Чтобы избежать занесения в журнал нежелательных сообщений, добавьте правило `deny` в раздел, описывающий входящий трафик на интерфейсе. Замените название интерфейса [.filename]#dc0#, упоминающегося в правилах ниже, на название интерфейса (NIC), который соединяет вашу систему с глобальной сетью. Для PPP соединений это будет [.filename]#tun0#.
+Если это единственный веб-сервер, это правило также будет работать, так как оно перенаправляет все внешние HTTP-запросы на `10.0.10.25`:
-Примечание по использованию этих правил.
+[.programlisting]
+....
+rdr dc0 0.0.0.0/0 port 80 -> 10.0.10.25 port 80
+....
-* Все запросы начала сессии с внешней сетью используют параметр `keep-state`.
-* Все разрешенные сервисы внешней сети имеют параметр `limit` для защиты от флуда.
-* Все правила используют параметры `in` или `out` для указания направления трафика.
-* Все правила используют параметр `via` _имя-интерфейса_ для уточнения интерфейса, через который проходит пакет.
+В IPF встроен FTP-прокси, который можно использовать с NAT. Он отслеживает весь исходящий трафик на предмет запросов активных или пассивных FTP-соединений и динамически создает временные правила фильтрации, содержащие номер порта, используемого FTP-каналом данных. Это устраняет необходимость открывать большие диапазоны портов высокого порядка для FTP-соединений.
-Следующие правила записываются в [.filename]#/etc/ipfw.rules#.
+В этом примере первое правило вызывает прокси для исходящего FTP-трафика из внутренней локальной сети. Второе правило пропускает FTP-трафик из межсетевого экрана в Интернет, а третье правило обрабатывает весь не-FTP трафик из внутренней локальной сети:
[.programlisting]
....
-################ Начало файла с правилами IPFW ###############################
-# Сброс всех правил перед началом работы скрипта.
-ipfw -q -f flush
+map dc0 10.0.10.0/29 -> 0/32 proxy port 21 ftp/tcp
+map dc0 0.0.0.0/0 -> 0/32 proxy port 21 ftp/tcp
+map dc0 10.0.10.0/29 -> 0/32
+....
-# Префикс для создания правил
-cmd="ipfw -q add"
-pif="dc0" # название внешнего интерфейса,
- # принадлежащего глобальной сети
-
-#################################################################
-# Нет ограничений на внутреннем интерфейсе локальной сети
-# Нет необходимости в этом, если у вас нет локальной сети.
-# Замените xl0 на название интерфейса вашей локальной сети
-#################################################################
-#$cmd 00005 allow all from any to any via xl0
-
-#################################################################
-# Нет ограничений на интерфейсе Loopback
-#################################################################
-$cmd 00010 allow all from any to any via lo0
+Правила FTP `map` размещаются перед правилом NAT, так что при совпадении пакета с правилом FTP прокси-сервер FTP создает временные правила фильтрации, позволяющие пакетам FTP-сессии проходить и подвергаться NAT. Все пакеты из локальной сети, не относящиеся к FTP, не будут соответствовать правилам FTP, но подвергнутся NAT, если они соответствуют третьему правилу.
-#################################################################
-# Разрешить пакет, если он был ранее добавлен в "динамическую"
-# таблицу при помощи выражения allow keep-state
-#################################################################
-$cmd 00015 check-state
-
-#################################################################
-# Раздел правил для исходящего трафика на внешнем интерфейсе
-# Анализ запросов начала сессии, идущих из-за межсетевого экрана
-# в локальную сеть или от этого шлюза в интернет.
-#################################################################
-
-# Разрешить исходящий трафик к DNS серверу провайдера
-# x.x.x.x должен быть IP адресом DNS сервера вашего провайдера
-# Продублируйте эти строки, если у вас больше одного DNS сервера
-# Эти IP адреса можно взять из файла /etc/resolv.conf
-$cmd 00110 allow tcp from any to x.x.x.x 53 out via $pif setup keep-state
-$cmd 00111 allow udp from any to x.x.x.x 53 out via $pif keep-state
+Без FTP-прокси потребуются следующие правила межсетевого экрана. Обратите внимание, что без прокси необходимо разрешить все порты выше `1024`:
-# Разрешить исходящий трафик к DHCP серверу провайдера для cable/DSL конфигураций.
-# Это правило не нужно для .user ppp. соединений с глобальной сетью
-# в этом случае вы можете удалить эти правила.
-# Используйте это правило для записи необходимого нам IP адреса в лог-файл.
-# Затем укажите IP адрес в закомментированном правиле и удалите первое правило.
-$cmd 00120 allow log udp from any to any 67 out via $pif keep-state
-#$cmd 00120 allow udp from any to x.x.x.x 67 out via $pif keep-state
+[.programlisting]
+....
+# Allow out LAN PC client FTP to public Internet
+# Active and passive modes
+pass out quick on rl0 proto tcp from any to any port = 21 flags S keep state
-# Разрешить исходящий трафик для незащищенного www соединения
-$cmd 00200 allow tcp from any to any 80 out via $pif setup keep-state
+# Allow out passive mode data channel high order port numbers
+pass out quick on rl0 proto tcp from any to any port > 1024 flags S keep state
-# Разрешить исходящий трафик для защищенного www соединения
-# https с поддержкой TLS и SSL
-$cmd 00220 allow tcp from any to any 443 out via $pif setup keep-state
+# Active mode let data channel in from FTP server
+pass in quick on rl0 proto tcp from any to any port = 20 flags S keep state
+....
-# Разрешить исходящий POP/SMTP
-$cmd 00230 allow tcp from any to any 25 out via $pif setup keep-state
-$cmd 00231 allow tcp from any to any 110 out via $pif setup keep-state
+Всякий раз, когда редактируется файл, содержащий правила NAT, выполните `ipnat` с `-CF`, чтобы удалить текущие правила NAT и очистить содержимое таблицы динамической трансляции. Используйте `-f` и укажите имя набора правил NAT для загрузки:
-# Разрешить исходящий трафик для FreeBSD (make install & CVSUP)
-# По сути назначаем пользователю root полные привилегии.
-$cmd 00240 allow tcp from me to any out via $pif setup keep-state uid root
+[source, shell]
+....
+# ipnat -CF -f /etc/ipnat.rules
+....
-# Разрешаем исходящий icmp ping
-$cmd 00250 allow icmp from any to any out via $pif keep-state
+Для отображения статистики NAT:
-# Разрешаем исходящий трафик Time
-$cmd 00260 allow tcp from any to any 37 out via $pif setup keep-state
+[source, shell]
+....
+# ipnat -s
+....
-# Разрешаем исходящий трафик nntp news
-$cmd 00270 allow tcp from any to any 119 out via $pif setup keep-state
+Для отображения текущих сопоставлений таблицы NAT:
-# Разрешаем исходящий защищённый трафик FTP, Telnet и SCP
-# Эта функция использует SSH (secure shell)
-$cmd 00280 allow tcp from any to any 22 out via $pif setup keep-state
+[source, shell]
+....
+# ipnat -l
+....
-# Разрешаем исходящий трафик whois
-$cmd 00290 allow tcp from any to any 43 out via $pif setup keep-state
+Чтобы включить подробный режим и отображать информацию, связанную с обработкой правил, активными правилами и записями таблиц:
-# Запрещаем и заносим в журнал остальной исходящий трафик.
-# Обеспечивает политику межсетевого экрана закрытого типа
-$cmd 00299 deny log all from any to any out via $pif
+[source, shell]
+....
+# ipnat -v
+....
-#################################################################
-# Раздел правил для входящего трафика на внешнем интерфейсе
-# Анализ пакетов, приходящих из глобальной сети,
-# предназначенных для этого шлюза или локальной сети
-########################################################################
+=== Просмотр статистики IPF
-# Запрещаем весь входящий трафик с немаршрутизируемых сетей
-$cmd 00300 deny all from 192.168.0.0/16 to any in via $pif #RFC 1918 private IP
-$cmd 00301 deny all from 172.16.0.0/12 to any in via $pif #RFC 1918 private IP
-$cmd 00302 deny all from 10.0.0.0/8 to any in via $pif #RFC 1918 private IP
-$cmd 00303 deny all from 127.0.0.0/8 to any in via $pif #loopback
-$cmd 00304 deny all from 0.0.0.0/8 to any in via $pif #loopback
-$cmd 00305 deny all from 169.254.0.0/16 to any in via $pif #DHCP auto-config
-$cmd 00306 deny all from 192.0.2.0/24 to any in via $pif #reserved for docs
-$cmd 00307 deny all from 204.152.64.0/23 to any in via $pif #Sun cluster interconnect
-$cmd 00308 deny all from 224.0.0.0/3 to any in via $pif #Class D & E multicast
+В пакет IPF входит программа man:ipfstat[8], которую можно использовать для получения и отображения статистики, собираемой при совпадении пакетов с правилами при прохождении через межсетевой экран. Статистика накапливается с момента последнего запуска межсетевого экрана или с момента последнего сброса статистики в ноль с помощью команды `ipf -Z`.
-# Запрещаем пинг извне
-$cmd 00310 deny icmp from any to any in via $pif
+Вывод `ipfstat` по умолчанию выглядит следующим образом:
-# Запрещаем ident
-$cmd 00315 deny tcp from any to any 113 in via $pif
+[source, shell]
+....
+input packets: blocked 99286 passed 1255609 nomatch 14686 counted 0
+ output packets: blocked 4200 passed 1284345 nomatch 14687 counted 0
+ input packets logged: blocked 99286 passed 0
+ output packets logged: blocked 0 passed 0
+ packets logged: input 0 output 0
+ log failures: input 3898 output 0
+ fragment state(in): kept 0 lost 0
+ fragment state(out): kept 0 lost 0
+ packet state(in): kept 169364 lost 0
+ packet state(out): kept 431395 lost 0
+ ICMP replies: 0 TCP RSTs sent: 0
+ Result cache hits(in): 1215208 (out): 1098963
+ IN Pullups succeeded: 2 failed: 0
+ OUT Pullups succeeded: 0 failed: 0
+ Fastroute successes: 0 failures: 0
+ TCP cksum fails(in): 0 (out): 0
+ Packet log flags set: (0)
+....
-# Запрещаем все Netbios службы. 137=name, 138=datagram, 139=session
-# Netbios это MS/Windows сервис обмена.
-# Блокируем MS/Windows hosts2 запросы сервера имен на порту 81
-$cmd 00320 deny tcp from any to any 137 in via $pif
-$cmd 00321 deny tcp from any to any 138 in via $pif
-$cmd 00322 deny tcp from any to any 139 in via $pif
-$cmd 00323 deny tcp from any to any 81 in via $pif
+Доступно несколько вариантов. При указании `-i` для входящего или `-o` для исходящего трафика команда получит и отобразит соответствующий список правил фильтрации, установленных и используемых ядром. Чтобы также увидеть номера правил, добавьте `-n`. Например, `ipfstat -on` выводит таблицу исходящих правил с номерами:
-# Запрещаем любые опоздавшие пакеты
-$cmd 00330 deny all from any to any frag in via $pif
+[source, shell]
+....
+@1 pass out on xl0 from any to any
+@2 block out on dc0 from any to any
+@3 pass out quick on dc0 proto tcp/udp from any to any keep state
+....
-# Запрещаем ACK пакеты, которые не соответствуют динамической таблице правил.
-$cmd 00332 deny tcp from any to any established in via $pif
+Включите `-h`, чтобы добавить перед каждым правилом количество его совпадений. Например, `ipfstat -oh` выводит таблицу внутренних правил для исходящего трафика, добавляя перед каждым правилом количество его использований:
-# Разрешаем входящий трафик с DHCP сервера провайдера. Это правило
-# должно содержать IP адрес DHCP сервера вашего провайдера, поскольку
-# только ему разрешено отправлять пакеты данного типа. Необходимо только
-# для проводных и DSL соединений. Для 'user ppp' соединений с глобальной
-# сетью использовать это правило нет необходимости. Это тот же IP адрес,
-# выбранный и используемый вами в разделе правил для исходящего трафика.
-#$cmd 00360 allow udp from any to x.x.x.x 67 in via $pif keep-state
+[source, shell]
+....
+2451423 pass out on xl0 from any to any
+354727 block out on dc0 from any to any
+430918 pass out quick on dc0 proto tcp/udp from any to any keep state
+....
-# Разрешить входящий трафик для www, так как я использую сервер apache
-$cmd 00400 allow tcp from any to me 80 in via $pif setup limit src-addr 2
+Для отображения таблицы состояний в формате, аналогичном man:top[1], используйте `ipfstat -t`. Когда межсетевой экран подвергается атаке, эта опция позволяет идентифицировать и просматривать атакующие пакеты. Дополнительные подфлаги дают возможность выбора IP-адреса назначения или источника, порта или протокола для мониторинга в реальном времени. Подробности смотрите в man:ipfstat[8].
-# Разрешить входящий трафик безопасных FTP, Telnet и SCP из глобальной сети
-$cmd 00410 allow tcp from any to me 22 in via $pif setup limit src-addr 2
+=== Журналирование IPF
-# Разрешить входящий нешифрованный трафик Telnet из глобальной сети
-# считается небезопасным, потому что ID и PW передаются через глобальную
-# сеть в открытом виде.
-# Удалите этот шаблон, если вы не используете telnet.
-$cmd 00420 allow tcp from any to me 23 in via $pif setup limit src-addr 2
+IPF предоставляет `ipmon`, который может использоваться для записи информации журналирования межсетевого экрана в удобочитаемом формате. Для этого требуется сначала добавить `options IPFILTER_LOG` в собственное ядро, следуя инструкциям в crossref:kernelconfig[kernelconfig,Настройка ядра FreeBSD].
-# Отбрасываем и заносим в журнал все входящие соединения снаружи
-$cmd 00499 deny log all from any to any in via $pif
+Эта команда обычно запускается в режиме демона для обеспечения непрерывного ведения системного журнала, чтобы можно было просматривать записи о прошлых событиях. Поскольку FreeBSD имеет встроенное средство man:syslogd[8] для автоматической ротации системных журналов, параметр `ipmon_flags` по умолчанию в [.filename]#rc.conf# использует `-Ds`:
-# Всё остальное запрещено по умолчанию
-# Запрещаем и заносим в журнал все пакеты для дальнейшего анализа
-$cmd 00999 deny log all from any to any
-################ Конец файла правил IPFW ###############################
+[.programlisting]
....
+ipmon_flags="-Ds" # D = start as daemon
+ # s = log to syslog
+ # v = log tcp window, ack, seq
+ # n = map IP & port to names
+....
+
+Ведение журналов предоставляет возможность последующего просмотра информации, такой как: какие пакеты были отброшены, с каких адресов они пришли и куда направлялись. Эта информация полезна при отслеживании злоумышленников.
-==== Пример правил с сохранением состояний и поддержкой NAT
+После включения системы журналирования в [.filename]#rc.conf# и запуска с помощью `service ipmon start`, IPF будет записывать в журнал только те правила, которые содержат ключевое слово `log`. Администратор межсетевого экрана решает, какие правила из набора должны записываться в журнал, и обычно регистрируются только правила с deny. Обычно ключевое слово `log` включают в последнее правило набора. Это позволяет увидеть все пакеты, которые не соответствуют ни одному из правил набора.
+
+По умолчанию режим `ipmon -Ds` использует `local0` как средство ведения журнала. Для дальнейшего разделения регистрируемых данных можно использовать следующие уровни ведения журнала:
+
+[source, shell]
+....
+LOG_INFO - packets logged using the "log" keyword as the action rather than pass or block.
+LOG_NOTICE - packets logged which are also passed
+LOG_WARNING - packets logged which are also blocked
+LOG_ERR - packets which have been logged and which can be considered short due to an incomplete header
+....
-Здесь перечислены некоторые дополнительные конфигурационные параметры, которые нужно включить, чтобы активировать функцию NAT в IPFW. В файл конфигурации ядра к остальным параметрам IPFIREWALL нужно добавить строку `option IPDIVERT`.
+Чтобы настроить IPF для записи всех данных в [.filename]#/var/log/ipfilter.log#, сначала создайте пустой файл:
-В дополнение к обычным параметрам IPFW в [.filename]#/etc/rc.conf# добавим следующее:
+[source, shell]
+....
+# touch /var/log/ipfilter.log
+....
+
+Затем, чтобы записывать все журналируемые сообщения в указанный файл, добавьте следующую строку в [.filename]#/etc/syslog.conf#:
[.programlisting]
....
-natd_enable="YES" # Включить функцию NATD
-natd_interface="rl0" # Название внешнего сетевого интерфейса
-natd_flags="-dynamic -m" # -m = по возможности сохранить номера портов
+local0.* /var/log/ipfilter.log
....
-Использование динамических правил с правилом `divert natd` (Network Address Translation) значительно затрудняет логику составления правил. Расположение `check-state` и `divert natd` в таблице правил влияет на поведение межсетевого экрана. Это уже не просто последовательный логический поток. При применении вышеозначенных параметров становится доступным новый тип действия `skipto`. При использовании `skipto` нумерация правил становится обязательной. В качестве аргумента `skipto` используется номер правила, к которому нужно перейти.
+Для активации изменений и указания man:syslogd[8] прочитать изменённый файл [.filename]#/etc/syslog.conf#, выполните команду `service syslogd reload`.
+
+Не забудьте отредактировать [.filename]#/etc/newsyslog.conf# для ротации нового файла журнала.
+
+Сообщения, генерируемые `ipmon`, состоят из полей данных, разделённых пробелами. Общие для всех сообщений поля:
+
+. The date of packet receipt.
+. Время получения пакета. Указывается в формате ЧЧ:ММ:СС.Д, где ЧЧ - часы, ММ - минуты, СС - секунды, а Д - доли секунды.
+. Имя интерфейса, обработавшего пакет.
+. Группа и номер правила в формате `@0:17`.
+. Действие: `p` — пропущено, `b` — заблокировано, `S` — короткий пакет, `n` — не совпало ни с одним правилом, `L` — правило для журналирования.
+. Адреса записываются в виде трёх полей: исходный адрес и порт, разделённые запятой, символ `->` и адрес назначения с портом. Например: `209.53.17.22,80 -> 198.73.220.17,1722`.
+. `PR` с указанием имени или номера протокола: например, `PR tcp`.
+. `len`, за которым следует длина заголовка и общая длина пакета: например, `len 20 40`.
+
+Если пакет является TCP-пакетом, будет дополнительное поле, начинающееся с дефиса, за которым следуют буквы, соответствующие установленным флагам. Список букв и соответствующих флагов приведен в man:ipf[5].
+
+Если пакет является ICMP-пакетом, в конце будут два поля: первое всегда `icmp`, а следующее — тип ICMP-сообщения и подтип, разделённые косой чертой. Например: `icmp 3/3` для сообщения о недоступности порта.
-Ниже последует пример метода кодирования, не снабженный комментариями, приведенный здесь для внесения ясности относительно последовательности прохождения пакетов через набор правил.
+[[firewalls-blacklistd]]
+== Blacklistd
-Обработка правил начинается с первого по счету и идет последовательно, по правилу за раз, до достижения конца файла, либо если проверяемый пакет соответствует критериям фильтрации; в последнем случае пакет покидает межсетевой экран. Для правил под номерами 100, 101, 450, 500 и 510 важен порядок их расположения. Эти правила управляют трансляцией исходящих и входящих пакетов, таким образом в таблицу keep-state заносятся только приватные IP адреса локальной сети. Обратите внимание, что все правила allow и deny указывают направление, по которому передается пакет (исходящее или входящее) и сетевой интерфейс. Также стоит отметить, что все запросы начала исходящей сессии передаются с использованием `skipto rule 500` для трансляции адресов.
+Blacklistd — это демон, который прослушивает сокеты, ожидая получения уведомлений от других демонов о неудачных или успешных попытках подключения. Он наиболее широко используется для блокировки чрезмерного количества попыток подключения к открытым портам. Типичный пример — SSH, работающий в интернете и получающий множество запросов от ботов или скриптов, пытающихся угадать пароли и получить доступ. Используя blacklistd, демон может уведомить межсетевой экран о необходимости создания правила фильтрации для блокировки чрезмерных попыток подключения с одного источника после нескольких попыток. Blacklistd был первоначально разработан в NetBSD и появился там в версии 7. FreeBSD 11 импортировал blacklistd из NetBSD.
-Предположим, что пользователь локальной сети запрашивает страницу через браузер. Веб-страницы передаются по порту 80. Пакет входит в межсетевой экран. Этот пакет не попадает под правило 100, потому что в критериях фильтрации этого правила указан параметр `in`. Этот пакет не попадает под правило 101, потому что это первый пакет сессии и он еще не был занесен в динамическую таблицу keep-state. Достигнув, наконец, правила 125, пакет удовлетворяет всем критериям фильтрации. Этот пакет является выходящим из интерфейса, взаимодействующим с глобальной сетью. На данном этапе у пакета в качестве исходящего адреса всё еще указан приватный IP адрес локальной сети. По условию этого правила к пакету применяются два действия. Параметр `keep-state` создаст новую запись в динамической таблице keep-state, и выполнится действие, указанное в правиле. Указанное действие является частью информации, заносимой в динамическую таблицу. В данном случае это `skipto rule 500`. Правило 500 транслирует (NAT) адреса пакета и отпускает его наружу. Данное замечание очень важно. Этот пакет идет к цели, где генерируется ответный пакет и отправляется обратно. Этот новый пакет входит в начало списка правил. На этот раз пакет соответствует правилу 100 и его IP адрес назначения транслируется обратно на соответствующий IP адрес локальной сети. Затем он обрабатывается правилом `check-state`, и поскольку для него уже присутствует в динамической таблице правило, соответствующее данной сессии, пакет пропускается в локальную сеть. Дальше пакет приходит к отправившему его компьютеру локальной сети, и генерируется новый пакет, запрашивающий новую порцию данных с удаленного сервера. На этот раз пакет сразу проверяется правилом `check-state`, и в случае присутствия исходящей записи данного пакета выполняется действие `skipto 500`. Пакет переходит к правилу 500, транслируется и пропускается во внешнюю сеть.
+В этой главе описывается, как настроить blacklistd, его конфигурация, а также приводятся примеры использования. Читатели должны быть знакомы с основными концепциями межсетевого экрана, такими как правила. Подробности см. в главе о межсетевом экране. В примерах используется PF, но другие межсетевые экраны, доступные в FreeBSD, также должны работать с blacklistd.
-Для входящего трафика все пакеты, являющиеся частью уже установленной сессии, автоматически разбираются правилом `check-state` и правильно расположенными правилами `divert natd`. Всё, что нам остается сделать, это запретить все плохие пакеты и разрешить прохождение внутрь сети пакетов только для разрешенных сервисов. Допустим, на сервере с межсетевым экраном запущен apache, и мы хотим разрешить людям из глобальной сети доступ на локальный веб-сайт. Новый входящий пакет, запрашивающий начало сессии, соответствует правилу 100, и его IP адрес транслируется как локальный IP системы с межсетевым экраном. Далее пакет проверяется на соответствие вредоносному трафику и в случае отсутствия соответствия попадает на правило 425. В случае соответствия данному правилу происходят две вещи. Пакет правил помещается в динамическую таблицу keep-state, но в этот раз любая новая сессия запросов, порожденных с этого IP, ограничена 2 одновременными соединениями. Это защищает от перегрузки сервис, работающей по указанному номеру порта. В качестве действия в правиле указан `allow`, следовательно пакет пропускается в локальную сеть. Пакет, сформированный в качестве ответа, попадает под `check-state` и распознается им как принадлежащий существующей сессии. Далее он передаётся на правило 500, где происходит обратная трансляция, после чего пакет пропускается на внешний интерфейс.
+=== Включение blacklistd
-Пример файла правил #1:
+Основная конфигурация для blacklistd хранится в man:blacklistd.conf[5]. Также доступны различные параметры командной строки для изменения поведения blacklistd во время выполнения. Постоянная конфигурация, сохраняемая после перезагрузок, должна храниться в [.filename]#/etc/blacklistd.conf#. Чтобы включить демон во время загрузки системы, добавьте строку `blacklistd_enable` в [.filename]#/etc/rc.conf# следующим образом:
+
+[source, shell]
+....
+# sysrc blacklistd_enable=yes
+....
+
+Чтобы запустить службу вручную, выполните следующую команду:
+
+[source, shell]
+....
+# service blacklistd start
+....
+
+=== Создание набора правил для blacklistd
+
+Правила для blacklistd настраиваются в man:blacklistd.conf[5], по одному правилу на строку. Каждое правило содержит кортеж, разделённый пробелами или табуляциями. Правила относятся либо к `local`, либо к `remote`, что применяется соответственно к машине, на которой работает blacklistd, или к внешнему источнику.
+
+==== Правила local
+
+Пример записи в blacklistd.conf для локального правила выглядит следующим образом:
[.programlisting]
....
-#!/bin/sh
-cmd="ipfw -q add"
-skip="skipto 500"
-pif=rl0
-ks="keep-state"
-good_tcpo="22,25,37,43,53,80,443,110,119"
+[local]
+ssh stream * * * 3 24h
+....
-ipfw -q -f flush
+Все правила, следующие за разделом `[local]`, рассматриваются как локальные правила (что является значением по умолчанию) и применяются к локальной машине. При обнаружении раздела `[remote]` все последующие правила обрабатываются как правила для удалённых машин.
-$cmd 002 allow all from any to any via xl0 # разрешаем трафик на локальном интерфейсе
-$cmd 003 allow all from any to any via lo0 # разрешаем трафик на интерфейсе loopback
+Семь полей, разделённых табуляцией или пробелами, определяют правило. Первые четыре поля идентифицируют трафик, который должен быть внесён в чёрный список. Следующие три поля определяют поведение backlistd. Подстановочные символы обозначаются звёздочками (`*`), которые соответствуют любому значению в данном поле. Первое поле определяет местоположение. В локальных правилах это сетевые порты. Синтаксис для поля местоположения следующий:
-$cmd 100 divert natd ip from any to any in via $pif
-$cmd 101 check-state
+[.programlisting]
+....
+[address|interface][/mask][:port]
+....
-# Разрешенные исходящие пакеты
-$cmd 120 $skip udp from any to xx.168.240.2 53 out via $pif $ks
-$cmd 121 $skip udp from any to xx.168.240.5 53 out via $pif $ks
-$cmd 125 $skip tcp from any to any $good_tcpo out via $pif setup $ks
-$cmd 130 $skip icmp from any to any out via $pif $ks
-$cmd 135 $skip udp from any to any 123 out via $pif $ks
+Адреса могут быть указаны в виде IPv4 в числовом формате или IPv6 в квадратных скобках. Также можно использовать имя интерфейса, например `_em0_`.
-# Запрещаем весь входящий трафик с немаршрутизируемых адресных пространств
-$cmd 300 deny all from 192.168.0.0/16 to any in via $pif #RFC 1918 для локальных IP
-$cmd 301 deny all from 172.16.0.0/12 to any in via $pif #RFC 1918 для локальных IP
-$cmd 302 deny all from 10.0.0.0/8 to any in via $pif #RFC 1918 для локальных IP
-$cmd 303 deny all from 127.0.0.0/8 to any in via $pif #loopback
-$cmd 304 deny all from 0.0.0.0/8 to any in via $pif #loopback
-$cmd 305 deny all from 169.254.0.0/16 to any in via $pif #DHCP авто-конфигурации
-$cmd 306 deny all from 192.0.2.0/24 to any in via $pif #Зарезервировано для документации
-$cmd 307 deny all from 204.152.64.0/23 to any in via $pif #Sun cluster
-$cmd 308 deny all from 224.0.0.0/3 to any in via $pif #Class D & E multicast
+Тип сокета определяется вторым полем. TCP-сокеты имеют тип `stream`, тогда как UDP обозначается как `dgram`. В приведённом выше примере используется TCP, так как SSH работает по этому протоколу.
-# Разрешаем входящие пакеты
-$cmd 400 allow udp from xx.70.207.54 to any 68 in $ks
-$cmd 420 allow tcp from any to me 80 in via $pif setup limit src-addr 1
+Протокол может быть указан в третьем поле правила blacklistd. Доступны следующие протоколы: `tcp`, `udp`, `tcp6`, `udp6` или числовое значение. Подстановочный символ, как в примере, обычно используется для соответствия всем протоколам, если нет необходимости различать трафик по определённому протоколу.
-$cmd 450 deny log ip from any to any
+В четвёртом поле определяется эффективный пользователь или владелец процесса демона, который сообщает о событии. Здесь можно использовать имя пользователя или UID, а также подстановочный знак (см. пример правила выше).
-# Раздел skipto для правил с сохранением состояния для исходящих пакетов
-$cmd 500 divert natd ip from any to any out via $pif
-$cmd 510 allow ip from any to any
+Имя правила фильтра пакетов объявляется пятым полем, которое начинает поведенческую часть правила. По умолчанию, blacklistd помещает все блокировки в якорь pf под названием `blacklistd` в [.filename]#pf.conf# следующим образом:
-######################## Окончание файла правил ##################
+[.programlisting]
+....
+anchor "blacklistd/*" in on $ext_if
+block in
+pass out
....
-Следующий пример во многом повторяет то, что приведено выше, но использует самодокументирующий стиль записи с исчерпывающими комментариями для того, чтобы помочь начинающему составителю правил IPFW лучше понимать, для чего предназначено то или иное правило.
+Для отдельных списков блокировки в этом поле можно использовать имя якоря. В остальных случаях подойдет подстановочный знак. Если имя начинается с дефиса (`-`), это означает, что следует использовать якорь с добавленным именем правила по умолчанию. Модифицированный пример из вышеприведенного с использованием дефиса будет выглядеть так:
-Пример файла правил #2:
+[.programlisting]
+....
+ssh stream * * -ssh 3 24h
+....
+
+С таким правилом любые новые правила из списка блокировки добавляются к якорю с именем `blacklistd-ssh`.
+
+Для блокировки целых подсетей за одно нарушение правила можно использовать символ `/` в имени правила. Это приводит к тому, что оставшаяся часть имени интерпретируется как маска, применяемая к адресу, указанному в правиле. Например, это правило заблокирует все адреса, входящие в подсеть `/24`.
[.programlisting]
....
-#!/bin/sh
-################ Начало файла правил IPFW ###############################
-# Сброс всех правил перед началом работы скрипта.
-ipfw -q -f flush
+22 stream tcp * */24 3 24h
+....
-# Задание стандартных переменных
-cmd="ipfw -q add"
-skip="skipto 800"
-pif="rl0" # название внешнего интерфейса,
- # принадлежащего глобальной сети
-
-#################################################################
-# Нет ограничений на внутреннем интерфейсе локальной сети
-# Замените xl0 на название интерфейса вашей локальной сети
-#################################################################
-$cmd 005 allow all from any to any via xl0
-
-#################################################################
-# Нет ограничений на интерфейсе Loopback
-#################################################################
-$cmd 010 allow all from any to any via lo0
-
-#################################################################
-# Трансляция адреса, если пакет является входящим
-#################################################################
-$cmd 014 divert natd ip from any to any in via $pif
-
-#################################################################
-# Разрешить пакет, если он был ранее добавлен в динамическую
-# таблицу при помощи выражения allow keep-state
-#################################################################
-$cmd 015 check-state
-
-#################################################################
-# Раздел правил для исходящего трафика на внешнем интерфейсе
-# Анализ запросов начала сессии, идущих из-за межсетевого экрана
-# в локальную сеть или от этого шлюза в интернет.
-#################################################################
-
-# Разрешить исходящий трафик к DNS серверу провайдера
-# x.x.x.x должен быть IP адресом DNS сервера вашего провайдера
-# Продублируйте эти строки, если у вас больше одного DNS сервер
-# Эти IP адреса можно взять из файла /etc/resolv.conf
-$cmd 020 $skip tcp from any to x.x.x.x 53 out via $pif setup keep-state
-
-# Разрешить исходящий трафик к DHCP серверу провайдера для cable/DSL конфигураций.
-$cmd 030 $skip udp from any to x.x.x.x 67 out via $pif keep-state
-
-# Разрешить исходящий трафик для незащищенного www соединения
-$cmd 040 $skip tcp from any to any 80 out via $pif setup keep-state
-
-# Разрешить исходящий трафик для защищенного www соединения
-# https с поддержкой TLS и SSL
-$cmd 050 $skip tcp from any to any 443 out via $pif setup keep-state
-
-# Разрешить исходящий POP/SMTP
-$cmd 060 $skip tcp from any to any 25 out via $pif setup keep-state
-$cmd 061 $skip tcp from any to any 110 out via $pif setup keep-state
-
-# Разрешить исходящий трафик для FreeBSD (make install & CVSUP)
-# По сути назначаем пользователю root полные привилегии.
-$cmd 070 $skip tcp from me to any out via $pif setup keep-state uid root
-
-# Разрешаем исходящий icmp ping
-$cmd 080 $skip icmp from any to any out via $pif keep-state
-
-# Разрешаем исходящий трафик Time
-$cmd 090 $skip tcp from any to any 37 out via $pif setup keep-state
-
-# Разрешаем исходящий трафик nntp news (т.е. news groups)
-$cmd 100 $skip tcp from any to any 119 out via $pif setup keep-state
-
-# Разрешаем исходящий защищённый трафик FTP, Telnet и SCP
-# Эта функция использует SSH (secure shell)
-$cmd 110 $skip tcp from any to any 22 out via $pif setup keep-state
-
-# Разрешаем исходящий трафик whois
-$cmd 120 $skip tcp from any to any 43 out via $pif setup keep-state
-
-# Разрешаем исходящий трафик ntp
-$cmd 130 $skip udp from any to any 123 out via $pif keep-state
-
-#################################################################
-# Раздел правил для входящего трафика на внешнем интерфейсе
-# Анализ пакетов, приходящих из глобальной сети,
-# предназначенных для этого шлюза или локальной сети
-#################################################################
-
-# Запрещаем весь входящий трафик с немаршрутизируемых сетей
-$cmd 300 deny all from 192.168.0.0/16 to any in via $pif #RFC 1918 private IP
-$cmd 301 deny all from 172.16.0.0/12 to any in via $pif #RFC 1918 private IP
-$cmd 302 deny all from 10.0.0.0/8 to any in via $pif #RFC 1918 private IP
-$cmd 303 deny all from 127.0.0.0/8 to any in via $pif #loopback
-$cmd 304 deny all from 0.0.0.0/8 to any in via $pif #loopback
-$cmd 305 deny all from 169.254.0.0/16 to any in via $pif #DHCP auto-config
-$cmd 306 deny all from 192.0.2.0/24 to any in via $pif #reserved for docs
-$cmd 307 deny all from 204.152.64.0/23 to any in via $pif #Sun cluster
-$cmd 308 deny all from 224.0.0.0/3 to any in via $pif #Class D & E multicast
-
-# Запрещаем ident
-$cmd 315 deny tcp from any to any 113 in via $pif
-
-# Запрещаем все Netbios службы. 137=name, 138=datagram, 139=session
-# Netbios это MS/Windows сервис обмена.
-# Блокируем MS/Windows hosts2 запросы сервера имен на порту 81
-$cmd 320 deny tcp from any to any 137 in via $pif
-$cmd 321 deny tcp from any to any 138 in via $pif
-$cmd 322 deny tcp from any to any 139 in via $pif
-$cmd 323 deny tcp from any to any 81 in via $pif
-
-# Запрещаем любые опоздавшие пакеты
-$cmd 330 deny all from any to any frag in via $pif
-
-# Запрещаем ACK пакеты, которые не соответствуют динамической таблице правил.
-$cmd 332 deny tcp from any to any established in via $pif
-
-# Разрешаем входящий трафик с DHCP сервера провайдера. Это правило
-# должно содержать IP адрес DHCP сервера вашего провайдера, поскольку
-# только ему разрешено отправлять пакеты данного типа. Необходимо только
-# для проводных и DSL соединений. Для 'user ppp' соединений с глобальной
-# сетью использовать это правило нет необходимости. Это тот же IP адрес,
-# выбранный и используемый вами в разделе правил для исходящего трафика.
-$cmd 360 allow udp from x.x.x.x to any 68 in via $pif keep-state
-
-# Разрешить входящий трафик для www, т.к. я использую Apache сервер.
-$cmd 370 allow tcp from any to me 80 in via $pif setup limit src-addr 2
-
-# Разрешить входящий трафик безопасных FTP, Telnet и SCP из глобальной сети
-$cmd 380 allow tcp from any to me 22 in via $pif setup limit src-addr 2
-
-# Разрешить входящий нешифрованный трафик Telnet из глобальной сети
-# считается небезопасным, потому что ID и PW передаются через глобальную
-# сеть в открытом виде.
-# Удалите этот шаблон, если вы не используете telnet.
-$cmd 390 allow tcp from any to me 23 in via $pif setup limit src-addr 2
-
-# Отбрасываем и заносим в журнал все неразрешенные входящие соединения из глобальной сети
-$cmd 400 deny log all from any to any in via $pif
-
-# Отбрасываем и заносим в журнал все неразрешенные исходящие соединения в глобальную сеть
-$cmd 450 deny log all from any to any out via $pif
-
-# Место для skipto в правилах с сохранением состояния для исходящих соединений
-$cmd 800 divert natd ip from any to any out via $pif
-$cmd 801 allow ip from any to any
-
-# Всё остальное запрещено по умолчанию
-# Запрещаем и заносим в журнал все пакеты для дальнейшего анализа
-$cmd 999 deny log all from any to any
-################ Окончание файла правил IPFW ###############################
+[NOTE]
+====
+Здесь важно указать правильный протокол. IPv4 и IPv6 обрабатывают /24 по-разному, поэтому `*` нельзя использовать в третьем поле для этого правила.
+====
+
+Это правило определяет, что если любой хост в этой сети ведёт себя неправильно, всё остальное в этой сети также будет заблокировано.
+
+Шестое поле, называемое `nfail`, устанавливает количество неудачных попыток входа, необходимых для внесения IP-адреса внешнего хоста в чёрный список. Если в этой позиции используется подстановочный знак, это означает, что блокировки никогда не будут происходить. В приведённом выше примере правила установлен лимит в три попытки, что означает, что после трёх попыток входа через SSH с одного соединения IP-адрес будет заблокирован.
+
+Последнее поле в определении правила blacklistd указывает, как долго хост будет находиться в чёрном списке. По умолчанию единицей измерения являются секунды, но также можно указать суффиксы `m`, `h` и `d` для минут, часов и дней соответственно.
+
+Пример правила в полном объеме означает, что после трех попыток аутентификации по SSH будет создано новое правило блокировки PF для этого хоста. Совпадения правил проверяются путем последовательной проверки локальных правил от наиболее специфичных к наименее специфичным. Когда совпадение найдено, применяются правила `remote`, а поля `name`, `nfail` и `disable` изменяются в соответствии с совпавшим правилом `remote`.
+
+==== Правила remote
+
+Удалённые правила используются для указания того, как blacklistd изменяет своё поведение в зависимости от удалённого хоста, который в данный момент оценивается. Каждое поле в удалённом правиле совпадает с таковым в локальном правиле. Единственное различие заключается в том, как blacklistd их использует. Для объяснения используется следующее примерное правило:
+
+[.programlisting]
....
+[remote]
+203.0.113.128/25 * * * =/25 = 48h
+....
+
+Поле `address` может содержать IP-адрес (как v4, так и v6), порт или оба варианта. Это позволяет задавать специальные правила для определённого диапазона удалённых адресов, как в этом примере. Поля для типа сокета, протокола и владельца интерпретируются так же, как в локальном правиле.
+
+Поле name отличается: знак равенства (`=`) в удаленном правиле указывает blacklistd использовать значение из соответствующего локального правила. Это означает, что запись правила межсетевого экрана берется, и добавляется префикс `/25` (маска сети `255.255.255.128`). Когда соединение из этого диапазона адресов попадает в черный список, затрагивается вся подсеть. Здесь также можно использовать имя якоря PF, и в этом случае blacklistd добавит правила для этого блока адресов в якорь с указанным именем. Если указана подстановка, используется таблица по умолчанию.
+
+В столбце `nfail` можно задать произвольное количество неудачных попыток для адреса. Это полезно для исключений из конкретного правила, например, чтобы разрешить кому-то менее строгое применение правил или немного больше попыток входа. Блокировка отключается, если в шестом поле указана звёздочка.
+
+Удаленные правила позволяют более строго ограничивать попытки входа по сравнению с попытками, поступающими из локальной сети, например, из офиса.
+
+=== Конфигурация клиента blacklistd
+
+В FreeBSD есть несколько программных пакетов, которые могут использовать функциональность blacklistd. Два наиболее заметных — это man:ftpd[8] и man:sshd[8], предназначенные для блокировки чрезмерных попыток подключения. Чтобы активировать blacklistd в демоне SSH, добавьте следующую строку в [.filename]#/etc/ssh/sshd_config#:
+
+[.programlisting]
+....
+UseBlacklist yes
+....
+
+Перезапустите sshd, чтобы изменения вступили в силу.
+
+Черный список для man:ftpd[8] включается с помощью `-B`, либо в [.filename]#/etc/inetd.conf#, либо как флаг в [.filename]#/etc/rc.conf# следующим образом:
+
+[.programlisting]
+....
+ftpd_flags="-B"
+....
+
+Вот и всё, что требуется для настройки взаимодействия этих программ с blacklistd.
+
+=== Управление blacklistd
+
+Blacklistd предоставляет пользователю утилиту управления под названием man:blacklistctl[8]. Она отображает заблокированные адреса и сети, которые внесены в список блокировки согласно правилам, определённым в man:blacklistd.conf[5]. Чтобы просмотреть список текущих заблокированных хостов, используйте команду `dump` с параметром `-b`, например.
+
+[source, shell]
+....
+# blacklistctl dump -b
+ address/ma:port id nfail last access
+213.0.123.128/25:22 OK 6/3 2019/06/08 14:30:19
+....
+
+Этот пример показывает, что было 6 попыток из трёх разрешённых на порт 22, исходящих из диапазона адресов `213.0.123.128/25`. Количество попыток превышает разрешённое, потому что SSH позволяет клиенту выполнять несколько попыток входа в рамках одного TCP-соединения. Текущее соединение не прерывается blacklistd. Последняя попытка соединения указана в столбце `last access` вывода.
+
+Чтобы увидеть оставшееся время, в течение которого этот хост будет в списке блокировки, добавьте `-r` к предыдущей команде.
+
+[source, shell]
+....
+# blacklistctl dump -br
+ address/ma:port id nfail remaining time
+213.0.123.128/25:22 OK 6/3 36s
+....
+
+В этом примере осталось 36 секунд, пока этот хост не будет разблокирован.
+
+=== Удаление узлов из списка блокировки
+
+Иногда необходимо удалить узел из чёрного списка до истечения оставшегося времени. К сожалению, в blacklistd нет функциональности для этого. Однако можно удалить адрес из таблицы PF с помощью pfctl. Для каждого заблокированного порта существует дочерний якорь внутри якоря blacklistd, определённого в [.filename]#/etc/pf.conf#. Например, если есть дочерний якорь для блокировки порта 22, он называется `blacklistd/22`. Внутри этого дочернего якоря находится таблица, содержащая заблокированные адреса. Эта таблица называется port с указанием номера порта. В данном примере она будет называться `port22`. Имея эту информацию, можно использовать man:pfctl[8] для отображения всех перечисленных адресов следующим образом:
+
+[source, shell]
+....
+# pfctl -a blacklistd/22 -t port22 -T show
+...
+213.0.123.128/25
+...
+....
+
+После определения адреса, который нужно разблокировать из списка, следующая команда удаляет его из списка:
+
+[source, shell]
+....
+# pfctl -a blacklistd/22 -t port22 -T delete 213.0.123.128/25
+....
+
+Адрес теперь удалён из PF, но всё ещё будет отображаться в списке blacklistctl, так как он не знает о внесённых в PF изменениях. Запись в базе данных blacklistd со временем истечёт и будет удалена из вывода. Запись будет добавлена снова, если хост снова совпадёт с одним из правил блокировки в blacklistd.