Alap tűzfal otthoni PC-re (iptables)

Ez egy nagyon nagy téma, én csak az alapokat szeretném megmutatni a teljesség igénye nélkül.

Elsősorban fontosnak tartom leírni, hogy a szabályokat egy fájlban fogjuk elhelyezni amit létrehozhatunk például a /usr/local/sbin/ könyvtárban firewall_start.sh néven (pl.).

iptables

Adminisztrációs eszköz az Ipv4 csomagszűréshez és NAT-oláshoz. (részlet az iptables manualból)
Az iptables a hálózati rétegben működik, vagyis IP csomagokkal dolgozik. Szabályokat (rules) lehet vele felállítani amiket táblákba szervez.

Három alapértelmezett (default) lánc (chain) létezik:

  • INPUT: a kintről befelé érkező csomagokra match-el
  • OUTPUT: a bentről kimenő csomagokra match-el
  • FORWARD: az adott gépen átmenő csomagokra match-el

Megjegyzés: van még kettő (PREROUTING és POSTROUTING) de azok nem tartoznak bele ebbe a leírásba. Talán egy későbbiben.

Hozhatunk létre saját láncokat is. Lánc műveletek:

-N új lánc létrehozása
pl.: iptables -N in_attack
– létrehozza az in_attack láncot

-P lánc policy beállítása
pl.: iptables -P INPUT DROP
? ez a parancs beállítja az INPUT lánc policy-ját DROP-ra ami azt jelenti, hogy ha az INPUT láncban szereplő szabályok közül egyikre sem match-el egy csomag, akkor el lesz dobva

-F töröl minden szabályt
pl.: iptables -F
? minden létező szabályt töröl, de nem változtatja meg a láncok policy-jét!!

-L kilistázza a szabályokat, az egészet, vagy csak egy láncét
pl.: iptables -L INPUT
– kilistázza az INPUT lánc összes szabályát.

-X törli az üres láncokat
pl.: iptables -X
Ennyi elmélet kezdésnek, a többit gyakorlati példákkal mutatnám be.

Tűzfal szabályok

Először hozzuk létre a fájlt a tűzfal szabályoknak (terminálban) és tegyük futtathatóvá:
Senki ne másolja be az általam írt parancsot, mindenki vegye a fáradtságot és kézzel írja be.

sudo touch /usr/local/sbin/firewall_start.sh
sudo chmod +x /usr/local/sbin/firewall_start.sh

Ezután már az elejét meg tudjuk írni:

sudo mcedit /usr/local/sbin/firewall_start.sh

mcedit helyett bármi lehet (nano, gedit, vi, vim …)

A tartalma pedig egyelőre:

#!/bin/bash
iptables -F
iptables -X
iptables -P INPUT DROP
iptables -P OUTPUT DROP
iptables -P FORWARD DROP

A sorokat a magyarázás miatt számoztam be.

  • 1.sor megadja az értelmező shellt
  • 2.sor törli az összes szabályt a filter (alapértelmezett táblából.) Van a nat vagy mangle táblában is vannak szabályok akkor plusz be kell tenni a következőket is: “iptables -F -t nat” és “iptables -F -t mangle”. Ezen táblák lekérdezése: “iptables -L -vn -t nat” és “iptables -L -vn -t mangle”
  • 3.sor törli az üres láncokat (-F miatt már mind üres)
  • 4.5.6.sor beállítja a policy-ket DROP-ra. Én ezt ajánlom. először mindent tiltsunk, és csak azt engedélyezzük, amire szükség van. Van aki mindent engedélyez, és tiltja azokat amik tilosak. Kevesebb szabály van ha az első megoldást választjuk, és biztonságosabb is.

Az INPUT és az OUTPUT láncot is azzal célszerű kezdeni, hogy a lo (localhost) felé és felől engedünk mindent:

iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT

Az “iptables” a program neve. A “-A INPUT|OUTPUT” mondja meg, hogy melyik láncra érvényes a szabály. A “-i” és “-o” a bejövő és kimenő interfészt jelenti. Vagyis a “-i lo” = bejövő interfész a localhost.”-j ACCEPT” határozza meg a csomagok sorsát amik illeszkednek erre a szabályra. a sorsok lehetnek: ACCEPT; DROP.

Amit még fontos betenni minden tűzfal szabályok közé:

iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

A “-m state ?state ESTABLISHED,RELATED” a csomag állapotára utal. Vagyis azokra a csomagokra vonatkozik a szabály amik tőlünk indult csomagokra érkező válaszok. Tehát nem lehet köztük NEW (syn) csomag. Az állapotkövető szabályok egy táblázatot tartanak nyilván a kapcsolatok állapotárol, és onnan hozzák meg a döntéseiket.
Jó tanács, hogy kifelé sem engedünk minden NEW csomagot, hiszen egy jó tűzfalban szűrni kell az OUTPUT láncot is. Vannak akik ezzel nem értenek egyet. (szerintem meg ne ezen spóroljunk)

Tűzfal beállítása

Most mérjük fel az igényeket, mert ettől a ponttól egyedi esetek állhatnak fent. Most számoljunk azzal, hogy a szkriptet készítő felhasználó a következőket szeretné: internet (HTTP, HTTPS), msn, irc, levelezés és FTP.

Internet:

  • 80(HTTP)/tcp
  • 443(HTTPS)/tcp
iptables -A OUTPUT -p tcp --dport 80 -j ACCEPT
iptables -A OUTPUT -p tcp --dport 443 -j ACCEPT
# Későbbi részben szó lesz róla, de a következő forma az ajánlott:
iptables -A OUTPUT -p tcp --dport 80 -m state --state NEW -j ACCEPT
iptables -A OUTPUT -p tcp --dport 443 -m state --state NEW -j ACCEPT

Ez egy egyszerű szabály ami kiengedi azokat a csomagokat amik TCP csomagok (-p tcp) és a célportjuk 80 és 443 (–dport 80|443). A 443-as port a HTTPS portja. Csakhogy ezzel még nem fok működni a böngészés, hiszen ezt a lépést megelőzi az IP cím felderítés (felodás [resolve]) DNS segítségével.

iptables -A OUTPUT -p udp --dport 53 -j ACCEPT

Így most már kiengedjük az 53-as célportú udp csomagokat is, amik a DNS szerverek felé mennek majd. A válasz befogadásáról nem kell külön gondoskodnunk, hiszen már van egy erre a célra írt szabályunk. (iptables -A INPUT -m state –state ESTABLISHED,RELATED -j ACCEPT, ezt a sort érdemes az OUTPUT lánc legelejére tenni (az lo lánc szabály után) mivel a legtöbb csomag valoszinűleg erre fog matchelni, s így nem kell áthladnia az összes többi láncon)

MSN:

  • 1863/tcp
iptables -A OUTPUT -p tcp --dport 1863 -j ACCEPT

IRC:

  • 6667/tcp
iptables -A OUTPUT -p tcp --dport 6667 -j ACCEPT

Levelezés:

  • 25 (SMTP)/tcp
  • 465(SMTPS)/tcp
  • 143(IMAP)/tcp
  • 993(IMAPS)/tcp
  • 110(POP3)/tcp
  • 995(POP3S)/tcp
iptables -A OUTPUT -p tcp --dport 25 -j ACCEPT
iptables -A OUTPUT -p tcp --dport 465 -j ACCEPT
iptables -A OUTPUT -p tcp --dport 143 -j ACCEPT
iptables -A OUTPUT -p tcp --dport 993 -j ACCEPT
iptables -A OUTPUT -p tcp --dport 110 -j ACCEPT
iptables -A OUTPUT -p tcp --dport 995 -j ACCEPT

FTP:

  • 20 (FTP-ADAT)/tcp
  • 21 (FTP)/tcp
iptables -A OUTPUT -p tcp --dport 20 -j ACCEPT
iptables -A OUTPUT -p tcp --dport 21 -j ACCEPT
modprobe ip_conntrack_ftp

A 3. sor egy FTP-hez szükséges modul betöltése. Pontosabban a passzív FTP működéséhez.
Itt nem téma az FTP részletes bemutatása, de talán megérne egy cikket. Mivel én is eltévesztettem,
ezért utána néztem, s azt láttam, hogy sok fórumban keverték a kettőt.
Tehát a modul betöltése nélkül csak aktív ftp fog működni, de a klienek általában a passzív módot támogatják, legalább is alapértelmezetten. Aktív kapcsolathoz elég a 20 és 21-es TCP port megnyitása, míg passzív kapcsolathoz a kliens kezdeményez egy új kapcsolatot egy véletlen portra (amit a szerver jelöl ki és küld el a kliens számára) a command csatornán(21)) 1024 felett.

Összefoglalás

Összefoglalva és egyszerűsítve:

#!/bin/bash

# modulok betolltese
modprobe ip_conntrack_ftp

iptables -F
iptables -X
iptables -P INPUT DROP
iptables -P OUTPUT DROP
iptables -P FORWARD DROP

# INPUT lanc
iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -m state ?state ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -j LOG --log-prefix "INPUT_DROP: "
iptables -A INPUT -j DROP

# 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,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

Lényegében ez egy nagyon egyszerű, de a semminél mégis lényegesen több tűzfal. Mind a két láncban van két utolsó “ismeretlen” szabály.
15. és 24. sor: sorsa LOG. Loggol minden csomagot ami nem illeszkedett egyetlen szabályra sem.
16. és 25. sor: Loggolás után eldob minden csomagot ami egyetlen előző szabálya sem illeszkedett. Igazából ez felesleges a default policy miatt, de hát a paranoia… :)

Tipp: A logot ki lehet kapcsolni, de én ezzel a módszerrel derítettem ki, hogy egyes alkalmazások milyen portokon szeretnének kommunikálni. A módszer:

tail -f /var/log/messages

Hagyni kell had fusson, majd elindítani a kérdéses alkalmazást és figyelni kell, milyen csomagokat dob el. A log-ban benne lesz, hogy milyen cél vagy forrás portot igényel és az tcp vagy udp -e.

Én szeretem bekapcsolva hagyni a logot, de hogy mégsem legyen sok felesleges log, van még pár szabály a tűzfalamban:

iptables -A INPUT -p tcp -m multiport  --dport 135,137,139,445,1026,1027,5900,6881 -j DROP
iptables -A INPUT -p udp -m multiport  --dport 135,137,139,445,1026,1027,5900 -j DROP

Ezeket a 14. sor elé tettem be. Így ezeket a csomagokat log nélkül eldobja, még mielőtt a kapcsolatállapot táblázatban kutakodna, értékes erőforrást pazarolva :)

  • 135 /tcp – epmap, # Location Service
  • 137 /tcp – netbios-ns, # NETBIOS Name Service
  • 139 /tcp – netbios-ssn # NETBIOS session service
  • 445 /tcp – microsoft-ds # Microsoft Naked CIFS
  • 1026/tcp – nem szabványos port
  • 1027/tcp – nem szabványos port
  • 135 /udp – epmap,
  • 137 /udp – netbios-ns,
  • 139 /udp – netbios-ssn
  • 445 /udp – microsoft-ds
  • 1026/udp – nem szabványos port
  • 1027/udp – nem szabványos port

Ezzel kész egy egyszerű tűzfal szkript ami a /usr/local/sbin/firewall_start.sh fájlban van.

Tűzfal automatikus indítása.
Elegánsabb megoldás, ha a tűzfal kézi inditása után kiadjuk a következő parancsot:

# Kimentéshez
sudo iptables-save > /etc/iptables.rules

# Visszatöltéshez
sudo iptables-restore < /etc/iptables.rules

Hol hasznos ez? Firewall szkriptünk /usr/local/sbin/firewall_start.sh utolsó sorába a következőt illesszük be:

# Ha létezik, töröljük.
if test -r /etc/iptables.rules; then
    rm -f /etc/iptables.rules
fi

#Tűzfal mentése
iptables-save -c > /etc/iptables.rules
if test -r /etc/iptables.rules; then
    echo "Tűzfal mentése sikeres!"
fi

Így nem az “iptables”-t kell hívogatni és a kimentett iptables.rules fájlt is lehet szerkeszteni. Sőtt, a fájlt megnézve hamar hozzá lehet szokni, és lehet eleve igy elkésziteni a szkriptet, de én ettől eltekintenék, ugyanis hátránya pl, hogy nehéz kommentezni, konnyen átláthatatlanná válik… Szerintem maradjon meg az eredeti fájl is amit szerkesztünk, majd futtatjuk, lementjuk es a továbbiakban azt töltjük vissza rendszerindításkor.

Visszatérve az automatikus indításhoz. A következőkben leírt megoldás azért is jó, mert nem kell kitallni az indulás idejét. Pontosan akkor fog felállni a tűzfal amikor az interfészek is felállnak.

sudo mcedit /etc/network/interfaces

tegyük a következő két sort a megfelelő interfészhez. pre-up iptables-restore < /etc/iptables.rules
post-down iptables-save -c > /etc/iptables.rules
Tehát a teljes konfig rész kb így néz ki:

auto eth0
iface eth0 inet static
      address 192.168.2.1
      network 255.255.255.0
      broadcast 192.168.2.255
      pre-up iptables-restore < /etc/iptables.rules
      post-down iptables-save -c > /etc/iptables.rules

Tipp: Az összess port listáját meg lehet nézni a /etc/services fájlban.

Minden esetben csak simán az “iptables” parancsot használtam. Sokan más formában írják meg, és talán igazuk van.
A szkript elején létrehozzák a parancsok változóit. Az iptables parancs helye: (which iptables) /sbin/iptables

Tehát a szkript eleje így néz ki:

#!/bin/bash

# valtozok deklaralasa
IPTABLES=$(which iptables)
# modulok betolltese
modprobe ip_conntrack_ftp

$IPTABLES -F
$IPTABLES -X
$IPTABLES -P INPUT DROP
$IPTABLES -P OUTPUT DROP
$IPTABLES -P FORWARD DROP

Jól látszik, hogy most már a $IPTABLES változóval hivatkozok a programra.

Végezetül, szükséges lehet egy szkript ami mindent visszaállít az eredeti állapotra:

echo "Tűzfal leállítása, és mindent engedélyezünk"
iptables -F
iptables -X
iptables -t nat -F
iptables -t nat -X
iptables -t mangle -F
iptables -t mangle -X
iptables -P INPUT ACCEPT
iptables -P FORWARD ACCEPT
iptables -P OUTPUT ACCEPT

Ez lehet pl a /root/fw.stop fájlban.

A fentiek alapján készítettem egy használható szkriptet, most ki is próbáltam.
http://pastebin.com/f1178aaad

Ellenőrzések

A szabályokat megnézhetjük a következő parancs segítségével:

iptables -L

# -L után megadható egy lánc neve is (iptables -L OUTPUT -vn)
iptables -L -vn
Chain OUTPUT (policy DROP 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
[…]
0 0 ACCEPT tcp — * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:25 state NEW
40 2400 ACCEPT tcp — * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:80 state NEW
Azt látjuk ebben a kimenetben, hogy a tcp/80-as portot használom, már 40 csomag, azaz 2400 byte (2,3KByte) már kiment rajta.
Viszont nem használtam még a 25-ös portot. (Mert nincs bekapcsolva a levelezőm :))

Az naplózott csomagokat a messages logban figyelhetjük meg:

sudo tail -f /var/log/messages
Apr 18 04:20:53 budacsika-laptop kernel: [  107.953276] OUTPUT_DROP: IN= OUT=wlan0 SRC=192.168.2.100 DST=91.189.94.4 LEN=76 TOS=0x00 PREC=0x00 TTL=64 ID=0 DF PROTO=UDP SPT=123 DPT=123 LEN=56
Apr 18 04:25:16 budacsika-laptop kernel: [  370.643450] INPUT_DROP: IN=wlan0 OUT= MAC=00:21:5d:55:a6:16:00:13:f7:1e:8f:8b:08:00 SRC=166.87.164.37 DST=192.168.2.100 LEN=46 TOS=0x00 PREC=0x00 TTL=103 ID=3816 PROTO=UDP SPT=49252 DPT=31323 LEN=26

Van egy eldobott NTP csomagom, amit azóta kiengedtem. A másk (bejövő) csomag valószínűleg jól van úgy, ha nem jön be. De ha tudni szeretnénk, hogy kicsoda, talán megtudhatjuk a következő módon:

host 166.87.164.37

