Iptables Grundlagen Linux

Hi @ All,

hier findet Ihr ein HowTo für Iptables Grundlagen Linux welches Euch die wichtigsten Funktionen erklärt mit Beispielen.

Also dann fangen wir mal an.

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

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 (wird auch Management IP genannt).


Diagramm:

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 Standardaktion die Iptables durchfü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.

Daher muss bei der ACCEPT Policy am ender jeder CHAIN in DROP befehl vorhanden sein

Steht die Policy auf DROP wird nur noch SSH zugelassen und alles andere wird gedropt (Verworfen).


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.


Chains:

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:

Beschreibung:

Mit dieser Regel erlauben (-j ACCEPT) wir für die Ziel IP (-d = Destination, welches immer unser Server ist) den Zugriff auf Destination Port (–dport – welcher immer der Port auf unserem Server ist) Port 22 – dies ist der SSH Dienst.

Zudem definieren wir mit -p welches Protokoll (tcp, udp, icmp) und mit -m welches Modul hierzu gibt es einige die man zum großteil alle auf https://linux.die.net/man/8/iptables findet.

Etwas Paranoider:

Beschreibung:

Wir erlauben nur der Source IP oder Quell IP (-s – immer von aussen) IP 79.5.48.7/32 den Zugriff auf die Destination oder Ziel IP (-d- immer unser Server) IP 82.105.45.201 auf den Destination Port oder Ziel Port 22(immer ein Lokaler Port auf unserem Server).

Bei einzelnen IPs muss kein /32 hinter die IP, das macht Iptables von alleine, wenn man aber ein Netzwerk freigeben möchte MUSS man diese angeben.

Netzwerk Freigabe:

Beschreibung:

Dem Netzwerk 79.5.0.0/16 (-s – Extern) ist es erlaubt auf die IP 82.105.45.201 (-d – Lokale IP des Servers) auf den Port 22 zuzugreifen.

Würde man dies jetzt aber so Online stellen würde man nicht mehr auf den Server kommen (vorausgesetzt die DROP Policy ist aktiv, bei der ACCEPT würde das weiter hin gehen)

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 aussehen:

Die Firewall weiß also das die dem Netzwerk den Port 22 Freigeben soll aber da in meinem Beispiel die DROP Policy aktiv ist würde alle anderen Pakete verworfen und es fehlt auch noch die erlaubnis das Pakete mit einem bestimmten Status rein dürfen.


Leider geht nichts mehr:

Da aktuell nur der Port 22 offen ist aber kein Status deklariert ist, würde nichts mehr gehen.

Wäre aber die ACCEPT Policy aktiv würde der Zugriff funktionieren und zwar auf alle Ports da am ende der Befehl fehlt alles zu verwerfen (DROP) was nicht für den Port 22 gedacht ist.

Hier kommt jetzt zum tragen welche Policy man nutzt!

Im 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 müssen sonst kann keine Kommunikation zu stande kommen(Status des Datenpakets).

Daher benötigen wir noch mindestens 2 Regel oder man schreibt den „Status“ in jede Zeile für jeden Port aber einmal ist einfach als 30 mal.

Beschreibung:

Quelle: https://linux.die.net/man/8/iptables

state

This module, when combined with connection tracking, allows access to the connection tracking state for this packet.
–state state
Where state is a comma separated list of the connection states to match. Possible states are INVALID meaning that the packet could not be identified for some reason which includes running out of memory and ICMP errors which don’t correspond to any known connection, ESTABLISHED meaning that the packet is associated with a connection which has seen packets in both directions, NEW meaning that the packet has started a new connection, or otherwise associated with a connection which has not seen packets in both directions, and RELATED meaning that the packet is starting a new connection, but is associated with an existing connection, such as an FTP data transfer, or an ICMP error.

Fügt man der bestehenden Iptables diese Zeile hinzu wird diese NACH der Freigabe von Port 22 eingetragen und wir erlauben die Kommunikation mit Datenpaketen die den Status RELATED und ESTABLISHED haben.

NEW ist NICHT notwendig da dies mit RELATED schon abgedeckt ist.

Wie schon geschrieben kann man auch für jede Freigabe den Status mit angeben.

Ich habe jetzt zu der Freigabe auch das Modul „state“ geladen und den Status RELATED und ESTABLISHED eingetragen, man kann auch noch NEW hinzufügen wenn man möchte ist aber nicht nötig – siehe Beschreibung oben.

Man sollte sich für ein System entscheiden entweder man trägt eine separate Zeile für jede CHAIN ein (INPUT, OUTPUT, FORWARD und CUSTOMCHAINS) oder in jede Zeile, vermischen der beiden Technik ist nicht zu empfehlen da es die fehler suchen am ende fast unmöglich macht und es sehr unübersichtlich wird, besonders wenn man mehr als 10 Regeln zu verwalten hat.

 


Abschluss der CHAIN:

Das Paket wird weggeworfen.

Der Befehl wird mit -A hinzugefügt da dieser wie oben beschrieben dafür sorgt das dieser Eintrag am ende der Regeln hinzugefügt wird und NICHT am Anfang.

Bei der ACCEPT Policy ist es in der INPUT CHAIN ein MUSS sowie bei CustomChains, es sei den man arbeitet bei CustomeChain mit dem RETURN befehl, aber dann muss dieser immer am Ende stehen.

Ist man ein befürworter der DROP Policy, so wie ich, muss man das NICHT machen da es Iptables selbst erledigt, aber man will es a) sauber und b) beruhigt es.


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

1. Zeile:

  • 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 wurde, daher kommt es auch nicht zu einer Verbindung.
  • Werden beide Antworten mit JA zurückgegeben wird die Verbindung Akzeptiert und die 2. Zeile tritt in kraft.

2. Zeile:

  • Wird nur angefasst wenn vorläufige Regeln mit JA beantwortet wurden.

3. Zeile:

  • Alle Pakete die in den Regel zuvor NICHT Akzeptiert wurden werden weggeschmissen (verworfen, drop) und damit auch keine Rückantwort gegeben.

Mit der jetzigen Konfiguration kann man nur eine Verbindung auf den Lokalen Port 22 (SSH) des Servers herstellen 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 – Quell IP) und DESTINATION (-d- Ziel IP) begrenzen bei allen Öffentlichen Diensten benötigt man nur die DESTINATION IP sofern man mit 2. IPs arbeitet.

Hat man nur eine IP was man NICHT machen sollte ist eine Destination IP unnötig da es nur eine IP gibt und für SSH kann man sich dann nur mit einen Source Netzwerk absichern oder auch noch einen SSH Key erstellen damit man nur mit diesem eine SSH Verbindung aufbauen kann.

Auf jedenfall sollte man immer soviel absicherungen wie möglich implementieren um das System sicher zu machen.

Daher empfehle ich IMMER sich bei seinem Provider eine 2. IP zu bestellen, kostet meisten nur einmalig 1€.


Ordnung schaffen:

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ängigsten Dienste, mal schnell erstellt, aber es sind nicht alle 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 einer 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.

Beispiel:

 

Mit diesem Kommando wurde jetzt die Chain TCP erstellt und mehr ist noch nichts passiert.

Um zu sehen was man gemacht hat:

Wie man sieht haben wir am Ende eine neue Chain mit dem Namen TCP aber es fehlen zum einem die References (0) und Regeln haben wir auch noch keine.

Nun haben wir eine References in der INPUT Chain , an oberster stelle, die besagt das ALLE Datenpakete die das Protokoll TCP haben in die Chain TCP geleitet werden sollen.

Aber wir haben wieder ein Problem!

Sämtlicher TCP traffic wird von der INPUT Chain in die TCP geleitet aber in der TCP Chain haben wir keine Regel definiert und da wir mit der DROP Policy arbeiten werden alle TCP Pakete nun verworfen (drop) und wir haben keinen Zugriff mehr auf das System, da die nach folgenden Regeln innerhalb der INPUT Chain nicht angefasst werden.

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 dann erst 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:

Die ankommenden TCP Pakete werden von der INPUT Chain in die TCP Chain geleitet und dort verarbeitet, alle anderen Regeln in der INPUT Chain werden weiterhin ignoriert und können daher gelöscht werden.


Löschen von Regeln:

Hierfür kann man diese via Console machen oder via Editor (schneller und einfacher).

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ß/kleinschreibung beachtet werden.

Console:

Wir haben über die Console 2 Möglichkeiten

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

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

Ausgabe:

Löschen:

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 zu bekommen 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:

 

Ausgabe Prüfen:

Jetzt haben wir bei TCP auch eine References mit 1 hat man mehr erhöht sich diese Zahl und solange dieser Wert auf 1 oder höher steht kann man die Chain TCP NICHT löschen.

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


Chain erstellen:

Jump von INPUT nach UDP erstellen:

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.


Extras:

Prüfung TCP Flags:

Prüft die TCP Flags sollte eine Übereinstimmung vorhanden sein wird die Verbindung zurückgewiesen (Reject)

Dies gilt für die DROP Policy! Arbeitet man mit der ACCEPT Policy muss vor -m tcp –tcp-flags ein !
Das heißt die Zeile muss so aus sehen: iptables -I INPUT 5 -p tcp ! -m tcp –tcp-flags FIN,SYN,RST,ACK SYN -j REJECT –reject-with tcp-reset
Sollte man dies NICHT machen werden alle TCP Pakete mit tcp-reset zurück gewiesen!


State Prüfung:

Sollte der Status der Verbindung nicht OK sein wird das Datenpaket direkt verworfen (drop).


Interface lo(localhost – 127.0.0.1):

Ich habe festgestellt das manche Dienste Problem machen können daher sollte man über die INPUT Chain alles was das Interface Betrifft freigeben.

Sämtlicher Traffic der beim Interface lo ankommt wird erlaubt, diese Regel sollte über den Custom Chains vorhanden sein oder man muss das Interface in jeder Customen Chain eintragen. Nach den Customen Chains macht es keinen Sinn und wird auch nicht abgefragt.


Tracking:

Tracken der Datenpakete die über eine Einzelne IP laufen

Hat keinerlei Funktion man kann aber mit einem Script auslesen wie viele Pakete an die IP gesendet wurden. Interessant zur Überwachung via Munin, Cacti oder Nagios.


Pings begrenzen und blocken:

Der Ordnung halber erstellen wir dafür Extra eine Chain den wir mögen es ja Ordentlich.

Erstellt die ICMP Chain

ICMP (ping) Pakete werden von der INPUT Chain in die ICMP Chain geleitet.

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

Erklärung:

Zeile 1: 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 2: Ping auf unsere 2. IP 82.105.45.201/32 ist für jeden Verboten und die Pakete werden verworfen (drop).
Zeile 3: Alle Pings auf alle IPs werden auf 1 Ping pro Minute begrenzt alles was mehr ist wird in die Syslog geschrieben (gilt nicht für die IP in Zeile 1).
Zeile 4: Verwerfen der Pakete die in Zeile 3. registriert wurden (drop).

Jeder aus dem Netzwerk 79.5.0.0/16 kann die IP 85.105.45.202 pingen solange und so oft dieser möchte.

Befindet sich die IP ausserhalb des Netzwerks von 79.5.0.0/16 und Versucht irgend eine der beiden IPs zu pingen, kann er dies nur einmal jede Minute tun, die restliche Zeit werden alle pings Verworfen und im Syslog Protokolliert mit dem vermerk „Ping Block: Ip Adresse“

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.

Heute erlaube ich nur noch Pings aus den Netzwerken in denen ich mich selbst bewege, alle anderen Pings werden radikal verworfen und Protokolliert.


Logging:

Beim Ping hatten wir das ja jetzt schon das große Mysterium des Loggings bei Iptables.

Nach dem ganzen Spaß den man vorher schon hatte ist dies aber das kleinste Übel.

Chain erstellen:

Erstellen der Einträge in der Chain LOGDROP

Ab hier arbeitet man am besten mit einem Editor da man Sicherstellen muss das die Einträge an der richtigen 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:

Öffnen mit dem Editor deiner Wahl:

Umbenennen von DROP nach LOGDROP

Es werden in allen Chains am ende das DROP nach LOGDROP umbenannt.

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 endgültig verworfen (drop).


Loggen in eine separate Datei:

Ä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.

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


Weitere Links:

Zum Thema GEOIP geht es hier, wenn Ihr hiermit klar gekommen seit sollte das kein Problem mehr sein.

Wer einige Templates sehen will bzw. Konzepte schaut am besten hier mal rein.


Iptables Autostart:

Zum Ende noch das Automatisch einbinden seiner Iptables Regeln:

Export der aktuellen Regeln

Über die rc.local:

Eintragen:

Speichern und schließen.

oder via Init.d:

Script:

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

Ab sofort wird die Datei bei jedem Boot geladen und Importiert.

Wenn man Änderungen durchführen will kann man das Bequem über die Datei erledigen.

That is the end.

Gruß
DocSchneidi ak Cheech

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

Schreibe einen Kommentar

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