Implementieren einer grundlegenden Firewall-Vorlage mit Iptables unter Ubuntu 14.04

Einführung

Die Implementierung einer Firewall ist ein wichtiger Schritt zur Sicherung Ihres Servers. Ein großer Teil davon hängt von den einzelnen Regeln und Richtlinien ab, die die Verkehrsbeschränkungen für Ihr Netzwerk durchsetzen. Mit Firewalls wieiptables können Sie auch über den strukturellen Rahmen mitbestimmen, in dem Ihre Regeln angewendet werden.

In diesem Handbuch erstellen wir eine Firewall, die als Grundlage für komplexere Regelsätze dienen kann. Diese Firewall konzentriert sich in erster Linie darauf, angemessene Standardeinstellungen bereitzustellen und ein Framework zu erstellen, das eine einfache Erweiterbarkeit fördert. Wir werden dies auf einem Ubuntu 14.04 Server demonstrieren.

Voraussetzungen

Bevor Sie beginnen, sollten Sie sich einen Überblick über die Firewall-Richtlinien verschaffen, die Sie implementieren möchten. Sie könnenthis guide folgen, um eine bessere Vorstellung von einigen Dingen zu bekommen, über die Sie nachdenken sollten.

Um mitzumachen, benötigen Sie Zugriff auf einen Ubuntu 14.04-Server. In diesem Handbuch wird ein Benutzer ohne Rootberechtigung verwendet, der mit den Berechtigungen vonsudokonfiguriert ist. In unserenUbuntu 14.04 initial server setup guide erfahren Sie, wie Sie diesen Benutzertyp konfigurieren.

Wenn Sie fertig sind, fahren Sie unten fort.

Installieren des Persistent Firewall Service

Um zu beginnen, müssen Sie das Paketiptables-persistentinstallieren, falls Sie dies noch nicht getan haben. Auf diese Weise können wir unsere Regelsätze speichern und beim Booten automatisch anwenden lassen:

sudo apt-get update
sudo apt-get install iptables-persistent

Während der Installation werden Sie gefragt, ob Sie Ihre aktuellen Regeln speichern möchten. Sagen Sie hier "Ja". Wir werden die generierten Regeldateien momentan bearbeiten.

Ein Hinweis zu IPv6 in diesem Handbuch

Bevor wir anfangen, sollten wir kurz über IPv4 und IPv6 sprechen. Der Befehliptables verarbeitet nur IPv4-Verkehr. Für IPv6-Verkehr wird ein separates Begleittool namensip6tables verwendet. Die Regeln werden in separaten Tabellen und Ketten gespeichert. Füriptables-persistent werden die IPv4-Regeln in/etc/iptables/rules.v4 geschrieben und daraus gelesen, und die IPv6-Regeln werden in/etc/iptables/rules.v6 gespeichert.

In diesem Handbuch wird davon ausgegangen, dass SienotIPv6 auf Ihrem Server aktiv verwenden. Wenn Ihre Dienste IPv6 nicht nutzen, ist es sicherer, den Zugriff vollständig zu blockieren, wie in diesem Artikel beschrieben.

Implementieren der grundlegenden Firewall-Richtlinie (der schnelle Weg)

Damit Sie so schnell wie möglich einsatzbereit sind, zeigen wir Ihnen, wie Sie die Regeldatei direkt bearbeiten, um die fertige Firewall-Richtlinie zu kopieren und einzufügen. Anschließend erklären wir die allgemeine Strategie und zeigen Ihnen, wie diese Regeln mit dem Befehliptablesimplementiert werden können, anstatt die Datei zu ändern.

Um unsere Firewall-Richtlinie und unser Framework zu implementieren, bearbeiten wir die Dateien/etc/iptables/rules.v4 und/etc/iptables/rules.v6. Öffnen Sie die Dateirules.v4in Ihrem Texteditor mit den Berechtigungensudo:

sudo nano /etc/iptables/rules.v4

Im Inneren sehen Sie eine Datei, die ungefähr so ​​aussieht:

/etc/iptables/rules.v4

# Generated by iptables-save v1.4.21 on Tue Jul 28 13:29:56 2015
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
COMMIT
# Completed on Tue Jul 28 13:29:56 2015

Ersetzen Sie den Inhalt durch:

/etc/iptables/rules.v4

*filter
# Allow all outgoing, but drop incoming and forwarding packets by default
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [0:0]

# Custom per-protocol chains
:UDP - [0:0]
:TCP - [0:0]
:ICMP - [0:0]

# Acceptable UDP traffic

# Acceptable TCP traffic
-A TCP -p tcp --dport 22 -j ACCEPT

# Acceptable ICMP traffic

# Boilerplate acceptance policy
-A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
-A INPUT -i lo -j ACCEPT

# Drop invalid packets
-A INPUT -m conntrack --ctstate INVALID -j DROP

# Pass traffic to protocol-specific chains
## Only allow new connections (established and related should already be handled)
## For TCP, additionally only allow new SYN packets since that is the only valid
## method for establishing a new TCP connection
-A INPUT -p udp -m conntrack --ctstate NEW -j UDP
-A INPUT -p tcp --syn -m conntrack --ctstate NEW -j TCP
-A INPUT -p icmp -m conntrack --ctstate NEW -j ICMP

# Reject anything that's fallen through to this point
## Try to be protocol-specific w/ rejection message
-A INPUT -p udp -j REJECT --reject-with icmp-port-unreachable
-A INPUT -p tcp -j REJECT --reject-with tcp-reset
-A INPUT -j REJECT --reject-with icmp-proto-unreachable

# Commit the changes
COMMIT

*raw
:PREROUTING ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
COMMIT

*nat
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
COMMIT

*security
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
COMMIT

*mangle
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
COMMIT

Speichern und schließen Sie die Datei.

Sie können die Datei auf Syntaxfehler testen, indem Sie diesen Befehl eingeben. Beheben Sie alle darin enthaltenen Syntaxfehler, bevor Sie fortfahren:

sudo iptables-restore -t /etc/iptables/rules.v4

Öffnen Sie als Nächstes die Datei/etc/iptables/rules.v6, um die IPv6-Regeln zu ändern:

sudo nano /etc/iptables/rules.v6

Wir können den gesamten IPv6-Verkehr blockieren, indem wir den Inhalt der Datei durch die folgende Konfiguration ersetzen:

/etc/iptables/rules.v6

*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT DROP [0:0]
COMMIT

*raw
:PREROUTING DROP [0:0]
:OUTPUT DROP [0:0]
COMMIT

*nat
:PREROUTING DROP [0:0]
:INPUT DROP [0:0]
:OUTPUT DROP [0:0]
:POSTROUTING DROP [0:0]
COMMIT

*security
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT DROP [0:0]
COMMIT

*mangle
:PREROUTING DROP [0:0]
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT DROP [0:0]
:POSTROUTING DROP [0:0]
COMMIT

Speichern und schließen Sie die Datei.

Um diese Datei auf Syntaxfehler zu testen, können Sie den Befehlip6tables-restore mit der Option-t verwenden:

sudo ip6tables-restore -t /etc/iptables/rules.v6

Wenn beide Regeldateien keine Syntaxfehler melden, können Sie die darin enthaltenen Regeln anwenden, indem Sie Folgendes eingeben:

sudo service iptables-persistent reload

Dadurch wird die in Ihren Dateien angegebene Richtlinie sofort implementiert. Sie können dies überprüfen, indem Sie die derzeit verwendeteniptables-Regeln auflisten:

sudo iptables -S
sudo ip6tables -S

Diese Firewall-Regeln werden bei jedem Start erneut angewendet. Prüfen Sie, ob Sie sich noch anmelden können und ob alle anderen Zugriffe gesperrt sind.

Eine Erklärung unserer allgemeinen Firewall-Strategie

In der Basis-Firewall, die wir mit den oben genannten Regeln erstellt haben, haben wir ein erweiterbares Framework erstellt, das einfach angepasst werden kann, um Regeln hinzuzufügen oder zu entfernen. Beim IPv4-Verkehr geht es hauptsächlich um dieINPUT-Kette in derfilter-Tabelle. Diese Kette verarbeitet alle Pakete, die für unseren Server bestimmt sind. Wir haben außerdem allen ausgehenden Datenverkehr zugelassen und die Weiterleitung aller Pakete abgelehnt. Dies wäre nur dann sinnvoll, wenn dieser Server als Router für andere Hosts fungieren würde. Wir akzeptieren Pakete in allen anderen Tabellen, da wir in diesem Handbuch nur Pakete filtern möchten.

Im Allgemeinen richten unsere Regeln eine Firewall ein, die eingehenden Datenverkehr standardmäßig verweigert. Anschließend erstellen wir Ausnahmen für die Dienste und Verkehrstypen, die von dieser Richtlinie ausgeschlossen werden sollen.

In der Hauptkette vonINPUThaben wir einige allgemeine Regeln für den Datenverkehr hinzugefügt, von denen wir sicher sind, dass sie immer auf die gleiche Weise behandelt werden. Zum Beispiel möchten wir immer Pakete ablehnen, die als "ungültig" eingestuft werden, und wir möchten immer Datenverkehr auf der lokalen Loopback-Schnittstelle und Daten, die mit einer eingerichteten Verbindung verbunden sind, zulassen.

Anschließend gleichen wir den Datenverkehr basierend auf dem verwendeten Protokoll ab und mischen ihn zu einer protokollspezifischen Kette. Diese protokollspezifischen Ketten enthalten Regeln, die übereinstimmen, und ermöglichen den Datenverkehr für bestimmte Dienste. In diesem Beispiel ist der einzige Dienst, den wir zulassen, SSH in unsererTCP-Kette. Wenn wir einen anderen Dienst wie einen HTTP (S) -Server anbieten, könnten wir auch hier Ausnahmen hinzufügen. Diese Ketten stehen im Mittelpunkt der meisten Anpassungen.

Jeder Datenverkehr, der nicht mit den generischen Regeln oder den Serviceregeln im Protokoll übereinstimmt, wird von den letzten Regeln in derINPUT-Kette verarbeitet. Wir haben die Standardrichtlinie für unsere Firewall aufDROP festgelegt, wodurch Pakete abgelehnt werden, die unseren Regeln entsprechen. Die Regeln am Ende derINPUT-Kette lehnen jedoch Pakete ab und senden eine Nachricht an den Client, die nachahmt, wie der Server reagieren würde, wenn auf diesem Port kein Dienst ausgeführt würde.

Für IPv6-Datenverkehr wird einfach der gesamte Datenverkehr gelöscht. Da unser Server dieses Protokoll nicht verwendet, ist es am sichersten, überhaupt nicht mit dem Datenverkehr zu interagieren.

(Optional) Aktualisieren Sie Nameserver

Das Blockieren des gesamten IPv6-Verkehrs kann die Lösung von Problemen im Internet durch Ihren Server beeinträchtigen. Dies kann beispielsweise die Verwendung von APT beeinflussen.

Wenn Sie beim Versuch,apt-get update auszuführen, solche Fehler erhalten:

Error

Err http://security.ubuntu.com trusty-security InRelease

Err http://security.ubuntu.com trusty-security Release.gpg
  Could not resolve 'security.ubuntu.com'

. . .

Befolgen Sie diesen Abschnitt, um APT wieder zum Laufen zu bringen.

Stellen Sie zuerst Ihre Nameserver auf externe Nameserver ein. In diesem Beispiel werden die Nameserver von Google verwendet. Öffnen Sie/etc/network/interfaces zum Bearbeiten:

sudo nano /etc/network/interfaces

Aktualisieren Sie die Zeiledns-nameserverswie folgt:

/etc/network/interfaces

