Firewall

В различных версиях ядра Linux используются разные механизмы фильтрации сетевых пакетов.

Самый ранний с исторической точки зрения механизм ipfw, управляемый командой ipfwadm, использовался в ядрах 1.2 - 2.2.

В версии 2.2.10 появился механизим ipchains, который позволил создавать "подпрограммы" из правил, но ещё не умел отслеживать состояние соединений.

С версии 2.4 появился механизм с поддержкой состояний — netfilter, который управляется программой iptables.

С версии 3.13 добавлен механизм nftables, заменяющий iptables, ip6tables, arptables и ebtables. nftables управляется утилитой nft.

В настоящий момент основным механизмом предлагается сделать bpfilter, на основе виртуальной машины eBPF.

Надо различать механизмы сетевой фильтрации в ядре и прикладные программы, которые этими механизмами управляют.

iptables — явное создание, удаление, печать правил netfilter

UFW — генерация правил на основе существующих шаблонов в Ubuntu

UFW

ufw — питоновский скрипт в Ubuntu для управление брандмауэром netfilter/iptables. Конфигурационные файлы находятся в каталоге /etc/ufw/.

Перед включением брандмауэра удалённо по сети необходимо убедиться, что правила разрешают удалённый доступ по SSH. Для этого надо посмотреть правила в файле /etc/ufw/user.rules или выполнить добавление фиктивного правила с опцией --dry-run:

ufw --dry-run allow 1

У UFW есть пара недостатков:

  1. Пока служба не запущена нельзя посмотреть в отформатированном виде правила, которые будут применены;
  2. При добавлени правил (без --dry-run) они одновременно применяются и записываются в файл конфигурации. Если вы отключите себе удалённый доступ то перезагрузка уже не поможет.

Включение/выключение

Проверка состояния UFW:

ufw status verbose

Включение UFW

ufw enable

Отключение UFW

ufw disable

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

Установка правил по умолчанию

ufw default deny incoming
ufw default allow outgoing

Добавление разрешающих правил

ufw allow ssh
ufw allow 8080
ufw allow 80/tcp

Добавление запрещающих правил

ufw deny http
ufw deny from 123.45.67.89

Добавление правил в начало

ufw prepend allow http

Добавление правил в список по номеру

ufw status numbered
...
ufw insert 4 allow http

Добавление диапазонов портов

sudo ufw allow 7100:7150

Добавление разрешений по IP

ufw allow from 123.45.67.89
ufw allow from 123.45.67.0/24
ufw allow from 123.45.67.0/24 to any port 22

Удаление правил

ufw delete allow http

Удаление правил по номеру

ufw status numbered
...
ufw delete 2

Удаление всех правил

ufw reset

Управление маршрутизируемыми пакетами

Если хочется изменить правила в цепочке FORWARD, то в начало правила надо добавить слово route

ufw route allow from 123.45.67.0/24
ufw route delete allow from 123.45.67.0/24

Логирование пакетов

Включение/выключение сохранения логов в syslog (файлы /var/log/ufw*)

ufw logging <op>

Где <op>

  • on — логи включены на уровень low
  • off — логи отключены
  • low — регистрируются заблокированные пакеты, не соответствующие заданной политике (с ограничением скорости), а также пакеты, соответствующие зарегистрированным правилам.
  • medium = low + все разрешенные пакеты, не соответствующие заданной политике, все недопустимые пакеты, и все новые соединения. Все записи ведутся с ограничением скорости.
  • high = medium + все пакеты с ограничением скорости.
  • full = high без ограниения скорости.

Поддержка шаблонов приложений

Пакеты приложений могут добавлять списки необходимых им портов в файлы в каталоге /etc/ufw/applications.d. В последующем при задании правил вместо номера порта можно указывать app <NAME>

Список приложений:

ufw app list

Информация о конфигурации приложения

ufw app info <NAME>

Разрешить доступ к приложению. Имя приложения указывается вместо имени порта.

ufw allow <NAME>
ufw allow from 192.168.0.0/16 to any app <NAME>

firewalld

firewalld позволяет описывать брандмауэр в терминах зон, сервисов и т.д. Конфигурация firewalld компилируется в правила iptables или nftables.

Список стандартных сервисов

firewall-cmd --get-services

Добавление разрешения на сервис или порт

firewall-cmd --permanent --add-service=ssh
firewall-cmd --permanent --add-port=4444/tcp

Удаление разрешения

firewall-cmd --permanent --remove-service=ssh

Список установленных разрешений

firewall-cmd --permanent --list-all

После всех установок необходимо их применить

firewall-cmd --reload

Просмотр всех соединений через NAT на маршрутизаторе

Подсистема netfilter/iptables в ядре отслеживает состояние соединений проходящих через NAT на маршрутизаторе.

Просмотреть текущие соединения можно командой

conntrack -L

Местоположение таблицы соединений в каталоге /proc может меняться в зависимости от версии ядра.

#new
cat /proc/net/nf_conntrack
#old
cat /proc/net/ip_conntrack

Брандмауэр уровня приложений - tcpwrappers

TCP Wrappers – изначально набор вспомогательных программ 'запускалок' (tcpd, miscd и вспомогательные программы), для контроля за IP адресами клиентов, стартующих сетевые сервисы через inetd. Основная функция, управляющая проверкой правил, hosts_access(request) была в последующем выделена в отдельную библиотеку libwrap. В настоящее время эту библиотеку используют самые разнообразные сервисы, такие как xinetd, sshd, rsyncs и т.п. Полный список программ, использующих TCP Wrappers, можно получить, выполнив следующую команду:

strings -f  /usr/sbin/* /usr/local/sbin/* |  grep hosts_access

Функция hosts_access использует два конфигурационных файла /etc/hosts.allow и /etc/hosts.deny (в FreeBSD только /etc/hosts.allow), которые могут иметь классический или расширенный синтаксис.

Классический вариант

В классическом варианте вначале проверяются все правила из hosts.allow. Если хоть одно правило применимо к паре сервис-клиент, то соединение устанавливается. Затем проверяются все правила из hosts.deny. При нахождении соответствия соединение отклоняется. Если правила нет, то соединение устанавливается. Чтобы явно разрешить доступ только по правилам из hosts.allow, необходимо добавить в hosts.deny правило ALL:ALL.

Классический синтаксис описан в man странице HOSTS_ACCESS(5). Файлы состоят из строк вида

daemon_list : client_list [ : shell_command ]

где

  • daemon_list – список имён сервисов (в xinetd имена прописываются явно в конфигурации службы, для остальных программ они совпадают с именем исполняемого файла) или ключевое слово ALL;
  • client_list – список имён/адресов клиентов;
  • shell_command – вспомогательная команда, например, для логирования событий. В современном варианте это поле имеет другой формат.

Современный вариант

Файлы /etc/hosts.allow и /etc/hosts.deny эквивалентны по своему назначению. Каждое правило может содержать результат – allow или deny. Если в правиле результат не прописан явно, то он вычисляется по правилу классического варианта. Можно считать, что все правила находятся hosts.allow, а hosts.deny остается пустым. Выполняется первое найденное правило.

Синтаксис правил описан в man странице HOSTS_OPTIONS(5). Файлы состоят из строк вида

daemon_list : client_list : option [: option ...]

daemon_list, client_list полностью совместимы с классическим синтаксисом, а опции позволяют понизить привилегии, запустить дополнительную программу параллельно с сервисом или вместо него, и, наконец, принять решение allow или deny. Опции выполняются слева направо. Опция allow/deny должна стоять последней, поскольку после неё произойдёт запуск сервиса или прекращение работы.

Для запуска дополнительных программ используются две опции: spawn shell_command – запуск программы в параллельном процессе одновременно с сетевым сервисом, и twist shell_command – запуск программы в текущем процессе вместо сервиса. Командам в качестве параметров можно передать некоторую информацию о соединении. spawn не влияет на запуск основного сервиса, поэтому за ней должна следовать опция allow или deny. twist затирает текущий процесс и, соответственно, дальнейшие проверки опций. Однако, через параметры в twist можно передать имя исполняемого файла сервиса, чтобы выполнить его после дополнительных проверок.

Кроме опций запуска программ, существуют опции смены владельца, установки маски создаваемых файлов, понижение приоритета и т.п.

В конце списка правил можно добавить правило по умолчанию ALL:ALL:deny, иначе подразумевается наличие ALL:ALL:allow.

Формат списка client_list

Список состоит из полей, разделённых пробелами и/или запятыми. Список может состоять из основной части и исключений, следующих за ключевым словом EXCEPT. Возможна группировка списков и исключений с помощью круглых скобок. В списке могут присутствовать IP адреса, имена хостов, ключевые слова и шаблоны.

Ключевые слова (часть опущена):

  • ALL – все хосты
  • PARANOID – хосты, у которых цепочка преобразований IP->Имя->IP даёт адрес, отличный от исходного.

Шаблоны (часть опущена):

  • .example.org – все имена из домена
  • 192.168.1. – все IP адреса подсети
  • 192.168.132.0/255.255.254.0 – IP адреса по маске
  • /etc/deny.list – текстовый файл, состоящий из строк, содержащих списки хостов в любой описанной выше форме
  • www.*.ru - подстановка вместо звёздочки любого количества символов. Не может быть частью предыдущих шаблонов.

Подстановки при запуске внешних команд

  • %a (%A) Адрес клиента (сервера)
  • %h (%H) Имя клиента (сервера)
  • %d Имя сервиса
  • %p Идентификатор процесса (PID)

Примеры

#классический стиль
sshd : .example.com
vsftpd : 192.168. 
ALL : 192.168.1.0/255.255.255


# Разрешаем подключение из домена .example.com
# кроме station15.example.com
sshd : station15.example.com : deny
sshd : .example.com : allow
#Дополнительно запрещаем всем кроме домена *.hacker.org
sshd : ALL EXCEPT *.hacker.org:twist /bin/echo "Reject - bad host name %h"
# Фактически разрешаем *.hacker.org (остальные уже заблокированы)
# с логированием соединений в файл /tmp/sshd.connections
sshd : ALL:spawn /bin/echo "%d at %I connected from %i" > /tmp/sshd.connections: allow
# Запрещаем остальные соединения
ALL:ALL:deny