Iptables - Was tun wenn das Limit mit ip_conntrack trackbarer Verbindungen erreicht ist?

Auf Grund eines aktuellen Anlasses tauchte dieses Wochenende in einer Diskussion das Thema "Was tun wenn ip_conntrack nicht mehr alle Verbindungen verarbeiten kann?" bzw "Wie kann man es vermeiden, daß Pakete im connection tracking des Linux Kernels landen?" auf. Im Endeffekt zeigten sich zwei Lösungen, die dritte Möglichkeit, das vollständige Deaktivieren von ip_conntrack, fällt für mich nicht darunter. Da es sich in der Problemstellung um einen sehr stark frequentierten Webserver handelt, haben sich die Betrachtungen auf Port 80 konzentriert.

ip_conntracki/nf_conntrack - erhöhen von nf_conntrack_max

Als erste Lösung bietet sich ein erhöhen der möglichen Verbindungen an, doch scheint jede Verbindung rund 350 Byte an nonswapable Kernelspeicher zu verbrauchen und sollte man Verkehr auf Port 80 wie in unserem Fall nicht weiter filtern sondern nur auf das Target ACCEPT umleiten, bietet sich ja noch die Möglichkeit Port 80 vom tracking auszunehmen. Dies bringt uns zur zweiten Lösung.

NOTRACK - einzelne matches vom connection tracking ausnehmen

/!\ Die folgende Befehle greifen tief in das Regelwerk einer iptables basierten Firewall ein. Sie können möglicherweise bestehendes Regelwerk umgehen und sollte auf keinen Fall unreflektiert und ungetestet übernomen werden.

Iptables bietet das Target NOTRACK um ein Paket, bevor es im üblicherweise genutzten filter-table abgearbeitet wird, im raw-table mit dem state UNTRACKED zu markieren und so nicht in das connection tracking von ip_conntrack bzw nf_conntrack auf zunehmen. Hiefür ist es in unserem Fall notwendig im raw-table des PREROUTINGs uns OUTPUTs das Paket von und für Port 80 als UNTRACKED zu markieren und dann im filter-table alle als UNTRACKED markierten Pakete rechtzeitig zu behandelt.

Erstellen des raw-tables

Als Ausgangslage nehme ich erst einmal es existiert noch kein raw-table. Wir flushen das PREROUTING und den OUTPUT im raw-table und markieren alle Pakete von und für Port 80 als UNTRACKED bzw leiten sie nach NOTRACK um.

Zuerst für das PREROUTING: Alle Pakete für Port 80 (dport 80) sollen den state UNTRACKED erhalten.

# iptables -t raw -F PREROUTING
# iptables -t raw -A PREROUTING -p tcp --dport 80 -j NOTRACK

Analog sollen alle Daten vom Webserver (sport 80) nicht getrackt werden.

# iptables -t raw -F OUTPUT
# iptables -t raw -A OUTPUT -p tcp --sport 80 -j NOTRACK

Obige iptables Befehle liefern folgenden raw-table.

# iptables -L -v -n -x --line-numbers -t raw
Chain PREROUTING (policy ACCEPT 15977 packets, 1286451 bytes)
num      pkts      bytes target     prot opt in     out     source               destination
1           0        0 NOTRACK    tcp  --  *      *       0.0.0.0/0            0.0.0.0/0           tcp dpt:80

Chain OUTPUT (policy ACCEPT 33729 packets, 7534935 bytes)
num      pkts      bytes target     prot opt in     out     source               destination
1           0        0 NOTRACK    tcp  --  *      *       0.0.0.0/0            0.0.0.0/0           tcp spt:80

Hieraus wird auch ersichtlich man könnte das tracking bzw das Ausnehmen vom tracking fein granuliert einstellen. Doch um diese Pakete richtig zu behandeln sind noch Eingriffe in den filter-table notwendig.

Anpassen des filter-tables zur richtigen Behandlung von UNTRACKED markierten Paketen

Um jetzt auch alle als UNTRACKED markierten Pakete, in unserem Fall, alle Pakete von und für Port 80, rechtzeitig zu behandeln, könnten Regeln für Port 80 in den filter-table eingebaut werden, oder es könnte, weit eleganter, der Dummystate UNTRACKED genutzt werden um alle nicht getrackten Pakete, in unserem Fall, zu akzeptieren. Um die zu erreichten fügen wir an erster Stelle (-I) je eine Regel für INPUT und OUTPUT ein, die alle als state UNTRACKED markierten Pakete abfängt und an das Target ACCEPT umleitet.

# iptables -I INPUT -m state --state UNTRACKED -j ACCEPT
# iptables -I OUTPUT -m state --state UNTRACKED -j ACCEPT

Sieht man sich nun /proc/sys/net/ip_conntrack an sollten keine neuen Verbindungen auf Port 80 getrackt werden und die Limits von ip_conntrack bzw nf_conntrack nicht mehr überschritten werden.

Fazit

Wer das Target NOTRACK nutzen will, sollte sich im Klaren sein,daß er, auch wenn er durch Nutzung dieses Targets möglicherweise Speicher spart und an Performance gewinnt, viele komplexe Mechanismen zur Paketbehandlung an den UNTRACKED markierten Paketen verliert. Sollte bisher kein komplexes Regelwerk vorhanden sein, mag das Einführen des Targets NOTRACK verlocken erscheinen, jedoch erreichen die wenigstens Server Zugriffszahlen, die auch nur annähert, meiner Meinung nach, diesen Verzicht auf eine mögliche Nutzung von komplexen Regelwerk rechtfertigen.

Einer weiteren Konsequenz sollte man sich bewußt sein, alle auf ip_conntrack bzw nf_conntrack basierten Tools zur Verbindungsanalyse, wie zB iptstate zeigen die UNTRACKED markierten Verbindungen nicht mehr an, jedoch netstat bietet noch immer eine Möglichkeit auch diese Verbindungen zu analysieren.

Sollte man sich dafür entscheiden das Target NOTRACK zu nutzen bietet es einen eleganten Weg nur einen Teil der Pakete vor einer Behandlung durch komplexere Regeln auszunehmen.