от Фахри Хасан(22-01-2017)

рейтинг (8)   [ добре ]  [ зле ]

Printer Friendly Вариант за отпечатване

Подробно ръководство за ipfw nat

Оригинална статия: Подробное руководство по ipfw nat
Автор: terminus

По странно стечение на обстоятелствата в интернет се намират много малко ръководства, които описват възможностите и сценарии за приложение на ipfw nat, въпреки факта, че се поддържа от дълго време - FreeBSD версия 7.0. Най-обидно е, че man секцията посветена на ipfw nat изглежда глупаво. И в действителност от там започва да чете всеки, който иска да настрои "in-kernel nat", и това е естествено - не всеки разбира. В резултат на това хората преминават към natd, някои луди глави дори започват да използват алтернативни защитни стени като pf/ipf. Целта на това ръководство е подробно описание на ipfw nat и използването на този инструмент в различни мрежови конфигурации. В тази статия ще има много смислови препратки към прекрасната статия от Вадим Гончаров (nuclight), където подробно описа вътрешната структура на ipfw и мрежовия стек на FreeBSD.

Примерите в моята статия са пробвани на FreeBSD 7.2-STABLE.


Преди всичко е необходимо да се опише детайлно движението на трафика в мрежовия стека на FreeBSD. Без това разбиране цялостната картина на "това, което правим", няма да бъде пълна. На фигури 1-а и 1-б е показана хипотетична система на два мрежови адаптера fxp0 и fxp1. Схема 1-а показва физическата връзка, а схема 1-б е логическата връзка. Нас ни интересува повече логическата - на нея ще видим, че във всяка мрежова връзка трафика има два пътя - IN и OUT. Както лесно може да се досетите, през път IN постъпва трафик, идващ към нас от мрежата, а през път OUT преминава трафика, който е адресиран да напусне мрежата, към която е свързана мрежовият адаптер. По този начин, връщайки се към примера на система с две мрежови карти, можем да видим, че тя има четири пътя за трафика. Когато добавим към системата допълнителни мрежови адаптери схемата се разширява.

Но предишната схема не е главна. Всъщност схемата на трафика през мрежовия стек на FreeBSD има само една логическа страна с пътища IN и OUT, независимо от броя на мрежови адаптери. Просто при движението на трафика през стека, операционната система избира самостоятелно път IN и/или OUT да бъде задействан при предаването на трафика. В съответствие с това, в пакета се намира вътрешна информация (хедър) за мрежовата подсистема, добавят се отметки, указващи през кой път IN (конкретен мрежови адаптер) е дошъл трафика и чрез кой OUT мрежови адаптер ще излезе от машината.



Указаните пътища IN и OUT са важни, защото при постъпването на мрежовия трафика в тях, той попадат в защитната стена, където преминава през правила за филтриране на ipfw. По този начин, трафика преминаващ през маршрутизатора, попада в правилата на ipfw два пъти – първо в път IN на мрежови адаптер, чрез който е бил получен, и в път OUT на мрежови адаптер, чрез които ще бъде препредаден (сега не разглеждаме случая с включена филтрация на ниво Ethernet - в този случай, трафика преминава през ipfw четири пъти). Както изходящия трафик от самия маршрутизатор, има свой път OUT, така и трафика адресиран непосредствено към маршрутизатора, идва през свой път IN.

По-долу представям част от статията на Вадим Гончаров – частта в която се обяснява движението на трафика чрез схема 2. Хубавото на този автор е, че в статията е включи това много, много подробно обяснение.

Допускаме, че наборът от правилата при нас е следният:

ipfw add 1 deny tcp from any to any 135,445
ipfw add 2 divert 8668 all from any to any via ext0
ipfw add 3 count icmp from any to any
ipfw add 4 allow all from any to any
# в 65535 по подразбиране deny

Когато пакета преминава през машината, системата прикрепя към съдържанието му допълнителна информация, видимо с tcpdump. Например на кой интерфейс е бил получен, чрез кой се изпраща и т.н. Това може да се провери със съответните опции в правилата на ipfw, на рисунката са показани местата, където ще сработят съответните указания in/out и recv/xmit за мрежата.

Да разгледаме по-подробно точките с функции, които се повикват в ядрото на рутера - схема 2. Всъщност, точките с функции на фигурата по-горе нямат две страни, тя е само една, и се различава по параметрите - обработени от мрежовата карта.

Това означава, че пакета на входа се предава на драйвера в ether_demux(), след това попада в ip_input(), в точка (2), където се изпълняват основни проверки за коректността на пакета, след което пакета пристига в ipfw - функция ipfw_chk(). Допускаме че, правилата са прости, без задействането на други подсистеми. Тогава, след като бъде върнат от ipfw, пакета продължава движението си по ip_input(), която следи, дали пакета е предназначен за нашата машина ("to me" от гледна точка на ipfw), или някой друг. Ако e за нас, пакета отива до точката (3), където ще се реши на кой сокет и коя програма ще го изпрати.

Ако пакета не е предназначен за нас, от ip_input() ще отиде към точката (4), където ip_forward() ще провери в sysctl, позволено ли е пренасочване, ще снижи TTL и други действия, след което пакета идва в точка (6), функция ip_output(). Тук попада директно, и когато някоя програма реши да изпрати нещо към мрежата и предаде данни към ядрото.

Функция ip_output() първо проверява в таблицата за маршрутизация и определя шлюз, и на кой интерфейс се намира. С тази информация, пакета се предава отново в ipfw и преминава през цялата поредицата от правила. После излиза от ipfw_chk() и се връща в ip_output(), ако ядрото е компилирано със съответната опция, се проверява дали не е бил променен в ipfw_chk() - ако е да, отново се проверява таблицата за маршрутизация, за да се получи MAC адреса на новия шлюз. След това в точката (7) пакета напуска ip_output() и се предава по- надолу в Layer 2, и към драйвера на интерфейса.

Това беше всичко в случая с простите правила на защитната стена. Сега да предположим, че там се появява divert, да разгледаме примера на гореописаните правила. Пакет, който ще отиде в интернет на порт 80, когато пристигне на вътрешния интерфейс в точка (1), преминава първоначална ip_input() проверка в (2), предава се в ipfw_chk() и започва проверка по правилата. Той не попада в 1-во правило, под 2-ро също, там има интерфейс на името int0, правило 3 отново не сработва, но правило 4 подхожда на всички пакети, и той излиза от ipfw_chk() и се връща в ip_input(). Там се изяснява, къде в интернет е предназначен да отиде, следователно пакета попада в точката (4) и след това (6), където ip_output() определя адреса на шлюза и че интерфейсът ще е ext0, с тази информация пакета попада отново в ipfw_chk() и наново преминава по правилата. Правило 1 отново не се вписва, но условието на правило 2 сработва - "via ext0, премини през интерфейс ext0 в правилното дестинация".

И тук работи divert - пакета от ipfw_chk() се предава в точка (8), в подсистемата divert, с предварително прикрепена метаинформация с посока (out), интерфейс (ext0) и номера на правило 2. Подсистема divert предава пакета в указания в правилото порт (8668), на който в нашият случай работи natd. Той обработва пакета, метаинформацията същото и връща променения пакет в подсистема divert, както следва (така постъпват повечето divert демони, въпреки че всеки от тях може да промени тази информация, и пакета ще бъде изпратен на друго място).

Подсистемата divert прехвърля получения пакет от natd от точки (9) в точката (6). Обърнете внимание - пакета попада в ip_output() ОТНОВО! Това е необходимо, защото демонът може да върне пакета с напълно различен адрес или дори да създадете нов пакет. Но в нашия случай, пакета носи divert tag, метаинформация, най-важната част от която е номера на правилото. При влизане в ipfw_chk() пакета първото се проверява за наличието на този маркер. Ако бъде открит и съдържа номер на правило (в случая 2), ipfw_chk() пропуска проверката на правила 1 и 2, и започва с цифрата 2 + 1, т.е. 3 (ако проверката на пакета започне от правилото с указаният номер, а не от следващото, той отново ще попадне на divert, т.е. ще се получи безкраен цикъл).

На този етап пакета продължава движението по правило 3 и след това отива в точка (7) в мрежата. По този начин, въпреки факта, че пакета е попаднал в ip_output() два пъти, от гледна точка на потребителя това изглежда, сякаш пакета е бил там веднъж и не е излизал извън защитната стена - просто на правило 2 се получава магически начин за промяна адреса и порта.

По аналогичен начин, пакета който се връща от интернет на интерфейс ext0, преминава през машината по пътя (1) - (2) - началото на ipfw_chk() - правило 1 - правило 2 – (8) - divert - natd - (9) - (2) - проверкa в ipfw_chk() - правило 3 - правило 4 - (4) - (6) - началото на ipfw_chk() - правило 1 - правило 2 - правило3 - правило 4 - (7) - изпращане през интерфейс int0.

Подобно е поведението на пакета след обработка от ipfw в друга подсистема – то не е уникално за divert, това е обща схема на работа на FreeBSD стека. Например, действия pipe и queue в dummynet предават пакета в netgraph (и така се появява в 7.0 ipfw nat) действа на този принцип. Разликата обаче е, че в тази подсистема пакета остава в ядрото, не се предава на демон. Затова на първо място в по-горната подсистема вместо номера на правилото се запазва пълният указател, и пакета се връща непосредствено към следващото правило, даже и да има същият номер. На второ място, за такива подсистеми действа настройката one_pass в sysctl - ако е включена, при повторно влизане на пакета в ipfw, след завръщането си от подсистема dummynet (netgraph), ipfw_chk() веднага връща пакета без да премине през правилата, сякаш към пакета е приложен allow. Това поведение позволява опростяване правилата на защитната стена, когато е известно, ако пакета попадне в тръбата (pipe), той се отправя напред и не е необходимо след всяко pipe правило да се поставя allow (за да не попадне пакета в следващо правило и следващите pipe/queue). Ако конфигурацията изисква, първо трябва да се ограничи трафика и след това да се разберат сложните изисквания, за някои ще бъде разрешено, а за някои забранено, за опростяването на правилата, правилният набор ще бъде включване на one_pass - вместо allow, до pipe правилата, би трябвало да се направи skipto.

И така, както вече беше казано, пакета преминава през поредицата от правила последователно, във възходящ ред на правилата. Поредицата от правилата може да се разглежда като таблица с три колони: номер, действие (и неговите параметри, като log), както и условията, при които един пакет отговаря на правилото (например от адрес 1.1.1.1 до адрес 2.2.2.2). Таблицата се разглежда отгоре надолу, пакета се сравнява с условията. При първо съвпадение по стълбицата, се изпълнява действие и спираме наблюдението ...

Вече знаем, в каква последователност излиза пакета през мрежовия стек на FreeBSD, ние можем да пристъпим към изучаване правилата на ipfw nat.

Механизма ipfw nat може да се разгледа като своеобразен филтър – преобразувател на трафика. В зависимост от това как е настроен nat и от това какви IP адреси на подател и получател, ще бъдат предадени чрез него, nat ще преобразува IP адреса на подателя или IP адреса на получателя, или просто ще отхвърли пакета. Важно е да запомните, че nat разделя трафикa на изходящ (такъв, който се маскира) и входящ (такъв, който се демаскира) в зависимост от това през какъв път (OUT или IN) е бил получен. Така че, трафика попаднал в nat през път OUT трябва да се маскира (заменя се IP адреса на подателя с IP адреса на nat машината), а трафикът който идва през път IN да се демаскира. За да разберем това поведение, може да използвате директивата revers - тогава цялото поведение ще се промени и може да бъде пуснат nat на външния мрежови интерфейс (който следи в интернет) и на вътрешния (който следи в локалната мрежа). Подробно описание за това как работи механизма на nat, вероятно е излишно. За поведението на механизма на nat влияе настройката на параметъра one_pass - в зависимост от него, трафика преминаващ през nat може да се върне в защитната стена, от където е бил изпратен в nat или да излезе от защитната стена. Тази гъвкавост позволява да се направят много интересни неща с трафика. ipfw nat ви позволява да стартирате много своите копия, всеки от които има свои nat таблици и настройки. Не трябва, да се обединяват няколко копия, за да се използва общата nat таблица.

Възможности и опции за конфигуриране на ipfw nat

ipfw nat е базиран на кода на библиотеката libalias. На нея е изграден както natd така и ng_nat. Функционалността на libalias е пренесена в ipfw nat, практически напълно повтаря всичко, което има в natd с изключение на някои специфични неща. За съжаление man страницата за ipfw nat дава много оскъдно описание на възможностите му, за това при изучаване на опциите за конфигуриране, може да използвате man страницата на natd.

man natd

Примери и сценарии за приложение на ipfw nat механизма

След като се запознахме с принципа на предвижване на трафика през стека, както и опциите за конфигуриране механизма на ipfw nat, може да пристъпим към създаването на правила и да разгледаме тяхната работа. Долните примери, ще бъдат основани на принципа "задача - решение", и така на този принцип постепенно, ще се усложнява конфигурацията с подробно описание и ще бъдат обяснени предполагаемите решения. Ако има мнения, спомагащи по-лесно да се разбере изучавания материал, в това число и примери, могат да се използват в работата.

Включване на ipfw nat и Dummynet

Прекомпилиране на ядрото с допълнителните параметри:
options IPFIREWALL
options IPFIREWALL_VERBOSE
options IPFIREWALL_VERBOSE_LIMIT=50
options IPFIREWALL_nat
options LIBALIAS
options ROUTETABLES=2
options DUMMYNET
options HZ="1000"

Или включване без прекомпилиране (но с по-малко възможности за конфигуриране)

/etc/rc.conf
firewall_nat_enable="YES"
dummynet_enable="YES"


Пример 1

Прост случай: рутер с два мрежови адаптера включени в локалната мрежа и в интернет. Адрес на локалната мрежа 192.168.1.1 (мрежови адаптер fxp0), адрес в интернет 1.2.3.4 (мрежови адаптер em0).
Задача: „раздаване на интернет“ за локална мрежа, обезпечен при повикване на порт за вътрешни адреси, разрешаване преминаването на трафика през отделните портове на този рутера.


Конфигурация:

/etc/rc.conf
gateway_enable="YES"
ifconfig_em0="inet 1.2.3.4 netmask 255.255.255.0 -rxcsum"
ifconfig_fxp0="inet 192.168.1.1 netmask 255.255.255.0"
defaultrouter="1.2.3.254"
firewall_enable="YES"
# Бележка: разгледайте /etc/defaults/rc.conf и /etc/rc.firewall във FreeBSD 11
firewall_type="/etc/firewall"

/etc/sysctl.conf

net.inet.ip.fw.one_pass=1

/etc/firewall
# правила разрешаващи трафик през локалния интерфейс lo0
# ще бъдат добавени автоматично при стартиране на защитната стена
# ipfw add 100 allow ip from any to any via lo0
# ipfw add 200 deny ip from any to 127.0.0.0/8
# ipfw add 300 deny ip from 127.0.0.0/8 to any

# разрешаваме всичко през интерфейса за локалната мрежа
ipfw add 1040 allow ip from any to any via fxp0

# боим се от неизвестни
ipfw add 1050 deny ip from any to 192.168.0.0/16 in recv em0
ipfw add 1060 deny ip from 192.168.0.0/16 to any in recv em0
ipfw add 1070 deny ip from any to 172.16.0.0/12 in recv em0
ipfw add 1080 deny ip from 172.16.0.0/12 to any in recv em0
ipfw add 1090 deny ip from any to 10.0.0.0/8 in recv em0
ipfw add 10100 deny ip from 10.0.0.0/8 to any in recv em0
ipfw add 10110 deny ip from any to 169.254.0.0/16 in recv em0
ipfw add 10120 deny ip from 169.254.0.0/16 to any in recv em0

# настройка на nat.
# опцията за пренос на нов ред "\", трябва да се отстрани, всичко трябва да е на един ред
# опциите redirect_port са примерни - как да се направи "пренасочване на порт"
ipfw nat 1 config log if em0 reset same_ports deny_in \
redirect_port tcp 1.2.3.4:6881 6881 \
redirect_port udp 1.2.3.4:4444 4444 \
redirect_port tcp 192.168.1.24:25 25

# пренасочваме всичко, което преминава през външния интерфейс към nat
ipfw add 10130 nat 1 ip from any to any via em0

# боим се от неизвестни
# Бележка: във FreeBSD 11 модула ipfw е компилиран, по подразбиране с deny
ipfw add 65534 deny all from any to any


Детайлно описание за преминаването на трафика през защитната стена в дадената конфигурация:

За рутера:

Трафика инициализиран непосредствено от рутера в точка (5) - рисунка 2, преминава в точка (6). Попаднал в ip_output(), ще му бъде присвоен шлюз по подразбиране с мрежови интерфейс em0, през който е длъжен да излезе в интернет (via em0, по-точно xmit em0). Когато трафика влезе в защитната стена, започва да минава през поредицата от правила. Трафика идва до правило 10130 и бива предаден в точка (8), ако се обработва в nat като изходящ трафик, ще постъпи в път OUT. В подсистема nat за трафика, ще бъде създаден запис за съответствие в таблицата за съединения, както следва: локално_IP:порт отдалечено_IP:порт. После в точка (9) трафика излиза от подсистема nat и се предава за обработка в точка (6), отново попада в ip_output(). Ако one_pass има стойност 1 (включен), трафика излиза от ipfw (сякаш към него е приложено правило allow) и отива в интернет през em0.

Трафика, който се връща като отговор, отива в точка (1) и попада в път IN, името на този мрежовия интерфейс е em0 (via em0, по-точно recv em0), през който е получен. По-нататък трафика отива в точка (2) и попада във функция ip_input(), после отива в защитната стена и започва да минава през поредицата от правила. Трафика идва до правило 10130 и бива предаден в точка (8), ако се обработва в nat като входящ трафик, ще постъпи в път IN. В подсистема nat за трафика, ще бъде намерен по-рано създадения запис за съответствие от таблицата за съединения, както следва: локално_IP:порт отдалечено_IP:порт, след което ще се демаскира (в този случай няма да има действителни изменя, тъй като маскиране/ демаскиране на адреса е едно и също – локален/1.2.3.4). После в точка (9) трафика излиза от подсистема nat и се предава за обработка в точка (2), отново попада в ip_input(). Ако one_pass има стойност 1 (включен), трафика излиза от ipfw (сякаш към него е приложено правило allow) и отива в локалния сокет, на който работи програма за ранно инициализиране на съединенията.

Ако от интернет дойде трафик, за който няма запис за съответствие в таблицата за съединения, при постъпване в nat, той ще бъде отхвърлен, сякаш nat e настроен с параметър deny_in.

Ако от интернет пристигне трафик адресиран за tcp 1.2.3.4:6881, той ще дойде до точка (8) и ще попадне в nat, където ще бъде успешно демаскиран, в таблицата за него ще има статичен запис съответстващ на 1.2.3.4:6881 отдалечено_IP:отдалечен_порт. После както е в случая с трафик, който се връща като отговор от интернет, ще бъде приет и ще постъпи в локалния сокет на порт 6881. Съответно, изходящия трафик от този сокет преминава през статичното правило и ще бъде обработен успешно, както е в случая с изходящия трафик към интернет.

За мрежа 192.168.1.0/24:

Трафика инициализиран от хост 192.168.1.56, от мрежа 192.168.1.0/24, ще влезе в рутера през мрежови интерфейс fxp0, в точка (1) получава tag на мрежови интерфейс fxp0 (via fxp0, по-точно recv fxp0), през който е получен. После трафика отива в точка (2) и попада във функция ip_input(), след това влиза в защитната стена и започва да минава през поредицата от правила. Трафика идва до правило 1040 и се предава в път IN на защитната стена, и попада обратно в ip_input(), където ще бъде прието решение, че той не е за нас, следователно трябва да се изпрати в точка (4), във функция ip_forward(). Когато попадне в ip_forward(), ще се снижи TTL-а на IP трафика, освен това ще се провери, дали е разрешено извършването на маршрутизация (установяване на съответните стойност в sysctl, които се прилагат в rc.conf чрез gateway_enable="YES"), тогава ще бъде предаден в точка (6), във функция ip_output(). Попаднал в ip_output() на него ще бъде присвоен шлюз по подразбиране и tag на мрежови интерфейс em0, през който е длъжен да излезе в интернет (via em0, по-точно xmit em0). Трафика влиза в защитната стена и започва да минава през поредицата от правила. Трафика идва до правило 10130 и бива предаден в точка (8), ако се обработва в nat като изходящ трафик, ще постъпи в път OUT. В подсистема nat за трафика, ще бъде създаден запис за съответствие в таблицата за съединения, както следва: 192.168.1.56:порт 1.2.3.4:порт отдалечено_IP:порт, а оригиналния адрес на подателя (192.168.1.56) в хедъра, ще бъде заменен с IP адреса указан в параметър „if“ в настройка nat. После в точка (9) трафика излиза от подсистема nat и се предава за обработка в точка (6), отново попада в ip_output(). Ако one_pass има стойност 1 (включен), трафика излиза от ipfw (сякаш към него е приложено правило allow) и отива в интернет през em0 с IP адрес на подател 1.2.3.4.

Трафика, който се връща като отговор, отива в точка (1) и попада в път IN, името на този мрежовия интерфейс е em0 (via em0, по-точно recv em0), през който е получен. По-нататък трафика отива в точка (2) и попада във функция ip_input(), после отива в защитната стена и започва да минава през поредицата от правила. Трафика идва до правило 10130 и бива предаден в точка (8), ако се обработва в nat като входящ трафик, ще постъпи в път IN. В подсистема nat за трафика, ще бъде намерен по-рано създадения запис за съответствие от таблицата за съединения, както следва: 192.168.1.56:порт 1.2.3.4:порт отдалечено_IP:порт, след което ще се демаскира – адреса на получателя в хедъра, ще бъде заменен от 1.2.3.4 на 192.168.1.56. После в точка (9) трафика излиза от подсистема nat и се предава за обработка в точка (2), отново попада в ip_input(). Ако one_pass има стойност 1 (включен), трафика излиза от път IN на защитната стена (сякаш към него е приложено правило allow) и попада обратно в ip_input(), където ще бъде прието решение, че той не е за нас, следователно трябва да се изпрати в точка (4), във функция ip_forward(). Когато попадне в ip_forward(), ще се снижи TTL-а на IP трафика, освен това ще се провери, дали е разрешено извършването на маршрутизация (установяване на съответните стойност в sysctl, които се прилагат в rc.conf чрез gateway_enable="YES"), тогава ще бъде предаден в точка (6), във функция ip_output(). Попаднал в ip_output() на него ще бъде присвоен шлюз по подразбиране и tag на мрежови интерфейс fxp0, през който е длъжен да отидете в локалната мрежа (via fxp0, по-точно xmit fxp0). Трафика влиза в защитната стена и започва да минава през поредицата от правила. Трафика идва до правило 1040. После този трафик излиза от ipfw и отива в локалната мрежа през fxp0 с IP адреса на получателя 192.168.1.56.

Ако от интернет дойде трафик, за който няма запис за съответствие в таблицата за съединения, при постъпване в nat, той ще бъде отхвърлен, сякаш nat e настроен с параметър deny_in.

Ако от интернет пристигне трафик адресиран за tcp 1.2.3.4:25, той ще дойде до точка (8) и ще попадне в nat, където ще бъде успешно демаскиран, в таблицата за него ще има статичен запис съответстващ на 192.168.1.24:25 1.2.3.4:25 предпочитан_IP:предпочитан_порт. После както е в случая с трафика, който се връща като отговор от интернет, ще бъде приет и ще премине по същия маршрут през IN и OUT, ще отиде в локалната мрежа на хост с IP 192.168.1.24. Съответно, изходящия трафик от IP 192.168.1.24, преминава през статичното правило и ще бъде обработен успешно, както е в случая с изходящия трафик към интернет.

Надолу при разглеждането на другите конфигурации, аз повече няма да описвам детайлно всички случаи. За разбирането на този механизъм, долното описание ще бъде достатъчно и може да преминем към останалите конфигурации. Детайлните описания ще бъдат там, където е необходимо.

Пример 2

Един по-сложен случай: рутер с два мрежови адаптера включени в локалната мрежа и в интернет. Адрес на локалната мрежа 192.168.1.1 (мрежови адаптер fxp0), адрес в интернет 1.2.3.4 и 1.2.3.5 (мрежови адаптер em0).

