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. Tisztelt budacsik úr,
    köszönet ezért a munkáért, teljesen kezdő vagyok, ez az első script amit létrehoztam, karaktarenként írtam be… …és működik… majd bekopiztam a pastebin-rol, az is működik, teljes sikerélmeny…
    Üdvözlettel Tóth István


  2. Toth Istvan: Orulok Istvan! Nem “mai gyerek” ez az iras :)
    Sok sikert kivanok a tovabbi tanulashoz!


  3. Előbb elfelejtettem megköszönni a NAT-rol szóló írását, pazar kincsesbánya
    számomra, sok homályos dologra fény derült… ez volt a bonus…
    Extra köszönet érte.
    Üdvözlettel Tóth István


  4. Nice post. I was checking constantly this blog
    and I’m inspired! Extremely useful information specially the ultimate section :
    ) I take care of such info much. I was looking for this certain info for a long time.
    Thanks and good luck.

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.