2012-03-14

NAT connection tracking naplózás Linuxon

Gyakran felmerülő probléma, hogy miképp lehet azonosítani linuxos SRC NAT mögötti gépeket megbízhatóan. Az ugye viszonylag egyértelmű, hogy címfordítást végző rendszeren valamit kezdenünk kell a kernel által vezetett conntrack táblával, amihez van egy sztenderd interfész minden Linuxon: a /proc/net/ip_conntrack-ből mindig ki lehet olvasni az éppen aktuális bejegyzéseket. Ez azonban igencsak behatárolt lehetőség. Tegyük fel, hogy percenként mentjük a táblázatot! Még így is igen könnyen lehetnek olyan NAT-olt kapcsolatok, amelyek az előző lekérdezés óta épültek ki, de azóta már kikerültek a conntrack táblázatból, ezért a percenkénti logjainkban semmilyen nyomuk nem marad, arról nem is beszélve, hogy rengeteg felesleges információt is eltárolunk, mert a conntrack bejegyzések jelentős része - a megnyitott, kiépített TCP sessionök - tipikusan több percen át élnek, és ezeket mindig újra és újra tárolgatjuk a percenkénti logokban.

Jobb lenne az eseményalapú megközelítés, csak akkor naplózni a conntrack bejegyzéseket, ha új kapcsolat épül ki, vagy ha az adott conntrack bejegyzés kikerül a conntrack táblázatból. Szerencsére ilyesmi létezik Linuxra, a szoftvercsomag neve conntrack-tools, a benne lévő eszközök pedig kiváló, dinamikus, userspace interfészt biztosítanak a kernel conntrack táblájához. A csomag két fontos eleme a conntrack és a conntrackd nevű program. Az előbbivel listázni, naplózni, létrehozni, módosítani, törölni lehet conntrack bejegyzéseket, az utóbbi (a démon) pedig redundáns NAT rendszerek közt képes a conntrack információk szinkronizálására. A conntrack naplózás tesztjéhez az alábbi topológiát használtam:



A "denobula" beállításait nem vittem túlzásba, egy teljesen alap Ubuntu 10.04 LTS telepítést kell elképzelni, ahol két paranccsal beállítható a 10.1.1.0/24 subnetből érkező csomagok forráscímeinek NAT-olása az eth0-ra aggatott külső IP-re, feltételezve, hogy az alapértelmezett ACCEPT iptables policy-ket senki és semmi nem állította át:
echo 1 > /proc/sys/net/ipv4/ip_forward
iptables -t nat -A POSTROUTING -o eth0 -s 10.1.1.0/24 -j MASQUERADE
Az interfészeket kell még beállítani, az /etc/network/interfaces fájlba kerüljenek a következők:
auto lo eth0 eth1

iface lo inet loopback

iface eth0 inet static
address 10.0.2.15
netmask 255.255.255.0
gateway 10.0.2.2

