Der von fli4l verwendete Linux-Kern stellt einen Paketfilter zur Verfügung. Mit Hilfe dieses Paketfilters wird gesteuert, wer mit dem Router bzw. über ihn hinweg kommunizieren darf. Weiterhin können Dinge wie Port-Weiterleitung (ein an den Router gerichtetes Paket wird an einen anderen internen Rechner weitergereicht) und Maskierung (engl. ``Masquerading''; Pakete, die von einem Rechner hinter dem Router kommen, werden so verändert, dass sie so aussehen, als kämen sie vom Router selbst) realisiert werden.
Die Struktur des Paketfilters ist in Abbildung 3.1 angedeutet. Pakete kommen über eine Netzwerk-Schnittstelle herein und durchlaufen die PREROUTING-Kette (eng. ``chain''). Hier werden die an den Router gerichteten Pakete an einen anderen Rechner weitergereicht, indem die Zieladresse und der Zielport manipuliert werden. Ist das Paket an den Router gerichtet, wird es an die INPUT-Kette, andernfalls an die FORWARD-Kette weitergereicht. Beide Ketten prüfen, ob das Paket zulässig ist. Wird das Paket akzeptiert, wird es an den lokalen Zielprozess zugestellt oder über die POSTROUTING-Kette (in der das Maskieren von Paketen stattfindet) an diejenige Netzwerk-Schnittstelle weitergereicht, über die das Paket sein Ziel erreichen kann. Lokal generierte Pakete werden in der OUTPUT-Kette gefiltert und schließlich (falls erfolgreich) über die POSTROUTING-Kette ebenfalls an die korrekte Netzwerk-Schnittstelle weitergereicht.
Mit der Paketfilterkonfiguration lassen sich die einzelnen Ketten des Paketfilters direkt konfigurieren. Dazu gibt es für jede relevante Kette ein eigenes Array, d.h. eine für die INPUT-Kette (PF_INPUT_%), eine für die FORWARD-Kette (PF_FORWARD_%), eine für die OUTPUT-Kette (PF_OUTPUT_%), eine für die PREROUTING-Kette, in der die Portweiterleitung durchgeführt wird (PF_PREROUTING_%), und eine für die POSTROUTING-Kette, in der das Maskieren der Pakete durchgeführt wird (PF_POSTROUTING_%).
Ein Eintrag in einem dieser Arrays besteht im Wesentlichen aus einer Aktion (s.u.), die durch zusätzliche Bedingungen eingeschränkt werden kann. Diese Bedingungen beziehen sich auf Eigenschaften des betrachteten Paketes. Ein Paket enthält Informationen über seine Herkunft (Quelle, welcher Rechner hat das Paket losgeschickt), sein Ziel (an welchen Rechner und welche Anwendung soll das Paket gehen) u.a.m. Bedingungen können sich auf folgende Eigenschaften eines Paketes beziehen:
Kommt ein Paket herein, werden die Einträge bzw. die daraus generierten Regeln von oben nach unten abgearbeitet und die erste Aktion ausgeführt, bei der alle Bedingungen gelten. Trifft keine der Regeln zu, wird die Standardaktion ausgeführt, die man für (fast) jede Tabelle angeben kann.
Ein Eintrag hat dabei folgendes Format, wobei zu beachten ist, dass alle Einschränkungen optional sind:
restriction{0,} [[source] [destination]] action [BIDIRECTIONAL|LOG|NOLOG]
An allen Stellen, an denen Netzwerke, IP-Adressen oder Hosts angegeben werden müssen, kann man sich auch auf IP_NET_%, IP_NET_%_IPADDR oder via @hostname auf einen Host aus HOST_% beziehen. Ist OPT_DNS aktiviert, dann können außerhalb von Aktionen via @fqdn auch Hosts über ihren Namen referenziert werden, die nicht in HOST_% zu finden sind. Das ist insbesondere dann sinnvoll, wenn es sich um externe Hosts handelt, die zudem viele (und wechselnde) IP-Adressen besitzen.
Aktionen können die folgenden sein:
Einige dieser Aktionen können durch die Optionen BIDIRECTIONAL, LOG oder NOLOG in ihrem Verhalten modifiziert werden. BIDIRECTIONAL generiert die gleiche Regel noch einmal, nur mit vertauschter Quell- und Zieladresse (und vertauschtem Quell- und Zielport und/oder vertauschter ein- und ausgehender Netzwerk-Schnittstelle, falls angegeben). LOG/NOLOG aktivieren bzw. deaktivieren das Protokollieren für diese eine Regel.
Einschränkungen können durch die in den folgenden Abschnitten aufgeführten Bedingungen vorgenommen werden. Bei den Bedingungen kann man immer any angeben, wenn man an irgendeiner Stelle keine Einschränkung vornehmen will, aber trotzdem etwas angeben will/muss. Einschränkungen können in beliebiger Reihenfolge angegeben werden, wenn sie einen vorangestellten Präfix haben. Das gilt für alle Einschränkungen, außer für die Angabe einer Quell- bzw. Zieladresse. Diese müssen immer direkt vor der Aktion stehen, die anderen Einschränkungen müssen vorher erfolgen. Einschränkungen können auch negiert werden, dazu wird einfach ein ! vorangestellt.
Jedes Paket enthält eine Quell- und eine Zielangabe, jeweils in Form eines Tupels einer IP-Adresse und eines Ports.3.2 Diese Quelle bzw. dieses Ziel kann für eine Einschränkung herangezogen werden. Die Angabe für die Quelle bzw. das Ziel kann folgendermaßen vorgenommen werden:
Ausdruck | Bedeutung |
ip |
eine einfache IP-Adresse |
network |
eine Netzwerkangabe der Form <ip>/<netmask> |
port[-port] |
ein Port bzw. ein Port-Bereich |
IP_NET_x_IPADDR |
die IP-Adresse der Schnittstelle x des Routers |
IP_NET_x |
das Subnetz x des Routers |
IP_ROUTE_x |
das in der Route x angegebene Subnetz
(Default-Routen können nicht verwendet werden, sie würden any entsprechen und
werden vorsichtshalber ausgeklammert) |
@name |
einer der via HOST_%_* vergebenen Namen oder Aliase; es wird die zugehörige IP-Adresse an dieser Stelle eingesetzt |
<ip oder netzwerk>:port[-port] |
Host- bzw. Netzwerk-Adresse in einer der obigen Varianten, kombiniert mit einem Port bzw. Port-Bereich |
Das könnte z.B. wie folgt aussehen: '192.168.6.2 any DROP'
Tauchen zwei dieser Angaben auf, wird die erste als Quelle, die zweite als Ziel betrachtet. In diesem Beispiel verwerfen wir also Pakete, die vom Rechner mit der IP-Adresse 192.168.6.2 gesendet wurden, unabhängig davon, an welches Ziel sie gerichtet sind.
Taucht nur eine Angabe auf, wird anhand des Wertes entschieden, ob die Quelle oder das Ziel gemeint ist, wobei die Entscheidung relativ einfach ist:
Wenn wir also z.B. das obige Beispiel abkürzen wollten,
könnten wir einfach '192.168.6.2 DROP'
schreiben. Es ist kein
Port angegeben, die Bedingung gilt also für die Quelle, den Rechner,
von dem das Paket gesendet wurde.
Wollen wir die Kommunikation mit dem ssh-Dämon erlauben, können
wir 'any any:22 ACCEPT'
(Pakete von einem beliebigen Rechner an den
ssh-Port 22 eines beliebigen Rechners werden akzeptiert) oder
kürzer '22 ACCEPT'
schreiben: Es ist nur ein Port angegeben,
also meinen wir das Ziel und damit Pakete, die an den Port 22
gerichtet sind.
Zur Vereinfachung der Regelmenge kann man an die Aktion ein BIDIRECTIONAL dranhängen, um auszudrücken, dass die Regel für beide Kommunikationsrichtungen gilt. Es werden dann Regeln generiert, in denen einfach die Quell- und die Ziel-Adressen und eventuell angegebenene Ports und Netzwerk-Schnittstellen vertauscht sind und der Rest gleich bleibt.
Beispiele:
127.0.0.1 ACCEPT |
Lokale Kommunikation (Quelle 127.0.0.1) ist erlaubt | ||
any 192.168.12.1 DROP |
Pakete an die Adresse 192.168.12.1 werden weggeworfen | ||
any 192.168.12.1 DROP LOG |
Pakete an die Adresse 192.168.12.1 werden weggeworfen und zusätzlich protokolliert | ||
any 192.168.12.1 DROP NOLOG |
Pakete an die Adresse 192.168.12.1 werden weggeworfen, werden aber nicht protokolliert | ||
22 ACCEPT |
Pakete an den Port 22 (ssh) werden akzeptiert | ||
IP_NET_1_NET ACCEPT |
Pakete aus dem an der ersten Schnittstelle hängenden Subnetz werden akzeptiert | ||
IP_NET_1_NET IP_NET_2_NET |
Kommunikation zwischen den an der ersten und zweiten | ||
ACCEPT BIDIRECTIONAL |
Schnittstelle hängenden Subnetzen ist gestattet |
Eine Regel kann eingeschränkt werden in Bezug auf die Schnittstelle, über die ein Paket hereinkam bzw. hinausgeht. Das Format sieht wie folgt aus: if:in:out
In der INPUT-Kette kann man die Schnittstelle für hinausgehende Pakete nicht einschränken (das Paket geht ja nicht mehr hinaus), in der POSTROUTING-Kette kann man die Schnittstelle für hereinkommende Pakete nicht einschränken, da die Information darüber nicht mehr vorhanden ist. Lediglich in der FORWARD-Kette kann man für beides Bedingungen angeben.
Möglich sind folgende Werte für in bzw. out:
IP_NET_x_DEV
Eine Regel kann eingeschränkt werden in Bezug auf das Protokoll, zu dem ein Paket gehört. Das Format sieht wie folgt aus: prot:protocol bzw. prot:icmp:icmp-type. protocol kann dabei einen der folgenden Werte annehmen:
Wenn eine solche Einschränkung nicht vorhanden ist, aber dennoch Portnummern in einer Regel verwendet werden, dann wird die Regel zweimal angelegt, nämlich einmal für das tcp- und einmal für das udp-Protokoll.
Mittels mac:mac-address kann eine Einschränkung bezüglich der MAC-Adresse vorgenommen werden.
Der von fli4l verwendete Paketfilter sammelt Informationen über den Zustand von Verbindungen. Diese Informationen kann man dann nutzen, um Pakete zu filtern, also z.B. nur Pakete durchzulassen, die zu bereits bestehenden Verbindungen gehören. Die Zustände einer Verbindung können sein:3.3
Zustand | Bedeutung |
INVALID | Das Paket gehört zu keiner bekannten Verbindung. |
ESTABLISHED | Das Paket gehört zu einer Verbindung, über die bereits in beide Richtungen Pakete geflossen sind. |
NEW | Das Paket hat eine neue Verbindung aufgebaut oder gehört zu einer Verbindung, bei der noch nicht Pakete in beide Richtungen geflossen sind. |
RELATED | Das Paket baut eine neue Verbindung auf, hat aber eine Beziehung zu einer bestehenden Verbindung (z.B. baut ftp eine separate Verbindung für den eigentlichen Datentransfer auf). |
Die Zustände werden wie folgt angegeben: state:state(s). Will man mehrere Zustände angeben, werden diese mit Komma getrennt. Um z.B. nur Pakete durchzulassen, die direkt oder indirekt zu bestehenden Verbindungen gehören, kann man state:ESTABLISHED,RELATED schreiben (dies ist in der INPUT- oder FORWARD-Kette sinnvoll).
Unter bestimmten Umständen möchte man die Häufigkeit von Aktionen begrenzen, z.B. nur eine ICMP-Echo-Anforderung pro Sekunde zulassen. Das kann man mit der limit-Einschränkung erreichen, die wie folgt aussieht: limit:Häufigkeit:Burst. Die Häufigkeit wird dabei als n/Zeiteinheit (second, minute, hour, day) angegeben, wobei zusätzlich noch Ereignisse gehäuft auftreten können (Burst). Die Angabe limit:3/minute:5 heißt z.B., dass höchstens drei Ereignisse pro Minute erlaubt sind, wobei auch mal fünf Ereignisse dicht aufeinander folgend akzeptiert werden.
Um den Umgang mit dem Paketfilter weiter zu vereinfachen, gibt es die Möglichkeit, häufig vorkommende Regeln zu sogenannten Schablonen (Templates) zusammenzufassen. Damit ist es möglich, eine ganze Reihe von Paketfilterregeln zusammenzufassen und dieser Sammlung von Regeln einen symbolischen Namen zu geben. Anstatt direkt mit Protokollen und Portnummern zu hantieren, verwenden Sie dann Einträge wie tmpl:ssh, wenn Sie das ssh-Protokoll in einer Regel verwenden wollen. Wie mit Schablonen zu verfahren ist, wird hier am Beispiel von ssh gezeigt.
Wollen Sie Ihren fli4l-Router vom Internet aus per ssh erreichen, so schreiben Sie in einen Eintrag der Array-Variable PF_INPUT_% den entsprechenden Dienstnamen (hier ssh) mit vorangestelltem tmpl: und der Aktion, die für diesen Dienst gelten soll. Beispiel:
PF_INPUT_2='tmpl:ssh ACCEPT'
Hierbei steht tmpl: dafür, dass eine Regel auf einer Schablone basieren soll. Den Namen des Dienstes geben Sie nach dem `:' an, in unserem Beispiel also ssh. Zum Schluss geben Sie an, welche Aktion mit dem Dienst verbunden werden soll. Da Sie den fli4l-Router aus dem Internet erreichen wollen, erlauben wir die Verbindung mit ACCEPT. Einschränkungen von IP-Adressen oder Netzen sind nicht angegeben, also ist der ssh-Dienst von allen Netzen und über alle Schnittstellen erreichbar. Sie könnten bei Bedarf die gewohnten Schreibweisen vom Paketfilter benutzen, um den Zugriff auf den ssh-Dienst weiter einzuschränken.
Für welche Dienste Regeln vorbereitet sind (d.h. Schablonen existieren),
kann in der Schablonen-Datei in opt/etc/fwrules.tmpl/templates
nachgelesen werden. Im Folgenden finden Sie die Aufstellung in Tabellenform
(siehe Tabelle 3.8).
Schablone | Protokoll | Port(s) |
dhcp | udp | 67-68 |
dns | tcp/udp | 53 |
elster | tcp | 159.154.8.2:21 |
elster | tcp | 159.154.8.35:21 |
elster | tcp | 193.109.238.26:8000 |
elster | tcp | 193.109.238.27:8000 |
elster | tcp | 193.109.238.58:80 |
elster | tcp | 193.109.238.59:80 |
elster | tcp | 62.157.211.58:8000 |
elster | tcp | 62.157.211.59:8000 |
elster | tcp | 62.157.211.60:8000 |
elster | tcp | 80.146.179.2:80 |
elster | tcp | 80.146.179.3:80 |
ftp | tcp | 21 |
http | tcp | 80 |
https | tcp | 443 |
hylafax | tcp | 4559 |
imap | tcp | 143 |
imaps | tcp | 993 |
imond | tcp | 5000 |
ipmi | tcp | 22 |
ipmi | tcp | 2937 |
ipmi | tcp | 443 |
ipmi | tcp | 5120 |
ipmi | tcp | 5123 |
ipmi | tcp | 5900 |
ipmi | tcp | 5901 |
ipmi | tcp | 80 |
ipmi | tcp | 8889 |
ipmi | udp | 623 |
irc | tcp | 6667 |
ldap | tcp/udp | 389 |
tcp | 110 | |
tcp | 143 | |
tcp | 25 | |
tcp | 465 | |
tcp | 587 | |
tcp | 993 | |
tcp | 995 | |
mysql | tcp | 3306 |
nfs | tcp/udp | 111 |
nfs | tcp/udp | 2049 |
nntp | tcp | 119 |
ntp | udp | 123 |
oracle | tcp | 1521 |
pcanywhere | tcp | 5631-5632 |
ping | icmp:0 | |
ping | icmp:8 | |
pop3 | tcp | 110 |
pop3s | tcp | 995 |
privoxy | tcp | 8118 |
proxmox | tcp | 8006 |
proxmox | tcp | 5900 |
proxmox | tcp | 3128 |
rdp | tcp | 3389 |
rsync | tcp | 873 |
samba | tcp | 139 |
samba | tcp | 445 |
samba | udp | 137-138 |
sip | tcp/udp | 5060-5061 |
smtp | tcp | 25 |
snmp | tcp/udp | 161 |
socks | tcp | 1080 |
squid | tcp | 3128 |
ssh | tcp | 22 |
ssmtp | tcp | 465 |
submission | tcp | 587 |
svn | tcp | 3690 |
syslog | udp | 514 |
teamspeak | tcp | 14534 |
teamspeak | tcp | 51234 |
teamspeak | udp | 8767 |
telmond | tcp | 5001 |
telnet | tcp | 23 |
teredo | udp | 3544 |
tftp | udp | 69 |
time | tcp/udp | 37 |
traceroute | udp | 33404-33464 |
vdr | tcp | 6419 |
vnc | tcp | 5900 |
whois | tcp | 43 |
xbl | tcp/udp | 3074 |
xbl | udp | 88 |
xmppclient | tcp | 5222 |
xmppserver | tcp | 5269 |
Die Syntax für diese Form der Paketfilterregeln lautet also immer
tmpl:<Name des Dienstes> <Einschränkungen> <Gewünschte Aktion>
wobei als <Einschränkungen>
alles erlaubt ist, was unter
3.10.2 beschrieben wird. Die möglichen Werte für
<Gewünschte Aktion>
sind in 3.10.1 aufgelistet und
beschrieben.
Ein paar weitere Beispiele sollen die Arbeitsweise verdeutlichen. Zuerst wollen wir uns PF_PREROUTING ansehen:
PF_PREROUTING_N='2' PF_PREROUTING_1='tmpl:xbl dynamic DNAT:@xbox' PF_PREROUTING_2='tmpl:https dynamic DNAT:192.168.193.250'
Die Regel PF_PREROUTING_1 versorgt die Xbox mit allem, was für Xbox Live notwendig ist. Im einzelnen werden mit tmpl:xbl alle Ports und Protokolle, die für Xbox Live notwendig sind, an den Host xbox weitergeleitet. Anstelle der IP-Adresse wird ein Eintrag aus dem HOST_%_NAME-Array benutzt. Durch dynamic weiß der fli4l, dass die Ports von der Internet-Schnittstelle weitergeleitet werden sollen.
Die zweite Regel leitet das https-Protokoll an einen Webserver in der DMZ weiter.
Jetzt sehen wir uns an, wie es mit PF_INPUT weitergeht:
PF_INPUT_N='3' PF_INPUT_1='if:IP_NET_1_DEV:any ACCEPT' PF_INPUT_2='if:pppoe:any prot:tcp 113 ACCEPT' PF_INPUT_3='if:br0:any tmpl:dns @xbox IP_NET_1_IPADDR ACCEPT'
Die erste Regel lässt alle aus dem Netz, das mit IP_NET_1 definiert ist, auf den Router zugreifen. Die zweite Regel ist für das oident-Paket. Dort wird der ident-Port geöffnet. Die dritte und letzte Regel erlaubt der Xbox den Zugriff auf den DNS Server auf dem fli4l. Hier ist auch wieder schön zu sehen, wie man einen Host-Alias einsetzt.
In PF_FORWARD und PF_POSTROUTING steht nichts tmpl-spezifisches mehr.
Es ist auch möglich, dass Sie eigene Schablonen anlegen oder dass
Pakete ihre eigenen Schablonen mitbringen. Um eine eigene
Schablone anzulegen, muss lediglich eine Datei mit den Namen der
Schablone erstellt und die entsprechenden Regeln dort
aufgenommen werden. Wenn Sie eine private Schablonendatei anlegen wollen,
erstellen Sie diese in dem Verzeichnis etc/fwrules.tmpl
unterhalb Ihres
config-Verzeichnisses, so wie es die Abbildung
3.2 zeigt. Wenn das Verzeichnis
etc/fwrules.tmpl unterhalb Ihres config-Verzeichnisses noch
nicht existiert, legen Sie bitte zuerst beide Verzeichnisse an. Alternativ
können Paket-Entwickler oder Benutzer, die Schablonen für mehr als eine
Konfiguration anlegen wollen, ihre Regeln direkt in das Verzeichnis
opt/etc/fwrules.tmpl ablegen. In dieses Verzeichnis kommen dann die
neuen Schablonen. Dabei gilt die Regel, dass die Schablonen im
config-Verzeichnis des Benutzers vorrangig behandelt werden.
Zum Schluss wird die Schablonendatei, die zum Lieferumfang von
fli4l gehört, ausgewertet. Sie können also Einträge in der fli4l-Schablonendatei
dadurch überschreiben, indem Sie eine
Schablonendatei mit dem Namen der zu überschreibenden Schablone in Ihrem
config-Verzeichnis anlegen.
Wenn Sie zum Beispiel die Schablone vpn_freunde anlegen wollen, legen Sie die Datei vpn_freunde an. Das Template soll die Dienste ssh, smtp, dns und samba enthalten. Also schreiben Sie in die Datei vpn_freunde Folgendes:
prot:tcp 22 prot:tcp 25 53 prot:udp 137-138 prot:tcp 139 prot:tcp 445
Wann immer Sie jetzt die Schablone vpn_freunde benutzen,
werden daraus Regeln für alle darin aufgeführten Protokolle und Ports erzeugt.
PF_FORWARD_x='tmpl:vpn_freunde ACCEPT'
etwa erstellt folgende
FORWARD-Regeln:
prot:tcp 22 ACCEPT prot:tcp 25 ACCEPT 53 ACCEPT prot:udp 137-138 ACCEPT prot:tcp 139 ACCEPT prot:tcp 445 ACCEPT
Der Paketfilter wird im Wesentlichen durch vier Array-Variablen konfiguriert:
Für alle folgenden Ketten gilt die in PF_LOG_LEVEL vorgenommene Einstellung der Protokoll-Stufe, deren Inhalt auf einen der folgenden Werte gesetzt werden kann: debug, info, notice, warning, err, crit, alert, emerg.
Über die INPUT-Kette wird konfiguriert, wer auf den Router zugreifen darf. Trifft keine der Regeln der INPUT-Kette zu, bestimmt die Standard-Aktion, was mit dem Paket passieren soll, und die Protokoll-Variable bestimmt, ob es bei einer Ablehnung ins System-Protokoll geschrieben werden soll.
Bei den verwendeten Parametern gibt es die folgenden Einschränkungen:
Möchte man das Verhalten komplett selbst definieren, kann man hier `no' eintragen, muss dann jedoch alle Regeln selbst definieren. Eine zum Standardverhalten äquivalente Konfiguration würde wie folgt aussehen (die Beschreibung der Liste für benutzerdefinierte Ketten erfolgt hier):
PF_INPUT_ACCEPT_DEF='no' # # limit ICMP echo requests - use a separate chain # PF_USR_CHAIN_N='1' PF_USR_CHAIN_1_NAME='usr-in-icmp' PF_USR_CHAIN_1_RULE_N='2' PF_USR_CHAIN_1_RULE_1='prot:icmp:echo-request length:0-150 limit:1/second:5 ACCEPT' PF_USR_CHAIN_1_RULE_2='state:RELATED ACCEPT' PF_INPUT_N='4' PF_INPUT_1='prot:icmp usr-in-icmp' PF_INPUT_2='state:ESTABLISHED,RELATED ACCEPT' PF_INPUT_3='if:lo:any ACCEPT' PF_INPUT_4='state:NEW 127.0.0.1 DROP BIDIRECTIONAL'
Die erste Regel verzweigt zur ratenlimitierenden ``usr-in-icmp''-Kette.
Die zweite Regel akzeptiert nur solche Pakete, die zu bestehenden Verbindungen
gehören (also Paketen, die entweder den Zustand ESTABLISHED oder
RELATED besitzen), und die dritte erlaubt lokale Kommunikation
(if:lo:any ACCEPT
). Die vierte filtert Pakete heraus,
die behaupten, lokale Kommunikation zu sein, aber nicht bereits von
der vorherigen Regel akzeptiert wurden.
Arbeitet man mit OpenVPN, muss man die Regeln noch ergänzen, um die von diesen Paketen verwendeteten Ketten einzubinden.
PF_INPUT_N='5' ... PF_INPUT_5='ovpn-chain'
Über die FORWARD-Kette wird konfiguriert, welche Pakete vom Router weitergeleitet werden. Trifft keine der Regeln der FORWARD-Kette zu, bestimmt die Standard-Aktion, was mit dem Paket passieren soll,und die Protokoll-Variable bestimmt, ob es bei einer Ablehnung ins System-Protokoll geschrieben werden soll.
Bei den verwendeten Parametern gibt es die Einschränkung, dass nur ACCEPT, DROP und REJECT als Aktion angegeben werden können.
'state:ESTABLISHED,RELATED ACCEPT'
,
weiterhin eine Regel, die Pakete mit unbekanntem Zustand verwirft:
'state:INVALID DROP'
.
und schließlich eine Regel, die Pakete mit gefälschten IP-Adressen verwirft:
'state:NEW 127.0.0.1 DROP BIDIRECTIONAL'
.
Zusätzlich generieren die anderen Subsysteme auch noch Standardregeln - eine Konfiguration ohne Standardregeln mit Portweiterleitung und OpenVPN würde mindestens folgende Regeln enthalten:
PF_FORWARD_ACCEPT_DEF='no' PF_FORWARD_N='5' PF_FORWARD_1='state:ESTABLISHED,RELATED ACCEPT' PF_FORWARD_2='state:INVALID DROP' PF_FORWARD_3='state:NEW 127.0.0.1 DROP BIDIRECTIONAL' PF_FORWARD_4='pfwaccess-chain' PF_FORWARD_5='ovpn-chain'
Über die OUTPUT-Kette wird konfiguriert, worauf der Router selbst zugreifen darf. Trifft keine der Regeln der OUTPUT-Kette zu, bestimmt die Standard-Aktion, was mit dem Paket passieren soll, und die Protokoll-Variable bestimmt, ob es bei einer Ablehnung ins System-Protokoll geschrieben werden soll.
Bei den verwendeten Parametern gibt es die folgenden Einschränkungen:
Möchte man das Verhalten komplett selbst definieren, kann man hier `no' eintragen, muss dann jedoch alle Regeln selbst definieren. Eine zum Standardverhalten äquivalente Konfiguration würde wie folgt aussehen:
PF_OUTPUT_ACCEPT_DEF='no' PF_OUTPUT_N='1' PF_OUTPUT_1='state:ESTABLISHED,RELATED ACCEPT'
Die erste (und einzige) Regel akzeptiert nur solche Pakete, die zu bestehenden Verbindungen gehören (also Paketen, die entweder den Zustand ESTABLISHED oder RELATED besitzen).
Aus verschiedenen Gründen besteht manchmal der Bedarf, eigene Ketten anzulegen und dort die Pakete genauer zu filtern. Diese Ketten kann man mittels PF_USR_CHAIN_% definieren und mit Regeln füllen. Die Namen der Ketten müssen dabei mit usr- beginnen und können nach ihrer Definition überall in der INPUT- oder FORWARD-Kette statt einer Aktion eingesetzt werden. Als Beispiel soll hier die bereits vorher verwendete ICMP-Filterkette dienen:
PF_USR_CHAIN_N='1' # # create usr-in-icmp # PF_USR_CHAIN_1_NAME='usr-in-icmp' # # add rule to usr-in-icmp # PF_USR_CHAIN_1_RULE_N='2' PF_USR_CHAIN_1_RULE_1='prot:icmp:echo-request length:0-150 limit:1/second:5 ACCEPT' PF_USR_CHAIN_1_RULE_2='state:RELATED ACCEPT' # # use chain in PF_INPUT # PF_INPUT_2='prot:icmp usr-in-icmp'
Pakete können vor und nach Routing-Entscheidungen noch manipuliert werden. Sie können zum Beispiel eine neue Zieladresse erhalten, um an einen anderen Rechner weitergeleitet zu werden (Portweiterleitung) oder eine andere Quelladresse erhalten, um das hinter dem Router liegende Netzwerk zu maskieren. Maskieren nutzt man beispielsweise, um ein privates Netz über eine öffentliche IP ins Netz zu bringen oder in einem DMZ-Setup die Struktur des lokalen Netzes vor den Rechnern in der DMZ zu verbergen.
Die Konfiguration erfolgt über zwei Ketten, die PREROUTING- und die POSTROUTING-Kette. Über die POSTROUTING-Kette wird konfiguriert, welche Pakete vom Router maskiert werden. Trifft keine der Regeln der POSTROUTING-Kette zu, werden die Pakete unmaskiert weitergeleitet.
Beim Maskieren gibt es zwei Varianten: eine für Netzwerk-Schnittstellen, die bei der Einwahl erst eine IP-Adresse zugewiesen bekommen (MASQUERADE) und eine für Netzwerk-Schnittstellen mit statischer IP-Adresse (SNAT). SNAT erwartet dabei zusätzlich die IP-Adresse, die im Paket als Quelle eingetragen werden soll. Diese kann als
Sowohl bei SNAT als auch bei MASQUERADE kann schließlich ein Port bzw. Portbereich angegeben werden, auf den der Quellport abgebildet werden soll. Normalerweise ist das nicht nötig, da der Kern die Ports allein auswählen kann. Es gibt aber Anwendungen, die verlangen, dass der Quellport unverändert bleibt (und somit ein 1:1-NAT erfordern) oder die ein PAT (Port Address Translation) oder NAPT (Network Address and Port Translation) verbieten. Der Portbereich wird einfach hinten angehängt, z.B. so: SNAT:IP_NET_1_IPADDR:4000-8000.
Bei der POSTROUTING-Kette können nur ACCEPT, SNAT, NETMAP und MASQUERADE als Aktionen verwendet werden.
Über die PREROUTING-Kette wird konfiguriert, welche Pakete an einen anderen Rechner weitergeleitet werden sollen. Trifft keine der Regeln der PREROUTING-Kette zu, werden die Pakete unverändert weiterbehandelt. Die Aktion DNAT erwartet dabei die IP-Adresse, die im Paket als Ziel eingetragen werden soll. Diese kann als
Schließlich kann noch ein Port bzw. Portbereich angegeben werden, auf den der Zielport abgebildet werden soll. Das ist aber nur nötig, wenn der Port geändert werden soll. Der Port bzw. Portbereich wird einfach hinten angehängt, z.B. so: DNAT:@server:21.
REDIRECT verhält sich wie DNAT, nur dass die Ziel-IP-Adresse immer auf die (primäre) IP-Adresse der Schnittstelle, auf der das Paket hereinkam, gesetzt wird und damit das Paket lokal zugestellt wird. Dies wird z.B. für transparente Proxys benötigt, siehe OPT_TRANSPROXY.
Will man eine Portweiterleitung auf Schnittstellen mit dynamischen Adressen machen, weiß man zum Zeitpunkt der Konfiguration noch nicht, an welche IP die Pakete gerichtet sein werden. Daher kann man in der PREROUTING-Kette dynamic als Platzhalter für die später zugewiesene IP verwenden, etwa wie folgt:
'dynamic:80 DNAT:1.2.3.4' # leite http-Pakete an die # IP-Adresse 1.2.3.4 weiter 'prot:gre any dynamic DNAT:1.2.3.4' # leite gre-Pakete (Teil des PPTP- # Protokolls) an die IP-Adresse # 1.2.3.4 weiter
Bei der PREROUTING-Kette können nur ACCEPT, DNAT, NETMAP und REDIRECT als Aktionen verwendet werden.
Für weitere Beispiele zur Portweiterleitung siehe den nächsten Abschnitt.
Im Folgenden sind einige Beispiele für die Paketfilter-Konfiguration angegeben.
Die fli4l-Standardkonfiguration der Distribution sieht für die INPUT-Kette wie folgt aus:
PF_INPUT_POLICY='REJECT' PF_INPUT_ACCEPT_DEF='yes' PF_INPUT_LOG='no' PF_INPUT_N='1' PF_INPUT_1='IP_NET_1 ACCEPT'
Damit erreichen wir, dass
PF_INPUT_1='IP_NET_1 ACCEPT'
),
PF_INPUT_ACCEPT_DEF='yes'
),
PF_INPUT_ACCEPT_DEF='yes'
),
PF_INPUT_POLICY='REJECT'
),
PF_INPUT_LOG='no'
).
Für die FORWARD-Kette sieht das so ähnlich aus: Nur Pakete unseres lokalen Netzes und Pakete, die zu Verbindungen gehören, die von Rechnern im lokalen Netz aufgebaut wurden, sollen weitergeleitet werden. Des Weiteren werden NetBIOS- und CIFS-Pakete verworfen.
PF_FORWARD_POLICY='REJECT' PF_FORWARD_ACCEPT_DEF='yes' PF_FORWARD_LOG='no' PF_FORWARD_N='2' PF_FORWARD_1='tmpl:samba DROP' PF_FORWARD_2='IP_NET_1 ACCEPT'
Was man hier gut sieht, ist die Abhängigkeit von der Reihenfolge der Regeln: Zuerst werden NetBIOS-Pakete verworfen, und danach werden die Pakete des lokalen Netzes akzeptiert.
Nun kann das lokale Netz mit dem Router kommunizieren, seine Pakete werden weitergeleitet, es fehlt nur noch das Maskieren, welches für den Zugriff eines privaten Netzwerkes auf das Internet notwendig ist:
PF_POSTROUTING_N='1' PF_POSTROUTING_1='IP_NET_1 MASQUERADE'
Wollen wir lokal mehrere Subnetze haben, die frei und unmaskiert miteinander kommunizieren können, müssen wir dafür sorgen, dass Pakete zwischen diesen Subnetzen nicht verworfen und auch nicht maskiert werden. Dazu fügen wir einfach eine Regel hinzu oder modifizieren die vorhandene.
Angenommen, wir haben einen DSL-Zugang über PPPoE, und die beiden Subnetze sind IP_NET_1 (192.168.6.0/24) und IP_NET_2 (192.168.7.0/24). Dann würde die Konfiguration wie folgt aussehen:
PF_FORWARD_POLICY='REJECT' PF_FORWARD_ACCEPT_DEF='yes' PF_FORWARD_LOG='no' PF_FORWARD_N='4' PF_FORWARD_1='IP_NET_1 IP_NET_2 ACCEPT BIDIRECTIONAL' PF_FORWARD_2='tmpl:samba DROP' PF_FORWARD_3='IP_NET_1 ACCEPT' PF_FORWARD_4='IP_NET_2 ACCEPT' PF_POSTROUTING_N='3' PF_POSTROUTING_1='IP_NET_1 IP_NET_2 ACCEPT BIDIRECTIONAL' PF_POSTROUTING_2='IP_NET_1 MASQUERADE' PF_POSTROUTING_3='IP_NET_2 MASQUERADE'
Regel eins sorgt jetzt dafür, dass Pakete zwichen den beiden Subnetzen ohne weitere Prüfung weitergeleitet werden. Die Regeln drei und vier sorgen dafür, dass beide Subnetze auch ins Internet kommen. Die erste Regel der POSTROUTING-Kette sorgt dafür, dass die Kommunikation zwischen den Subnetzen unmaskiert erfolgt.
Alternativ könnten wir auch sagen, dass nur Pakete, die über die pppoe-Schnittstelle hinausgehen, maskiert werden sollen:
PF_POSTROUTING_N='1' PF_POSTROUTING_1='if:any:pppoe MASQUERADE'
Genauso hätte man die Filterung der Ports auch auf die pppoe-Schnittstelle beschränken und die beiden Subnetze zu einem zusammenfassen können, das würde dann wie folgt aussehen:
PF_FORWARD_POLICY='REJECT' PF_FORWARD_ACCEPT_DEF='yes' PF_FORWARD_LOG='no' PF_FORWARD_N='2' PF_FORWARD_1='if:any:pppoe tmpl:samba DROP' PF_FORWARD_2='192.168.6.0/23 ACCEPT' PF_POSTROUTING_N='1' PF_POSTROUTING_1='if:any:pppoe MASQUERADE'
Pakete, die über die pppoe-Schnittstelle hinausgehen und die an die udp-Ports 137-138 oder an die tcp-Ports 139 und 445 adressiert sind, werden verworfen (Regel 1), alle anderen Pakete, die aus dem Subnetz 192.168.6.0/23 kommen, werden weitergeleitet (Regel 2).
Fügen wir dem Ganzen noch ein Netzwerk 10.0.0.0/24 hinzu (z.B. ein Dial-In-Netzwerk), mit dem wir unmaskiert kommunizieren wollen, wobei Pakete an die udp-Ports 137-138 sowie an die tcp-Ports 139 und 445 verworfen werden sollen, dann würde das wie folgt aussehen:
PF_FORWARD_POLICY='REJECT' PF_FORWARD_ACCEPT_DEF='yes' PF_FORWARD_LOG='no' PF_FORWARD_N='4' PF_FORWARD_1='IP_NET_1 IP_NET_2 ACCEPT BIDIRECTIONAL' PF_FORWARD_2='tmpl:samba DROP' PF_FORWARD_3='192.168.6.0/23 ACCEPT' PF_FORWARD_4='10.0.0.0/24 ACCEPT' PF_POSTROUTING_N='2' PF_POSTROUTING_1='10.0.0.0/24 ACCEPT BIDIRECTIONAL' PF_POSTROUTING_2='192.168.6.0/23 MASQUERADE'
PF_FORWARD_ACCEPT_DEF='yes'
abgedeckt.
Alternativ ginge auch:
PF_POSTROUTING_N='1' PF_POSTROUTING_1='if:any:pppoe MASQUERADE'
Diese Regel besagt, dass nur Pakete, die über die pppoe-Schnittstelle hinausgehen, maskiert werden.
Blacklists (ein Rechner in dieser Liste darf etwas nicht) und Whitelists (ein Rechner in dieser Liste darf etwas) werden prinzipiell ähnlich umgesetzt. Es werden Regeln geschrieben, die am Anfang sehr speziell sind und nach hinten immer allgemeiner werden. Bei einer Blacklist stehen am Anfang Regeln, die etwas verbieten und am Ende Regeln, die allen bisher nicht erwähnten etwas erlauben. Bei einer Whitelist ist es genau umgekehrt.
Beispiel 1: Alle Rechner im Subnetz 192.168.6.0/24 außer Rechner 12 dürfen ins Internet, solange sie nicht mit den CIFS Ports 137-138 (udp), 139 und 445 (tcp) kommunizieren wollen:
PF_FORWARD_POLICY='REJECT' PF_FORWARD_ACCEPT_DEF='yes' PF_FORWARD_LOG='no' PF_FORWARD_N='3' PF_FORWARD_1='192.168.6.12 DROP' PF_FORWARD_2='tmpl:samba DROP' PF_FORWARD_3='192.168.6.0/23 ACCEPT' PF_POSTROUTING_N='1' PF_POSTROUTING_2='192.168.6.0/24 MASQUERADE'
Beispiel 2: Nur Rechner 12 darf ins Internet (aber nicht an die o.g. Ports ...), alle anderen dürfen nur lokal mit einem anderen Subnetz kommunizieren:
PF_FORWARD_POLICY='REJECT' PF_FORWARD_ACCEPT_DEF='yes' PF_FORWARD_LOG='no' PF_FORWARD_N='3' PF_FORWARD_1='192.168.6.0/24 192.168.7.0/24 ACCEPT BIDIRECTIONAL' PF_FORWARD_2='tmpl:samba DROP' PF_FORWARD_3='192.168.6.12 ACCEPT' PF_POSTROUTING_N='1' PF_POSTROUTING_1='if:any:pppoe MASQUERADE'
# # Zugriff auf den Router # PF_INPUT_POLICY='REJECT' PF_INPUT_ACCEPT_DEF='yes' PF_INPUT_LOG='no' PF_INPUT_N='1' PF_INPUT_1='IP_NET_1 ACCEPT' # alle Hosts im lokalen Netz dürfen # auf den Router zugreifen # # Zugriff auf das ``Internet'' # PF_FORWARD_POLICY='REJECT' PF_FORWARD_ACCEPT_DEF='yes' PF_FORWARD_LOG='no' PF_FORWARD_N='2' PF_FORWARD_1='tmpl:samba DROP' # Samba-Pakete, die das Netz # verlassen wollen, werden verworfen PF_FORWARD_2='IP_NET_1 ACCEPT' # alle anderen Pakete dürfen das # lokale Netz verlassen # # Maskieren des lokalen Netzes # PF_POSTROUTING_N='1' PF_POSTROUTING_1='IP_NET_1 MASQUERADE' # maskiere Pakete, die das Subnetz # verlassen
# # Zugriff auf den Router # PF_INPUT_POLICY='REJECT' PF_INPUT_ACCEPT_DEF='yes' PF_INPUT_LOG='no' PF_INPUT_N='2' PF_INPUT_1='IP_NET_1 ACCEPT' # alle Hosts im lokalen Netz dürfen # auf den Router zugreifen PF_INPUT_2='IP_NET_2 ACCEPT' # alle Hosts im lokalen Netz dürfen # auf den Router zugreifen # # Zugriff auf das ``Internet'' # PF_FORWARD_POLICY='REJECT' PF_FORWARD_ACCEPT_DEF='yes' PF_FORWARD_LOG='no' # # Freie Kommunikation zwischen den Netzen # PF_FORWARD_N='4' PF_FORWARD_1='IP_NET_1 IP_NET_2 ACCEPT BIDIRECTIONAL' PF_FORWARD_2='tmpl:samba DROP' # Samba-Pakete, die das Netz # verlassen wollen, werden verworfen PF_FORWARD_3='IP_NET_1 ACCEPT' # alle anderen Pakete dürfen das # lokale Netz verlassen PF_FORWARD_4='IP_NET_2 ACCEPT' # alle anderen Pakete dürfen das # lokale Netz verlassen # # Maskieren der lokalen Netze, unmaskierte Kommunikation zwischen den # Netzen # PF_POSTROUTING_N='3' PF_POSTROUTING_1'IP_NET_1 IP_NET_2 ACCEPT BIDIRECTIONAL' PF_POSTROUTING_2='IP_NET_1 MASQUERADE' # maskiere Pakete, die das Subnetz # verlassen PF_POSTROUTING_3='IP_NET_2 MASQUERADE' # maskiere Pakete, die das Subnetz # verlassen
# # Zugriff auf den Router # PF_INPUT_POLICY='REJECT' PF_INPUT_ACCEPT_DEF='yes' PF_INPUT_LOG='no' PF_INPUT_N='4' PF_INPUT_1='IP_NET_1 ACCEPT' # alle Hosts im lokalen Netz dürfen # auf den Router zugreifen PF_INPUT_2='IP_NET_2 ACCEPT' # alle Hosts im lokalen Netz dürfen # auf den Router zugreifen PF_INPUT_3='tmpl:ssh ACCEPT' # gestatte Zugriff auf SSH-Dienst # von überall her PF_INPUT_4='tmpl:http 1.2.3.4/24 ACCEPT' # gestatte Rechner aus # einem bestimmten Subnetz Zugriff # auf HTTP-Dienst # # Zugriff auf das ``Internet'' # PF_FORWARD_POLICY='REJECT' PF_FORWARD_ACCEPT_DEF='yes' PF_FORWARD_LOG='no' # # Keine Kommunikation zwischen den Netzen, beide Netze dürfen ins # Internet, Samba-Pakete werden verworfen # PF_FORWARD_N='2' PF_FORWARD_1='tmpl:samba if:any:pppoe DROP' # Samba-Pakete, die das Netz # verlassen wollen, werden verworfen PF_FORWARD_2='if:any:pppoe ACCEPT' # alle anderen Pakete dürfen das # lokale Netz verlassen # # Maskieren der lokalen Netze, unmaskierte Kommunikation zwischen den # Netzen # PF_POSTROUTING_N='1' PF_POSTROUTING_1='if:any:pppoe MASQUERADE' # maskiere Pakete, die das Subnetz # verlassen
Portweiterleitungen lassen sich mit den PREROUTING-Regeln wie folgt
umsetzen (TARGET
bezeichnet die ursprüngliche Zieladresse (optional) und
den ursprünglichen Zielport, NEW_TARGET
bezeichnet die neue Zieladresse
und den neuen Zielport (optional), PROTOCOL
bezeichnet das jeweilige
Protokoll):
TARGET='<port>' NEW_TARGET='<ip>' PROTOCOL='<proto>' PF_PREROUTING_x='prot:<proto> dynamic:<port> DNAT:<ip>' TARGET='<port1>-<port2>' NEW_TARGET='<ip>' PROTOCOL='<proto>' PF_PREROUTING_x='prot:<proto> dynamic:<port1>-<port2> DNAT:<ip>' TARGET='<ip>:<port-a>' NEW_TARGET='<ip>:<port-b>' PROTOCOL='<proto>' PF_PREROUTING_x='prot:<proto> any <ip>:<port-a> DNAT:<ip>:<port-b>'
PF_FORWARD_x='IP_NET_1 ACCEPT'
nicht existiert (FORWARD).
Beispiel 1: Angenommen, wir haben nur ein Netz IP_NET_1,
in dem auf einem Rechner namens proxy ein Squid-Proxy läuft, und
wollen den gesamten http-Datenverkehr über ihn leiten. Squid lauscht
auf Port 3128. Der Einfachheit halber beziehen wir uns via @proxy auf
den eingetragenen Host aus HOST_1_NAME='proxy'
(vgl.
Domainkonfiguration).
Das Ganze würde wie folgt aussehen:
... PF_PREROUTING_x='@proxy ACCEPT' # Pakete vom Proxy sollen nicht umgeleitet werden PF_PREROUTING_x='prot:tcp IP_NET_1 80 DNAT:@proxy:3128' # HTTP-Pakete aus IP_NET_1 mit einem beliebigen Ziel werden # umgeleitet nach @proxy, Port 3128 PF_POSTROUTING_x='any @proxy:3128 SNAT:IP_NET_1_IPADDR' # alle Pakete an den Proxy-Port 3128 so umschreiben, als wären sie # vom fli4l (IP_NET_1_IPADDR) PF_FORWARD_x='prot:tcp @proxy 80 ACCEPT' # HTTP-Pakete vom Proxy durch die FORWARD-Kette durchlassen (wenn nötig) ...
Gibt es mehrere Netze oder potentielle Konflikte mit anderen Portweiterleitungen (die ja auch nichts anderes sind als DNAT-Regeln), muss man die Regeln vielleicht noch etwas enger formulieren.
Beispiel 2: Unser Proxy namens proxy steht in IP_NET_1, lauscht auf Port 3128 und soll nur für Clients aus IP_NET_1 wirksam werden. IP_NET_1 ist über IP_NET_1_DEV erreichbar. Pakete aus weiteren Netzen sollen nicht berücksichtigt werden.
... PF_PREROUTING_x='if:IP_NET_1_DEV:any !@proxy 80 DNAT:@proxy:3128' # Anfragen an den HTTP-Port, die nicht vom Proxy, aber über eine # interne Schnittstelle (IP_NET_1_DEV) kommen, an den Proxy-Port umleiten. # An dieser Stelle ist es wichtig, mit if:IP_NET_1_DEV:any zu # überprüfen, ob die Pakete von innen kommen, da sonst auch Pakete von # außen umgeleitet würden (Sicherheitslücke!). PF_POSTROUTING_x='prot:tcp IP_NET_1 @proxy:3128 SNAT:IP_NET_1_IPADDR' # HTTP-Pakete die aus IP_NET_1 stammen und für den Proxy-Port 3128 # gedacht sind, so umschreiben, als wären sie vom fli4l (IP_NET_1_IPADDR) PF_FORWARD_x='prot:tcp @proxy 80 ACCEPT' # HTTP-Pakete vom Proxy durch die FORWARD-Kette durchlassen (wenn nötig) ...
Beispiel 3: Um sich das Leben etwas zu erleichtern und die Regeln kürzer zu gestalten, kann man auch Templates einsetzen (vgl. Templates im Paketfilter). Zweckmäßig ist an dieser Stelle das tmpl:http, das in prot:tcp any any:80 übersetzt wird. So wird z.B. aus tmpl:http IP_NET_1 DNAT:@proxy:3128 dann prot:tcp IP_NET_1 80 DNAT:@proxy:3128.
Sowohl IP_NET_1 als auch IP_NET_2 sollen transparent über den Proxy umgeleitet werden. Damit ließe sich vereinfacht auch schreiben:
... PF_PREROUTING_x='tmpl:http @proxy ACCEPT' # HTTP-Pakete vom Proxy sollen nicht umgeleitet werden PF_PREROUTING_x='tmpl:http IP_NET_1 DNAT:@proxy:3128' # HTTP-Pakete aus IP_NET_1 sollen umgeleitet werden PF_PREROUTING_x='tmpl:http IP_NET_2 DNAT:@proxy:3128' # HTTP-Pakete aus IP_NET_2 sollen umgeleitet werden PF_POSTROUTING_x='IP_NET_1 @proxy:3128 SNAT:IP_NET_1_IPADDR' PF_POSTROUTING_x='IP_NET_2 @proxy:3128 SNAT:IP_NET_2_IPADDR' PF_FORWARD_x='tmpl:http @proxy ACCEPT' ...
Und so ließe sich das endlos fortsetzen ...
fli4l gestattet auch den Aufbau einer DMZ. Hier sei erstmal auf das Wiki verwiesen. https://ssl.nettworks.org/wiki
Die Verwendung von IP-Masquerading hat zwar den Vorteil, dass mehrere Rechner im LAN über eine einzige offizielle IP-Adresse geroutet werden kann, es gibt aber auch Nachteile, die man in Kauf nehmen muss.
Ein großes Problem ist zum Beispiel, dass kein Rechner von außen von sich aus eine Verbindung zu einem Rechner aufnehmen kann. Das ist zwar aus Sicherheitsgründen eigentlich durchaus erwünscht, aber bestimmte Protokolle funktionieren nicht mehr, weil sie einen Verbindungsaufbau von außen einfach erfordern.
Ein klassisches Beispiel ist FTP. Neben dem Kommunikationskanal, auf dem Befehle und Antworten ausgetauscht werden, wird ein weiterer Kanal (in Form eines IP-Ports) verwendet, um die eigentlichen Nutzdaten zu versenden. fli4l verwendet dafür bestimmte Conntrack-Helfer, um solche zusätzlichen Ports, die verwendet werden, ad hoc dann freizuschalten und an den internen Rechner weiterzuleiten, wenn sie benötigt werden. Dabei ``horcht'' der Conntrack-Helfer in den Datenstrom, um zu erkennen, wann ein zusätzlicher Port benötigt wird.
Typische Anwendungen für Conntrack-Helfer sind Chat-Protokolle und Spiele im Internet.
Ein solcher Conntrack-Helfer wird über Regeln in zwei speziellen Arrays aktiviert. Das Array PF_PREROUTING_CT_% enthält Helfer-Zuordnungen zu Paketen, die von außen kommen, das Array PF_OUTPUT_CT_% enthält Helfer-Zuordnungen zu Paketen, die auf dem Router generiert werden. Einige Beispiele aus der Praxis sollen dies verdeutlichen.
Beispiel 1: Soll aktives FTP aus dem LAN erlaubt werden, ist das aus der Sicht des Routers eine Verbindung von außerhalb, somit muss ein Eintrag in PF_PREROUTING_CT_% vorgenommen werden:
PF_PREROUTING_CT_N='1' PF_PREROUTING_CT_1='tmpl:ftp IP_NET_1 HELPER:ftp'
Damit wird für alle TCP-Verbindungen aus dem lokalen Netz (IP_NET_1) zu irgendeiner anderen Adresse an Port 21 (dies ist der ftp-Port) das ftp-Hilfsmodul geladen. Dieses Modul erlaubt dann im Laufe der Verbindung, dass der FTP-Server zurück zum Client eine Datenverbindung aufbauen kann, indem temporär ein ``Loch'' in der Firewall aufgemacht wird.
Beispiel 2: Soll passives FTP für einen FTP-Server im LAN ermöglicht werden (dabei wird die Datenverbindung von außen nach innen aufgebaut, so dass auch hier kurzfristig ein Loch in der Firewall geöffnet werden muss), ist dies ebenfalls aus der Sicht des Router eine Verbindung von außerhalb des Routers. Hier sieht die Regel folgendermaßen aus:
PF_PREROUTING_CT_N='1' PF_PREROUTING_CT_1='tmpl:ftp any dynamic HELPER:ftp'
Mit dieser Regel wird ausgedrückt, dass alle FTP-Verbindungen, die an die dynamische Adresse des Routers gesandt werden, mit dem FTP-Conntrack-Helfer assoziiert werden. Hier wurde dynamic verwendet, da angenommen wird, dass der Router für die Einwahl ins Internet verantwortlich ist und somit eine externe IP-Adresse besitzt. Falls der Router eine Einwahl via DSL durchführt, kann man die Regel auch so schreiben:
PF_PREROUTING_CT_N='1' PF_PREROUTING_CT_1='tmpl:ftp if:pppoe:any HELPER:ftp'
Mit dieser Regel wird ausgedrückt, dass alle FTP-Verbindungen, die von der DSL-Schnittstelle (pppoe) kommen, mit dem FTP-Conntrack-Helfer assoziiert werden.
Falls der Router sich nicht einwählt, sondern z.B. hinter einem anderen Router (Fritz!Box, Kabelmodem etc.) hängt, so kann die folgende Regel verwendet werden:
PF_PREROUTING_CT_N='1' PF_PREROUTING_CT_1='tmpl:ftp if:IP_NET_2_DEV:any HELPER:ftp'
Dabei wird im Beispiel angenommen, dass die Verbindung zum anderen Router über die Schnittstelle durchgeführt wird, die dem zweiten Subnetz zugeordnet ist (IP_NET_2_DEV).
Zu beachten ist, dass natürlich zusätzlich eine entsprechende Konfiguration der FORWARD-Kette nötig ist, um die FTP-Pakete auch tatsächlich weiterzuleiten. Eine typische Regel wäre etwa
PF_PREROUTING_1='tmpl:ftp any dynamic DNAT:@ftpserver'
wobei angenommen wird, dass der Host, auf dem das FTP-Serverprogramm läuft, den Namen ftpserver hat.
Beispiel 3: Schließlich muss auch, wenn man vom fli4l direkt aktives FTP benutzen möchte (etwa mit Hilfe des ftp-Programms aus dem tools-Paket), die Firewall dafür vorbereitet werden, diesmal in der OUTPUT-Kette, die mit Hilfe des Arrays PF_OUTPUT_CT_% konfiguriert wird:
PF_OUTPUT_CT_N='1' PF_OUTPUT_CT_1='tmpl:ftp HELPER:ftp'
Diese Regel ist jedoch unnötig, falls FTP_PF_ENABLE_ACTIVE='yes'
benutzt wird - siehe hierzu die Dokumentation des ftp-OPTs im
tools-Paket.
Es folgt eine Übersicht über die existierenden Conntrack-Helfer:
Helfer | Erläuterung |
ftp | File Transfer Protocol |
h323 | H.323 (Voice over IP) |
irc | Internet Relay Chat |
pptp | PPTP Masquerading (Mit diesem Modul lässt sich mehr als ein PPTP-Client gleichzeitig hinter einem fli4l-Router betreiben.) |
sip | Session Initiation Protocol |
sane | SANE Network Procotol |
snmp | Simple Network Management Protocol |
tftp | Trivial File Transfer Protocol |
Es folgt eine Übersicht der zu konfigurierenden Variablen: