Tűzfal tervezés, építés

Ennek a leírásnak a célja, hogy ismertessen bizonyos alapelveket amiket figyelembe kell venni Linuxos tűzfal építésekor. Fontos az alapos tervezés, és a megfelelő lépések becsületes végrehajtása. Továbbá célja, hogy megértesse kezdő rendszergazdákkal, hogy miért fontos egy tűzfal rendes, igényes beállítása, és saját példáimon keresztül mutatom be, hogy mennyi időt és energiát spórolhat meg az a rendszergazda vagy IT-felelős ember, aki megfelelő körültekintéssel telepített tűzfalat a rendszere védelmére.

! Ez a dokumentáció nem tekinthető teljes referenciának. Csupán szerény tapasztalatom szülte, amivel próbálok másoknak segíteni, és remélem a bírálatokból tovább fejlődhet egy teljesebb (akár) referencia dokumentumnak.

Mik ezek a lépések? Milyen szempontokat kell figyelembe venni?

Egy rossz példa!

A rossz példa én leszek. Az első komolyabb tűzfalam előtt igyekeztem minél többet olvasni az iptables-ről, és próbáltam elsajátítani, hogy utána nagyon biztonságos tűzfalat építsek. Az első lépés a tervezés volt. Ez annyiból állt, hogy felírtam egy papírra kb a következőket:

  • A szervernek milyen interfészei vannak
  • Milyen szolgáltatásokat kell elérni bentről (belső hálózat, LAN)
  • Milyen szolgáltatásokat kell elérni kintről (internet felől, INT)
  • Milyen szolgáltatásokat érhetnek el a kliensek a szerveren keresztül

Ez nem volt rossz kezdés, de kimaradt pár lépés:

  • Biztonsági lépések.Biztonsági hibák felderítése. Mert minden lánc csak annyira erős mint a leggyengébb láncszem. Hiába szűrök mindent, ha nincs a láncok végén egy DROP szabály, vagy a policy ACCEPT marad.
  • Szabályok sorrendje, és spagetti kód. Fontos, hogy azok a szabályok előrébb legyenek amikre több csomag match-el (illeszkedik). Igaz, hogy ez több száz szabálynál és nagyobb terhelésnél jön elő, de tervezéskor sosem csak a jelenlegi igényeket vegyük szemügyre. És itt a következő pont.
  • Előre tervezés. Nem árt ha használunk például ciklusokat, változókat és egyéb bash nyújtotta eszközöket, hogy a kódunk szép és átlátható legyen, valamint ha már nem mi fogjuk kezelni, akkor az új kolléga is hamar megismerje a kódot. Ehhez elengedhetetlen a helyes, ésszerű kommentezés. Ésszerű alatt azt értem, hogy nem feltétlenül kell egy szabály fölé 3-10 sor komment. Legyen rövid, és leíró. Változókkal segíthetjük, az interfészek dokumentálását, és változás esetén gyors felcserélését. Nem kell replace, sed és egyéb ?furmányos” eszközhöz nyúlni :).

Én elkövettem jó pár hibát, emiatt pár hónap múlva ránézve a kódomra, nehezen ismertem ki magam.

  • Nem volt, vagy alig komment.
  • Minden szabály egymás alatt, rendezetlenül, logikátlanul, és még csak alig több mint 50 sor volt ekkor
  • ifconfig-al nézegettem, hogy melyik interfész mi is. ?Nah, megint elfelejtettem, melyik is az eth2?” Akkor megint ifconfig…

Nem volt egyszerű, ezt komolyan mondom. És nem egyszerű az elejéről kezdeni mindent. A felhasználóknak nem szabad, hogy megszakadjanak a szolgáltatások, nem zavarhatjuk őket a munkában, a főnökről nem is beszélve. Tehát éjjel vagy hétvégén… Kell ez?!

Akkor szedjük össze, hogyan kezdjünk neki a tervezésnek.

  • A szervernek milyen interfészei vannak
  • Milyen szolgáltatásokat kell elérni bentről (belső hálózat, LAN)
  • Milyen szolgáltatásokat kell elérni kintről (internet felől)
  • Milyen szolgáltatásokat érhetnek el a kliensek a szerveren keresztül
  • Biztonsági lépések.
  • Szabályok sorrendje.
  • Saját láncok használata.
  • Ciklusok és változók használata.
  • Fontosabb kernel paraméterek megismerése és helyes beállítása.
  • Tesztelési terv felépítése, ne rögtönözzünk. Tervezzük meg a tesztelést is!

Nem írtam a tesztelésről, pedig fontos. Nem akartam kihagyni :) Ezt első alkalommal is elég jól, de rögtönözve végeztem. Szerencsém volt, ennyi.

A továbbiakban feltételezzünk egy kis irodai hálózatot. Mondjuk egy magán vállalkozás. Mindegy mi, de legyen mondjuk könyvelői iroda :)

Akkor menjünk sorba.

A szervernek milyen interfészei vannak?

Tegyük fel, hogy most csak két interfész van:

  • eth0 a belső hálózat felé néz
  • ppp0 egy ADSL kapcsolat.

Joggal feltételezhetjük, hogy ez a könyvelő iroda nőni fog, vagy költözni. Tök mindegy, nevezzük el az interfészeket, és kommentezzük fel őket:

# Belső hálózat
LAN="eth0"

# Internet
INT="ppp0"

Itt felmerül egy probléma. Lehet, hogy a későbbiek során kelleni fog a ppp0 ip címe. Viszont nem írhatjuk be fixen, mert tudjuk (mert tudjuk), hogy hacsak nem kértünk fix IP-t felárért, akkor ez dinamikus IP cím. Akkor alkalmazhatjuk a következő példát:

INT_IP=$(ifconfig ppp0 | grep "inet addr" | sed 's/:/ /g' | awk '{print $3}')

Biztos van ennél egyszerűbb megoldás is. Ez nem kötelező, lehet, hogy nem fog kelleni, a gondolkodás mód a lényeg. Ez a tervezés alatt kiderül majd, hogy fog e kelleni ehhez hasonló infomáció.

Ami fontos, hogy a továbbiakban az interfészekre $INT és $LAN-ként hivatkozzunk a tűzfal scriptben.

Milyen szolgáltatásokat kell elérni bentről (belső hálózat, LAN)

Ez alatt azt értem, hogy milyen szerver szolgáltatásokat? A könyvelői irodában legyen mondjuk egy

  • Belső levelező szerver (mert minden utasításról szeretik van van e-mail, és a szerveren egy biztonsági másolat)
  • Samba szerver (A munkákat ide lehet menteni, vagy fájlokat megosztani egymással)
  • Könyvelő szoftver (Tegyük fel, hogy van egy szerver <-> kliens alapú szoftverük amivel dolgoznak.)

A szolgáltatásokat felírtuk, írjuk fel az ehhez szükséges portokat és protokollokat.

Belső levelező szerver (25 és 110). Erősen ajánlott titkosított SMTP és IMAP használata!!

Samba szerver:

netbios-ns	137/tcp				# NETBIOS Name Service
netbios-ns	137/udp
netbios-dgm	138/tcp				# NETBIOS Datagram Service
netbios-dgm	138/udp
netbios-ssn	139/tcp				# NETBIOS session service
netbios-ssn	139/udp
microsoft-ds	445/tcp				# Microsoft Naked CIFS
microsoft-ds	445/udp

Könyvelő szoftver. Ezt megtaláltuk a szoftver dokumentációjában. TCP 33555.

Pontosan meg kell határozni, – ami utánajárást, vagy kitesztelést igényel – hogy melyik portot milyen módon kell ki illetve beengedni. Nem szabad ész nélkül mindet kinyitni. Lehet, hogy működi fog, de nem ez a végleges cél. Hanem egy biztonságoz és használható tűzfal építése. Ennek a dokumentációnak pedig most nem feladata, hogy leírja, pontosan milyen portokat kell kinyitni sambahoz szerver oldalon. Én egyszer kiteszteltem, azóta jól megy. Nyitogattam megosztásokat, s közben figyeltem mit dob el a tűzfal, és azokat engedélyeztem. Kb 10 perc munka ha már kézreáll…

Milyen szolgáltatásokat kell elérni kintről (internet felől)

Talán semmit, talán egy VPN vagy/és egy FTP szervert esetleg. Minél kevesebbet. Itt is érvényes, hogy pontosan meg kell határozni, hogy milyen portot melyik irányba. Lesz több feltétel is a biztonság résznél részletezem.

Milyen szolgáltatásokat érhetnek el a kliensek a szerveren keresztül

Talán szükséges engedélyezni, hogy tudjanak külső SMTP szervert is használni, mert a vállalat hivatalos emailszervre egy szerverparkban van. Ekkor a TCP 25-ös portot át kell engedni a szerveren, ám ezt sem ész nélkül. Biztonság résznél lesz erről is szó.

Biztonsági lépések.

  • Minden szabály végén legyen egy mindent loggol (naplóz) majd eldob szabály. Szokták mondani, hogy a policy is legyen DROP. De ha a láncok végi naplóz és eldob szabályok bent vannak, akkor felesleges a policy-t bántani.
  • Egy szabály felépítésénél értelmes határokon belül próbáljuk meg minél jobban a célra formálni a feltételeket. Minél több feltétel meg van adva, annál biztonságosabb, és tökéletesebb a tűzfalunk. Nézzünk egy példát. A 25-ös port kiengedése. Egyre szigorúbban:
iptables -A FORWARD -p tcp --dport 25 -j ACCEPT
# bejövő és kimenő interfészek meghatározása
iptables -A FORWARD -i $LAN -o $INT -p tcp --dport 25 -j ACCEPT
# Forrás hálózati cím meghatározása
iptables -A FORWARD -i $LAN -o $INT -s 192.168.2.0/24 -p tcp --dport 25 -j ACCEPT
# SMTP szerver konkrét megadása
iptables -A FORWARD -i $LAN -o $INT -s 192.168.2.0/24 -d 11.22.33.44 -p tcp --dport 25 -j ACCEPT
# Csak az új csoamagokat engedjük ki
iptables -A FORWARD -i $LAN -o $INT -s 192.168.2.0/24 -d 11.22.33.44 -p tcp --dport 25
-m state --state NEW -j ACCEPT
(a kapcsolathoz tartozó csomagokról majd később gondoskodunk.)

Kezdetnek ez már nem lenne rossz. Én például anno minden felé kiengedtem a 25-ös portot hibásan. Egyszer emiatt kerültünk fekete listára, mert egy belső gép ami megfertőződött, több ezer levelet kezdett küldözgetni. Nem kellemes.

  • Hamis forráscímek kiszűrése. Erre lehet találni példákat az interneten, de soha ne tegyünk be olyan szabályt a tűzfalunkba, amiről nem tudjuk pontosan, hogy mire való!
  • Különböző támadások elleni védelmek: ping-flood, syn-flood, érvénytelen SYN csomagok, portscan….

Szabályok sorrendje.

A szabályok sorrendje azért fontos, mert a kernel szekvenciálisan megy végig a tűzfal szabályainkon. És ha van egy csomag ami a 34. helyen van beengedve, akkor az mire odaér 33 szabályra megpróbál illeszkedni. Ezért előrébb kell tenni azokat a szabályokat amikre sűrűbben érkezik csomag. Ezt ellenőrizni tudjuk a következő paranccsal (A filter táblában. Más tábla esetében meg kell adni a -t kapcsolóval a tábla nevét.):

iptables -L -vn

A fenti parancs kimenetében láthatjuk a csomag és byte számlálót, ami alapján helyesen optimalizálhatjuk a csomagok kiértékelésének sorrendjét.

Saját láncok használata.

Saját láncokat létrehozhatunk különböző feladatokra is mint pl.: naplózás vagy tcp csomagok ellenőrzése. Csinálhatunk olyan láncot amibe az összes TCP csomagot irányítjuk, majd ellenőrzéseket hajtunk végre rajtuk, majd ami helyes csomag az nem dobódott el, tehát a RETURN target-el visszadobjuk abba a láncba ahonnan jött, és majd match-el valahová. Ha nem, naplózzuk és eldobjuk :)

Vagy én például szoktam az ICMP csomagok kezelésére is egy külön láncot csinálni, mert elég sokféle icmp csomag létezik, és sok olyan van amit nem szabadna eldobni.

http://www.iana.org/assignments/icmp-parameters

Például amik szükségesek lehetnek:

  • Echo Reply - ping válaszok. Igen fontos!
  • Destination Unreachable

    – Ha a célállomás elérhetetlen. Ezt is kell tudnunk.

  • Echo

    – vagy echo request, a pingelés kifelé. Ezt sem árt kiengedni. Befelé nem kell, ha azt akarjuk, hogy ne tudjanak pingelni minket.

A ?Destinatiob Unreachable"

sok fontos üzenetet tartalmazhat. Nagyon fontosakat, amikből kiderülhet számunkra, hogy miért elérhetetlen a célállomás. Például: hálótat, hoszt, port vagy protokoll az ami elérhetetlen, vagy túl nagyok a csomagok (nagyobb mint az MTU mérete).

Az ICMP szűrés nagyon fontos, gondosan kell eljárni, nem szabad mindent ész nélkül tiltani. Csak kárt és felesleges munkát okozhat a későbbiekben.

Ciklusok és változók használata.

Ha van 5-10 szabály, ami semmiben nem különbözik, csak a portszámokban például, akkor a következő példát alkalmazhatjuk:

# Kiengedni kívánt portok felsorolása.
FWD_TCP="20 21 25 465"

# TCP portok kiengedese. 465 = SMTP over SSL
if test -n "$OUT_TCP"; then
	for tport in $OUT_TCP; do
		$IPTABLES -A OUTPUT -p tcp --dport $tport -m state --state NEW -j ACCEPT
	done

Ez igazából 4 különálló szabályt generál, talán nem is célszerű 4 port esetében használni.

If-ek, elágazások segítségével okosíthatjuk tűzfalunkat. Ellenőrizhetjük bizonyos opciók meglétét melyek teljesülése esetén további szabályokat vezetünk be stb…

Fontosabb kernel paraméterek megismerése és helyes beállítása.

A sysctl parancsot használhatjuk a kernel paraméterek beállításához. Minden paraméter kiíratása

sysctl -a

Legfontosabb az ip forward beállítása. Lekérdezhetjük így:

sysctl net/ipv4/ip_forward

Ha ?0″ akkor nincs engedélyezve az IP csomagok továbbítása egyik interfészről a másik felé. Alapértelmezetten ez nincs engedélyezve. Engedélyezéséhez tegyük a következő sort a /etc/sysctl.conf fájlba, vagy ha benne van akkor vegyük ki előle a kommentet:

sysctl net.ipv4.ip_forward=1
# vagy
echo "0" > /proc/sys/net/ipv4/ip_forward

rp_filter – forráscím hamisítást figyeli és tiltja. Ez alapértelmezetten be van kapcsolva, viszont érdemes lehet kikapcsolni, és magunk végezni ezt a munkát. Jobb az ha látjuk mi történik. Persze naplózzunk is szorgosan.

Tesztelési terv felépítése, ne rögtönözzünk. Tervezzük meg a tesztelést is!

Minden szabályt le kell tesztelni! Be lehet vonni teszt felhasználókat ha van lehetőség, és pár napig őket az új tűzfalra tenni. Nem lehet olyan szabály amit nem teszteltünk. Ne sajnáljuk erre az időt.

Egyéb tanácsok:

1.) Minden scriptben használt parancsot érdemes a következő kép használni:

IPTABLES=$(which iptables)
SYSCTL=$(which sysctl)

2.) Használjuk az iptables-save és iptables-restore parancsokat a mentésre és betöltésre. Sokkal gyorsabb, ami főleg nagyobb script esetén érezhető.

Hibakereséshez:

  • loggoltassunk
  • tcpdump

4 hozzászólás


  1. & g t ;

    -t akartam irni, szokozok nelkul csak atveste > -re :) :D


  2. echo “0” > /proc/sys/net/ipv4/ip_forward

    erre gondoltál? Ezt kijavítottam, de szerintem nem erre gondoltál.

Vélemény, hozzászólás?

Az email címet nem tesszük közzé. A kötelező mezőket * karakterrel jelöljük.