|
Превод: Светослав Генов (Inventive)
Connection_tracking Какво е connection tracking? Connection tracking се обяснява с възможноста да поддържате дадена информация за връзките в таблица, като предназначение и сорс на IP адресите и сътветните портове, видове протоколи, изтичане на времето и състояние на връзката. Firewall-и които правят това са познати като stateful. На stateful firewall-ите им е присъща по-голяма сигурност отколкото на тяхните "stateless" дубликати ... прости пакетни филтри. Connection tracking се извършва със state опцията в iptables. От man страницата: state Този модул когато се комбинира с connection tracking, позволява достъп до connection tracking състоянията за този пач. --state state Кадето state е списък разделен със запетайки за в сяка state връзка която съвпада. Валидните states са INVALID значещ че пакетът е асоцииран като непозната връзка, ESTABLISHED което означава че пакетът е асоцииран като връзка която може да вижда пакети и в двете посоки, NEW значещ че пакета е започнал нова връзка, или по друг начин казано с връзка която не вижда пакети в двете посоки, и RELATED означаващо че пакета започва нова връзка, но е асоцииран с вече създадена връзка, нещо като FTP дата трансфер, или ICMP грешка. Connection tracking се изпълнява през PREROUTING веригата, или OUTPUT веригата за локално генерирани пакети. Connection tracking дефрагментира всички пакети преди да проследи тяхното положение. Това обяснява защо няма ip_always_defrag както имаше в 2.2 кернела. State таблицата за udp и tcp връзки се намира в /proc/net/ip_conntrack. Ще дискутираме съдържанието и по-долу. Максималният брой връзки които state таблицата може да съдържа се намира в /proc/sys/net/ipv4/ip_conntrack_max. Първоначално тази стойност твърдо е зададена от това колко физическа памет имате (на моята 512 Mb машина, ip_conntrack_max по начало е 32760). Как работи connection tracking? Бърз поглед За пренасочването на пакети м/ интерфейсите серията от вериги ще бъде : 1) PREROUTING веригата - DNAT пакета ако е нужно. Разделяме пакетите ако е нужно. Connection tracking се дефрагментира и проследява (класифицира) пакета по някакъв начин : Ако пакетът съвпада с входа от state таблицата то тогава това е част от ESTABLISHED връзката. Ако е icmp трафик може да бъде RELATED към udp/tcp връзка която вече е в state таблицата. Пакетът може да стартира NEW връзка, или да не е свързан към нито една връзка в който случай се смята че е INVALID. 2) FORWARD веригата - Сравнява състоянието на пакетите срещу правилата в таблицата за филтриране докате първото съвпадне, или докато началната политика на веригата се изпълни. 3) POSTROUTING веригата - SNAT пакет ако е нужно. Забележете, че всички пакети се сравняват с правило в филтър таблицата. Това лесно се доказва - ако имате декларирани в state таблицата и промените правилото да забранява всичкият трафик, тогава входът вписан в state таблицата остава, целият трафик е със сигурност отхвърлен както трябва да е. Повече информация Ще разгледаме всеки един от трите протокола, udp, tcp и icmp поред. UDP Понеже при него липсват редица числа, udp е още познат като 'stateless' протокол. Както и да е, това не означава че ние не можем да проследим udp връзките. Има още много полезна информация която можем да използваме. Ето примерен вход от state таблицата за новоформирана udp връзка : udp 17 19 src=192.168.1.2 dst=192.168.1.50 sport=1032 dport=53 [UNREPLIED] src=192.168.1.50 dst=192.168.1.2 sport=53 dport=1032 use=1 За набор от правила създадени в началото на deny базирана конфигурация, този вход на state таблицата може да бъде направен ако има филтриращо правило от iptables което позволява NEW връзки, нещо като следното правило което позволява NEW връзки : iptables -A INPUT -p udp -m state --state ESTABLISHED -j ACCEPT iptables -A OUTPUT -p udp -m state --state NEW,ESTABLISHED -j ACCEPT Нещата които можем да разберем от входа на state таблицата са :
UDP прекъсванията се настройват в /usr/src/linux/net/ipv4/netfilter/ip_conntrack_proto_udp.cat по време на компилиране. Ето това са нещата които трябва да се променят : #define UDP_TIMEOUT (30*HZ) #define UDP_STREAM_TIMEOUT (180*HZ) Единична заявка ще се добави в state за 30*HZ (30 секунди). В примера по-горе, кадето имаме 19 секунди оставащи, 11 секунди са вече изтекли без да бъде получен отговор. Веднъж щом отговорът е приет и позволен от правилото ESTABLISHED връзки, прекъсването се слага отново на 30 секунди и UNREPLIED маркировката се маха. Тук виждаме връзка която е заела мястото си след няколко секунди : udp 17 28 src=192.168.1.2 dst=192.168.1.50 sport=1032 dport=53 src=192.168.1.50 dst=192.168.1.2 sport=53 dport=1032 use=1 Ако имаме много заявки и се появят отговори между едни и същи двойки сокети, входът се смята като поток и прекъсването се слага на 180 секунди. Тук виждаме връзката няколко секунди след като е заела мястото си: udp 17 177 src=192.168.1.2 dst=192.168.1.50 sport=1032 dport=53 src=192.168.1.50 dst=192.168.1.2 sport=53 dport=1032 [ASSURED] use=1 Можем да видим, че входът е маркиран като ASSURED. Веднъж щом връзката е станала ASSURED те няма да бъдат прекъснати при голямо претоварване. Ако state таблицата е пълна например и нова връзка се появи, входовете маркирани като UNREPLIED се прекъсват като превигилировани. Няма абсолютно прекъсване за udp връзките (или tcp връзките), трафика си продължава да си тече. TCP TCP връзката се открива чрез тройно захващена включващо синхронизирана молба от клиента, синхронизацията и потвърждението от сървъра, и най-накрая потвърждението от клиента. Следващият трафик течящ между сървъра и клиента е потвърден във всякакъв случай. Редът изглежда така: Client Server SYN ---> <--- SYN+ACK ACK ---> <--- ACK ACK ---> ......... ......... SYN и ACK се онсаят към сложените флагове в tcp хиидъра. Също така има и 32 бита ред и потвърждаващи номера в tcp хиидъра, които се подават напред назад и се преработват по време на сесията. За да подкарате проследяването на tcp връзката ви трябва правило, което изглежда така: iptables -A INPUT -p tcp -m state --state ESTABLISHED -j ACCEPT iptables -A OUTPUT -p tcp -m state --state NEW,ESTABLISHED -j ACCEPT Обяснение Това, което ще правим сега е да минем през осъществяването на нормална tcp връзка, да погледе state таблицата за всяко ниво и да ги обсъдим: 1) Веднъж щом осъщественият SYN е пратен към OUTPUT веригата, и приет от правило, което позволява NEW връзка, входът от таблицата за връзките може да изглежда по следния начин: tcp 6 119 SYN_SENT src=140.208.5.62 dst=207.46.230.218 sport=1311 dport=80 [UNREPLIED] src=207.46.230.218 dst=140.208.5.62 sport=80 dport=1311 use=1 Статусът на TCP връзката е SYN_SENT и е маркирана като UNREPLIED. 2) Сега чакаме да престигне SYN+ACK, след кето state на tcp връзката се променя на SYN_RECV и UNREPLIED изчезва: tcp 6 57 SYN_RECV src=140.208.5.62 dst=207.46.230.218 sport=1311 dport=80 src=207.46.230.218 dst=140.208.5.62 sport=80 dport=1311 use=1 3) Сега ще чакаме за финалната част от захващането, ACK. Когато пристигне проверяваме поредицата от номера които съвпадат със ACK от захващането от сървърът към клиентът. State на tcp връзката сега вече е ESTABLISHED и входът от state таблицата е маркиран като ASSURED (ASSURED връзките не се прекъсват от state таблицата когато връзката е твърде натоварена). Тук виждаме една ESTABLISHED връзка : tcp 6 431995 ESTABLISHED src=140.208.5.62 dst=207.46.230.218 sport=1311 dport=80 src=207.46.230.218 dst=140.208.5.62 sport=80 dport=1311 [ASSURED] use=1 Преспективи на state таблицава на connection tracking Туко що говорихме доста за state на tcp връзките. Нека сега разгледаме това от преспективата на connection tracking: Connection tracking използва само NEW, ESTABLISHED, RELATED и INVALID, класифицирани както са описани по горе в iptables man страницата. Ще цитирам Joszef Kadlecsik, който ми помогна за този проблем : Когато пакет с SYN+ACK флагове се появи като отговор на пакет с SYN connection tracking си мисли: "Туко що видях пакет с SYN+ACK който отговори с SYN който видях преди това, така че това е ESTABLISHED връзка." Важното тук е че conntrack states не са еквивалентни на tcp states. Вече видяхме че връзката не осъществява tcp връзка със статус ESTABLISHED докато ACK след SYN+ACK не е получен. Репрезентацията на tcp state връзката в state таблицата е напълно за прекъсванията. Можете да си докажете това като изпратите ACK пакет през вашият firewall до несъществуваща машина (така че да не получите RST обратно). Ще създаде без проблемно вход от state таблицата защото това е първият пакет от връзката а и също така се смята като NEW (входът няма да бъде маркиран като ASSURED). Ако съдим по фактите ACK пакетите могат да създадат входове от state таблицата. За да се уверите че NEW tcp връзките са пакети с SYN, използвайте следното правило : iptables -A INPUT -p tcp ! --syn -m state --state NEW-j DROP Забележете, че правейки това вие ще прекратите idle сесията от продължаване, веднъж щом те са изтегки от conntrack таблицата. В нормалното "relaxed" виждане подобни връзки създадени в правилната посока (т.е посоката през която позволявате NEW пакети да приминат) могат да продължат нормално независимо дали са изтекли в conntrack, също така първият data/ack пакет продължава връзката идвайки от правилната посока. Ако искате наистина stateful филтриране което се нужнае от правилно осъществена връзка и проследява поредица от номера, добавете tcp-window-tracking пача от patch-o- matic. Прекъсвания Нещо което трябва да спомена, е че прекъсванията се слагат отново на максимум всеки път връзката види трафик. Прекъсванията се слагат в usr/src/linux/net/ipv4/netfilter ip_conntrack_proto_tcp.c при компилиране. Ето часта която трябва да се промени : static unsigned long tcp_timeouts[] = { 30 MINS, /* TCP_CONNTRACK_NONE, */ 5 DAYS, /* TCP_CONNTRACK_ESTABLISHED, */ 2 MINS, /* TCP_CONNTRACK_SYN_SENT, */ 60 SECS, /* TCP_CONNTRACK_SYN_RECV, */ 2 MINS, /* TCP_CONNTRACK_FIN_WAIT, */ 2 MINS, /* TCP_CONNTRACK_TIME_WAIT, */ 10 SECS, /* TCP_CONNTRACK_CLOSE, */ 60 SECS, /* TCP_CONNTRACK_CLOSE_WAIT, */ 30 SECS, /* TCP_CONNTRACK_LAST_ACK, */ 2 MINS, /* TCP_CONNTRACK_LISTEN, */ }; Няма пълно прекъсване за връзките. Connection termination Connection termination се среща по два начина. Естественото завършване в краят на сесията се среща когато клиентът изпраща пакет с FIN и ACK флагове. Закриването се извършва по следният начин: Client Server ......... ......... FIN+ACK ---> <--- ACK <--- FIN+ACK ACK ---> Понякога през, или в края на този цикъл, статусът на state таблицата се промена на TIME_WAIT и входът се премахва след 2 минути по подразбиране. Друг начин за connection termination се среща ако някоя изпрати пакет с RST (reset) флаг. RST не се приемат. В този случай статусът на state таблицата се промена на CLOSE и изтича след 10 секунди. Това често се случва с http заявки, когато сървърът изпраща RST след период на пасивност. ICMP На езика на iptables, има само четири вида icmp които могат да се категоризират като NEW, или ESTABLISHED: 1) Echo request (ping, 8) и echo reply (pong, 0). 2) Timestamp request (13) и reply (14). 3) Information request (15) и reply (16). 4) Address mask request (17) и reply (18). Заявката във всеки случай е класифицирана като NEW и отговорът като ESTABLISHED. Други видове на ICMP не са request-reply базирани и могат да бъдат само RELATED към други връзки. Нека да разгледаме няколко примера и правила: iptables -A OUTPUT -p icmp -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT iptables -A INPUT -p icmp -m state --state ESTABLISHED,RELATED -j ACCEPT 1) icmp echo request е NEW и така е допуснат в OUTPUT веригата. 2) icmp echo reply, стига само да отговаря на echo request, е ESTABLISHED и така е допустим в INPUT веригата. echo reply не може да се допусне в OUTPUT веригата заради правилата по горе защото няма NEW в INPUT веригата да позволи echo заявки и отговорът трябва да бъде в отговор с заявката. 3) icmp redirect, защото не е request-reply базиран и е RELATED, така че може да бъде допуснат в двете INPUT и OUTPUT вериги стига само да има вече tcp или udp връзка в state таблицата, която може да съвпадне отново. Connection tracking и ftp Първоначално трябва да заредите ip_conntrack_ftp модулът. Предполагайки че имате една домашна машина; просто правило позволяващо ftp връзките ще бъде: iptables -A INPUT -p tcp --sport 21 -m state --state ESTABLISHED -j ACCEPT iptables -A OUTPUT -p tcp --dport 21 -m state --state NEW,ESTABLISHED -j ACCEPT (Моля да обърнете внимание, че предполагам че имате отделни правила позволяващи всякакви icmp RELATED връзки. Моля да видите примерът ми за това). Това не е цялата история. ftp връзката се нуждае също така от data-channel, който също така може да бъде един от двата: 1) Active ftp FTP клиентът изпраща номерът на портът през ftp канал чрез PORT команда към ftp сървърът. Тогава ftp сървърът се свързва от 20 порт на този порт и изпраща информация, като файл, или изходът на команда. За да позволите active ftp без да знаете номерът на портът който се използва, ще ви трябва правило което позволява връзки от 20 порт от ftp сървъри до големи портове (портове > 1023) на ftp клиентите. Просто това е толкова общо за да бъде защитено. Включете ip_conntrack_ftp модулът. Този модул може да разпознае PORT команда и да отвори порт. Също така, ftp-data връзката може да се класифицира като RELATED към оригиналната изхождаща вризка от 21 порт, така че не ни трябва NEW като state съвпадение за връзката в INPUT веригата. Следните правила ще обслужат нуждите ни: iptables -A INPUT -p tcp --sport 20 -m state --state ESTABLISHED,RELATED -j ACCEPT iptables -A OUTPUT -p tcp --dport 20 -m state --state ESTABLISHED -j ACCEPT 2) Passive ftp Отново се използва PORT командата, но този път е от сървърът към клиента. Клиентът се свързва към сървърът за трансфер на данни. Откакто връзката е със същото значение както оригинална ftp връзка, passive ftp е по защитено от active ftp, но обърнете внимание, че този път дори незнаем портовете. Сега имаме връзка м/ почти произволни портове. Включете още един път ip_conntrack_ftp модула. Този модул може да разпознае PORT команда и да отвори порт. Вместо NEW в state съвпадението на OUTPUT веригата, можем да използваме RELATED. Следните правила ще ви задоволят: iptables -A INPUT -p tcp --sport 1024: --dport 1024: -m state --state ESTABLISHED -j ACCEPT iptables -A OUTPUT -p tcp --sport 1024: --dport 1024: -m state --state ESTABLISHED,RELATED -j ACCEPT
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||








