?

Log in

No account? Create an account
 
 
17 August 2016 @ 05:29 pm
Firewall FreeBSD, работаем с "открытой" системой.  

-Откуда у системы утечки?
-Они думают, что всё закрытло и прикрыто, хотя на самом деле всё дырявое при серьезном натиске, заходи кто хочешь...
-Если не прикрывают, или вне действия. Нада сделать, чтобы "заходи не бойся, - уходи не плач!"
-Сответственно на это и изжержки, если нету проработки базового и развития. Это как РФ  дырявая, и без обновлений... на маневрах, уснули навреное.

IPFW - штатный файрволл FreeBSD

Автор: lissyara.


В составе FreeBSD есть штатный файрволл - IPFW. К сожалению, раздел хандбука, ему посвящённый, до сих пор не переведён... зато в английской части эта тема неплохо окучена :) Кстати, во многом именно по этому начинающим он тяжело даётся - сам помню, как ковырялся почти две недели, пытаясь настроить его - ничё не получалось... Зато потом был миг озарения, когда я пришёл утром на работу, и, неторопясь, набрал все правила, придумывая их находу из головы. После чего отправил комп в перезагрузку и пошёл курить - абсолютно уверенный что всё работает. И оно работало. Это был момент перехода количества в качество...


Эта статья является скорее кратким переводом той аглицкой статьи из хандбука, щедро разбавленное собственным видением происходящего :)


Итак. Для включения файрволла придётся пересобрать ядро со следующими опциями:


options         IPFIREWALL               # собственно файрволл
options         IPFIREWALL_VERBOSE       # логгинг пакетов, если в правиле 
                                         # написано `log`
options         IPFIREWALL_VERBOSE_LIMIT=5 # ограничение логов (повторяющихся) - на 
                                           # случай атак типа флудинга
                                           # (я, правда, 100 ставлю)
options         IPFIREWALL_FORWARD       # перенаправление (форвардинг) пакетов
                                         # например, для прозрачного прокси
options         IPDIVERT                 # если нужен NAT (трансляция адресов)
options         DUMMYNET                 # если понадобится ограничивать скорость 
                                         # инета пользователям (обычно - да :))
options         IPFIREWALL_DEFAULT_TO_ACCEPT  # дефолтовое правило (последнее)
                                           # будет разрешающим (во всех других)
                                           # случаях - запрещающее

Кстати, ядро можно и не пересобирать - достаточно загрузить модуль при старте системы, для этого внесём строку firewall_enable="YES" в файл /etc/rc.conf и после перезагрузки файрволл заработает. Никто, кстати, не мешает сделать это и находу, без перезагрузки (советую подумать, если вы сидите на машине, по ssh прежде чем выполнять - по дефолту будет одно правило - запрещено всё), загрузив соответствующий модуль:


%su
/usr/home/lissyara/>kldload ipfw
/usr/home/lissyara/>ipfw show
65535 0 0 deny ip from any to any
/usr/home/lissyara/>

Управляется загруженный на ходу файрволл также как и обычный, некоторые специфические опции включаемые в ядро при статической сборке есть в sysctl:


/usr/home/lissyara/>sysctl -a | grep ip.fw
net.inet.ip.fw.enable: 1
net.inet.ip.fw.one_pass: 1
net.inet.ip.fw.debug: 1
net.inet.ip.fw.verbose: 1
net.inet.ip.fw.verbose_limit: 1000
net.inet.ip.fw.dyn_buckets: 256
net.inet.ip.fw.curr_dyn_buckets: 256
net.inet.ip.fw.dyn_count: 0
net.inet.ip.fw.dyn_max: 1000
net.inet.ip.fw.static_count: 294
net.inet.ip.fw.dyn_ack_lifetime: 300
net.inet.ip.fw.dyn_syn_lifetime: 20
net.inet.ip.fw.dyn_fin_lifetime: 1
net.inet.ip.fw.dyn_rst_lifetime: 1
net.inet.ip.fw.dyn_udp_lifetime: 10
net.inet.ip.fw.dyn_short_lifetime: 5
net.inet.ip.fw.dyn_grace_time: 10
/usr/home/lissyara/>

Это был вывод с тестовой машины. Кстати ipfw, статически собранный в ядре, также прекрасно рулится через sysctl:


/usr/home/lissyara/>sysctl net.inet.ip.fw.verbose_limit=10
net.inet.ip.fw.verbose_limit: 1000 -> 10
/usr/home/lissyara/>sysctl -a | grep ip.fw.verbose_
net.inet.ip.fw.verbose_limit: 10
/usr/home/lissyara/>

Учтите - эти изменения живут ровно до первой перезагрузки, если хотите чтобы они остались насовсем, то читайте тут. Вообще, глубокий смысл вкомпиляции файрволла в ядро - на мой взгляд, повышение быстродействия, и опции недоступные через sysctl.

   Если собирали ядро без опции IPFIREWALL_DEFAULT_TO_ACCEPT, или грузили его модулем, то изначально правило только одно - запрещающее. В rc.conf есть несколько опций касающихся файрволла:

firewall_enable="YES" - если файрволл грузится модулем

firewall_type="/etc/rc.firewall" - файл с правилами файрволла

firewall_logging="YES" - единственное что делает эта строка - устанавливает значение net.inet.ip.fw.verbose равным 1. Не забудте поставить лимиты, через sysctl.

   Для просмотра установленных правил файрволла есть следующие команды (а если быть точным - ключи, потому как для всего используется одно приложение):

ipfw list - показывает список правил

ipfw show - тоже показывает список правил, но вместе с числом пакетов и байт, что попали под эти правила. Очень удобно при отдладке - смотрим на чём зарубаются пакеты.

ipfw zero - обнуление всех счётчиков. Если вести в виде ipfw zero №_правила то будет обнулён только счётчик правила с этим номером.

   Вот пример простого файрволла для обычнейшей ситуации - сервер организации, одним интерфейсом смотрит в локалку, другим торчит наружу, на нём крутится почта, и работает www сервер:


#!/bin/sh

# для начала вводим переменные - для нашего же удобства, чтобы не 
# вводить по сотне раз одно и то же, а потом искать почему не работает,
# и в итоге выяснять, что ошибся IP адресом в одном из правил

FwCMD="/sbin/ipfw" # собственно где лежит бинарник ipfw
LanOut="xl0"            # внешний интерфейс
LanIn="sis0"            # внутренний интерфейс
IpOut="222.222.222.222" # внешний IP адрес машины
IpIn="192.168.20.254"   # внутренний IP машины
NetMask="24"            # маска сети (если она разная для внешней 
                        # и внутренней сети - придётся вводить ещё 
                        # одну переменную, но самое забавное, что 
                        # можно и забить - оставить 24 - всё будет 
                        # работать, по крайней мере я пробовал - 
                        # работаало на 4-х машинах, в разных сетях, 
                        # с разными масками - настоящими разными! но - 
                        # это неправильно.)
NetIn="192.168.20.0"    # Внутренняя сеть

# Сбрасываем все правила:
${FwCMD} -f flush

# Проверяем - соответствует ли пакет динамическим правилам:
${FwCMD} add check-state

# Разрешаем весь траффик по внутреннему интерфейсу (петле)
# Вообще я во многих местах читал что без него может ничё не заработать вообще
# и прочие страшилки. Работает - почта, апач, .... А вот squid - не работает :)
# так что без него и правда - никуда.
${FwCMD} add allow ip from any to any via lo0
# рубим попытки lo0 куда-то лезть и откуда-то лезть на lo0 (вот честно - ни
# одного пакета по этим правилам не зарубилось за всё время... Может в этом
# моё счастье? :))
${FwCMD} add deny ip from any to 127.0.0.0/8
${FwCMD} add deny ip from 127.0.0.0/8 to any


# Вводим запреты:
# режем частные сети на внешнем интерфейсе - по легенде он у нас 
# смотрит в интернет, а значит пакетам этим браться неоткуда на нём.
# рубим частные сeти
${FwCMD} add deny ip from any to 10.0.0.0/8 in via ${LanOut}
${FwCMD} add deny ip from any to 172.16.0.0/12 in via ${LanOut}
${FwCMD} add deny ip from any to 192.168.0.0/16 in via ${LanOut}
${FwCMD} add deny ip from any to 0.0.0.0/8 in via ${LanOut}
# рубим автоконфигуреную частную сеть
${FwCMD} add deny ip from any to 169.254.0.0/16 in via ${LanOut}
# рубаем мультикастовые рассылки
${FwCMD} add deny ip from any to 240.0.0.0/4 in via ${LanOut}
# рубим фрагментированные icmp
${FwCMD} add deny icmp from any to any frag
# рубим широковещательные icmp на внешнем интерфейсе
${FwCMD} add deny log icmp from any to 255.255.255.255 in via ${LanOut}
${FwCMD} add deny log icmp from any to 255.255.255.255 out via ${LanOut}

# а тут собственно файрволл и начался:

# отправляем всех на frox
${FwCMD} add fwd ${IpIn},2121 tcp from ${NetIn}/${NetMask} to any 21 via ${LanOut}
# отправляем всех на squid (в данном случае - прокси прозрачный)
${FwCMD} add fwd 127.0.0.1,3128 tcp from ${NetIn}/${NetMask} to any 80 via ${LanOut}


# пропускаем траффик через трансляцию сетевых адресов (NAT)
${FwCMD} add divert natd ip from ${NetIn}/${NetMask} to any out via ${LanOut}
${FwCMD} add divert natd ip from any to ${IpOut} in via ${LanOut}