Задача: „раздаване на интернет“ за локална мрежа, обезпечен при повикване на порт за вътрешни адреси, разрешаване преминаването на трафика през отделните портове на този рутера, а главно – използване на шейпър Dummynet, за да осигури справедливо разпределение на пропускателната способност между клиентите в локалната мрежа. Да се осигури пренасочване на целия трафик към 1.2.3.5 на 192.168.1.36 с използване на redirect_addr.



/etc/rc.conf


gateway_enable="YES"
ifconfig_em0="inet 1.2.3.4 netmask 255.255.255.0 -rxcsum"
ifconfig_em0_alias0="inet 1.2.3.5 netmask 255.255.255.255"
ifconfig_fxp0="inet 192.168.1.1 netmask 255.255.255.0"
defaultrouter="1.2.3.254"
firewall_enable="YES"
firewall_type="/etc/firewall"


/etc/sysctl.conf

net.inet.ip.fw.one_pass=0


/etc/firewall

ipfw add 1040 allow ip from any to any via fxp0

ipfw add 1050 deny ip from any to 192.168.0.0/16 in recv em0
ipfw add 1060 deny ip from 192.168.0.0/16 to any in recv em0
ipfw add 1070 deny ip from any to 172.16.0.0/12 in recv em0
ipfw add 1080 deny ip from 172.16.0.0/12 to any in recv em0
ipfw add 1090 deny ip from any to 10.0.0.0/8 in recv em0
ipfw add 10100 deny ip from 10.0.0.0/8 to any in recv em0
ipfw add 10110 deny ip from any to 169.254.0.0/16 in recv em0
ipfw add 10120 deny ip from 169.254.0.0/16 to any in recv em0

ipfw pipe 1 config bw 10Mbit/s queue 60 gred 0.002/10/30/0.1
ipfw queue 1 config pipe 1 queue 60 mask src-ip 0xffffffff gred 0.002/10/30/0.1

ipfw pipe 2 config bw 10Mbit/s queue 60 gred 0.002/10/30/0.1
ipfw queue 2 config pipe 2 queue 60 mask dst-ip 0xffffffff gred 0.002/10/30/0.1

ipfw nat 1 config log if em0 reset same_ports deny_in \
redirect_port tcp 1.2.3.4:6881 6881 \
redirect_port udp 1.2.3.4:4444 4444 \
redirect_port tcp 192.168.1.24:25 25

ipfw nat 2 config log same_ports redirect_addr 192.168.1.36 1.2.3.5

ipfw add 10130 skipto 10190 ip from 192.168.1.36 to any out xmit em0
ipfw add 10140 skipto 10210 ip from any to 1.2.3.5 in recv em0

ipfw add 10150 queue 1 ip from any to any out xmit em0
ipfw add 10160 nat 1 ip from any to any via em0
ipfw add 10170 queue 2 ip from any to any in recv em0

ipfw add 10180 allow all from any to any

ipfw add 10190 queue 1 ip from any to any out xmit em0
ipfw add 10200 nat 2 ip from 192.168.1.36 to any out xmit em0
ipfw add 10210 nat 2 ip from any to 1.2.3.5 in recv em0
ipfw add 10220 queue 2 ip from any to any in recv em0

ipfw add 10230 allow all from any to any

ipfw add 65534 deny all from any to any

Детайлно описание за преминаването на трафика през защитната стена в дадената конфигурация:

Настройката на параметъра queue mask 0xffffffff е указан за това, че динамичните редове ще бъдат създавани въз основа на разликата на предпочитаните битове от IP адреса на подателя или получателя. Скоростта на изходящия и входящия трафик, ще бъде ограничена под 10 Mbit/s.

За рутера:

Трафика инициализиран непосредствено от рутера преминава през поредицата от правила на ipfw в път OUT до правило с номер 10150. Трафика попада в Dummynet и отива в динамично създадената опашка и тръба, в резултат на което скоростта на изходящия трафик се ограничава до 10Mbit/s. След като излезе от Dummynet трафика се връща в защитната стена (тъй като е изключен параметъра one_pass) и попада в правило 10160. След като премине през nat, трафика отново се връща в защитната стена и идва до правило 10180, излиза от защитната стена и отива във външната мрежа.

