NAT с помощью IPFW на FreeBSD 9.1

Как то так сложилось исторически, что для меня сервер вне зависимости от возложенных на него функций является фаерволом. Скорее всего это связано с безопасностью. Не важно, сайт на нем крутится или почтарик или просто это шлюз в интернет для небольшой компании — он должен быть защищен и точка. Я уже писал о фаерволе средствами PF, но есть в нем некоторые минусы и сложности. В любом случае опыт лишним не бывает. Вот и решил освоить хотя бы минимально работу с IPFW — родным фаерволом во фряхе. Да и очевидно же, что такая качественная система не может за основу взять некачественный фаервол. Кроме того изучения сравнительных характеристик показали очевидное превосходство IPFW. Пора заставить себя использовать только лучшее.

Для теста была выбрана самая свежая на тот момент версия — FreeBSD 9.1. Во время установки никаких сложностей не возникло. Первим же делом я обновил порты (привычка) и решил собрать своё ядро не с модульной а нативной поддержкой IPFIREWALL. Никаких трудностей, все по стандарту.
Копируем GENERIC ядро и начинаем править его под свои нужды:

cd /usr/src/sys/i386/conf/
cp GENERIC IPFW

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

ident IPFW 
options IPFIREWALL
options IPFIREWALL_DEFAULT_TO_ACCEPT
options IPFIREWALL_FORWARD
options IPFIREWALL_VERBOSE
options IPFIREWALL_VERBOSE_LIMIT=100
options IPFIREWALL_NAT
options LIBALIAS
options ROUTETABLES=2
options DUMMYNET
options HZ="1000"

сохраняем и занимаемся непосредственно сборкой

config IPFW
cd ../compile/IPFW/ && make cleandepend && make depend && make && make install && reboot

В /etc/rc.conf необходимо добавить следующие строки:

gateway_enable="YES" # наш сервер будет шлюзом
ifconfig_sk0="inet 192.168.4.57 netmask 255.255.255.0" # настройки внешнего интерфейса
ifconfig_rl0="inet 192.168.7.1 netmask 255.255.255.0" # настройки внутреннего интерфейса
defaultrouter="192.168.4.222" # дефолтный шлюз для самого сервера
firewall_enable="YES" # активируем фаервол
firewall_nat_enable="YES" # активируем NAT 
dummynet_enable="YES" # активируем средство ограничения трафика
firewall_type="/etc/ipfw-nat" # файл с правилами фаервола

Дальше создание файла конфигурации для нашего пакетного фильтра. Для этого создадим указанный выше файл и внесём в него следующие строки:

add 1 allow ip from any to any via rl0
nat 1 config log if sk0 reset same_ports
add 2 nat 1 ip from any to any via sk0

Этого было бы достаточно что бы просто работал NAT. Дальше немного добавим безопасности.

# Разрешаем весь трафик по внутреннему интерфейсу (петле)
add allow ip from any to any via lo0
# Блокируем попытки lo0 куда-то лезть и откуда-то лезть на lo0
add deny ip from any to 127.0.0.0/8
add deny ip from 127.0.0.0/8 to any
# Блокируем частные сети на внешнем интерфейсе
add deny ip from any to 10.0.0.0/8 in via sk0
add deny ip from any to 172.16.0.0/12 in via sk0
add deny ip from any to 0.0.0.0/8 in via sk0
# Блокируем автоконфигуреную частную сеть
add deny ip from any to 169.254.0.0/16 in via sk0
# Блокируем мультикастовые рассылки
add deny ip from any to 240.0.0.0/4 in via sk0
# Блокируем фрагментированные icmp
add deny icmp from any to any frag
# Блокируем широковещательные icmp на внешнем интерфейсе
add deny log icmp from any to 255.255.255.255 in via sk0 
add deny log icmp from any to 255.255.255.255 out via sk0
# отправляем всех на прозрачный squid
add fwd 127.0.0.1,3128 tcp from 192.168.7.0/24 to any 80 via sk0
# пропускаем траффик через трансляцию сетевых адресов (NAT)
nat 1 config log if sk0 reset same_ports
add nat 1 ip from any to any via sk0
# Блокируем траффик к частным сетям через внешний интерфейс
add deny ip from 10.0.0.0/8 to any out via sk0
add deny ip from 172.16.0.0/12 to any out via sk0
add deny ip from 0.0.0.0/8 to any out via sk0
# Блокируем автоконфигуреную частную сеть
add deny ip from 169.254.0.0/16 to any out via sk0
# Блокируем мультикастовые рассылки
add deny ip from 224.0.0.0/4 to any out via sk0
add deny ip from 240.0.0.0/4 to any out via sk0
# разрешаем все установленные соединения
add allow tcp from any to any established
# разрешаем весь исходящий траффик
add allow ip from me to any out xmit sk0
# разрешаем DNS снаружи
add allow udp from any 53 to any via sk0
# разрешаем DNS входящий снаружи - если на этой машине работает named
# и держит какую-то зону.
add allow udp from any to any 53 via sk0
# разрешаем некоторые типы ICMP траффика - эхо-запрос, эхо-ответ и время жизни пакета истекло
add allow icmp from any to any icmptypes 0,8,11
# открываем снаружи порты (WEB, SMTP, SSH, IMAP соответственно)
add allow tcp from any to me 80 via sk0
add allow tcp from any to me 25 via sk0
add allow tcp from any to me 22 via sk0
add allow tcp from any to me 143 via sk0
# разрешаем весь tcp трафик внутри локалки (на внутреннем интерфейсе)
add allow tcp from any to any via rl0
# разрешаем весь udp траффик внутри локалки (на внутреннем интерфейсе)
add allow udp from any to any via rl0
# разрешаем весь icmp траффик внутри локалки (на внутреннем интерфейсе)
add allow icmp from any to any via rl0
# запрещаем всё и всем.
add deny ip from any to any

Применить изменения можно перезапустив фаервол:

root@ipfw:/usr/home/gleb # /etc/rc.d/ipfw restart
net.inet.ip.fw.enable: 1 -> 0
net.inet6.ip6.fw.enable: 1 -> 0
Flushed all rules.
00100 allow ip from any to any via lo0
00200 deny ip from any to 127.0.0.0/8
00300 deny ip from 127.0.0.0/8 to any
00400 deny ip from any to ::1
00500 deny ip from ::1 to any
00600 allow ipv6-icmp from :: to ff02::/16
00700 allow ipv6-icmp from fe80::/10 to fe80::/10
00800 allow ipv6-icmp from fe80::/10 to ff02::/16
00900 allow ipv6-icmp from any to any ip6 icmp6types 1
01000 allow ipv6-icmp from any to any ip6 icmp6types 2,135,136
01100 allow ip from any to any via lo0
01200 deny ip from any to 127.0.0.0/8
01300 deny ip from 127.0.0.0/8 to any
01400 deny ip from any to 10.0.0.0/8 in via sk0
01500 deny ip from any to 172.16.0.0/12 in via sk0
01600 deny ip from any to 0.0.0.0/8 in via sk0
01700 deny ip from any to 169.254.0.0/16 in via sk0
01800 deny ip from any to 240.0.0.0/4 in via sk0
01900 deny icmp from any to any frag
02000 deny log logamount 100 icmp from any to 255.255.255.255 in via sk0
02100 deny log logamount 100 icmp from any to 255.255.255.255 out via sk0
ipfw nat 1 config if sk0 log same_ports reset
02200 nat 1 ip from any to any via sk0
02300 deny ip from 10.0.0.0/8 to any out via sk0
02400 deny ip from 172.16.0.0/12 to any out via sk0
02500 deny ip from 0.0.0.0/8 to any out via sk0
02600 deny ip from 169.254.0.0/16 to any out via sk0
02700 deny ip from 224.0.0.0/4 to any out via sk0
02800 deny ip from 240.0.0.0/4 to any out via sk0
02900 allow tcp from any to any established
03000 allow ip from 192.168.4.57 to any out xmit sk0
03100 allow udp from any 53 to any via sk0
03200 allow udp from any to any dst-port 53 via sk0
03300 allow icmp from any to any icmptypes 0,8,11
03400 deny tcp from any to 192.168.4.57 dst-port 80 via sk0
03500 allow tcp from any to 192.168.4.57 dst-port 25 via sk0
03600 allow tcp from any to 192.168.4.57 dst-port 22 via sk0
03700 allow tcp from any to 192.168.4.57 dst-port 143 via sk0
03800 allow tcp from any to any via rl0
03900 allow udp from any to any via rl0
04000 allow icmp from any to any via rl0
04100 deny ip from any to any
Firewall rules loaded.

После этого все норм. Интернет на локальных машинках за натом есть. «Что и требовалось доказать»

Добавить комментарий