IPFW — настраиваем файрвол на FreeBSD

По умолчанию в дистрибутиве предустановлено сразу 3 firewall’a: IPFILTER, IPFW и PF. Какой использовать — выбирает пользователь. Мы же попробуем рассмотреть нормально закрытую конфигурацию IPFW.

Вводные данные: Имеется сервер с TrueNAS’ом и запущенными на нем сервисами, например FTP, необходимо разрешить доступ к FTP для всех сетей организации, а управление и мониторинг сервера выделить в отдельные менеджмент сети.

Создадим два файлика:
где firewall.conf — файл конфигурации файрвола, а allowed_nets.ipfw — сети с которых есть доступ к сервисам на сервере. Каждая сеть в файлике allowed_nets указывается с новой строки

touch /etc/firewall.conf 
touch /etc/allowed_nets.ipfw
# Пример файла с разрешенными сетями
root@truenas[~]# cat /etc/allowed_nets.ipfw
10.10.5.0/24
10.10.6.0/25
10.20.7.0/26
192.168.0.0/27
172.17.10.0/23

Содержимое файла firewall.conf

root@truenas[~]# cat /etc/firewall.conf
#!/bin/sh
 
# need to add to rc.conf
#firewall_enable="YES"
#firewall_script="/etc/firewall.conf"
  
# firewall command
FwCMD="/sbin/ipfw -q"
${FwCMD} -f flush
 
# Interfaces setup
WAN_IF="lagg0"
 
#Allow ip addresses
ALLOW_IP_INT="10.86.60.0/24,10.90.90.10,192.168.1.1"
ipfw table 10 flush
cat /etc/allowed_nets.ipfw | while read ip; do
ipfw table 10 add $ip
done
ALLOW_IP_ADD="table(10)"
 
# DNS
${FwCMD} add 3 allow udp from any 53 to any via ${WAN_IF}
 
# Allow all traffic to loopback
${FwCMD} add 010 allow all from any to any via lo0
#Enable allow from world to me some types of ICMP
${FwCMD} add 300 allow icmp from any to me in via ${WAN_IF} icmptype 0,3,8,12
#Enable some types of ICMP from me to world
${FwCMD} add 310 allow icmp from me to any out via ${WAN_IF} icmptype 0,3,11,12
 
# FTP
${FwCMD} add 990 allow tcp from ${ALLOW_IP_ADD} to me dst-port 20,21
${FwCMD} add 990 allow tcp from ${ALLOW_IP_INT} to me dst-port 20,21
${FwCMD} add 991 deny log tcp from any to me dst-port 20,21
# FTP passive connections
${FwCMD} add 992 allow tcp from ${ALLOW_IP_ADD} to me dst-port 30000-35000
${FwCMD} add 992 allow tcp from ${ALLOW_IP_INT} to me dst-port 30000-35000
 
# internal services
${FwCMD} add 1000 allow tcp from ${ALLOW_IP_INT} to me in via ${WAN_IF} dst-port 22,80,443,10050
${FwCMD} add 1000 allow udp from ${ALLOW_IP_INT} to me in via ${WAN_IF} dst-port 22,80,443,10050
${FwCMD} add 1001 deny tcp from any to me in via ${WAN_IF} dst-port 22,80,443,10050
${FwCMD} add 1001 deny udp from any to me in via ${WAN_IF} dst-port 22,80,443,10050
 
# Allow outgoing connections
${FwCMD} add 2000 allow all from me to any via ${WAN_IF}
${FwCMD} add 2001 allow log all from any to any established
 
#deny all
${FwCMD} add 65534 deny log all from any to me in via ${WAN_IF}

Рассмотрим подробнее что мы тут наделали:

# need to add to rc.conf
#firewall_enable="YES"
#firewall_script="/etc/firewall.conf"

Комментарий говорит сам за себя, эти строки необходимо добавить в rc.conf чтобы файрвол запускался автоматически. Делаем

echo '#Enable IPFW
firewall_enable="YES"
firewall_script="/etc/firewall.conf"' >> /etc/rc.conf

Далее следует блок запуска файрвола и очистки правил, если таковые вдруг в файрволе при старте окажутся. А также определяем интерфейс на котором будем применять правила

# firewall command
FwCMD="/sbin/ipfw -q"
${FwCMD} -f flush
 
# Interfaces setup
WAN_IF="lagg0"

Следующий блок описывает сети с доступом к сервисам сервера и менеджмент сети

#Allow ip addresses
ALLOW_IP_INT="10.86.60.0/24,10.90.90.10,192.168.1.1"
ipfw table 10 flush
cat /etc/allowed_nets.ipfw | while read ip; do
ipfw table 10 add $ip
done
ALLOW_IP_ADD="table(10)"

