[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: iptables



Malte Thoma schrieb:
> Wenn mir iregndein Experte sagen könnte, ob die Regeln so OK sind,
> oder ob es noch irgendwo ein gravierendes Loch gibt, dann wäre ich
> sehr dankbar.

Eigentlich fühle ich mich von "irgendein" nie angesprochen ;-> Na gut:

Die Regeln sind Müll. Keine Notwendigkeit viel zu diskutieren. Entferne
ipmasq und gshield bzw. solange, bis Du nach dem Start eine leere
Auflistung bei "iptables -vnL" bekommst und nicht irgend welche
Zusatzpakete dort viel Müll abladen.

Dann rekonfiguriere iptables mit "dpkg-reconfigure -s iptables" und
aktiviere dabei die init.d Skripte mit "yes".

Danach kannst Du in /var/lib/iptables eine Datei mit dem Namen "active"
und eine "inactive" ablegen, die beim Hoch- und Runterfahren bzw. durch
/etc/init.d/iptables start/stop geladen werden. Es können dort auch
weitere Dateien (z.B. Sicherheitskopien oder Testexemplare liegen) und
mit /etc/init.d/iptables load/save dateiname geladen oder gespeichert
werden. Du kannst somit auch mit dem Kommando iptables Regeln
interaktiv erstellen und anschliessend den gesamten neuen Regelsatz
speichern. Für den Anfang kann auch inactive identisch mit active sein
(symb. Link).

Anbei mal (ausnahmsweise) ein Anhang mit einer Minimalversion einer
"active" für ppp-Kontakt zur Aussenwelt und ggf. internem Netzwerk auf
einer weiteren lokalen Schnittstelle. Dieser Regelsatz arbeitet nur mit
Schnittstellen (benötigt also keine IPs) und Stateful Inspection.

Das einzige, was angepasst werden muss ist der Name der weiteren
lokalen Schnittstelle, falls ein internes Netz angeschlossen ist. Im
Moment lautet diese "int+". Ohne den Wunsch ein internes Netz
anzuschliessen, können diese Regeln also schadlos drin bleiben. Bei
einem internem Netz kann entweder die Schnittstelle von ethX nach intX
mit dem Kommando "ip" (Paket iproute) umbenannt werden, oder der
Eintrag "int+" in active wird durch den exakten Namen der Schnittstelle
ersetzt.

Noch als Vorbemerkung: das ist ein Paketfilter und keine Firewall.
Firewall ist der Begriff für ein Konzept, zentral an einer Stelle alle
Filter und Zugangsvorgänge zu organisieren. Der Paketfilter "filtert"
relativ wenig im wörtlichen Sinne. Es ist mehr ein Verteilerknoten.
Wesentlich mehr "gefiltert" werden muss auf der Applikationsebene.

Dieser Paketfilter hat die Leistungsfähigkeit eines normalen
Türschlosses. Vermutlich hast Du zu Hause auch kein atombombensicheres
Wohnzimmer und den Garten mit NATO-Draht umzäunt. Ein Teil des
denkbaren Schindluders bzw. eigentlich notwendige Funktionen werden
hierbei auch der Verantwortung Deines Providers überlassen.

Hier eine kurze Kommentierung.

---NAT
Chain POSTROUTING (policy ACCEPT 0 packets, 0 bytes)
num target      prot opt in    out
1   MASQUERADE  all  --   *    ppp+

Verbindungen von internen Quellen nach draussen über jedes ppp-Device
werden maskiert, d.h. bekommen die externe IP als Absendeadresse. Das
"+" ist bei iptables die Wildcard entsprechend einem "*" bei
Dateinamen. Das hier legt einfach die Funktionalität fest.
Berechtigungsfragen regelt man im FORWARD Filter.

---FILTER
Chain INPUT (policy DROP 0 packets, 0 bytes)

Die INPUT-Regeln betreffen alle Pakete, die an das System selbst gehen
sollen. Alle Regelsätze sollten nach dem Prinzip "vom Allgemeinen zum
Speziellen" aufgebaut sein, und damit wie ein immer feiner werdendes
Sieb funktionieren. Am Ende steht ein DROP. Was nicht erlaubt war,
fällt bis zum DROP durch, wird vorher protokolliert und verworfen.

num target     prot opt in     out
1   ACCEPT     all  --  *      *   state RELATED,ESTABLISHED

Das ist Stateful Inspection. Der Kernel führt eine Liste aller aktiven
Verbindungen (siehe cat /proc/net/ip_conntrack). Alle hereinkommenden
Pakete, die zu einer bereits aktiven Verbindung gehören, werden direkt
akzeptiert.

2   ACCEPT     all  --  lo     *
3   ACCEPT     all  --  int+   *

Lokale Verbindungen über das loop-Device sind nicht immer Stateful und
werden daher generell akzeptiert. Das hier auch nur lokale Pakete
hereinkommen stellt der Kernel in der Standardeinstellung von alleine
sicher.

4   extern     all  --  *      *

Hier springen wir zu einer sogenannten Userchain (siehe unten). Da
keine weiteren Bedingungen definiert sind, wird diese Chain immer
angesteuert. Man könnte es auch bedingt gestalten, z.B. nur "-i ppp+".
Bringt aber aktuell keinen Vorteil. Durch Userchains lassen sich
komplexe Filter übersichtlicher gestalten. Hier wird z.B. auch die
Handhabung vereinfacht: man muss sich keine Gedanken im die richtige
Position im Filter machen, sondern kann alle Regeln um externen Zugriff
einfach in der "extern" Userchain anhängen.

5   ACCEPT     icmp --  *      *

Hier werden alle ICMP-Pakete akzeptiert. Grundsätzlich sollte man auf
keinen Fall auf ICMP verzichten. Sonst geht kein Ping und viele
wichtige Netzfunktionen arbeiten nicht richtig. Für 08/15-Sicherheit
wird das kein zu grosses Problem sein, alles zu erlauben. Für den
fortgeschritteneren Anspruch wäre stattdessen eine Userchain angesagt
und zuerst eine Einschränkung auf z.B. icmp-type 0,3,5,8,11

6   LOG        all  --  *      *   limit: avg 1/sec burst 10 LOG flags
0 level 4 prefix `DROP INPUT '

Pakete, die jetzt noch nicht angenommen wurden, sollen geblockt werden.
Um auch zu wissen, was das ist, wird hiermit ein Logfile-Eintrag in
/var/log/kern.log erzeugt. Damit das Logfile nicht geflutet wird, ist
es sehr wichtig Limits zu setzen. Dabei geht es weniger um Plattenplatz
(jedes mittelmässige Apache-Log wächst schneller), sondern auch darum,
dass der klogd  bei einer zu grossen Flut wegknacken könnte. Avg-Limits
von weniger als 1/sec sind nicht praxisnah. Den Burst sollte man auf
3*Zahl der ext. IPs des Anschlusses setzen, um auch Netzscans sauber in
den Logs zu haben,

7   REJECT     all  --  *      *   reject-with icmp-port-unreachable

Alle Pakete die einfach durchfallen, würden von der Policy der Chain
(immer DROP = kommentarlos löschen) erfasst werden. Bei INPUT sollte
man ein REJECT machen (Gegenstelle bekommt eine ICMP-Nachricht
geschickt). So funktionieren auch Traceroutes zum eigenen System.

Als 8. würde ich normalerweise noch ein explizites, unbedingtes DROP
einbauen, auch wenn die Policy schon auf DROP ist. Motto: doppelt
gemoppelt, ist übersichtlicher, usw. Hier aus Minimalismusgründen
ausgelassen.


Chain FORWARD (policy DROP 0 packets, 0 bytes)

Dieser Regelsatz legt fest, welche Pakete von internen
Netzwerkschnittstellen zu anderen weitergeleitet werden und umgekehrt.

num target     prot opt in     out
1   LOG        udp  --  int+   *   limit: avg 1/sec burst 10 udp
            dpts:137:139 LOG flags 0 level 4 prefix `LOG SMB-OUT '

Nur ein Beispiel, wie man sehr spezielle Dinge mitprotokollieren kann.
Hier geht es z.B. darum zu erfahren, ob interne Rechner Pakete auf Port
137-139 nach draussen schicken. Das passiert besonders, wenn sich ein
Windowssystem einen der aktuellen Würmer eingefangen hat.

Hier ist auch die Grundstruktur aller iptables-Kommandos sichtbar:

iptables [iptables-Optionen] [Match u. Match-Optionen]
       [ggf. weitere Match-Konstrukte] [Jump-Target und Target-Optionen]

In diesem Punkt unterscheidet sich iptables deutlich von ipchains. Hier
stolpern die Leute auch zuerst, wenn Sie die Optionen wild
durcheinander wirbeln und alle dem iptables-Kommando selbst zuordnen.
Mit den Match- und Target-Optionen kann das iptables-Kommando aber gar
nichts anfangen, sondern nur die entsprechenden Match- und
Target-Module.


2   ACCEPT     all  --  *      *   state RELATED,ESTABLISHED
3   ACCEPT     all  --  int+   *

Wir erlauben alle Wünsche von innen nach draussen grundsätzlich. Das
ist ein Thema, über das man ein ganzes Buch schreiben könnte. Nur
soviel:

Wer glaubt, er könne vorsorglich bösen Geistern (Trojanern) den Kontakt
verwehren, sieht die Tatsachen nicht. Die wenigsten Leute können z.B.
auf https oder DNS verzichten. Somit kann man also prinzipiell nach
draussen tunneln. Darüber hinaus führen zu repressive Einstellungen bei
Benutzern zu den kreativsten und abenteuerlichsten work-arounds, die
meistens kontraproduktiv sind. Nach dem Motto: wenn der selbstdenkende,
intelligente Türmechanismus nicht wie gewünscht funktioniert, legen wir
einfach einen Keil dazwischen. Folge: noch schlechtere Sicherheit, als
ohne Repression.

Beschränkungen von intern->draussen sind äusserst wartungsintensiv und
komplex zu handhaben. Schwieriger, als die Gegenrichtung. Das kann man
anfangen, wenn man Vollzeit-Firewall Operator ist, und die Effekte
immer sofort in den Logs sieht.

4   LOG        all  --  *      *   limit: avg 1/sec burst 10 LOG flags
0 level 4 prefix `DROP FORWARD '

s.o.

Chain OUTPUT (policy DROP 0 packets, 0 bytes)
num target     prot opt in     out
1   ACCEPT     all  --  *      *   state RELATED,ESTABLISHED

Das gleiche wie in den anderen Regelsätzen. Die Regel um Pakete zu
schon bestehenden Verbindungen zu akzeptieren steht ziemlich weit oben.
Damit wird (gerade wenn er komplexer wird) ein kompletter Regelsatz nur
beim ersten Paket der Verbindung durchlaufen. Anschliessend stehen
akzeptierte Verbindung in der Datenbank und werden von dieser Regel
erfasst.

Vor dieser Regel könnte man noch Regeln zum Accounting und zum
generellen Protokollieren einfügen. Auch eine Regel, "unclean" Pakete
zu verwerfen macht Sinn. Das Unclean-Modul hat aber im Moment einen
dummen Bug mit UDP Checksums und verwirft auch akzeptable Pakete.
Bräuchte man also einen Kernel-Patch oder voraussichtlich Kernel
>=2.4.20 dazu.

2   ACCEPT     all  --  *      *   state NEW

Alle Verbindungen, die vom eigenen Host gestartet werden, werden
akzeptiert und stehen damit im Connection Tracking. Es gäbe hier ein
paar Details zu Situationen, in denen kein NEW-State gesetzt ist. Ist
nun ja keine 5-Tage-Schulung. Vieles muss prinzipbedingt unter den
Tisch fallen.... ;-)

3   ACCEPT     all  --  *      lo

s.o.

4   LOG        all  --  *      *   limit: avg 1/sec burst 10 LOG flags
0 level 4 prefix `DROP OUTPUT '

Wenn ein OUTPUT verworfen werden sollte, dann kann man sich das mal
genauer anschauen. Das sollte in diesem Regelsatz eigentlich nicht
vorkommen. Es könnte also irgend ein Konfigurationsfehler vorliegen.

Chain extern (1 references)
num target     prot opt in     out
1   ACCEPT     tcp  --  ppp+   *   tcp dpt:22

Hier kannst Du analog alle Protokolle eintragen, die von ausserhalb
erlaubt sein sollen. Sobald die Verbindung akzeptiert wurde, stehen sie
wieder in der Connection Tabelle. Somit wird keine Regel für den Output
benötigt. Weitere Dienste einfach dazufügen.

Dieser Regelsatz ist, wie gesagt, ein Grundgerüst, mit dem Ziel ein
praktikables Minimum zu zeigen. Für den professionelleren Anspruch
wären die nächsten Schritte die hereinkommend erlaubten icmp-Typen
näher zu spezifizieren und die Weiterleitung von/zu RFC1918-Adressen
zu untersagen und viele weitere Details.

Auch gehe ich davon aus, dass Du einen vertrauenswürdigen Internet
Provider hast. Die meisten üblen Sachen setzen voraus, das der
Manipulator bei Deinem Provider direkt am anderen Ende der Leitung
sitzt oder im lokalen Netz. Im kommerziellen Umfeld ist somit das
lokale Netz auch der weitaus problematischere und schwierigere Teil,
als die Internetanbindung. Viele haben das aber noch nicht begriffen.

Gerade in den Wireless-Zeiten. Es sind dann die Dir nicht untergebenen
Führungskräfte, die sich, um auch in der Sofaecke mit dem schicken
Lappi arbeiten zu können, ungefragt im Supermarkt eine Wireless
Ausrüstung kaufen und das Ding einfach an's Netz klemmen. Der Admin
erfährt davon gar nichts, funktioniert ja.

Admins, die wie das Karnickel nur auf das "böse Internet" und die
Aussenanbindung starren, sind da verloren. Der grössere Brocken Arbeit
ist im internen Bereich zu finden. Das geht schon bei kleineren Firmen
los, wo z.B. auch externe Mitarbeiter mit Ihren Lappis ein- und
ausgehen. Und da helfen auch nicht die üblichen "ich nehme einen ollen
PC als Gateway" Konstrukte. Bei 2Mbit Uplink vielleicht. Aber nicht bei
einigen Servern mit je 100MBit am Switch.

Das sind auch die heutigen typischen Angriffszenarien. Irgend so ein
Billig-Wireless-Kit oder eine Spielconsole mit zu verschmerzenden
Verlustkosten mit der Putzkolone eingeschleppt, unter'm Schrank oder
sonstig unauffällig deponiert, Kabel in die nächste Dose und man ist in
deren Netz...


> 2. Ausschließlich ssh erlauben will?
> 	b) Wo werden sie mitgeloggt?