Sajnos ez esetben nem :(

Vagy

whois 166.87.164.37

Amsterdam-i IP cím, mint kiderült. Viszont a whois-nak kell a TCP 43-as portot kiengedni.

Ne felejts le lapozni a folytatásért!

24 hozzászólás


  1. “modprobe ip_conntrack_ftp
    A 3. sor egy FTP modul betöltése. Ez szükséges ahhoz, hogy működjön az aktív FTP is. A modul betöltése nélkül csak a passive FTP működik, ami nem akar visszafelé egy új portot nyitni az adat hozdozásra.”

    Pont fordítva: az aktív FTP-hez kell a 20-as port, INPUT irányba (az adatkapcsolatot ilyenkor a KLIENS nyitja, ettől “aktív”); míg a passzív mód adatkapcsolata közlekedik teljesen véletlen portokon (alaphelyzet a 1025:65535 tartomány – őszinte gratuláció a protokollt tervezőknek), amire engedő OUTPUT szabály kell, különben nem jön a pr0n.
    Ennek segítésére való a conntrack modul, ami figyeli a 21-es (control, hálistennek ez állandó) porton folyó kapcsolatok PORT parancsát, és megfelelő ideiglenes engedő OUTPUT szabályt illeszt be a FTP server kénye-kedve szerint nyitott adatportra.
    Titkosított control kapcsolat (FTPS/FTP-TLS – nem árt, ha nem akarsz plaintext jelszóval rohangálni a neten) esetén természetesen nem működik.


  2. Köcsi Csigaa!
    Megnézem és javítom!


  3. Csigaa és gbor: köszi javítottam.
    FTPS-t is bele kellene tenni szerintetek? Ennek a dokumentációnak igazából ezt nem feladata bemutatni, csupán az iptables eszköz használatának megtanítása bizonyos szintig, ahonnan már egyedül is jól lehet folytatni.


  4. gbor: Kadlecsik Jószef előadásait ép tegnap hajnalban kezdtem el nézni:
    Csaek ez frissebb: http://vod.niif.hu/index.php?lg=hu&mn=archive&eid=90&sm=listevent
    Próbálok témákat meríteni a folytatáshoz. Ilyeneket írtam fel magamnak eddig:
    – Kititltas megadott ideig…
    – támadások elleni védelnek
    – ipv6
    – routing
    – mangle tábláról többet, és hasonló finomságok, de ez már nem az otthoni tűzfal kategóriába fog kerülni szerintem :)

    Örülök ha tetszik, remélem marad a véleményed miután végigolvasod :)


  5. budacsik: FTPS-t szerintem nem kell betenni, annyira nem elterjedt, hogy otthoni felhasználásnál problémát okozhasson (tapasztalatok szerint vállalati felhasználásnál meg direkt nem foglalkoznak vele, annyira macerás az egész).


  6. gbor
    Ez egy baromi jó kép, ismerem, de szerintem ebbe a doksiba nem illik.
    Szerinted egy újat megérne? Ami csak erről szól?


  7. csak próbáltam hozzárakni még, videóban is volt ez a kép, ahogy jónak látod, ahogy van szabadidőd :)


  8. Nem lenne rossz kihívás, viszont az ebtables rész még ismeretlen. A zöld réteg talán most is menne. De a legfontosabb, hogy érdekelheti e az embereket ilyesmi?!


  9. aki a szakmában van/lesz, annak mindig jól jön egy leírás az adott témáról, mivel így hatékonyabb lehet megtanulni, megérteni, mint hogy összecsipegesse az ember a netről, szerintem.


  10. Ha megpróbálom futtatni a firewall_start.sh-t, akkor a -F-es 6. sortól már elhasal.

    “No chain/target…”

    A többi pedig már ettől a sortól “csonkolva” fut le.

    “‘ptables…”

    Mit kellene tenni, hogy ne egyenként írjam be a parancssorba?

    Előre is köszi…


  11. Már nem érdekes, megoldódott.
    A sorvég karakterek…
    :-)

    ui:
    Nagyon jó a leírás.
    Segített feleleveníteni egy-két régi “képet” a fejemben.
    De hasznosnak tartanám, – ha valaki már ott tart, hogy cikket ír – hogy kicsit sűrűbben figyelje a hozzászólásokat.
    ;-)


  12. Szia nenix!

    Ne haragudj, kicsit elfoglalt vagyok egy ideje. Írni sincs több időm.
    Viszont, talán így, hogy magad ekllett megküzdened a problémával, talán jobb is. Mellesleg sosem jöttem volna rá így látatlanból, hogy ez a hiba :)


  13. egy apró javítást kéne eszközölni:
    SNAT a célcímet fogja módosítani 83.321.221.421 helyett;
    SNAT a forráscímet fogja módosítani 83.321.221.421
    nagyon jó cikk, várok még hasonló gyakorlatiasakat a biztonságról


  14. Szia!

    Igazad van, elírtam. Javítom!

    Köszönöm az észrevételt!
    Örülök ha hasznos bárninek az írásom.

    Üdv / budacsik


  15. Sziasztok!

    budacsik! Nagyon szépen köszönöm ezt a leírást. Sokat segítettél vele.
    Üdv,
    Dávid


  16. Szia Dávid!

    Örülök neki és köszönöm!

    Üdv /budacsik

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.