Iptables Grundlagen

Hi @ All,

hier findet Ihr ein Iptables HowTo welches Euch die wichtigsten Grundlagen und Funktionen erklärt mit Beispielen.

Also dann fangen wir mal an.

Diese Anleitung ist für Server Betreiber nicht für Cients !!!

Ich empfehle jedem Server Betreiber mindestens 2. IPs zu haben. Eine Öffentliche für E-Mail und Webserver oder sonstiges und eine NUR zur Administration wie SSH oder Plesk.

Erstmal ein Diagramm welches Aufzeigt wie die Datenpakete in Iptables verarbeitet werden.

iptables flow diagram pakete fluss

iptables flow diagram pakete fluss

 

 

 

 

Das Bild habe ich von https://www.lammertbies.nl

 

 

 

 

Grundbefehle:

Anzeige:
iptables -L CHAINNAME = Zeigt die Chain in einer Liste an.
iptables -L -vn = Zeigt alles an im Detail und ohne Namensauflösung. Egal bei welchem -L Befehl sollte immer ein -n am ende sein da sonst eine Namensauflösung versucht wird und das kann dann dauern.
iptables -L -vn –line-number = Zeigt alles mit der Zeilennummer

Unterschied zwischen der Policy ACCEPT und DROP:
Dabei geht es um die Standard Aktion die Iptables durch führt wenn es für ein Paket keine Regel gibt.
Hat man z.B.: nur eine Regel für SSH und die Policy steht auf ACCEPT werden alle anderen Paket zugelassen.
Steht die Policy auf DROP wird nur noch SSH zugelassen und alles andere wird gedropt.

Zum Einfügen von neuen Regeln via Console gibt es 2. Möglichkeiten:

INSERT:
Fügt die neue Regel an die OBERSTEstelle ein, hat man schon Regeln in seine Iptables drin wird diese über alle anderen eingefügt, also aller erste Regel.

APPEND:
Fügt die neue Regel an das ENDE ein, hat man schon Regeln definiert wird diese an das ENDE eingefügt und zum Schluss ausgeführt. Normal macht man einen -j DROP am Ende.

Und los geht es:
Iptables arbeitet mit CHAINS (wird so genannt) die Standard CHAINS sind INPUT, FORWARD und OUTPUT (immer in Großschrift) die immer vorhanden sein MÜSSEN
Will man eine Regel erstellen muss man IMMER die CHAIN mit angeben.

  • INPUT reget den kompletten rein kommenden traffic
  • FORWARD regelt den kompletten traffic der weitergeleitet wird (NUR für NAT)
  • OUTPUT regelt den kompletten traffic der raus geht.

Bsp:

Mit dieser Regel erlauben wir für die Ziel IP (Destination) den Zugriff auf Port 22 (SSH)
Etwas Paranoider

Wir erlauben nur der IP 79.5.48.7 den Zugriff auf die IP 82.105.45.201 Port 22. Bei einzelnen IPs muss kein /32 hinter die IP, das macht Iptables von alleine, wenn man aber ein Netzwerk frei geben möchte MUSS man die angeben.

Netzwerk Freigabe:

Das Netzwerk 79.5.0.0/16 ist es erlaubt auf die IP 82.105.45.201 über den Port 22 erlaubt Zugriff auf das System zu bekommen.

Würde man dies jetzt aber so Online stellen würde es nichts bringen da wir im Moment nur den Port 22 Freigegeben haben und das war es.
Wie am Anfang geschrieben arbeitet Iptables immer alle Regeln von oben nach unten ab und würde man sich die Iptables jetzt mal mit iptables -L INPUT -vn ansehen würde das ungefähr so aus sehen:

Die Firewall weiß also das die dem Netzwerk den Port 22 Freigeben soll aber nicht was mit dem restlichen Traffic passieren soll.
Hier kommt jetzt zum tragen welche Policy man nutzt!

In letzten block sieht man in der ersten Zeile:
Chain INPUT (policy DROP …..)

Dieser Punkt ist GANZ wichtig, wie oben schon beschrieben, würde die Firewall so live gehen würde man nicht mehr auf seinen Server kommen.
Wir haben zwar den Port 22 freigegeben aber bei dieser Policy ist es existentiell das wir auch eine neue Verbindung und/oder ein bestehende Verbindung erlauben sonst kann keine Kommunikation zu stande kommen.

Daher benötigen wir noch mindestens 2 Regel.
iptables -A INPUT -m state –state RELATED,ESTABLISHED -j ACCEPT = der Status der Verbindung wird geprüft auf Related und Established und wenn einer der beiden erfüllt ist wird das Paket durch gelassen.

Ich nutze hier -A weil ich die Regel an das ENDE der Liste haben will, würde ich diese Regel mit -I eintragen wäre diese über der Regel zum Erlauben des Zugriffs auf Port 22 aber das will man nicht.

WARUM ??? Wenn eine Verbindung den Status Established oder Related hat und dies Akzeptiert (ACCEPT) ist keine weitere Filterung mehr möglich!!!
Daher muss die KOMPLETTE Filterung vorher passieren.

Ohne die Regel RELATED,ESTABLISHED kann keine Verbindung aufgebaut werden, es reicht auch wenn diese einmal unter INPUT steht, man kann aber auch die Regel für jede einzelne Freigabe eintragen, ist aber mehr schreib arbeit und auch mit der Regel oben unnötig.

iptables -A INPUT -j DROP = Das Paket wird weggeworfen. (Wenn man die Policy DROP nutz muss das nicht gemacht werden, nur wenn man mit der Policy ACCEPT, standard, arbeitet.)
Sollte aber trotzdem drin stehen ist einfach sauberer und gibt einem das Gefühl der Sicherheit.

Arbeitet man mit der Policy ACCEPT muss man das Modul „state“ mit RELATED,ESTABLISHED nicht nutzen macht es aber weil sauberer.

In vielen HowTo’s steht bei RELATED,ESTABLISHED noch NEW dabei muss man aber nicht da RELATED NEW beinhaltet zu dem kann es mit dem Befehl NEW alleine Probleme geben, also immer alle 3 oder nur die 2 aus meinem Beispiel.

Schauen wir uns jetzt nochmal die Iptables an sieht die Welt schon viel Besser aus und macht auch mehr Sinn.

Linie: Prüfung von das Paket aus dem Netzwerk 79.5.0.0/16 kommt JA/NEIN, Zugriff auf IP 82.105.45.201 Port 22 JA/NEIN
Wird einer(1) der Fragen mit Nein beantwortet geht es direkt zu DROP weil die Regel nicht erfüllt, daher kommt es auch nicht zu einer Verbindgung.
Werden beide Antworten mit JA zurück gegeben wird die Verbindung Akzeptiert und die 2. Linie tritt in kraft.

Linie: Wird nur angefasst wenn vor läufige Regeln mit JA beantwortet wurden.
Linie: Alle Pakete die in den Regel zuvor NICHT Akzeptiert wurden werden weggeschmissen und damit auch keine Rückantwort gegeben.

Mit der jetzigen Konfiguration kann man nur eine Verbindung auf den Port 22 (SSH) erstellen und sonst nichts und dies auch nur aus einem bestimmten Netzwerk auf eine IP.

Jetzt kann man Anfange und weiter Dienste via iptables -I INPUT -d 82.105.45.201 -p tcp -m tcp –dport xxxx -j ACCEPT freigeben.

Bei Administrativen Diensten wie SSH sollte man den Zugriff immer mit einer SOURCE (-s) und DESTINATION (-d) begrenzen bei allen Öffentlichen Diensten benötigt man nur die DESTINATION IP sofern man mit 2. IPs arbeitet.