/var/log/auth.log

> 3. Mit welchem 'Einbruchswerkzeug' kann man das testen?

Mit brachialem Hacker-Einbruch aus dem Internet muss man als einfacher
Netzteilnehmer nicht rechnen. Die meisten Portscans zielen in Bezug auf
Linux auf typische Fehler bei der Konfiguration bzw. Bug-behaftete und
nicht aktualisierte Software auf den Ports 21 (ftp), 22 (ssh), 80
(http), sowie Ports von Proxy- und Socks-Servern (1080, 3128, 8080)
oder P2P-Diensten.

Es geht dabei mehr um Vandalismus und Missbrauch, als um Einbruch.
Solche Scans treffen haupsächlich Windowssysteme auf Port 137, Port 80
bzw. 1433 (SQL-Server). Bei Linux kommen hier Port 111 (rpc) und
aktuell 443 (https) in Frage. Mit Software auf aktuellem Stand aber
kein Problem.

Das jemand gezielt Dein System angreift, das passiert typischerweise
nicht auf der Paketfilter-, sondern der Applikationsebene. Dazu reichen
die üblichen schlecht konzipierten LAMP-Konstrukte.

--
rainer@ellinger.de

# Generated by iptables-save v1.2.6a
*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT DROP [0:0]
:extern - [0:0]
[0:0] -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
[0:0] -A INPUT -i lo -j ACCEPT
[0:0] -A INPUT -i int+ -j ACCEPT
[0:0] -A INPUT -j extern
[0:0] -A INPUT -p icmp -j ACCEPT
[0:0] -A INPUT -m limit --limit 1/sec --limit-burst 10 -j LOG --log-prefix "DROP INPUT "
[0:0] -A INPUT -j REJECT --reject-with icmp-port-unreachable
[0:0] -A FORWARD -i int+ -p udp -m limit --limit 1/sec --limit-burst 10 -m udp --dport 137:139 -j LOG --log-prefix "LOG SMB-OUT "
[0:0] -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
[0:0] -A FORWARD -i int+ -j ACCEPT
[0:0] -A FORWARD -m limit --limit 1/sec --limit-burst 10 -j LOG --log-prefix "DROP FORWARD "
[0:0] -A OUTPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
[0:0] -A OUTPUT -m state --state NEW -j ACCEPT
[0:0] -A OUTPUT -o lo -j ACCEPT
[0:0] -A OUTPUT -m limit --limit 1/sec --limit-burst 10 -j LOG --log-prefix "DROP OUTPUT "
[0:0] -A extern -i ppp+ -p tcp -m tcp --dport 22 -j ACCEPT
COMMIT
# Generated by iptables-save v1.2.6a
*mangle
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
COMMIT
# Generated by iptables-save v1.2.6a
*nat
:PREROUTING ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
[0:0] -A POSTROUTING -o ppp+ -j MASQUERADE
COMMIT
# Completed

Reply to: