Предыдущая статья "Интернет шлюз на FreeBSD" оказалась довольно популярной среди, в основном, начинающих системных администраторов.
Тем не менее там были недочеты, плюс со временем многое изменилось и появилось желание внедрить что-нибудь другое, возможно более удобное.
Основные отличия второй части: использование пакетного фильтра PF вместо связки IPFW + natd + rinetd; использование последнего стабильного релиза FreeBSD-7.1 RELEASE.
Приступим...
Задача: организовать шлюз, раздающий корпоративной сети Интернет сервисы, пробросить необходимые порты на внутренние серверы с учетом использования диапазона внешних ip адресов.
Установка FreeBSD и сборка ядра для поддержки PF.
Устанавливаем FreeBSD в комплектации без иксов, игр и коллекции пакетов.
В конце настраиваем сетевые интерфейсы и включаем ssh.
После загрузки системы собираем ядро для поддержки PF. Вообще этот шаг можно пропустить в случае если вы не собираетесь использовать всякие очереди, приоретезацию трафика и ограничение скорости. Единственное - при подгрузке правил фаера будет мозолить глаза сообщение о том что в ядре нет поддержки всяких ALTQ...
# cd /usr/src/sys/i386/conf/ # cp GENERIC ROUTER
Правим конфиг нового ядра:
... cpu I686_CPU ident ROUTER
makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols
device pf device pflog device pfsync 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 ...
Собираем и устанавливаем новое ядро:
# cd /usr/src # make buldkernel KERNCONF=ROUTER # make installkernel KERNCONF=ROUTER
options { // Relative to the chroot directory, if any directory "/etc/namedb"; pid-file "/var/run/named/pid"; dump-file "/var/dump/named_dump.db"; statistics-file "/var/stats/named.stats";
// RFC 1912 zone "localhost" { type master; file "master/localhost-forward.db"; }; zone "127.in-addr.arpa" { type master; file "master/localhost-reverse.db"; }; zone "255.in-addr.arpa" { type master; file "master/empty.db"; };
// RFC 1912-style zone for IPv6 localhost address zone "0.ip6.arpa" { type master; file "master/localhost-reverse.db"; };
// "This" Network (RFCs 1912 and 3330) zone "0.in-addr.arpa" { type master; file "master/empty.db"; };
// Private Use Networks (RFC 1918) zone "10.in-addr.arpa" { type master; file "master/empty.db"; }; zone "16.172.in-addr.arpa" { type master; file "master/empty.db"; }; zone "17.172.in-addr.arpa" { type master; file "master/empty.db"; }; zone "18.172.in-addr.arpa" { type master; file "master/empty.db"; }; zone "19.172.in-addr.arpa" { type master; file "master/empty.db"; }; zone "20.172.in-addr.arpa" { type master; file "master/empty.db"; }; zone "21.172.in-addr.arpa" { type master; file "master/empty.db"; }; zone "22.172.in-addr.arpa" { type master; file "master/empty.db"; }; zone "23.172.in-addr.arpa" { type master; file "master/empty.db"; }; zone "24.172.in-addr.arpa" { type master; file "master/empty.db"; }; zone "25.172.in-addr.arpa" { type master; file "master/empty.db"; }; zone "26.172.in-addr.arpa" { type master; file "master/empty.db"; }; zone "27.172.in-addr.arpa" { type master; file "master/empty.db"; }; zone "28.172.in-addr.arpa" { type master; file "master/empty.db"; }; zone "29.172.in-addr.arpa" { type master; file "master/empty.db"; }; zone "30.172.in-addr.arpa" { type master; file "master/empty.db"; }; zone "31.172.in-addr.arpa" { type master; file "master/empty.db"; }; zone "168.192.in-addr.arpa" { type master; file "master/empty.db"; };
// Link-local/APIPA (RFCs 3330 and 3927) zone "254.169.in-addr.arpa" { type master; file "master/empty.db"; };
// TEST-NET for Documentation (RFC 3330) zone "2.0.192.in-addr.arpa" { type master; file "master/empty.db"; };
// Router Benchmark Testing (RFC 3330) zone "18.198.in-addr.arpa" { type master; file "master/empty.db"; }; zone "19.198.in-addr.arpa" { type master; file "master/empty.db"; };
// IANA Reserved - Old Class E Space zone "240.in-addr.arpa" { type master; file "master/empty.db"; }; zone "241.in-addr.arpa" { type master; file "master/empty.db"; }; zone "242.in-addr.arpa" { type master; file "master/empty.db"; }; zone "243.in-addr.arpa" { type master; file "master/empty.db"; }; zone "244.in-addr.arpa" { type master; file "master/empty.db"; }; zone "245.in-addr.arpa" { type master; file "master/empty.db"; }; zone "246.in-addr.arpa" { type master; file "master/empty.db"; }; zone "247.in-addr.arpa" { type master; file "master/empty.db"; }; zone "248.in-addr.arpa" { type master; file "master/empty.db"; }; zone "249.in-addr.arpa" { type master; file "master/empty.db"; }; zone "250.in-addr.arpa" { type master; file "master/empty.db"; }; zone "251.in-addr.arpa" { type master; file "master/empty.db"; }; zone "252.in-addr.arpa" { type master; file "master/empty.db"; }; zone "253.in-addr.arpa" { type master; file "master/empty.db"; }; zone "254.in-addr.arpa" { type master; file "master/empty.db"; };
// IPv6 Unassigned Addresses (RFC 4291) zone "1.ip6.arpa" { type master; file "master/empty.db"; }; zone "3.ip6.arpa" { type master; file "master/empty.db"; }; zone "4.ip6.arpa" { type master; file "master/empty.db"; }; zone "5.ip6.arpa" { type master; file "master/empty.db"; }; zone "6.ip6.arpa" { type master; file "master/empty.db"; }; zone "7.ip6.arpa" { type master; file "master/empty.db"; }; zone "8.ip6.arpa" { type master; file "master/empty.db"; }; zone "9.ip6.arpa" { type master; file "master/empty.db"; }; zone "a.ip6.arpa" { type master; file "master/empty.db"; }; zone "b.ip6.arpa" { type master; file "master/empty.db"; }; zone "c.ip6.arpa" { type master; file "master/empty.db"; }; zone "d.ip6.arpa" { type master; file "master/empty.db"; }; zone "e.ip6.arpa" { type master; file "master/empty.db"; }; zone "0.f.ip6.arpa" { type master; file "master/empty.db"; }; zone "1.f.ip6.arpa" { type master; file "master/empty.db"; }; zone "2.f.ip6.arpa" { type master; file "master/empty.db"; }; zone "3.f.ip6.arpa" { type master; file "master/empty.db"; }; zone "4.f.ip6.arpa" { type master; file "master/empty.db"; }; zone "5.f.ip6.arpa" { type master; file "master/empty.db"; }; zone "6.f.ip6.arpa" { type master; file "master/empty.db"; }; zone "7.f.ip6.arpa" { type master; file "master/empty.db"; }; zone "8.f.ip6.arpa" { type master; file "master/empty.db"; }; zone "9.f.ip6.arpa" { type master; file "master/empty.db"; }; zone "a.f.ip6.arpa" { type master; file "master/empty.db"; }; zone "b.f.ip6.arpa" { type master; file "master/empty.db"; }; zone "0.e.f.ip6.arpa" { type master; file "master/empty.db"; }; zone "1.e.f.ip6.arpa" { type master; file "master/empty.db"; }; zone "2.e.f.ip6.arpa" { type master; file "master/empty.db"; }; zone "3.e.f.ip6.arpa" { type master; file "master/empty.db"; }; zone "4.e.f.ip6.arpa" { type master; file "master/empty.db"; }; zone "5.e.f.ip6.arpa" { type master; file "master/empty.db"; }; zone "6.e.f.ip6.arpa" { type master; file "master/empty.db"; }; zone "7.e.f.ip6.arpa" { type master; file "master/empty.db"; };
// IPv6 ULA (RFC 4193) zone "c.f.ip6.arpa" { type master; file "master/empty.db"; }; zone "d.f.ip6.arpa" { type master; file "master/empty.db"; };
// IPv6 Link Local (RFC 4291) zone "8.e.f.ip6.arpa" { type master; file "master/empty.db"; }; zone "9.e.f.ip6.arpa" { type master; file "master/empty.db"; }; zone "a.e.f.ip6.arpa" { type master; file "master/empty.db"; }; zone "b.e.f.ip6.arpa" { type master; file "master/empty.db"; };
// IPv6 Deprecated Site-Local Addresses (RFC 3879) zone "c.e.f.ip6.arpa" { type master; file "master/empty.db"; }; zone "d.e.f.ip6.arpa" { type master; file "master/empty.db"; }; zone "e.e.f.ip6.arpa" { type master; file "master/empty.db"; }; zone "f.e.f.ip6.arpa" { type master; file "master/empty.db"; };
// IP6.INT is Deprecated (RFC 4159) zone "ip6.int" { type master; file "master/empty.db"; };
zone "domain.local" { type master; file "master/domain.local"; allow-transfer { 192.168.1.225; }; };
zone "0.168.192.in-addr.arpa" { type master; file "master/0.168.192"; allow-transfer { 192.168.1.1; }; };
zone "1.168.192.in-addr.arpa" { type master; file "master/1.168.192"; allow-transfer { 192.168.1.1; }; };
Файлы внутренней зоны:
# cat /etc/namedb/master/domain.local
$TTL 86400
domain.local. IN SOA ns.domain.local. admin.domain.local. ( 2006240801 ; Serial (YYYYDDMM plus 2 digit serial) 86400 ; refresh (1 day) 7200 ; retry (2 hours) 8640000 ; expire (100 days) 86400) ; minimum (1 day)
IN NS ns.domain.local. localhost IN A 127.0.0.1 ns IN A 192.168.0.1 bsd IN A 192.168.0.1 mail IN A 192.168.0.2 pbx IN A 192.168.1.3 ....
Резюме по этому конфигу: вырезаем весь мультимедиа контент и запрещаем в рабочее время сайты, лежащие в файле deny_domains. Играничения не касаются тех, кто прописан в файле inet_full. Под сквид у меня отдельный раздел /squid где находится кеш и логи.
Дальше создаем необходимые файлы и папки, настриаваем права:
# Определяем политику при блокировке пакетов set block-policy drop # Поведение пакетного фильтра при использовании таблицы состояний set state-policy floating # Логируемый интерфейс set loginterface $ext_if # Максимальное количество записей в пуле отвечающем за нормализацию трафика (scrub) # Максимальное количество вхождений в пул отвечающий за состояние таблицы состояний соединений (keep state) set limit { frags 100000, states 100000 } # Устанавливаем тип оптимизации set optimization normal # Игнорируем фильтрацию на кольцевом интерфейсе set skip on lo0 # Нормализация всего входящего трафика на всех интерфейсах scrub in all
# NAT для Asterisk # Из-за ната Астериск работал с кучей косяков, поэтому пришлось сделать бинат binat on $ext_if inet from $pbx to any -> $ext_ip_pbx
# NAT для локалки nat on $ext_if inet from $lannet to any -> $ext_ip
# Отправляем локальных интернетчиков на squid. rdr on $int_if proto tcp from $lannet to any port www -> 127.0.0.1 port 3129
# Пробрасываем порты на Asterisk rdr on $ext_if from any to $ext_ip_pbx -> $pbx
# Пробрасываем порты на web сервер rdr on $ext_if proto tcp from any to $ext_ip_bserv port www -> $bserv
# Пробрасываем порты на почтовый сервер - smtp для всех. rdr on $ext_if proto tcp from any to $ext_ip port smtp -> $mail
# Пробрасываем порты на почтовый сервер - pop3 для филиалов. rdr on $ext_if proto tcp from $friends to $ext_ip port pop3 -> $mail
# Пробрасываем порты на почтовый сервер - https вебморда для всех. rdr on $ext_if proto tcp from any to $ext_ip port https -> $mail
# Пробрасываем порты на виндовый терминальный сервер. rdr on $ext_if proto tcp from any to $ext_ip port rdp -> $terminal
# Пробрасываем еще один rdp. rdr on $ext_if proto tcp from any to $ext_ip port 3390 -> $serv3 port 3389
# Пробрасываем порты на root rdr on $ext_if proto tcp from any to $ext_ip port 44444 -> $root port 44444
# Пробрасываем SSH rdr on $ext_if proto tcp from any to $ext_ip port 33330 -> $mail port 22 rdr on $ext_if proto tcp from any to $ext_ip port 33331 -> $pbx port 22 rdr on $ext_if proto tcp from any to $ext_ip port 33332 -> $dc port 22 rdr on $ext_if proto tcp from any to $ext_ip port 33333 -> $serv1 port 22 rdr on $ext_if proto tcp from any to $ext_ip port 33334 -> $serv2 port 22 rdr on $ext_if proto tcp from any to $ext_ip port 33335 -> $pdc port 22
#------------------------------ # Правила фильтрации #------------------------------
# Защита от спуфинга antispoof quick for { lo0, $int_if, $ext_if }
# Блокируем всё block log all
# Блокируем тех, кто лезет на внешний интерфейс с частными адресами block drop in quick on $ext_if from $private_nets to any
# Разрешаем icmp pass inet proto icmp icmp-type echoreq
# Разрешаем DNS для локалки pass in on $int_if proto udp from $lannet to $bsd port domain
# Разрешаем NTP для локалки pass in on $int_if proto udp from $lannet to $bsd port ntp
# Тестовый полный выход для отладки #pass in on $int_if from $lannet to any
# Выпускаем Asterisk pass in on $int_if from $pbx to any
# Выпускаем почтовик pass in on $int_if proto tcp from $mail to any port smtp
# Выпускаем админские сервисы pass in on $int_if proto tcp from $root to any port $admin_ports
# Выпускаем клиентске сервисы pass in on $int_if proto tcp from $lannet to any port $client_ports
# Разрешаем нашему шлюзу полный выход с обоих интерфейсов pass out on $ext_if proto tcp from any to any pass out on $ext_if proto udp from any to any keep state pass out on $int_if proto tcp from any to any pass out on $int_if proto udp from any to any keep state
#------------------------------ # Icoming #
# Разрешаем входящий ssh pass in log on $ext_if proto tcp from any to $ext_ip port 33339 flags S/SA synproxy state pass in log on $ext_if proto tcp from any to $mail port 22 flags S/SA synproxy state pass in log on $ext_if proto tcp from any to $pbx port 22 flags S/SA synproxy state pass in log on $ext_if proto tcp from any to $dc port 22 flags S/SA synproxy state pass in log on $ext_if proto tcp from any to $serv1 port 22 flags S/SA synproxy state pass in log on $ext_if proto tcp from any to $serv2 port 22 flags S/SA synproxy state
# Разрешаем входящий smtp для всех pass in on $ext_if proto tcp from any to $mail port smtp flags S/SA synproxy state
# Разрешаем входящий https pass in on $ext_if proto tcp from any to $mail port https flags S/SA synproxy state
# Разрешаем входящий www pass in on $ext_if proto tcp from any to $ext_ip port www flags S/SA synproxy state
# Разрешаем входящий ftp pass in on $ext_if proto tcp from any to $ext_ip port ftp flags S/SA synproxy state
# Разрешаем входящий pop3 для филиалов pass in on $ext_if proto tcp from $friends to $mail port pop3 flags S/SA synproxy state
# Разрешаем входящий rdp pass in log on $ext_if proto tcp from $friends to $terminal port rdp flags S/SA synproxy state
# Разрешаем входящий rdp еще на один виндовый сервер pass in log on $ext_if proto tcp from $friends to $serv3 port rdp flags S/SA synproxy state
# Проброс на root pass in log on $ext_if proto tcp from any to $root port 4899 flags S/SA synproxy state
# Разрешаем входящий Asterisk pass in on $ext_if proto tcp from any to $pbx port $pbx_tcp flags S/SA synproxy state pass in on $ext_if proto udp from any to $pbx port $pbx_udp keep state
# Разрешаем входящий www на serv1 pass in on $ext_if proto tcp from any to $bserv port www flags S/SA synproxy state
Перед загрузкой проверим правила:
# pfctl -nf /etc/pf.conf
Если все ок, то загрузим:
# pfctl -f /etc/pf.conf
Посмотрим правила трансляции:
# pfctl -sn
Правила фильтрации:
# pfctl -sr
Посмотрим стстистику по внешнему интерфейсу:
# pfctl -si
Просомтреть всё скопом можно так:
# pfctl -sa
При написании статьи использовались следующие материалы: