IPTABLES II Elkészült az Iptables 2. része ami teljes mértékben az első részre épül. Igyekszem mindent gyakorlati példákkal szemléltetni. Igaz a dokumentum főleg a gyakorlatra szorítkozik, mégis van egy két rész ahol elengedhetetlen valamennyi elméleti rész kifejtése. TARTALOM – Saját láncok létrehozása – IP és|vagy MAC alapján történő szűrés (IP or MAC filter) – ICMP szűrés – hogyan lehet korlátozni az illeszkedések számát – Port forward – Hálózati címfordítás (NAT) – forgalom számlálás (transfer counting) Jelenlegi tűzfalunk így néz ki (IPTABLES I. rész): #!/bin/bash # modulok betolltese modprobe ip_conntrack_ftp iptables iptables iptables iptables iptables
-F -X -P INPUT DROP -P OUTPUT DROP -P FORWARD DROP
# INPUT lanc iptables -A INPUT iptables -A INPUT iptables -A INPUT iptables -A INPUT
-i -m -j -j
lo -j ACCEPT state --state ESTABLISHED,RELATED -j ACCEPT LOG --log-prefix "INPUT_DROP: " DROP (nem fontos)
# OUTPUT lanc iptables -A OUTPUT -o lo -j ACCEPT iptables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT iptables -A OUTPUT -p tcp -m multiport --dport 20,21,22,25,80,110,143,443,465,993,995,1863,6667 -j ACCEPT iptables -A OUTPUT -p udp --dport 53 -j ACCEPT iptables -A OUTPUT -j LOG --log-prefix "OUTPUT_DROP: " iptables -A OUTPUT -j DROP (nem fontos)
Kipróbáltam: internet (DNS,HTTP,HTTPS,) FTP, levelezés (POP3,SMTP), IRC, MSN, Skype. Ezeket próbáltam ki ezzel a tűzfallal és megy minden. Saját láncok létrehozása Előfordulhat, hogy saját láncot szeretnénk létrehozni. Ennek ezer oka lehet, ha pl.: valamivel kiemelten szeretnénk foglalkozni. Mi most a hamis forráscímről érkező csomagokat „küldjük” egy saját láncra ahol külön foglalkozunk vele.
Tegyük fel, hogy a mi interfészünk (ami legyen eth0) IP címe 82.321.112.321. (Szándékosan írtam ezt a példát, hogy véletlenül se egyezzen valós IP címmel. A valóságban 255 lehet egy oktett maximális értéke, de ebbe hosszú lenne belemenni, és nem feltétlenül tartozik a témához.) Az IP címünket az ifconfig paranccsal tekinthetjük meg. eth0
Link encap:Ethernet HWaddr NA:ez:Az:hE:9jA:cD inet addr:82.321.122.321 Bcast:255.255.255.255 Mask:255.255.254.0 inet6 addr: fefe::100:fifi:feri:caca/ca Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:241396 errors:0 dropped:0 overruns:0 frame:0 TX packets:331809 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:27705142 (26.4 MiB) TX bytes:350623261 (334.3 MiB) Interrupt:16 Base address:0x6000
Egyszerűbb formában: $ ifconfig eth0 | grep "inet addr" | cut -d ":" -f 2 | awk {'print $1'}
(Ha az eth0-át elvesszük akkor megkapjuk az összes interfészük IP címét.) Az IP címeket alapvetően 5 osztályba sorolják, de hármat használunk rendszeresen a világban, A,B és C osztályú címek. Az A 24 bit, a B osztályban 16 bit a C osztályban 8 bit szolgál a gépek megcímzésére. Vannak „privát” IP címek melyeket magáncélra, belső hálózatokban használnak. Ezekről a külvilág nem tud, így akárhány alhálózatban használhatjuk őket. Privát címeket csak privát/belső hálózatban használunk. Az interneten lévő eszközöknek csak publikus IP címük lehet, melyből nem lehet kettő egyforma. (Ugyan így nem lehet egy privát belső hálózatban sem két egyforma IP-val rendelkező eszköz) Éppen ezért nem valószínű, hogy valódi csomagokat kapnánk ilyen forrás címekről. A privát címtartományok a következők: "A" osztályú hálózathoz: 10.0.0.0/8 "B" osztályú hálózathoz: 172.16.0.0/16 (- 172.31.0.0) "C" osztályú hálózathoz: 192.168.0.0/16 (- 192.168.255.0 (A hálózati maszkok jelentését sem írnám le. Rengeteg erről szóló dokumentum található az interneten a TCP/IP alapok témakörben.) Ezekről tehát biztos nem kapunk fontos csomagokat, így tiltsuk le őket. De szeretnénk a biztonság kedvéért ezeket az eldobott csomagokat külön loggolni, hogy megnézhessük eredményes e a beállítás. Tegyük hát külön láncba, hogy egyszerűbb dolgunk legyen. Ehhez létre kell hozni egy új láncot. Legyen a neve in_attack. (Szándékosan írom kis betűvel.) Lássuk a szabályokat: iptables -N in_attack iptables -A INPUT -i eth0 -s 10.0.0.0/8 -j in_attack iptables -A INPUT -i eth0 -s 172.16.0.0/16 -j in_attack
iptables -A INPUT -i eth0 -s 192.168.0.0/16 -j in_attack
Új opció a „-s”. Ezzel adjuk meg a forráscímet|címeket. Ezzel a leírás későbbi részében részletesebben foglalkozok. Láthatjuk, hogy a -j kapcsolóval nem egy default láncba irányítottam az eldobni kívánt csomagokat hanem a saját láncunkba ami jelenleg üres, pedig szeretnénk ezeket a csomagokat loggolni majd törölni: iptables -A in_attack -j LOG --log-prefix ”HAMIS_FORRAS_IP_CIM” iptables -A in_attack -j DROP
A ”-A|--append” opcióval a saját láncunkba tesszük ezeket a szabályokat. Vagyis minden ebbe a láncba érkező csomagot loggol majd eldob. ! Saját láncnak nem kell megadni default policy-t. IP és/vagy MAC alapján történő szűrés (IP or MAC filter) Talán inkább szerveren hasznos ez a funkció, de előfordulhat, hogy bizonyos szolgáltatásokhoz (a gépünkön) nem szeretnénk ha mindenki hozzáférne. Viszont akinek szeretnénk engedélyezni tudjuk az IP címét (statikus, - tehát nem változik automatikusan) vagy a MAC címét. (hálózati interfész fizikai címe). IP szűrés Megadhatunk egy IP címet is, vagy egy IP tartományt is. Megadhatjuk, hogy forráscímre szűrünk vagy célcímre. Példa: iptables -A INPUT -i eth0 -s 82.133.122.133 -p tcp --dport 80 -j ACCEPT
Ezzel a szabállyal csak a megadott IP címről férhetnek hozzá a webszerverünkhöz ami a 80/TCP port. Előfordulhat, hogy egy szervergépünk van ami 8 alhálózathoz kapcsolódik, és csak az egyik alhálózatnak szeretnénk tiltani a hozzáférést a webszerverünkhöz. Ehhez nem kell írni 7 szabályt, elég egyet amit ”tagadunk”. iptables -A INPUT -i eth0 -s ! 192.168.2.32/27 -p tcp --dport 80 -j ACCEPT
A felkiáltó jellel azt mondjuk, hogy bármire jó, csak arra nem ami utána áll. A felkiáltó jel után kell egy szóköz! MAC szűrés Lehetőség van a forrás ethernet kártyájának a MAC címére szűrni. Kapcsolója a
-m mac --mac-source. Példa: iptables -A INPUT -p tcp --dport 22 -m mac --mac-source 00:01:02:03:04:05 -j ACCEPT
A MAC cím csak kitalált, amikor kipróbáltam, valósat használtam. Ez a szabály azt mondja, hogy csak a megadott MAC címmel rendelkező kártya felől enged be SSH kapcsolatot. (Figyelem: MAC hamisítás létezik.) ICMP szűrés El akarunk rejtőzni? Vagy csak nem szeretnénk hogy meg lehessen pingelni minket? Ezzel nem lehet teljesen levédeni magunkat, de sokan hisznek ennek a hasznosságában. Először is ismernünk kell az ICMP típusokat. Internetről 1 perc alatt le lehet tölteni: http://www.iana.org/assignments/icmp-parameters A -p icmp --icmlp-type kapcsolóval adhatunk meg icmp típusokat. Ha nem szeretnénk, hogy a gépünk válaszoljon a ping kérésekre: (egyébként sem válaszol a default DROP policy miatt) iptables -A INPUT -p icmp --icmp-type echo-request -j DROP
Szemléltetés miatt kipróbálhatjuk, ezt a négy szabályt: iptables -A INPUT -p icmp --icmp-type echo-request -j LOG --log-prefix "ping_ACCEPT: " iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT iptables -A OUTPUT -p icmp --icmp-type echo-reply -j LOG --log-prefix "ping_DROP: " iptables -A OUTPUT -p icmp --icmp-type echo-reply -j DROP
és pingessük meg magunkat egy másik gépről. Valami ilyesmi lesz: Aug 24 00:47:33 budacsik-desktop kernel: [16456.722458] ping_ACCEPT: IN=eth0 OUT= MAC=xxxxxxxxx SRC= 82.323.122.323 DST= 82.321.112.321 LEN=84 TOS=0x00 PREC=0x00 TTL=55 ID=0 DF PROTO=ICMP TYPE=8 CODE=0 ID=30330 SEQ=1 Aug 24 00:47:33 budacsik-desktop kernel: [16456.722492] ping_DROP: IN= OUT=eth0 SRC= 82.321.112.321 DST= 82.323.122.323 LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=55656 PROTO=ICMP TYPE=0 CODE=0 ID=30330 SEQ=1 Aug 24 00:47:34 budacsik-desktop kernel: [16457.721670] ping_ACCEPT: IN=eth0 OUT= MAC= xxxxxxxxx SRC= 82.323.122.323 DST= 82.321.112.321 LEN=84 TOS=0x00 PREC=0x00 TTL=55 ID=1 DF PROTO=ICMP TYPE=8 CODE=0 ID=30330 SEQ=2 Aug 24 00:47:34 budacsik-desktop kernel: [16457.721703] ping_DROP: IN= OUT=eth0 SRC= 82.321.112.321 DST= 82.323.122.323 LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=55657 PROTO=ICMP TYPE=0 CODE=0 ID=30330 SEQ=2
A példa jól mutatja, hogy a gépünk beengedi az icmp kéréseket, de a választ nem engedjük ki. Persze ennek nincs értelme, csak szemléltetésre jó, hogy lássuk, hogyan is működik.
Hogyan lehet korlátozni a csomagok illeszkedések számát A -m limit --limit kapcsolót nagyon jól lehet használni pl.: naplózásnál, vagy ha korlátozni szeretnénk az SSH csatlakozásának számát egy percen belül. Rengeteg indokot lehet felsorolni, hogy miért hasznos ez a kapcsoló. Lássunk is egy példát:
iptables -A INPUT -p tcp --dport 22 -m limit --limit 3/m -j LOG --log-prefix "SSH_ACCEPT: " iptables -A INPUT -p tcp --dport 22 -m limit --limit 3/m -j ACCEPT
Note: Ha ilyen szigorú a beállítás arra figyelni kell, hogy egy SSH támadás alatt állunk, - amikor másodpercenként több kéréssel próbálkoznak – akkor a támadás idejéig mi sem tudunk kapcsolódni a szerverhez. Hacsak előtte a mi IP címüket nem engedélyeztük külön.
Megadhatunk másodpercet (s), percet(m), órát(h), napot(d). A fenti példa percenként három ssh connect-et enged, és ez látszik is a logokban. Ki lehet próbálni, szemléltetésnek szintén nagyon jó. A ping válaszcsomagok korlátozása már okos dolog lehet! Note: csináltam egy tesztet, hogy ha van egy szabályunk pl.: iptables -A INPUT -p icmp --icmp-type echo-request -m limit --limit 3/m -j ACCEPT
Három pinget enged be percenként. A többit egyszerűen tovább engedi a listán hiszen nem match-elt a limit miatt. Így az utolsó szabályom az INPUT láncban eldobta: (iptables -A INPUT -j DROP) Ha limitálom a pingeket pl.: 1/m, vagyis egyet engedek be percenként akkor az első 5 ping kérésre válaszol, utána viszont már csak percenként egyet. SSH kapcsolat kéréssel viszont ugyanez jól működik, de azért inkább biztosra menjünk. Ez azért van, mert fentebb nem voltam pontos. Percenként 3 alkalommal enged be 5 csomagot. Honnan jön az öt? A --limit-burst alapértelmezett értéke 5. Helyesen így néz ki a szabály: iptables -A INPUT -p icmp --icmp-type echo-request -m limit --limit 3/m -limit-burst 1 -j ACCEPT
Ez azt jelenti, hogy 3 megfelelés percenként (--limit 3/m) egy csomagra (-limit-burst 1).
Hálózati címfordítás (NAT – Network Address Translation) A NAT a mi netfilter rendszerünkön áthaladó forrás vagy cél IP címeinek vagy portjainak módosítását végzi. Legáltalánosabb használata amikor egy belső hálózat számára szeretnénk internet hozzáférést biztosítani, s így a (S)NAT segítségével a szerveren keresztül haladó (kifelé) forrás privát IP címeket lehet megváltoztatni a szerver publikus címére. Így egyetlen publikus IP címmel egy egész vállalat képes a világhálóra kapcsolódni. Három része van : – SNAT – DNAT – MASQUERADE Erre nézünk egy példát. Erre a célra az SNAT-ot kell használni, ami a source vagyis forrás címet változtatja meg. Belső hálózat --> Gateway(átjáró) --> Internet privát IP SNAT publikus IP Konkrét példa: Privát IP cím: 192.168.2.1/24 Publikus IP cím: 83.321.221.421 Belső hálózat: | | 192.168.2.1 \ | | 192.168.2.1 \ | forrás IP csere | 192.168.2.2 --|>--> SNAT -|>--> ... /| | 192.168.2.99 / | | | |
83.321.221.421
Az összes belső hálózati felhasználó ugyan azt az IP címet fogja használni amikor az interneten kommunikálnak. Kapcsolatkövetésnek köszönhető, hogy a csomagok vissza is találnak a megfelelő privát IP-címhez. A kapcsolatkövetés miatt egy adatfolyamnak csak az első csomagja fog illeszkedni szabályra, a többi automatikusan megy utána. Amikor visszafelé jönnek a csomagok akkor az SNAT a célcímet fogja módosítani 83.321.221.421-ről a megfelelő belső hálózati címre. Ahhoz, hogy leírjunk egy ilyen szabályt 2 új láncot kell megérteni: POSTROUTING és PREROUTING. Az SNAT a POSTROUTING-ot fogja használni,a DNAT pedig a PREROUTING-ot. Tehát a fogalom zavar tisztázására: SNAT: Source-NAT, forrás cím vagy port szám megváltoztatása a POSTROUTING láncban. DNAT: Destination-NAT: cél cím vagy port szám megváltoztatása a PREROUTING láncban. MASQUERADE: címálcázás, (-j MASQUERADE) az SNAT egyik típusa. Megváltoztatja a kimenő csomagok forrás címét a sajátjára, mintha azok tőle
mentek volna ki a világhálóra. PREROUTING: az INPUT, OUTPUT és a FORWARD láncok után ez a kettő beépített lánc van még összesen. A PREROUTING még az INPUT lánc előtt hajtódik végre, rögtön miután egy hálózati csatolótól megérkezik a csomag. POSTROUTING: pedig az OUTPUT lánc után hajtódik végbe, épp mielőtt elhagyná a csomag a hálózati csatolót. Nézzünk egy kis ábrát még meg a csomagok útjáról: -> PREROUTING -> routing -> FORWARD -> POSTROUTING -> | ^ | routing ˇ | INPUT OUTPUT | | ˇ ^ helyi folyamat helyi folyamat Ezeket belépési pontoknak is nevezik, én is most így nevezem, hogy érthető legyen a magyarázat. Egy csomag először a PREROUTING belépési pontra érkezik a netfilter (csomagszűrés) rendszerbe. Ezután a routing eldönti, hogy lokális gépnek szól e a csomag vagy sem. Ha igen belép az INPUT belépési pontba, ha nem akkor a FORWARD belépési ponton halad keresztül. Ha egy csomag a lokális gépről indul, rögtön az PUTPUT belépési ponton halad keresztül, majd a routing eldönti, hogy mely interfésznek szól a csomag és a FORWARD ponton keresztül haladó csomagokkal együtt a POSTROUTING belépési pontba kerülnek ahol még mindig van lehetőség a csomag megváltoztatására. Had jegyezzem meg, hogy a POSTROUTING és a PREROUTING nem tartozik a csomagszűrés folyamatához. Az már csomag manipuláció amit ezekben a láncokban végzünk. Nézzünk konkrét szabály példát egy belső hálózat (S)NAT-olására: iptables -t nat -A POSTROUTING -o eth1 -s 192.168.2.0/24 -j SNAT
A NAT táblát használva, a POSTROUTING belépési pontban megváltoztatjuk a 192.168.2.0/24-es hálózati forráscímekkel rendelkező összes csomag forráscímét az átjáró (vagy szerver, gateway) saját IP címére (arra ami az eth1nek az IP címe). Ez az eset azt feltételezi, hogy statikus IP címünk van. Ha dinamikus akkor a -j SNAT helyett -j MASQUERADE -et kell írni, ami megbírkózik azzal is ha dinamikus IP címünk van. Ez az eset azt is feltételezi, hogy az eth1 a publikus IP-címet birtokló hálózati interfész. Ahhoz, hogy ez működjön be kell kapcsolni a port forward-ot is két interfész között. echo "1" > /proc/sys/net/ipv4/ip_forward
Ez a parancs egy 1-est illeszt az ip_forward fájlba, ami annyit tesz, engedélyezve. Alapértelmezetten 0. Mikor használható a DNAT? Vajon mikor lehet szükség arra, hogy egy csomag célcímét és|vagy célportját megváltoztassuk? Ez a következő rész fő témája. Port forward DNAT: akkor lehet használni ha saját publikus IP címmel rendelkező gépünk van, és szeretnénk ha a tűzfalra érkező bizonyos kéréseket egy belső gép szolgálja ki aminek privát IP címe van. Konkrét példa: Van egy kis vállalat akiknek van 3 szerverük, egy FTP, egy web és egy levelező szerver. Mind a három fizikailag külön szerver, de a vállalatnak csak egyetlen publikus IP címe van. DNAT segítségével tudják működtetni mind a három szervert. FTP szerver: 192.168.0.1 Web szerver: 192.168.0.2 Levelező szerver: 192.168.2.3 Publikus IP: 82.321.112.321 Iptables szabályok: echo "1" > /proc/sys/net/ipv4/ip_forward iptables -t nat -A PREROUTING -i eth0 -p destination 192.168.0.1:21 iptables -t nat -A PREROUTING -i eth0 -p destination 192.168.0.1:80 iptables -t nat -A PREROUTING -i eth0 -p destination 192.168.0.1:25 iptables -t nat -A PREROUTING -i eth0 -p destination 192.168.0.1:110
tcp --dport 21 -j DNAT --totcp --dport 80 -j DNAT --totcp --dport 25 -j DNAT --totcp --dport 110 -j DNAT --to-
Nem szabad elfelejteni, hogy ezzel sikerült ugyan a port továbbítás, de a csomagok hogyan is fognak kinézni visszafelé? A forráscím interneten ismert publikus IP lesz, ezért nem fog visszatalálni. Ezért mielőtt elhagyja a csatolónkat át kell írni a forráscímet a gw privát IP-címére (192.168.0.254) iptables -t nat 192.168.0.254 iptables -t nat 192.168.0.254 iptables -t nat 192.168.0.254 iptables -t nat 192.168.0.254
-A POSTROUTING -o eth1 -p tcp --dport 21 -j SNAT --to-source -A POSTROUTING -o eth1 -p tcp --dport 80 -j SNAT --to-source -A POSTROUTING -o eth1 -p tcp --dport 25 -j SNAT --to-source -A POSTROUTING -o eth1 -p tcp --dport 110 -j SNAT --to-source
Igy biztosak lehetünk benne, hogy a csomagok visszatalálnak a szerverig. Ezenkívül a sikeres port forward-hoz kell még: iptables-A iptables-A iptables-A iptables-A
FORWARD FORWARD FORWARD FORWARD
-d -d -d -d
192.168.0.1 192.168.0.2 192.168.0.3 192.168.0.3
-p -p -p -p
tcp tcp tcp tcp
--dport --dport --dport --dport
21 -j ACCEPT 80 -j ACCEPT 25 -j ACCEPT 110 -j ACCEPT
Forgalom számlálás Tegyük fel, hogy a bejövő forgalmat szeretnénk számlálni az eth0 interfészen. (Megjegyzem, ugyan így kell a kimenő vagy átmenő forgalmat is számlálni.) Egy nagyon egyszerű szabályt kell beillesztenünk az INPUT lánc legelső szabályaként. Fontos, hogy ez legyen a legelső szabály, mert erre minden csomagnak (a későbbiekben elfogadott és visszautasított) illeszkednie kell a pontos számlálás érdekében, és a rendszer a szabályokat fentről lefelé kezdi értelmezni. Erre minden alkalommal oda kell figyelni. Tehát: iptables -A INPUT -i eth0
Ezután generáljunk egy kis forgalmat, mondjuk böngésszük a netet, vagy töltsünk le egy fájlt. Majd a következő parancsot kell kiadni: sudo iptables -L INPUT -v -n
”-L” listáz, az ”INPUT” láncot csak, ”-v”-vel kérünk részletesebb információt és a ”-n” kapcsolóval azt érjük el, hogy az IP címeket és a port számokat írja ki, hostnevek és portnevek helyett. Célt nem kell adni, így ezen a szabályon egyszerűen „átfolynak” a csomagok. A legelső sorban kell nézni az első két oszlopot. Első oszlop: – pkts (csomagszám) – bytes (össz. csomagméret) pkts 8902
bytes target 10M
prot opt in 0 -- eth0
out *
source 0.0.0.0/0
destination 0.0.0.0/0
Az én esetemben 8902db csomag érkezett be aminek össz. mérete: 10MB. Ha a tűzfalat újra lefuttatjuk ezek a számlálók lenullázódnak.
Szerző: Budácsik Attila (budacsik) Elérhetőségek:
[email protected] [email protected] Licenc: A dokumentum szabadon másolható, de nem módosítható. A dokumentumot tilos pénzért, vagy bármilyen járandóságért árusítani. Minden jog a szerzőnek van fenntartva. További információk: Az esetleges hibákért a szerző nem vállal felelősséget. A szövegben felfedezett hibákat és észrevételeket a Makay József email-címére kérjük. Minden jog fenntartva! © SKL-Projekt