Zorp

A Unix/Linux szerverek üzemeltetése wikiből

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:

Személyes eszközök