Tut man dies nicht kann man die Angabe mit -d immer weglassen da es eh nur eine IP gibt.
Daher empfehle ich IMMER sich bei seinem Provider eine 2. IP zu bestellen, kostet meisten nur einmalig 1€.

Wenn man mit dem ganzen Spass fertig ist hat man eventuell eine recht unübersichtliche Liste in seiner INPUT Chain was sich dadurch lösen lässt in dem man CUSTOM Chains erstellt.
Custom Chains sind selbst erstellt Chains die nicht INPUT, OUTPUT oder FORWARD heissen dürfen.

Eine kleine Liste für die gänigsten Dienste, mal schnell erstellt, aber es ist nicht alles drin.

Eine Liste alle Standard Port kann man auf Wiki finden
https://de.wikipedia.org/wiki/Liste_der_standardisierten_Ports

Wenn man das jetzt noch weiter ausbaut hat man mal schnell die Übersicht verloren.

Erstellen eine CUSTOM Chain:

iptables -N CHAINNAME = erstellt eine neu Custom Chain mit einem “frei” wählbaren Namen kann groß und klein geschrieben werden, ich bevorzuge reine Großschrift.

Bsp.: iptables -N TCP = erstellt eine Custom Chain mit dem Namen TCP

Um zu sehen was man gemacht hat:

Wie man sehen kann haben wir noch keine Regeln in der TCP Chain, da wir diese bis jetzt nur Erstellt haben und wir haben auch noch meine Reference, was soviel heisst das es keine Regel gibt die auf die Chain TCP verweisst und das machen wir jetzt.

iptables -I INPUT -p tcp -m tcp -j TCP = Erste Zeile in den Regeln (weil -I genutzt) jeglicher TCP Traffic soll in die Chain TCP
Da wir noch keine Regeln in der TCP haben wird jegliches TCP Paket gedropt, da wir in meinem Beispiel mit der DROP Policy arbeiten, nutzt man die ACCEPT Policy wird jeglicher TZCP traffic erlaubt.

Also Lösen wir das Problem.

Wenn man Zeile für Zeile eingibt wird nach und nach die einzelnen Ports freigegeben und ganz zum Schluss am Ende dieser Chain wird der DROP befehl gegeben damit alles andere was TCP ist gedropt wird.

Das freigeben und die Reihenfolge der einzelnen Port ist egal Wichtig ist aber das der STATE und der dann der DROP am ende der Liste stehen daher muss hier mit -A (APPEND) gearbeitet werden.

Die Ausgabe mit iptables -L -vn sieht dann so aus:

Wie wir sehen sind immer noch die anderen TCP Regeln in der INPUT Chain, die kann man Löschen.
Hierfür kann man diese via Console machen oder via Editor (schneller und einfacher).

Befehl: iptables -D CHAINNAME LINENUMBER/REGEL = Löscht eine Zeile/Regel aus der jeweiligen Chain ohne Chain passiert nichts.
Bei dem Befehl iptables -D CHAINNAME REGEL muss man darauf achten das man die komplette Syntax der Regel schreibt und dies ist auch noch keysenitive, also muss groß/klein schreibung beachtet werden.

Console:
Wir haben über die Console 2 Möglichkeiten

Einmal in dem man die Zeilennummer angibt oder die komplette Regel.

Mit der Zeilenummer muss man sich diese erst einmal Anzeigen lassen mit iptables -L INPUT -vn –line-number
Ausgabe:

Löschen: iptables -D INPUT 2 = Löscht die 2. Zeile
Zu Beachten ist das wenn man Zeile 2 löscht und man will danach die Zeile 3 löschen diese nach der vorherigen Ausgabe nicht mehr die gleiche Zeile ist da alle Zeilen um eine Zeile nach oben gerutscht sind.

Neue Abfrage:

Neue Ausgabe:

Wie man sehen kann hat sich alles nach der 2. Zeile im Gegensatz zu vorher um eine Zahl verringert. VORSICHT HIER

Löschen via Regel:

Löscht die Regel in der Chain INPUT mit exakt diesem Eintrag macht man einen Typo bekommt man eine Fehlermeldung das es diesen Eintrag in dieser Chain nicht gibt.

Löschen via Editor:
Um eine Datei zubekommen die man editieren kann muss man die aktuellen Regeln exportieren.

Datei mit dem Editor öffnen:

Jetzt kann man mit F9 (nano) die Zeile Löschen die man nicht mehr haben möchte.

Die Datei abspeichern und danach Importieren
Import: iptables-restore < /home/user/iptables

Ausgabe Prüfen:

Wie man sehen kann hat die TCP Chain jetzt eine Reference (vorher oben war da noch eine 0) so lange dies vorhanden ist kann man die Chain nicht löschen und bekommt eine Fehlermeldung.

Den selben Spass den wir mit TCP gemacht habe können wir jetzt auch noch für UDP Pakete machen.

Chain erstellen:
iptables -N UDP

Jump von INPUT nach UDP erstellen:
iptables -I INPUT -p udp -m udp -j UDP = Alle UDP Pakete springen in die Chain UDP

UDP Regeln:

Löschen der UDP Regel aus der INPUT CHAIN

Überprüfung der INPUT CHAIN

Überprüfung der UDP CHAIN

Nach dem jetzt die Grundkonfiguration beendet ist kann man mit zusätzlichen Einträgen das ganze noch verfeinern.

Prüfung TCP Flags:
iptables -I INPUT 5 -p tcp -m tcp –tcp-flags FIN,SYN,RST,ACK SYN -j REJECT –reject-with tcp-reset = Prüft die TCP Flags sollte eine Übereinstimmung vorhanden sein wird die Verbindung zurück gewiesen (Reject)

State Prüfung:
iptables -I INPUT 6 -m state –state INVALID -j DROP = Sollte der Status der Verbindung nicht OK sein wird direkt gedropt.

Interface lo:
Ich habe festgestellt das mache Dienste Problem machen können daher sollte man über die INPUT Chain alles was das Interface Betrifft freigeben.
iptables -I INPUT -i lo -j ACCEPT = Sämtlicher Traffic der beim Interface lo ankommt wird erlaubt. lo = localhost

Tracking:
Tracken der Datenpakte die über eine Einzelen IP laufen
iptables -I INPUT -d 85.105.45.202/32 = hat keinerlei Funktion man kann aber mit einem Script aus lesen wie viele Pakte an die IP gesendet wurden.

Pings begrenzen und blocken:
Der Ordnung halber erstellen wir dafür Extra eine Chain den wir mögen es ja Ordentlich.

iptables -N ICMP = Erstellt die ICMP Chain
iptables -I INPUT -p icmp -j ICMP = Trägt als ersten Eintrag das alle ICMP Pakte in die Chain ICMP sollen.

In der Chain machen wir dann unsere Einträge wer und wie oft gepingt werden darf.

Erklärung:

Zeile: erlaubt das Pingen von dem Netzwerk 79.5.0.0/16 auf die IP 85.105.45.202 und zwar nur der Type 8/0
Zeile: Ping auf unsere 2. IP 82.105.45.201/32 ist für jeden Verboten und die Pakte werden gedropt.
Zeile: Alle Pings auf alle IPs werden auf 1 Ping pro Minute begrenzt alles was mehr ist wird in die Syslog geschrieben.
Zeile: Dropen der Pakte die in Zeile 3. registriert wurden.

Würde jemand der sich nicht im Netzwerk von 79.5.0.0/16 befinden würde 1 ping gehen und dann 1 Minute lang geblockt. Wobei jemand aus diesem Netzwerk soviel pingen kann wie er will.
Für die IP 82.105.45.201/32 wird sowieso jedes ICMP Paket gedropt und zwar für alle.
Die 3. Zeile übernimmt nur das Logging und die letzte Zeile sorgt dafür das die Pakete auch gedropt werden.

Ich mache das aus einem einfachen Grund, wenn dann habe nur ich keinen Grund meinen Server zu pingen und sonst niemand und wenn dann darf mich jemand Fremdes gerne 1mal jede Minute einmal pingen.
Man kann das aber auch durch andere Zahlen etwas entschärfen, jeder kann hier Zahlen verwenden wie er will.

Beim Ping hatten wir das ja jetzt schon das große Mystherium des Loggings bei Iptables.
Nach dem ganzen Spass den man vorher schon hatte ist dies aber das kleinste Übel.

Chain erstellen:
iptables -N LOG
So und hab hier arbeitet man am besten mit einem Editor da man Sicherstellen muss das die Einträge an der richten Stelle landen und alle Einträge die wir jetzt schon erstellt haben müssen abgeändert werden und ich glaube keiner will wieder bei 0 Anfangen.

Export der jetzigen Iptables Regeln:
iptables-save > /home/user/iptables

Öffnen mit dem Editor deiner Wahl:
nano /home/user/iptables

Über die Zeile -A INPUT -j DROP müssen die Einträge:

 

Und zum Schluss wird aus jedem DROP ein LOGDROP
AUSSER Folgende Einträge:

Wobei der Eintrag -A INPUT -j DROP nur eine doppelte Sicherung ist um auch ganz sicher zu gehen das man alles unerwünschte oder bei Fehlern in seine Logik nicht frei gegeben wird, besonder wichtig wenn man mit der ACCEPT Policy arbeitet.

Nach dem Bearbeiten sollte das bei meinem Beispiel so aussehen:

Danach die Datei Speichern und wieder Importieren.

Dann die Prüfung wie das ganze in Iptables aussieht:

Erklärung:
Alle Datenpakete die bei den Regeln ein NEIN bekommen hat spring von seiner Chain aus in die Chain LOGDROP dort wird erfasst ob es ein ICMP, UDP oder TCP Paket ist,
wird in der Syslog eingetragen und dann entgültig gedropt.

Änderungen am System wenn man seine Syslog nicht voll mit iptables Einträgen haben will:
nano /etc/rsyslog.conf
Die Zeilen wie folgt abändern:

Und am Ende Hinzufügen:

Pfade und Dateinamen können natürlich frei gewählt werden.

Wer alles in eine Datei haben will kann auch oben bei den Kernel Warning Eintragen:
kern.warning -/var/log/drop.log
Pfad und Dateiname sind auch hier frei wählbar oder man macht es so wie ich und hat beides drin, dann hat man die Freie Wahl in welche Log man schauen will, besonders wenn man UDP und TCP zusammen via Tail oder Script auslesen möchte.

Wie das dann bei Systemd läuft weiß ich leider nicht da es ja dort nur noch journalcrt gibt.

So das waren die Grundlagen von Iptables ich hoffe es ging jedem ein Licht auf und der Beitrag kann weiter helfen.

Zum Thema GEOIP geht es hier, wenn Ihr hiermit klar gekommen seit sollte das kein Problem mehr sein.
http://cheech-page.de/iptables-und-geoip-xtables-addons-mit-debian-squeeze-und-plesk/

Zum Ende noch das Automatisch einbinden seiner Iptables Regeln:
iptables-save > /home/user/iptables = Export der aktuellen Regeln

Über die rc.local:
nano /etc/rc.local

Eintragen:
iptables-restore < /home/user/iptables
Abspeichern und schliessen.

Oder via Init.d:
nano /etc/init.d/firewall
Script:

Wichtig ist das die Datei von Euch auch so heisst ansonsten Pfad und Dateiname anpassen.

Ab sofort wird die Datei bei jeden Boot geladen und Importiert.
Wenn man Änderungen durch führen will kann man das Bequem über die Datei erledigen.

That is the end.

Gruß
Cheech

Tagged , , , , , , , , , , , , , , . Bookmark the permalink.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.