iface eth1 inet static
address 10.1.1.1
netmask 255.255.255.0
Majd állítsuk be a DNS-t, végül húzzuk fel az interfészeket (újraindítás után ez már az init alatt megtörténik az előbbi auto bejegyzés miatt):
echo "nameserver 8.8.8.8" > /etc/resolv.conf
ifup eth0
ifup eth1
Következik a lényeg, a conntrack-tools telepítése (valójában csak a conntrack csomag szükséges ahhoz, amiről ebben a posztban szó lesz):
apt-get update
apt-get install conntrack conntrackd
A "denobula" beállítása ezzel meg is van, a tesztkörnyezetből még hiányzik a NAT mögötti kliens, az "andoria", ez bármi lehet, Live CD-s Linux, akármi, a lényeg, hogy konfiguráljunk rajta egy 10.1.1.2/24-es IP-t, majd a 10.1.1.1-et gatewaynek, valamint egy DNS szervert (pl. 8.8.8.8). Ezek után nincs más hátra, mint beröffenteni a NAT-os gépen a connttrack programot, a sok opció közül most a -E lesz az, amire szükségünk lesz, további opcióként megadtam a -o id,timestamp-et, így az egyes bejegyzések pontos időbélyege és az adott NAT-olt kacsolat belső ID-je is látszani fog a kimenetben:
root@denobula:~# conntrack -E -o id,timestamp,extended
[1331710267.511683]        [NEW] ipv4     2 tcp      6 120 SYN_SENT src=10.1.1.2 dst=74.125.232.247 sport=39059 dport=80 [UNREPLIED] src=74.125.232.247 dst=10.0.2.15 sport=80 dport=39059 id=3607679456
[1331710267.513939]        [NEW] ipv4     2 tcp      6 120 SYN_SENT src=10.1.1.2 dst=74.125.232.247 sport=39060 dport=80 [UNREPLIED] src=74.125.232.247 dst=10.0.2.15 sport=80 dport=39060 id=3607679216
[1331710267.513992]     [UPDATE] ipv4     2 tcp      6 60 SYN_RECV src=10.1.1.2 dst=74.125.232.247 sport=39059 dport=80 src=74.125.232.247 dst=10.0.2.15 sport=80 dport=39059 id=3607679456
[1331710267.514021]     [UPDATE] ipv4     2 tcp      6 60 SYN_RECV src=10.1.1.2 dst=74.125.232.247 sport=39060 dport=80 src=74.125.232.247 dst=10.0.2.15 sport=80 dport=39060 id=3607679216
[1331710267.514047]     [UPDATE] ipv4     2 tcp      6 432000 ESTABLISHED src=10.1.1.2 dst=74.125.232.247 sport=39059 dport=80 src=74.125.232.247 dst=10.0.2.15 sport=80 dport=39059 [ASSURED] id=3607679456
[1331710267.514076]     [UPDATE] ipv4     2 tcp      6 432000 ESTABLISHED src=10.1.1.2 dst=74.125.232.247 sport=39060 dport=80 src=74.125.232.247 dst=10.0.2.15 sport=80 dport=39060 [ASSURED] id=3607679216
[1331710272.506759]     [UPDATE] ipv4     2 tcp      6 120 FIN_WAIT src=10.1.1.2 dst=74.125.232.247 sport=39060 dport=80 src=74.125.232.247 dst=10.0.2.15 sport=80 dport=39060 [ASSURED] id=3607679216
[1331710272.507065]     [UPDATE] ipv4     2 tcp      6 60 CLOSE_WAIT src=10.1.1.2 dst=74.125.232.247 sport=39060 dport=80 src=74.125.232.247 dst=10.0.2.15 sport=80 dport=39060 [ASSURED] id=3607679216
[1331710272.507135]     [UPDATE] ipv4     2 tcp      6 30 LAST_ACK src=10.1.1.2 dst=74.125.232.247 sport=39060 dport=80 src=74.125.232.247 dst=10.0.2.15 sport=80 dport=39060 [ASSURED] id=3607679216
[1331710272.507208]     [UPDATE] ipv4     2 tcp      6 120 TIME_WAIT src=10.1.1.2 dst=74.125.232.247 sport=39060 dport=80 src=74.125.232.247 dst=10.0.2.15 sport=80 dport=39060 [ASSURED] id=3607679216
A kimenetben megtalálhatók a kért paraméterek, az első mező a timestamp, az utolsó mező a conntrack ID, a sorok egyébként elég beszédesek, minden sorban a második mező a conntrack esemény, amiből összesen három létezik, a NEW értelemszerűen egy új conntrack bejegyzés létrejöttekor generálódik, az UPDATE egy már létező bejegyzésben valamiféle változást jelez, például az UPDATE bejegyzésekben a TCP állapotátmenet-változások kiválóan követhetők. A harmadik, DESTROY nevű esemény pedig azt jelzi (a fenti példában épp nincs ilyen), hogy egy bejegyzés kikerül a conntrack táblából.

Ez a fajta eseményvezérelt kimenet már egészen közel van ahhoz, hogy használható legyen, két apróságra térnék még ki. Az első, hogy az STDOUT-ra küldött log nem tekinthető valódi log-nak, valahova át kell irányítanunk, a következő példában a tee-t használom, amivel így, ahogy van, ott lehet hagyni egy ötös vagy hatos szöveges terminálon, úgysem nyúl hozzá soha senki ;). A másik dolog, hogy általában az UPDATE eseményekre nincs szükség, hiszen az ilyesfajta logoknak az a lényege, hogy ki lehessen hámozni belőlük, hogy egy SRC NAT mögötti gép mettől meddig, milyen külső IP-vel, hová kommunikált, ehhez pedig elég a bejegyzés létrejöttét (NEW) és a bejegyzés végét (DESTROY) naplózni, ami közben történt a bejegyzéssel, nem érdekes. A "végső" NAT naplózó parancs tehát, amit természetesen ezer módon tovább lehet még fejlesztgetni, így néz ki:
conntrack -E -o id,timestamp,extended -e NEW,DESTROY | tee /var/log/ctrack.log

Nincsenek megjegyzések:

Megjegyzés küldése