Ответния трафик преминава през път IN на защитната стена до правило 10160, където попада в nat и се демаскира (в долния случай е несъществено) и се приема в nat, тъй като вече има активно съединение. Излизайки от nat, трафика попада в правило 10170 и се предава в Dummynet и отива в динамично създадената опашка и тръба, в резултат на което скоростта на входящия трафик се ограничава до 10Mbit/s. След като излезе от Dummynet трафика се връща в защитната стена и попада в правило 10180, където ще бъде разрешен и ще излезе от защитната стена в сокет програма инициализираща съединенията.


Ако в рутера дойде случаен трафик от интернет, той ще премине през правило 10160 и ще бъде отхвърлен, сякаш nat e настроен с параметър deny_in.

Трафик идващ на порт 6881, 4444 и 25, ще бъде заведен в nat на правило 10160, после в Dummynet на правило 10170, а след това се пропуска или до самия рутер, или до хост 192.168.1.24 съответно.

За IP адреси 192.168.1.36 и 1.2.3.5

Трафика идващ от интернет на външен IP адрес 1.2.3.5 е длъжен да бъде пренасочен към 192.168.1.36. Когато такъв трафик премине през път IN на защитната стена, той ще бъде обработен в правило 10140, което ще прехвърли обработката на 10210 – трафика ще бъде предаден във второ копие на nat, където ще се извърши демаскиране (IP адрес 1.2.3.5 на получателя, ще бъде заменен с 192.168.1.36). После този трафик се връща в защитната стена и през правило 10220 попада в Dummynet. Излизайки от там се връща в защитната стена и идва до правило 10230, после излиза то път IN на защитната стена и отива в път OUT, където идва до правило 1040 и се приема, излиза от защитната стена, и се изпраща на 192.168.1.36.

Ответния трафик (както и друг предпочетен изходящ трафик) от 192.168.1.36 преминава през 1040 в път IN, след това в път OUT през 10130, 10190, 10200 и 10230, после отива във външната мрежа.

За мрежа 192.168.1.0/24:

Трафик идващ от мрежата 192.168.1.0/24 (например от хост с IP 192.168.1.24), ще мине през мрежов адаптер fxp0 в път IN на защитната стена и ще дойде до правило 1040, после ще излезе от IN и ще бъде позволен. Трафика ще отиде в път OUT, където ще премине през правилата до 10150. Трафика попада в Dummynet и отива в динамично създадената опашка и тръба, в резултат на което скоростта на изходящия трафик ще се ограничи до 10Mbit/s. След като излезе от Dummynet трафика се връща в защитната стена (тъй като параметър one_pass e изключен) и попада в правило 10160. След като премине през nat, трафика се връща в защитната стена и идва до правило 10180, където излиза от защитната стена и отива във външната мрежа.

Ответния трафик преминава през път IN на защитната стена до правило 10160, където попада в nat и се демаскира и се приема в nat, тъй като вече има активно съединение. Излизайки от nat, трафика попада в правило 10170 и се предава в Dummynet, и отива в динамично създадената опашка и тръба, в резултат на което скоростта на входящия трафик ще се ограничи до 10Mbit/s. След като излезе от Dummynet трафика се връща в защитната стена и попада в правило 10180, където ще бъде разрешен и ще излезе от път IN на защитната стена. Трафика попада в път OUT на защитната стена, където идва до правило 1040, излиза от защитната стена, и се изпраща на мрежа 192.168.1.0/24 през адаптер fxp0.

Ако в рутера дойде случаен трафик от интернет, той ще премине през правило 10160 и ще бъде отхвърлен, сякаш nat e настроен с параметър deny_in.


Бележка: За повече примери вижте оригиналната статия. Тази статия е преведена, за да разбера по-добре механизма на работа на мрежовия стек на FreeBSD. С оглед оскъдните ръководства за FreeBSD на български език, надявам се, превода да бъде полезен и на други.

Превод: Моника Александрова и Веселин Александров
Редакция: Фахри Хасан
Актуален превод: FreeBSD


<< | Mikrotik + Openvpn + android >>