Причем сети для менеджмент сервисов мы добавляем просто в поименованном пуле ALLOW_IP_INT, а сети с доступом к FTP сервису через создание таблицы с пулом адресов из файлика allowed_nets.ipfw, если у вас этих сетей немного думаю проще создать пул в файле конфигурации, но в нашем случае сети могут меняться, а файлик с разрешенными сетями — перезаписываться.

Дальше несколько сумбурно свалено в кучу, то что наверно стоило бы разнести, но лень.

# DNS
${FwCMD} add 3 allow udp from any 53 to any via ${WAN_IF}
# Allow all traffic to loopback
${FwCMD} add 010 allow all from any to any via lo0
#Enable allow from world to me some types of ICMP
${FwCMD} add 300 allow icmp from any to me in via ${WAN_IF} icmptype 0,3,8,12
#Enable some types of ICMP from me to world
${FwCMD} add 310 allow icmp from me to any out via ${WAN_IF} icmptype 0,3,11,12

Разрешаем запросы к DNS, трафик на лупбек интерфейсе и некоторые типы icmp пакетов, подробнее о разрешенных пакетах:

# 0 - Echo Reply (эхо-ответ)
# 3 - Destination Unreachable (Адресат недоступен)
# 8 - Echo Request (эхо-запрос)
# 11 - Time Exceeded (Время жизни дейтаграммы истекло)
# 12 - Parameter Problem: Bad IP header (Неверный параметр (ошибка в IP-заголовке или отсутствует необходимая опция))

Далее следует секция описывающая доступ к FTP. Для пассивных соединений предварительно задаем соответствующий диапазон портов в настройках FTP-сервера

# FTP
${FwCMD} add 990 allow tcp from ${ALLOW_IP_ADD} to me dst-port 20,21
${FwCMD} add 990 allow tcp from ${ALLOW_IP_INT} to me dst-port 20,21
${FwCMD} add 991 deny log tcp from any to me dst-port 20,21
# FTP passive connections
${FwCMD} add 992 allow tcp from ${ALLOW_IP_ADD} to me dst-port 30000-35000
${FwCMD} add 992 allow tcp from ${ALLOW_IP_INT} to me dst-port 30000-35000

Секция описывающая доступ к менеджмент сервисам: SSH, HTTP, HTTPS и Zabbix

# internal services
${FwCMD} add 1000 allow tcp from ${ALLOW_IP_INT} to me in via ${WAN_IF} dst-port 22,80,443,10050
${FwCMD} add 1000 allow udp from ${ALLOW_IP_INT} to me in via ${WAN_IF} dst-port 22,80,443,10050
${FwCMD} add 1001 deny tcp from any to me in via ${WAN_IF} dst-port 22,80,443,10050
${FwCMD} add 1001 deny udp from any to me in via ${WAN_IF} dst-port 22,80,443,10050

Завершают конфигурацию правила разрешающие исходящие соединения с сервера, если серверу конечно нужен интернет, если таковой не требуется — для пущей безопастности можно и их фильтрануть и запрет всего остального трафика

# Allow outgoing connections
${FwCMD} add 2000 allow all from me to any via ${WAN_IF}
${FwCMD} add 2001 allow log all from any to any established
 
#deny all
${FwCMD} add 65534 deny log all from any to me in via ${WAN_IF}

После того как правила готовы — перезапускаем файрвол

root@truenas[~]# service ipfw stop
root@truenas[~]# service ipfw start

Командочки для проверки правил и отчетов о работе файрвола:

ipfw list               # check active rules
ipfw table 10 list      # check allowed IP pool
ipfw show               # check counters for active rules

Если в процессе настройки необходимо проверить работу каких-либо правил и провести отладку в правила после allow или deny добавляем значение log и включаем логирование файрвола

# Включаем логирование в rc.conf и sysctl
# enable logging for firewall
echo 'firewall_logging="YES"' >> /etc/rc.conf
sysctl net.inet.ip.fw.verbose=1
sysctl net.inet.ip.fw.verbose_limit=10
# Добавляем логирование в требуемые правила
# add logging to needed rules in firewall.conf
# for example
${FwCMD} add 991 deny log tcp from any to me dst-port 20,21
${FwCMD} add 2000 allow log all from me to any via ${WAN_IF}
# Перезапускаем IPFW
# restart firewall
service ipfw restart
# Проверяем логи
# check logs
tail -n 15 /var/log/security

Совет. Для проверки активных портов во время отладки, пользуйтесь lsof

lsof -i -P -n | grep LISTEN

Важное замечание. Т.к. мы настраиваем TrueNAS то у нас по умолчанию RO файловая система и все изменения работают только до ребута, поэтому все измененные и созданные файлы не забываем скопировать в /conf/base/*