Защищенный шлюз на FreeBSD часть третья. IPFW.

 
В каталоге etc мы создали скрипт rc.ipfw с правилами для ipfw.

# Объявляем, что файл является скриптом sh
#!/bin/sh
cmd=”ipfw –q add”
# Сбрасываем все правила
ipfw –q –f flush
# Отправляем пакеты на наш NAT
$cmd 014 divert natd ip from any to any via em1
# Разрешающее правило для всего
$cmd 100 allow ip from any to any

 

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

 

Для удобства мы создали переменную cmd и вложили в нее префикс создания правила ipfw -q add. Каждое новое правило будет начинаться с этой переменной.

 

Добавим еще пару переменных.

 

Поскольку сервер будет выполнять роль шлюза, у него будет как минимум два интерфейса. Внешний и внутренний. Назовем их LanOut и LanIn.
 
LanOut это внешний интерфейс, через который сервер подключается к интернету. На всякий случай я добавил комментарий с его айпи адресом. В моем случае это 192.168.73.55. Заодно закомментируем устаревшие правила.

#!/bin/sh
cmd=”ipfw –q add”
LanOut=”em1” # 192.168.73.55  
LanIn=”em0” # 192.168.56.111
ipfw –q –f flush
#$cmd 014 divert natd ip from any to any via em1
#$cmd 100 allow ip from any to any

 

Сделаем разрешающее правило для локальной сети.

#!/bin/sh
cmd=”ipfw –q add”
LanOut=”em1” # 192.168.73.55  
LanIn=”em0” # 192.168.56.111
ipfw –q –f flush
#$cmd 014 divert natd ip from any to any via em1
#$cmd 100 allow ip from any to any
$cmd 005 allow all from any to any via $LanIn

 

Вставим переменную $cmd. Переменная обозначается знаком доллара в начале. Добавим порядковый номер для правила, например 005. Диапазон номеров у ipfw от 1 до 65535, нам же для всех правил хватит трёхзначной цифры. Действие будет разрешающее allow всем all от всех from any ко всем to any. И укажем, что правило действует для внутреннего интерфейса via $LanIn. Таким образом мы разрешили весь трафик внутри локальной сети. В будущем правила для локальной сети можно будет настроить более тонко.

 

Продолжим. Сделаем такое же правило для loopback интерфейса.

$cmd 010 allow all from any to any via lo0

 

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

$cmd 014 divert natd ip from any to any in via $LanOut
$cmd 800 divert natd ip from any to any out via $LanOut

 

Правило будет почти в конце скрипта. Дадим ему номер, например, 800. На него будут посылаться все исходящие пакеты посредствам типа действий skipto. Сделаем для него переменную.
 
На данный момент у нас получился такой набор правил:

#!/bin/sh
cmd=”ipfw –q add”
LanOut=”em1” # 192.168.73.55  
LanIn=”em0” # 192.168.56.111
skip="skipto 800"
ipfw –q –f flush
#$cmd 014 divert natd ip from any to any via em1
#$cmd 100 allow ip from any to any
$cmd 005 allow all from any to any via $LanIn
$cmd 014 divert natd ip from any to any in via $LanOut
$cmd 800 divert natd ip from any to any out via $LanOut

 

Добавим разрешающее правило для всех прошедших 800 правило пакетов и отбросим все остальное.

$cmd 801 allow ip from any to any
$cmd 802 deny log all from any to any

 

Добавим поддержку динамических правил.

#!/bin/sh
cmd=”ipfw –q add”
LanOut=”em1” # 192.168.73.55  
LanIn=”em0” # 192.168.56.111
skip="skipto 800"
ks="keep-state"
ipfw –q –f flush
#$cmd 014 divert natd ip from any to any via em1
#$cmd 100 allow ip from any to any
$cmd 005 allow all from any to any via $LanIn
$cmd 014 divert natd ip from any to any in via $LanOut
$cmd 015 check-state
$cmd 800 divert natd ip from any to any out via $LanOut
$cmd 801 allow ip from any to any
$cmd 802 deny log all from any to any

 

Check-state будет проверять пакет по набору динамических правил, сами правила мы добавим позже, используя ключевое слово “keep-state”. Для него мы сделали переменную.

 

Разрешим исходящий доступ к днс и dhcp провайдера, 53 и 67 порты соответственно. Также разрешим входящий трафик от dhcp сервера провайдера по udp протоколу. Для удобства визуально разделим в скрипте правила на 2 группы для исходящих и входящих пакетов, out и in соответственно.

#!/bin/sh
cmd=”ipfw –q add”
LanOut=”em1” # 192.168.73.55  
LanIn=”em0” # 192.168.56.111
skip="skipto 800"
ks="keep-state"
ipfw –q –f flush
#$cmd 014 divert natd ip from any to any via em1
#$cmd 100 allow ip from any to any
$cmd 005 allow all from any to any via $LanIn
$cmd 014 divert natd ip from any to any in via $LanOut
$cmd 015 check-state
#########################out#####################
# dns & dhcp
$cmd 030 $skip udp from any to 192.168.73.2 53,67 out via $LanOut $ks
#########################in######################
$cmd 300 allow udp from 192.168.73.2 to any 68 in via $LanOut $ks
#################################################
$cmd 800 divert natd ip from any to any out via $LanOut
$cmd 801 allow ip from any to any
$cmd 802 deny log all from any to any

 

Добавим в группу исходящих out еще пару правил.

 

Разрешим исходящий http и https трафик на порт 80 и 443 соответственно. Чтобы пользователи в локальной сети могли просматривать интернет страницы в браузере.

# http(s)
$cmd 040 $skip tcp from any to any 80,443 out via $LanOut setup $ks

 

Так же стоит разрешить исходящий трафик для почты.

# mail
$cmd 041 $skip tcp from any to any 25,465,110,143 out via $LanOut setup $ks

 

Порты 25 и 465 это SMTP протокол. 110 порт это POP3 протокол и 143 порт это IMAP протокол.

 
Разрешим всё для пользователя root.

# root
$cmd 042 $skip tcp from me to any out via $LanOut setup $ks uid root

 

Разрешаем исходящий пинг.

# ping
$cmd 043 $skip icmp from any to any out via $LanOut $ks

 

Перейдем к группе входящих in.
Запретим входящий траффик из незарегистрированных адресных пространств.

$cmd 200 deny all from 169.254.0.0/16 to any in via $LanOut
$cmd 201 deny all from 127.0.0.0/8 to any in via $LanOut
$cmd 202 deny all from 0.0.0.0/8 to any in via $LanOut
$cmd 203 deny all from 192.0.2.0/24 to any in via $LanOut
$cmd 203 deny all from 204.152.64.0/23 to any in via $LanOut
$cmd 204 deny all from 224.0.0.0/3 to any in via $LanOut

 

Запрещаем ident и Netbios.

$cmd 205 deny tcp from any to any 113,137-139 in via $LanOut

 

Запрещаем опоздавшие пакеты.

$cmd 206 deny all from any to any frag in via $LanOut

 

Запрещаем ACK пакеты которые не совпадают с динамической таблицей правил.

$cmd 207 deny tcp from any to any established in via $LanOut

 

Предположим, что у нас запущен FTP сервер. Чтобы пользователи через интернет могли подключиться к нашему FTP серверу, потребуется еще одно правило. Добавим его к правилам in.

$cmd 301 allow tcp from any to me 21 in via $LanOut setup $ks

 

Наконец запретим все не прошедшие по условиям наших правил пакеты.

#!/bin/sh
cmd=”ipfw –q add”
LanOut=”em1” # 192.168.73.55  
LanIn=”em0” # 192.168.56.111
skip="skipto 800"
ks="keep-state"
ipfw –q –f flush
#$cmd 014 divert natd ip from any to any via em1
#$cmd 100 allow ip from any to any
$cmd 005 allow all from any to any via $LanIn
$cmd 014 divert natd ip from any to any in via $LanOut
$cmd 015 check-state
#########################out#####################
# dns & dhcp
$cmd 030 $skip udp from any to 192.168.73.2 53,67 out via $LanOut $ks
# http(s)
$cmd 040 $skip tcp from any to any 80,443 out via $LanOut setup $ks
# mail
$cmd 041 $skip tcp from any to any 25,465,110,143 out via $LanOut setup $ks
# root
$cmd 042 $skip tcp from me to any out via $LanOut setup $ks uid root
#ping
$cmd 043 $skip icmp from any to any out via $LanOut $ks
#########################in######################
$cmd 200 deny all from 169.254.0.0/16 to any in via $LanOut
$cmd 201 deny all from 127.0.0.0/8 to any in via $LanOut
$cmd 202 deny all from 0.0.0.0/8 to any in via $LanOut
$cmd 203 deny all from 192.0.2.0/24 to any in via $LanOut
$cmd 203 deny all from 204.152.64.0/23 to any in via $LanOut
$cmd 204 deny all from 224.0.0.0/3 to any in via $LanOut
$cmd 205 deny tcp from any to any 113,137-139 in via $LanOut
$cmd 206 deny all from any to any frag in via $LanOut
$cmd 207 deny tcp from any to any established in via $LanOut
# dhcp
$cmd 300 allow udp from 192.168.73.2 to any 68 in via $LanOut $ks
# ftp
$cmd 301 allow tcp from any to me 21 in via $LanOut setup $ks
#################################################
$cmd 400 deny log all from any to any in via $LanOut
$cmd 401 deny log all from any to any out via $LanOut
$cmd 800 divert natd ip from any to any out via $LanOut
$cmd 801 allow ip from any to any
$cmd 802 deny log all from any to any

 

Этого пока хватит, теперь как это работает.
 
С компьютера в локальной сети через браузер пользователь хочет открыть сайт. Сайт работает по протоколу http и использует 80 порт. Пакет от нашего локального пользователя попадает на сервер. Проверяется его соответствие правилам, которые заданы в ipfw. А именно, это исходящий пакет на восьмидесятый порт внешнего интерфейса. Соответствующее правило находится у нас под номером 040. В этом правиле у нас есть ключевое слово keep-state, соответственно правило попадает в динамическую таблицу “keep-state”. Кроме того, так как у нас есть skipto 800 попадаем на правило 800. Правило 800 транслирует IP адрес пакета из локального во внешний, после чего выпускает его.
 
Ответный пакет от внешнего сервера попадает в начало списка наших правил. В этот раз он совпадает с правилом 014 и IP адрес его пункта назначения транслируется обратно в его адрес в локальной сети. Затем он попадает на check-state и выпускается в локальную сеть.
 
Следующий пакет от этого компьютера из локальной сети сразу попадает в check-state и выполняет skipto 800.
 
Добавим строчку в rc.conf c ключами для nat.

ee /etc/rc.conf
natd_flags="-m"

 

Ключ «m» будет пытаться по возможности сохранить номер порта уходящих пакетов. Файл rc.conf в итоге должен выглядеть примерно так:

hostname=""
ifconfig_em0="inet 192.168.56.111"
ifconfig_em1="DHCP"
defaultrouter="192.168.0.110"
 
sshd_enable="YES"
dumpdev="AUTO"
firewall_enable="YES"
firewall_script=”/etc/rc.ipfw”
 
named_enable=”YES”
gateway_enable=”YES”
natd_enable=”YES”
natd_intetface=”em1”
natd_flags="-m"

 

Перезапустим ipfw и nat.

service ipfw restart

 

Видео

Оставить комментарий