Squeeze please – Firewall als erweitertes Kiosk-System
Die letzten zwei Tage habe ich zum Großteil damit verbracht, mit Reinhard ein “kleines” Firewall-System aufzusetzen. Die Anforderungen:
- Firewalling eines LANs hinter einem Linux-Gateway an DSL
- Einstufung des Vertrauens gegen einzelne Hosts im LAN
- Dynamische Zugangskontrolle zum Internet über NAT, einen transparenten Proxy und ein Webinterface zur Authentifikation
Als Grundlage für das System dient PC-Hardware älteren Datums (500 MHz Pentium-Prozessor, 256 MB RAM, 14 GB IDE-Harddisk). Das Grundsystem ist ein Debian GNU/Linux Squeeze (wegen veralteter Software in lenny).
Zur Zeit ist das System bzgl. der Firewall-Zonen noch recht statisch. Grundlegend unterscheidet das Setup zwischen 4 Zonen:
Die Firewallregeln baut die Shorewall, ein Perl-Skript, das mit Hilfe von Tabellen iptables-Regeln baut und pflegbar macht. Die Zonen bedeuten:
LAN
In der LAN-Zone befindet sich das komplette Netzwerk hinter dem lokalen Ethernet-Interface. Es wird, wie üblich, von der Firewall restriktiv behandelt. Hosts im LAN haben keinen Zugang zum Internet, sofern sie nciht zu einer der eingebetteten Zonen gehören.
AUTHentifiziert
Authentifizierte Hosts sind Hosts, die sich erfolgreich am Webinterface angemeldet haben. Ein beliebiger Client im LAN wird per DNAT im Webbrowser auf die Loginmaske der FIrewall weitergeleitet. Dort kann sich der Benutzer einloggen, wodurch sein Host dynamisch zur AUTH-Zone hinzugefügt wird. Die Systeme haben dann eine Route ins Internet, HTTP wird jedoch durch einen transparenten Proxy geleitet.
PRIVilegiert
Privilegierte Systeme gehören zu einem bestimmten Adressbereich und werden mit einer MAC-Liste gefiltert. Prinzipiell bietet diese Maßnahme natürlich keine verlässliche Sicherheit, in usnerem Fall ist dies aber ausreichend. Privilegierte Hosts haben eine direkte Internetverbindung ohne Proxy und dürfen darüberhinaus die Administrationsoberfläche des Webinterfaces aufrufen. Die Adressen der privilegierten Systeme werden von einem ISC DHCPd verteilt.
Um der Shorewall die Arbeit mit dynamischen Zonen im NAT beizubringen, wird mindestens Version 4.4 benötigt. Außerdem verlässt sich diese Version auf die xtables-addons, welche noch nicht in der Kerneldistribution enthalten sind. In Debian squeeze können die benötigten Module jedoch mit module-assistant gebaut werden.
Mit Hilfe einiger kreativer NAT-Regeln regelt die Shorewall dann die Routen aus den verschiedenen Zonen ins Internet, zum Proxy oder zum Login:
NONAT priv all all NONAT auth all tcp 443 NONAT auth fw:192.168.2.1 tcp 80 DNAT auth fw:192.168.2.1:3128 tcp 80 DNAT lan fw:192.168.2.1 tcp 80,443
Wichtig ist hier die kaskadierende Reihenfolge, die die Restriktionen durch DNAT von Zone zu Zone aufhebt. Die Shorewall baut daraus dann NAT-Regeln in iptables:
Shorewall 4.4.2 NAT Table at blackhawk - Do 8. Okt 21:25:08 CEST 2009 Counters reset Do 8. Okt 20:28:38 CEST 2009 Chain PREROUTING (policy ACCEPT 152 packets, 13678 bytes) pkts bytes target prot opt in out source destination 2767 230K dnat all -- * * 0.0.0.0/0 0.0.0.0/0 Chain POSTROUTING (policy ACCEPT 173 packets, 12419 bytes) pkts bytes target prot opt in out source destination 623 39249 ppp0_masq all -- * ppp0 0.0.0.0/0 0.0.0.0/0 Chain OUTPUT (policy ACCEPT 164 packets, 12059 bytes) pkts bytes target prot opt in out source destination Chain auth_dnat (1 references) 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:443 0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:443 0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:443 0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:443 0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:443 0 0 ACCEPT tcp -- * * 0.0.0.0/0 192.168.2.1 tcp dpt:80 0 0 DNAT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:80 to:192.168.2.1:3128 Chain dnat (1 references) pkts bytes target prot opt in out source destination 2491 209K priv_dnat all -- eth0 * 0.0.0.0/0 0.0.0.0/0 source IP range 192.168.2.200-192.168.2.250 0 0 RETURN all -- eth0 * 0.0.0.0/0 0.0.0.0/0 source IP range 192.168.2.200-192.168.2.250 0 0 auth_dnat all -- eth0 * 0.0.0.0/0 0.0.0.0/0 match-set auth_eth0 src 0 0 RETURN all -- eth0 * 0.0.0.0/0 0.0.0.0/0 match-set auth_eth0 src 267 20702 lan_dnat all -- eth0 * 0.0.0.0/0 0.0.0.0/0 Chain lan_dnat (1 references) pkts bytes target prot opt in out source destination 124 7440 DNAT tcp -- * * 0.0.0.0/0 0.0.0.0/0 multiport dports 80,443 to:192.168.2.1 Chain ppp0_masq (1 references) pkts bytes target prot opt in out source destination 469 28140 MASQUERADE all -- * * 192.168.2.0/24 0.0.0.0/0 Chain priv_dnat (1 references) pkts bytes target prot opt in out source destination 2491 209K ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0 0 0 ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0 0 0 ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0 0 0 ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0 0 0 ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0
In einer MySQL-Datenbank werden Benutzer verwaltet, die sich auf der Firewall einloggen können. Das Webinterface bietet diese Möglichkeit nur Clients aus dem AUTH-Adressbereich an, wenn diese sich noch nicht authentifiziert haben. Nach erfolgtem Login legt das Webinterface einen Session-Eintrag in der Datenbank an, der im Admin-Teil gesteuert werden kann.
Zusätzlich prüft ein von cron aufgerufenens Backend-Script regelmäßig, ob die in der Datenbank hinterlegten Sessions noch aktiv sind (Ping-Probe) und terminiert sie bei Bedarf, indem es die zugehörige IP-Adresse wieder aus der dynamischen AUTH-Zone entfernt und den Datenbankeintrag abschließt.
Das System wird bei Gelegenheit noch ein bisschen aufgeräumt und erweitert, so dass es “benutzbar” wird.
Ein paar Zahlen:
- Arbeitsstunden: 13
- PHP-Code (Webinterface): 580 Zeilen
- iptables-Regeln: ca. 400
- Benötigter Festplattenplatz (vor dem Aufräumen): 1,4 GB

