OpenBSD PF - Anchors (привязанные правила) [FAQ PF - На главную]



Введение

Помимо основного набора правил, PF может применить и наборы подправил (sub-rulesets). Поскольку этими подравилами можно управлять на лету при помощи pfctl(8), они предоставляют удобный способ динамического изменения активного набора правил. В то время как таблицы используются для хранения динамического списка адресов, наборы подправил используются для хранения динамического комплекта правил. Наборы подправил прикреплены (attached) к основному набору правил посредством anchor.

Anchor'ы могут быть вложенными, что позволяет объединять подгуппы правил. Anchor'ные правила будут оцениваться относительно anchor'а, в который они загружены. Например, anchor'ные правила в основном наборе правил будут создавать точки привязки (attachment points) с основным набором правил как родительскими, а anchor'ные правила, загруженные из файлов при помощи директивы load anchor создадут anchor'ные точки с этим anchor'ом как c родительским.

Anchor'ы

Anchor представляет из себя набор правил, таблиц и других anchor'ов, которым были назначены имена. Когда PF проходит через anchor правило в основном наборе правил, он обрабатывает правила внутри точки anchor'а как если бы он обрабатывал правила из основного набора правил. Обработка затем продолжится в основном наборе правил до тех пор, пока пакет не попадёт под действие правила фильтра, который использует опцию quick. В этом случае совпадение будет считаться финальным и PF прекратит оценку правил как в anchor'е так и в основном наборе правил.

Например:

block on     egress
pass  out on egress

anchor goodguys
Этот набор правил устанавливает политику блокировки (deny policy) по умолчанию на ergress интерфейс для входящего и исходящего трафика, который затем передается с сохранением состояния, и создаётся anchor'ное правило с именем goodguys. Anchor'ы могут быть заполнены тремя способами: Правило load заставляет pfctl заполнять указанный anchor путем чтения правил из текстового файла. Правило load должно быть размещено после anchor правила.

Пример:

anchor goodguys
load anchor goodguys from "/etc/anchor-goodguys-ssh"
Вот так можно добавить правила к anchor'у при помощи pfctl:
# echo "pass in proto tcp from 192.0.2.3 to any port 22" | pfctl -a goodguys -f -
Правила также можно сохранять в текстовом файле (и загружать из него). Например, добавить следующие две строки в файл /etc/anchor-goodguys-www:
pass in proto tcp from 192.0.2.3 to any port 80
pass in proto tcp from 192.0.2.4 to any port { 80 443 }
При помощи этой команды изменения вступят в силу:
# pfctl -a goodguys -f /etc/anchor-goodguys-www
Чтобы загрузить правила непосредственно из основного набора правил, поместите anchor-правила в блок с фигурными скобками:
anchor "goodguys" {
        pass in proto tcp from 192.168.2.3 to port 22
}
Встроенные (inline) anchor'ы также могут содержать (свои вложенные) anchor'ы.
allow = "{ 192.0.2.3 192.0.2.4 }"

anchor "goodguys" {
  anchor {
       pass in proto tcp from 192.0.2.3 to port 80
  }
  pass in proto tcp from $allow to port 22
}
В случае использования встроенного anchor'а его имя становится необязательным. Обратите внимание на то, что вложенная привязка в приведенном выше примере не имеет имени. Макрос $allow создается вне anchor'а (в основном наборе правил) и затем используется внутри anchor'а.

Правила могут быть загружены в anchor при помощи того же синтаксиса и опций, что и правила, загруженные в основной набор правил. Одно предостережение заключается в том, что, если не используются встроенные anchor-привязки, любые используемые макросы также должны быть определены в самой anchor-привязке. Макросы, определенные в родительском наборе правил, не видны из anchor-привязки.

Поскольку anchor'ы могут быть вложенными, можно указать, что все дочерние anchor'ы должны обрабатываться в указанном anchor'е:

anchor "spam/*"
Этот синтаксис вызывает оценку каждого правила в каждом anchor'е, прикрепленном к anchor'у spam. Дочерние anchor'ы будут обрабатываться в алфавитном порядке, но не будут рекурсивными. Anchor'ы всегда оцениваются относительно anchor'а, в котором они определены.

Каждый anchor, а также основной набор правил, существуют отдельно от других наборов правил. Операции, выполняемые с одним набором правил, такие как очистка правил, не влияют ни на какие другие. Кроме того, удаление anchor-точки из основного набора правил не приводит к уничтожению anchor'а или любых дочерних anchor'ов, прикрепленных к нему. Anchor не уничтожается, пока он не будет очищен от всех правил при помощи pfctl(8), и в нем не будет дочерних anchor'ов.

Возможности anchor'ов

При желании правила anchor могут указывать интерфейс, протокол, адрес источника и назначения, тег, и т.д., используя тот же синтаксис, что и другие правила. Когда предоставляется такая информация, anchor правила обрабатываются только в том случае, если пакет соответствует указаной информации.

Например:

block          on egress
pass       out on egress
anchor ssh in  on egress proto tcp to port 22
Правила в anchor'е ssh обрабатываются только для TCP-пакетов, предназначенных для порта 22, которые поступают на выходной (egress) интерфейс. Затем к anchor добавляются следующие правила:
# echo "pass in from 192.0.2.10 to any" | pfctl -a ssh -f -
Таким образом, даже если в правиле фильтра не указан интерфейс, протокол или порт, хосту 192.0.2.10 будет разрешено подключаться по SSH только из-за определения правила anchor.

Тот же синтаксис может применяться к встроенным anchor'ам.

allow = "{ 192.0.2.3 192.0.2.4 }"
anchor "goodguys" in proto tcp {
   anchor proto tcp to port 80 {
      pass from 192.0.2.3
   }
   anchor proto tcp to port 22 {
      pass from $allow
   }
}

Управление anchor'ами

Управление anchor'ами осуществляется при помощи pfctl(8). Его можно использовать для добавления и удаления правил из anchor без перезагрузки основного набора правил.

Команда, которая покажет все правила из anchor'а ssh:

# pfctl -a ssh -s rules
Команда, котоая удалит все правила из того же anchor:
# pfctl -a ssh -F rules
Список всех доступных команд и их описание можно посмотреть в pfctl(8).