# рубим траффик к частным сетям через внешний интерфейс
# заметтьте - эти правила отличаются от тех что были выше!
${FwCMD} add deny ip from 10.0.0.0/8 to any out via ${LanOut}
${FwCMD} add deny ip from 172.16.0.0/12 to any out via ${LanOut}
${FwCMD} add deny ip from 192.168.0.0/16 to any out via ${LanOut}
${FwCMD} add deny ip from 0.0.0.0/8 to any out via ${LanOut}
# рубим автоконфигуреную частную сеть
${FwCMD} add deny ip from 169.254.0.0/16 to any out via ${LanOut}
# рубаем мультикастовые рассылки
${FwCMD} add deny ip from 224.0.0.0/4 to any out via ${LanOut}
# рубаем мультикастовые рассылки
${FwCMD} add deny ip from 240.0.0.0/4 to any out via ${LanOut}


# разрешаем все установленные соединения (если они установились - 
# значит по каким-то правилам они проходили.)
${FwCMD} add allow tcp from any to any established
# разрешаем весь исходящий траффик (серверу-то в инет можно? :))
${FwCMD} add allow ip from ${IpOut} to any out xmit ${LanOut}

# разрешаем DNS снаружи (нам же надо узнавать IP по именам машин?)
${FwCMD} add allow udp from any 53 to any via ${LanOut}
# разрешаем DNS входящий снаружи - если на этой машине работает named
# и держит какую-то зону. В остальных случаях - не нужно
${FwCMD} add allow udp from any to any 53 via ${LanOut}
# разрешаем UDP (для синхронизации времени - 123 порт)
${FwCMD} add allow udp from any to any 123 via ${LanOut}
# разрешаем ftp снаружи (оба правила - для пасивного режима)
# для узнавания портранджа по которому будет работать, лезем в 
#/usr/home/lissyara/>sysctl net.inet.ip.portrange.first
# net.inet.ip.portrange.first: 49152
# /usr/home/lissyara/>sysctl net.inet.ip.portrange.last
# net.inet.ip.portrange.last: 65535
${FwCMD} add allow tcp from any to ${IpOut} 21 via ${LanOut}
#Можно изгалиться примерно так, если есть желание, но я предпочитаю руками
#${FwCMD} add allow tcp from any to ${IpOut} \
#`sysctl net.inet.ip.portrange.first | awk '{print $2}'`-\
#`sysctl net.inet.ip.portrange.last | awk '{print $2}'` via ${LanOut}
${FwCMD} add allow tcp from any to ${IpOut} 49152-65535 via ${LanOut}
# разрешаем некоторые типы ICMP траффика - эхо-запрос, 
# эхо-ответ и время жизни пакета истекло
${FwCMD} add allow icmp from any to any icmptypes 0,8,11
# открываем снаружи 80 порт - если у нас есть WWW сервер на машине
${FwCMD} add allow tcp from any to ${IpOut} 80 via ${LanOut}
# открываем снаружи 25 порт (SMTP) если на машине крутится почта
#${FwCMD} add allow tcp from any to ${IpOut} 25 via ${LanOut}
# открываем снаружи 22 порт - если надо будет ходить на машину по ssh
${FwCMD} add allow tcp from any to ${IpOut} 22 via ${LanOut}
# открываем снаружи 143 порт(если надо смотреть почту снаружи по IMAP)
${FwCMD} add allow tcp from any to ${IpOut} 143 via ${LanOut}
# открываем снаружи 110 порт(если надо смотреть почту снаружи по POP)
${FwCMD} add allow tcp from any to ${IpOut} 110 via ${LanOut}
# по поводу следующих трёх правил, для tcp, udp и icmp - их можно
# заменить одним правилом:
#${FwCMD} add allow ip from any to any via ${LanIn}
# но для удобства наладки и контроля происходящего я предпочитаю три отдельных
# правила, хотя могут быть грабли - например протокол gre не пройдёт - 
# придётся стругать отдельное правило для него, типа 
#${FwCMD} add allow gre from any to any via ${LanIn}
# итак:
# разрешаем весь tcp траффик внутри локалки (на внутреннем интерфейсе)
${FwCMD} add allow tcp from any to any via ${LanIn}
# разрешаем весь udp траффик внутри локалки (на внутреннем интерфейсе)
${FwCMD} add allow udp from any to any via ${LanIn}
# разрешаем весь icmp траффик внутри локалки (на внутреннем интерфейсе)
${FwCMD} add allow icmp from any to any via ${LanIn}
# запрещаем всё и всем. Если тип файрволла не open то это правило добавится
# автоматически, но всё-же ну его. Лучше сам. Надёжней.
${FwCMD} add deny ip from any to any

Такой вот несложный, и логически понятный файрволл. Надо заметить, что для внутренней локалки в этом фаере всё разрешено.

***********сокращено*********** полностю, на
Ссылка на обсуждение: http://forum.lissyara.su/viewtopic.php?t=277.