. . .
iface eth0 inet6 static
        address 2604:A880:0800:0010:0000:0000:00B2:0001
        netmask 64
        gateway 2604:A880:0800:0010:0000:0000:0000:0001
        autoconf 0
        dns-nameservers 8.8.8.8 8.8.4.4

Aktualisieren Sie Ihre Netzwerkeinstellungen:

sudo ifdown eth0 && sudo ifup eth0

Die erwartete Ausgabe ist:

Ausgabe

RTNETLINK answers: No such process
Waiting for DAD... Done

Erstellen Sie als Nächstes eine neue Firewall-Regel, um IPv4 zu erzwingen, wenn es verfügbar ist. Erstellen Sie diese neue Datei:

sudo nano /etc/apt/apt.conf.d/99force-ipv4

Fügen Sie der Datei diese einzelne Zeile hinzu:

/etc/apt/apt.conf.d/99force-ipv4

Acquire::ForceIPv4 "true";

Speichern und schließen Sie die Datei. Jetzt sollten Sie in der Lage sein, APT zu verwenden.

Implementieren unserer Firewalls mit dem Befehl IPTables

Nachdem Sie die allgemeine Idee hinter der von uns erstellten Richtlinie verstanden haben, werden wir erläutern, wie Sie diese Regeln mit den Befehlen voniptableserstellen können. Wir werden dieselben Regeln haben, die wir oben angegeben haben, aber wir werden unsere Richtlinien erstellen, indem wir Regeln iterativ hinzufügen. Daiptables jede der Regeln sofort anwendet, ist die Reihenfolge der Regeln sehr wichtig (wir lassen die Regeln, die Pakete ablehnen, bis zum Ende).

Setzen Sie Ihre Firewall zurück

Wir werden zunächst unsere Firewall-Regeln zurücksetzen, damit wir sehen können, wie Richtlinien über die Befehlszeile erstellt werden können. Sie können alle Ihre Regeln löschen, indem Sie Folgendes eingeben:

sudo service iptables-persistent flush

Sie können überprüfen, ob Ihre Regeln zurückgesetzt wurden, indem Sie Folgendes eingeben:

sudo iptables -S

Sie sollten sehen, dass die Regeln in der Tabellefilterweg sind und dass die Standardrichtlinie für alle Ketten aufACCEPT festgelegt ist:

output-P INPUT ACCEPT
-P FORWARD ACCEPT
-P OUTPUT ACCEPT

Erstellen Sie protokollspezifische Ketten

Wir beginnen damit, alle unsere protokollspezifischen Ketten zu erstellen. Diese werden verwendet, um die Regeln zu speichern, die Ausnahmen von unserer Verweigerungsrichtlinie für Dienste schaffen, die wir verfügbar machen möchten. Wir erstellen eine fürUDP Verkehr, eine fürTCP und eine fürICMP:

sudo iptables -N UDP
sudo iptables -N TCP
sudo iptables -N ICMP

Wir können direkt vorgehen und die Ausnahme für SSH-Verkehr hinzufügen. Da SSH TCP verwendet, fügen wir eine Regel hinzu, die den TCP-Verkehr für Port 22 zur TCP-Kette akzeptiert:

sudo iptables -A TCP -p tcp --dport 22 -j ACCEPT

Wenn wir zusätzliche TCP-Dienste hinzufügen möchten, können wir dies jetzt tun, indem wir den Befehl mit der ersetzten Portnummer wiederholen.

Erstellen Sie allgemeine Annahme- und Ablehnungsregeln

In derINPUT-Kette, in der der gesamte eingehende Datenverkehr zu filtern beginnt, müssen wir unsere allgemeinen Regeln hinzufügen. Dies sind einige vernünftige Regeln, die die Grundlage für unsere Firewall bilden, indem sie risikoarmen Datenverkehr (lokaler Datenverkehr und Datenverkehr, der mit bereits überprüften Verbindungen verbunden ist) akzeptieren und Datenverkehr verwerfen, der eindeutig nicht nützlich ist (ungültige Pakete).

Zunächst erstellen wir eine Ausnahme, um den gesamten Datenverkehr zu akzeptieren, der Teil einer eingerichteten Verbindung ist oder mit einer eingerichteten Verbindung zusammenhängt:

sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

Diese Regel verwendet die Erweiterungconntrack, die eine interne Nachverfolgung bietet, sodassiptables den Kontext hat, der zum Auswerten von Paketen als Teil größerer Verbindungen und nicht als Strom diskreter, nicht verwandter Pakete erforderlich ist. TCP ist ein verbindungsbasiertes Protokoll, daher ist eine hergestellte Verbindung ziemlich genau definiert. Bei UDP und anderen verbindungslosen Protokollen beziehen sich eingerichtete Verbindungen auf Verkehr, auf den eine Antwort eingegangen ist (die Quelle des ursprünglichen Pakets ist das Ziel des Antwortpakets und umgekehrt). Eine verwandte Verbindung bezieht sich auf eine neue Verbindung, die in Verbindung mit einer vorhandenen Verbindung initiiert wurde. Das klassische Beispiel hierfür ist eine FTP-Datenübertragungsverbindung, die sich auf die bereits hergestellte FTP-Steuerungsverbindung bezieht.

Wir möchten auch allen Datenverkehr zulassen, der von der lokalen Loopback-Schnittstelle ausgeht. Dies ist der vom Server generierte und für den Server bestimmte Datenverkehr. Es wird von Diensten auf dem Host verwendet, um miteinander zu kommunizieren:

sudo iptables -A INPUT -i lo -j ACCEPT

Schließlich möchten wir alle ungültigen Pakete ablehnen. Pakete können aus mehreren Gründen ungültig sein. Sie können sich auf nicht vorhandene Verbindungen beziehen, für nicht vorhandene Schnittstellen, Adressen oder Ports bestimmt sein oder einfach fehlerhaft sein. In jedem Fall verwerfen wir alle ungültigen Pakete, da es keine angemessene Möglichkeit gibt, mit ihnen umzugehen, und weil sie böswillige Aktivitäten darstellen könnten:

sudo iptables -A INPUT -m conntrack --ctstate INVALID -j DROP

Erstellen der Sprungregeln zu den protokollspezifischen Ketten

Bisher haben wir einige allgemeine Regeln in derINPUT-Kette und einige Regeln für bestimmte akzeptable Dienste in unseren protokollspezifischen Ketten erstellt. Derzeit gelangt der Datenverkehr jedoch in dieINPUT-Kette und kann unsere protokollspezifischen Ketten nicht erreichen.

Wir müssen den Verkehr in derINPUT-Kette in die entsprechenden protokollspezifischen Ketten leiten. Wir können den Protokolltyp abgleichen, um ihn an die richtige Kette zu senden. Wir werden auch sicherstellen, dass das Paket eine neue Verbindung darstellt (alle bestehenden oder verwandten Verbindungen sollten bereits früher behandelt werden). Für TCP-Pakete wird die zusätzliche Anforderung hinzugefügt, dass das Paket ein SYN-Paket ist. Dies ist der einzig gültige Typ, um eine TCP-Verbindung herzustellen:

sudo iptables -A INPUT -p udp -m conntrack --ctstate NEW -j UDP
sudo iptables -A INPUT -p tcp --syn -m conntrack --ctstate NEW -j TCP
sudo iptables -A INPUT -p icmp -m conntrack --ctstate NEW -j ICMP

Alle verbleibenden Zugriffe ablehnen

Wenn ein Paket, das an eine protokollspezifische Kette übergeben wurde, keiner der darin enthaltenen Regeln entsprach, wird die Kontrolle an dieINPUT-Kette zurückgegeben. Alles, was diesen Punkt erreicht, sollte von unserer Firewall nicht zugelassen werden.

Wir werden den Datenverkehr mithilfe des ZielsREJECTablehnen, das eine Antwortnachricht an den Client sendet. Auf diese Weise können wir das ausgehende Messaging angeben, damit wir die Antwort nachahmen können, die beim Versuch des Clients, Pakete an einen regulären geschlossenen Port zu senden, erfolgt. Die Antwort ist abhängig von dem vom Client verwendeten Protokoll.

Der Versuch, einen geschlossenen UDP-Port zu erreichen, führt zu einer ICMP-Meldung, dass der Port nicht erreichbar ist. Wir können dies nachahmen, indem wir Folgendes eingeben:

sudo iptables -A INPUT -p udp -j REJECT --reject-with icmp-port-unreachable

Der Versuch, eine TCP-Verbindung an einem geschlossenen Port herzustellen, führt zu einer TCP-RST-Antwort:

sudo iptables -A INPUT -p tcp -j REJECT --reject-with tcp-reset

Für alle anderen Pakete können wir eine ICMP-Nachricht "Protokoll nicht erreichbar" senden, um anzuzeigen, dass der Server nicht auf Pakete dieses Typs antwortet:

sudo iptables -A INPUT -j REJECT --reject-with icmp-proto-unreachable

Anpassen der Standardrichtlinien

Die letzten drei Regeln, die wir hinzugefügt haben, sollten den gesamten verbleibenden Datenverkehr in derINPUT-Kette behandeln. Wir sollten jedoch vorsorglich die Standardrichtlinie aufDROP setzen. Wir sollten diese Richtlinie auch in derFORWARD-Kette festlegen, wenn dieser Server nicht als Router für andere Computer konfiguriert ist:

sudo iptables -P INPUT DROP
sudo iptables -P FORWARD DROP

Warnung

[.warning] # Wenn Sie Ihre Richtlinie aufDROP setzen und Ihreiptables mitsudo iptables -F löschen, wird Ihre aktuelle SSH-Verbindung unterbrochen! Das Flushing mitsudo iptables-persistent flush ist eine bessere Möglichkeit, Regeln zu löschen, da auch die Standardrichtlinie zurückgesetzt wird.
#

Um unserer IPv6-Richtlinie zum Löschen des gesamten Datenverkehrs zu entsprechen, können wir die folgendenip6tables-Befehle verwenden:

sudo ip6tables -P INPUT DROP
sudo ip6tables -P FORWARD DROP
sudo ip6tables -P OUTPUT DROP

Dies sollte unsere Regeln ziemlich genau wiedergeben.

Speichern von IPTables-Regeln

An diesem Punkt sollten Sie Ihre Firewall-Regeln testen und sicherstellen, dass sie den Datenverkehr abdecken, den Sie fernhalten möchten, ohne Ihren normalen Zugriff zu beeinträchtigen. Wenn Sie sich davon überzeugt haben, dass sich Ihre Regeln korrekt verhalten, können Sie sie speichern, damit sie beim Systemstart automatisch auf Ihr System angewendet werden.

Speichern Sie Ihre aktuellen Regeln (sowohl IPv4 als auch IPv6), indem Sie Folgendes eingeben:

sudo service iptables-persistent save

Dadurch werden Ihre/etc/iptables/rules.v4- und/etc/iptables/rules.v6-Dateien mit den Richtlinien überschrieben, die Sie in der Befehlszeile erstellt haben.

Fazit

Wenn Sie diese Anleitung befolgen, indem Sie entweder Ihre Firewall-Regeln direkt in die Konfigurationsdateien einfügen oder sie manuell anwenden und in der Befehlszeile speichern, haben Sie eine gute Firewall-Startkonfiguration erstellt. Sie müssen die einzelnen Regeln hinzufügen, um den Zugriff auf die Dienste zu ermöglichen, die Sie zur Verfügung stellen möchten.

Der in diesem Handbuch festgelegte Rahmen sollte es Ihnen ermöglichen, einfach Anpassungen vorzunehmen und Ihre bestehenden Richtlinien zu präzisieren. Sehen Sie sich einige unserer anderen Anleitungen an, um zu erfahren, wie Sie Ihre Firewall-Richtlinie mit einigen gängigen Diensten ausbauen können: