Zorp
Tartalomjegyzék |
1 A Zorp tűzfal
A Zorp tűzfalrendszer központi eleme egy moduláris proxy együttes. A Zorp alapfilozófiája, hogy egy adott protokollal kapcsolatos tudás a protokollhoz készített alacsony szintű proxyban van implementálva. Ezeket az alacsony szintű proxykat viszont a tűzfal adminisztrátora szabadon építheti össze bonyolult protokollok szűrésére. Az összekötő elem, egyben a tűzfal konfigurációs nyelve Python, ami lehetővé teszi hogy az adminisztrátor tetszőleges feltételek alapján döntsön a forgalom szűréséröl. A döntést segíti, hogy a proxyk minden protokollinformációt eljuttatnak a döntési mechanizmus részére. Ha egy adott protokoll szűrésére még nincsen alacsony szintű proxy, az adminisztrátornak lehetösége van akár arra, hogy egy általános célú proxy segítségével valamilyen szinten kordában tartsa a forgalmat, akár arra, hogy Python nyelven lekezelje az adott protokollt (sőt mindkettőt teheti egyszerre). [Balabit]
A Zorp-nak létezik üzleti (Zorp Professional) és ingyenes (GPL-es) verziója egyaránt. A GPL verzió általában kicsit le van maradva az üzletihez képest, viszont mostmár a ZorpOS-nek nevezett teljes Debian-ra épülő disztribúció is elérhető ingyen, csak telepítő nélkül. A GPL-eshez továbbá nincs "management server", grafikus UI, kevesebb proxy modult tartalmaz, és még pár dolog hiányzik belőle. A továbbiakban csak az ingyenes verzióról lesz szó.
2 Telepítés
A telepítésre két lehetsőség adódik:
- Feltelepítünk egy minimális Debian woody-t, majd az /etc/apt/sources.list-ben lecseréljük a forrást a ZorpOS repository-ra ([1]), majd „apt-get dist-upgrade”. Ezzel megvan a patch-elt kernelünk, iptables-ünk és további Zorp-hoz szükséges csomagok.
- Ha mondjuk nem akarunk Debian-t használni, vagy szeretünk kézzel csinálni mindent, akkor mindezt manuálisan is megtehetjük (tproxy patch a kernelhez, Zorp fodítás stb.)
3 Tproxy
A Tporxy kernelmodul felelős az átlátszó proxy funkcionalitásért. A Tporxy-nak szüksége lesz a dummy interface-re, ezt a következőképpen adhatod meg:
auto dummy0 iface dummy0 inet static address 1.2.3.4 netmask 255.255.255.255
Fontos, hogy a dummy interface címe egyik hálózatba se tartozzon.
4 iptables
A Zorp erősen együttműködik az iptables-el. Azokat a csomagokat, amelyeket a Zorp proxy-val szeretnénk ellenőrizni alkalmazás szinten, iptables szabályok segítségével irányítjuk a proxy-hoz. (Letölthető a Balabit oldaláról egy iptables-utils nevű segédprogram, amely segítségével könnyebben/hatékonyabban tudjuk az iptables konfigurációinkat kezelni. Érdemes lehet kipróbálni.)
Példa
Tegyük fel, hogy ellenőrizni szeretnénk a http forgalmat a belső hálózatunkból az Internet felé. Először is az iptables-t állítjuk be. Általános konvenció, hogy zónákat határozunk meg, és az egyes zónákhoz külön láncokat hozunk létre. Azokat a láncokat amelyek az áthaladó forgalomra vonatkozóan tartalmaznak szabályokat PR prefixel, a tűzfal számára küldött csomagokra vonatkozó szabályokat tartalmazókat pedig LO prefixel megadott névvel látjuk el. Nekünk most két zónánk lesz, egy a belső hálózatnak (intra), egy pedig az Internetnek (inter). A proxy szabályokat a tproxy táblában, a helyi szabályokat pedig a filter táblában helyezzük el. A tproxy tábla rendelkezik saját PREROUTING és OUTPUT láncokkal. A tproxy/PREROUTING lánccal továbbítjuk a csomagokat az adott proxy felé.
iptables -t tproxy -P PREROUTING ACCEPT iptables -t tproxy -A PREROUTING -i eth1 -j PRintra iptables -t tproxy -P OUTPUT ACCEPT iptables -t tproxy -N PRintra iptables -t tproxy -A PRintra -p tcp --dport 80 -j TPROXY --on-port 50080
A PRintra láncban a http forgalmat a proxy-nkra küldjük, amely a 50080-as porton csücsül. Az INPUT láncban a tproxy által küldött csomagokat elfogadjuk. Engedélyezzük továbba a meglévő kapcsolatokhoz tartozó és a helyi csomagokat.
iptables -P INPUT DROP iptables -A INPUT -m tproxy -j ACCEPT iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT iptables -A INPUT -i lo -j ACCEPT iptables -A INPUT -i eth1 -j LOintra iptables -A INPUT -i eth0 -j LOinter iptables -A INPUT -j LOG --log-prefix "INPUT DROP: " iptables -A INPUT -j DROP
A LOintra és LOinter láncokban meghatározhatjuk hogy mit kezdjünk a belső hálóból ill. az Internetről érkező tűzfalnak szánt csomagokkal. Például SSH engedünk:
iptables -A LOintra -p tcp --dport 22 -j ACCEPT
Mivel egy proxy tűzfalat valósítunk meg a FORWARD láncunk mindent eldob, az OUTPUT láncunk mindent kienged.
iptables -P FORWARD DROP iptables -A FORWARD -j LOG --log-prefix "FORWARD DROP: " iptables -A FORWARD -j DROP iptables -P OUTPUT ACCEPT
5 Zorp konfigurációs fájlok
Alapfogalmak:
- Instance: a Zorp egy példánya. A Zorp több példányban (processzként) futhat, általában minden zónához szokás egyet indítani. Több példány is használhat egy konfigurációs fájlt.
- Zone: egy zóna egy hálózat, vagy hálózat részletet jelent. Minden egyes kliens vagy szerver pontosan egy zónában helyezkedik el. A Zorp hozzáférésvédelmi rendszere teljes mértékban a zónákra alapul.
- Service: egy service egy proxy-t jelent a hozzá tartozó beállításokkal.
- Listener: a listener objektumok hallgatnak a beállított portokon, amire a csomagszűrő átirányítja az odaszánt csomagokat. Kapcsolódás esetén a listener elindítja az adott service egy példányát.
A Zorp két különböző konfigurációs fájlt használ. Az egyik az instances.conf, amelyben a futtatandó példányokat adhatjuk meg. A másik, a policy.py pedig egy vagy több példány beállításait, szabályait tartalmazza.
Az instances.conf-ban a következőképpen definiálhatunk egy példányt:
zorp -v3 -p /etc/zorp/policy.py --autobind-ip 1.2.3.4
A v3 a naplóüzenetek részletességére vonatkozik, az 1.2.3.4 pedig a proxy által használt dummy interface címe. Az instance-unk neve zorp lesz. A példány beállításait a policy.py tartalmazza, ami tulajdonképpen egy Python modul. Ez a mi esetünkben így nézhet ki:
from Zorp.Core import * from Zorp.Http import * InetZone('intra', '192.168.0.0/24', outbound_services=['intra_HTTP']) InetZone('inter', '0.0.0.0/0', inbound_services=['intra_HTTP']) def zorp(): Service('intra_HTTP', HttpProxy) Listener(SockAddrInet('192.168.0.254', 50080), 'intra_HTTP')
A file elején importáljuk a szükséges modulokat. A Zorp.Core modulra mindig szükségünk lesz, ezenkívül a szükséges proxy osztályokhoz tartozó modulokat is importálnunk kell. Az InetZone segítségével definiálhatjuk a zónákat, és hogy milyen ki- és bemeneti szolgáltatások engedélyezettek. A szolgáltatások is Python osztályok, itt csak a HttpProxy osztályt használjuk, de létrehozhatunk saját proxy osztályokat is, amelyeket származtathatunk egy már meglévőből (lásd később). A példányunkat egy egyszerű függvény definicióval adhatjuk meg, amelyben a Service segítségével nevet rendelhetünk a használt proxy osztályhoz és Listener-eket hozhatunk létre.
Most nézzünk egy kicsit összetettebb példát, amelyben megjelenik a Zorp modularitása. A következő policiy fájlunkban egy HTTPS proxy-t állítunk be, vagyis egy SSL proxy-ba ágyazott http proxy-t hozunk létre.
from Zorp.Core import * from Zorp.Pssl import * from Zorp.Http import * InetZone('intra', '192.168.0.0/24', inbound_services=["*"], outbound_services=["*"]) InetZone('inter', '0.0.0.0/0', inbound_services=["*"], outbound_services=["*"]) class MyHttpsProxy(PsslProxy): class EmbeddedHttpProxy(HttpProxy): def config(self): HttpProxy.config(self) self.request_headers["User-Agent"] = (Http.HTTP_CHANGE_VALUE, "My browser") def config(self): self.server_need_ssl = TRUE self.client_need_ssl = TRUE self.client_key = '/etc/zorp/server.key' self.client_cert = '/etc/zorp/server.crt' self.stack_proxy = EmbeddedHttpProxy def zorp(): Service("https", MyHttpsProxy) Listener(SockAddrInet("192.168.0.254", 500443), "https")
Az SSL proxy osztály használata miatt importáljuk a Pssl modult. A zónadefiníciókban a * azt jelenti, hogy minden szolgáltatás engedélyezett (most csak egy van). Definiálunk egy saját MyHttpsProxy-t, amelyet egyrész a Pssl osztályból származtatunk, és definiálunk benne egy beágyazott proxy osztályt EmbeddedHttpProxy néven, amit pedig a http proxy osztályból származtatunk. A proxy osztályok config függvényével módosításokat eszközölhetünk, például a HttpProxy request_headers változójával megadhatjuk, hogy a proxy-n átmenő HTTP GET kérésekben a User-Agent fejlécet cserélje ki az általunk megadottra, így elrejthetjük a böngészőnk típusát. A MyHttpsProxy config függvényében a stack_proxy változóban adjuk meg a beágyazott proxy-nkat. Az SSL proxy ellenőrzi a szerver tanúsítványát, kititkosítja a forgalmat és továbbadja a csomagokat a beágyazott proxynak, esetünkben az általunk definiált EmbeddedHttpProxy-nak. Amikor a tűzfal mögül csatlakozunk egy SSL szerverhez, gyakorlatilag mi a Zorp-hoz fogunk csatlakozni és az SSL proxy-ban beállított client_cert-ben megadott tanúsítványt is fogjuk látni. A Zorp egy külön kapcsolatot hoz létre a szerverrel, és ő maga dönti el, hogy a szerver tanúsítványa helyes-e vagy sem. (Az elfogadott CA-k tanúsítványait a Zorp megfelelő könyvtárába kell másolnunk.) Tehát a tűzfalunk számára generálnunk kell egy tanúsítványt és a hozzá tartozó titkos kulcsal együtt meg kell adnunk az SSL proxy beállításában.
6 Ajánlott irodalom
További információ érdekében érdemes körülnézni ezeken a helyeken: