Iptables Firewall - Wann beim Portforwarding ein DNAT nicht genug ist

Betreibt man Firewalls auf einem Linux-Router mit iptables, kommt man früher oder später in die Verlegenheit, Portforwarding machen zu müssen. Schaut man dann einschlägige Anleitungen im Internet an, findet man solche, die das allein über ein DNAT (Destination Natt ing) in der Prerouting-Chain lösen, manche wiederum sagen, dass man unbedingt auch ein SNAT (Source Natting) in der Postrouting-Chain machen muss, sonst würde das überhaupt nicht funktionieren.

Ich hatte das Problem letztens und möchte das hier mal etwas aufdröseln, damit ich beim nächsten mal nicht wieder Schaubildchen malen muss. Vielleicht hilft es ja auch dem ein oder anderen von euch, wenn ihr mal einen ähnlichen Routing-Fall lösen müsst.

Ich gehe in diesem Artikel nicht auf die Grundlagen des Routings und Firewallings ein, sondern möchte nur den oben erwähnten speziellen Fall genauer beschreiben.

Zunächst schauen wir uns grob an, wie so ein IP-Paket die einzelnen Chains (Ketten) unserer Firewall durchläuft.

Schematische Darstellung der Routing-Chains

Wie man sieht, haben wir zwei NAT-Chains (Network Adress Translation), nämlich die Prerouting- und die Postrouting-Chain. Jedes IP-Paket enthält unter anderem eine Absender-IP und eine Empfänger-IP. In diesen beiden Ketten kann iptables diese beiden Adressen umschreiben, nämlich die Empfänger-Adresse im Prerouting und die Absender-Adresse im Postrouting. Das besondere ist, dass diese Adressen, sobald die Antwort auf so ein verändertes Paket wieder bei unserem Router ankommen, auch wieder zurück übersetzt werden können.

Unsere Router zu Hause machen das übrigens ständig, wenn wir im Internet surfen. Bei allen Paketen wird die private IP-Adresse aus unserem Heimnetz in die öffentliche IP-Adresse ausgetauscht, die wir von unserem Provider erhalten haben. Kommt eine Anwort zurück, tauscht der Router die Adresse wieder zurück und sendet die Internetinhalte an das Gerät in unserm LAN, das sie auch angefordert hat.

Diese spezielle Form des SNAT in der Postrouting-Chain nennt man auch Masquerading.

Doch nun zu einem etwas komplexeren Setting, bei dem wir spezielle Adressumschreibungen benötigen, die über ein pauschales Masquerading hinaus gehen.

Wir haben als Beispiel eine Firewall mit drei Netzwerkkarten, eine (eth0) zeigt ins Internet mit einer öffentlichen IP-Adresse 1.2.3.4, eine Karte (eth2) zeigt in unser internes Firmennetz und hat die IP 192.168.1.1/24. Die dritte Karte (eth1) mit der IP 192.168.10.1/24 zeigt auf ein Netzwerk, in dem zwei Webservices laufen, die aus dem Internet erreichbar sein sollen.

Alle Pakete aus dem Internet, die auf für die IP-Ports 80 und 443 ankommen, sollen auf einen Reverse-Proxy weitergeleitet werden, der dann den Verkehr weiter an die zuständigen Rechner für die jeweiligen Services verteilt.

Das ganze schaut schematisch so aus:

Schematische Darstellung des Beispiel-Netzwerks

Die beiden Adressen “service_a.example.com” und “service_b.example.com” werden vom DNS auf die IP-Adresse 1.2.3.4 geleitet. Also müssen unsere Firewall anweisen, alle Pakete, die auf der IP-Adresse 1.2.3.4 auf Port 80 und 443 ankommen, an unseren Reverse-Proxy zu forwarden.

Dazu müssen wir zunächst das Forwarding für diese Ports in der FORWARD-Chain erlauben:

iptables -A FORWARD -i eth0 -o eth1 -p TCP --dport 80 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
iptables -A FORWARD -i eth0 -o eth1 -p TCP --dport 443 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT

iptables -A FORWARD -i eth1 -o eth0 -m state --state ESTABLISHED,RELATED -j ACCEPT

Dann kommt das eigentliche Portforwarding, also das Umschreiben der Empfängeradresse im Paket.

iptables -t nat -A PREROUTING -d 1.2.3.4 -p TCP --dport 80 -j DNAT --to-destination 192.168.10.10:80

iptables -t nat -A PREROUTING -d 1.2.3.4 -p TCP --dport 443 -j DNAT --to-destination 192.168.10.10:443

Das funktioniert zunächst für alle Pakete, die aus dem Internet (hier als Beispiel von der IP-Adresse 3.4.5.6) kommen. Die Empfänger-Adresse wird auf den Proxy umgeschrieben:

Source          Dest
3.4.5.6         1.2.3.4  -> DNAT -> 192.168.10.10

und auf dem Rückweg:

Source          Dest
3.4.5.6         1.2.3.4  <- DNAT <- 192.168.10.10

Der Absender 3.4.5.6 erhält also als Antwort auf sein Paket, dass mit der Empfängeradresse 1.2.3.4 abgesendet wurde.

Das gleiche funktioniert auch, wenn ein Rechner aus dem internen Netz ein Paket an einen unserer beiden Services sendet. Der Router sorgt auch hier wieder für den Aus- und Zurücktausch der Empfänger-Adresse des Pakets.

Jetzt kommen wir aber zu einem Fall, in dem das so nicht funktioniert. Nehmen wir einmal an, der Rechner “service_a.example.com” muss ein IP-Verbindung zu “service_b.example.com” herstellen. Da “service_b.example.com” auch im internen Netz mit der IP 1.2.3.4 übersetzt wird, geht unser IP-Paket also an unseren Router, der auch wieder brav die Empfängeradresse austauscht.

Source          Dest
192.168.10.50   1.2.3.4  -> DNAT to 192.168.10.10

Das Paket geht zunächst ordnungsgemäß an unseren Reverse-Proxy, der an 192.168.10.60 (service_b) vermittelt. Nun soll der Proxy eine Antwort an den Absender schicken und hat folgendes IP-Paket vorliegen:

Source          Dest
192.168.10.50   192.168.10.10

Ah, das Paket kommt von einer IP aus dem eigenen Netz, die ganz ohne Routing direkt erreicht werden kann, also wird die Antwort direkt an 192.168.10.50 gesendet.

Dieser Rechner kann aber mit der Antwort nichts anfangen, denn er hat nie ein Paket an die IP 192.168.10.10 gesendet, sondern an 1.2.3.4.

Also wird die Antwort verworfen, die IP-Verbindung kommt in diesem Fall nicht zustande. Hier haben wir den Fall, in dem ein DNAT für das Portforwarding nicht ausreicht.

Um dafür zu sorgen, dass die Antwort den gleichen Weg nimmt wie das Ursprungspaket auf dem Weg zum Reverse-Proxy und damit der Router die Daten des Pakets wieder auf den ursprünglichen Wert zurücksetzt, müssen wir in der Postrouting-Chain die Absender-Adresse des Pakets auf die IP des Routers ändern:

iptables -t nat -I POSTROUTING -s 192.168.10.0/24 -d 192.168.10.10 -p tcp --dport 80 -j SNAT --to-source 192.168.10.1

iptables -t nat -I POSTROUTING -s 192.168.10.0/24 -d 192.168.10.10 -p tcp --dport 443 -j SNAT --to-source 192.168.10.1

Zusätzlich benötigen wir an dieser Stelle eine Forwarding-Regel, die das Forwarding auch von eth1 zu eth1 erlaubt:

iptables -A FORWARD -i eth1 -o eth1 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT

Dadurch stellen wir sicher, dass das Paket bei Beantwortung zunächst wieder an den Router geschickt wird, der dann die IP-Adressen wieder auf die alten Werte korrigiert.

Als Regel kann man festhalten, dass wir immer dann eine SNAT-Regel für das Portforwarding benötigen, wenn durch das umschreiben der Empfänger-Adresse (DNAT) das IP-Paket so geändert wird, dass sich der Routing-Pfad auf dem Rückweg so ändert dass der Router, der das Natting durchgeführt hat, nicht mehr beteiligt ist. Dann ist es notwendig, auch die Absenderadresse so zu manipulieren, dass das Paket den gleichen Weg zurück nimmt und am NAT-Router wieder umgeschrieben wird.

Eine Tasse Kaffee am Sonntagmorgen 001

Am Sonntag bin ich morgens immer etwas früher wach als der Rest der Familie (ob das schon an diesem Alter liegt?). Mit einer Tasse Kaffee sitze ich dann oft am Rechner, stöbert im Internet und manchmal kommt dann im koffein-gefluteten Gehirn ein Thema vorbei, über dass man etwas sagen möchte.

Dafür ist diese Rubrik jetzt hier und ihr müsst mit mir zusammen da durch.

Also legen wir los.

Über gekürzte RSS-Feeds

Als ich im April 2006 hier mit meinem Blog gestartet bin, war die “Blogosphäre” noch übersichtlich. Alles war etwas kleiner und gefühlt privater. Es gehörte dazu, eine “Blogroll” mit seinen Lieblings-Blogs in der Seitenleiste zu haben und über Verlinkungen fand man andere interessante Blogs.

Die ersten Blog-Verzeichnisse kamen auf, in denen man seinen Blog eintragen konnte und so entstanden nach Themen kategorisierte Verzeichnisse.

Irgendwann wurde es trotzdem schwer, auf allen Seiten die neuen Blogbeiträge im Auge zu behalten und seit dieser Zeit nutze ich RSS-Feeds, um Neuigkeiten im Netz zu verfolgen.

Ein RSS-Feed ist eine XML-Datei, die die Inhalte einer Webseite in einem genormten Format enthält und die man mit einem sogenannten RSS-Reader abonnieren kann. Der Reader ruft diese Datei in regelmäßigen Abständen ab und stellt die Inhalte hübsch aufbereitet dar. Auf diese Weise sieht man an einer zentralen Stelle Neuerungen auf den abonnierten Seiten. Im Prinzip kann man solch einen RSS-Feed auf beliebigen Internetseiten anbieten, sie sind jedoch besonders sinnvoll auf Nachrichten-Seiten und eben auf Blogs. Die folgenden Gedanken sind daher eher auf diese Spezies von Webseiten bezogen.

Ja, RSS-Feeds sind immer noch ein Ding und ein paar von uns nutzen sie immer noch intensiv. Leider ist es etwas aus der Mode gekommen, auf seiner Seite einen solchen Feed anzubieten. Auf vielen Blogs (oder Nachrichten-Seiten) findet man keinen Link oder Hinweis mehr auf einen RSS-Feed. Mit diversen Browsererweiterungen kann man diese Feeds aber immer noch finden und abonnieren.

In der letzten Zeit habe ich einige neue Blogs gefunden und in meinen Feedreader aufgenommen. Dabei stelle ich fest, das immer mehr Blogger zwar einen Feed zur Verfügung stellen, dieser aber gekü rzt wird. Das bedeutet, ich sehe im Reader immer nur einen Artikelteaser oder die ersten Sätze des Artikels und muss, um den Beitrag vollständig zu lesen, über einen Link auf die Webseite des Blogs wechseln.

Auch einige Blogs, die schon länger in meinem Feedreader liegen, haben in den letzten Monaten von einem Volltext- auf einen gekürzten Feed umgestellt.

Das nervt mich. Ich kann nicht mehr einfach die Beiträge im Reader durchlesen. Ich muss anhand des angebotenen Schnipsels entscheiden, ob ich den Beitrag weiter lesen möchte und dann über den Link auf die jeweilige Webseite wechseln. Manchmal stellt sich dann nach ein paar weiteren Sätzen heraus, dass das Thema doch nicht so meins ist.

Es gibt natürlich ein paar Gründe dafür, den RSS-Feed gekürzt anzubieten. Seiten, die sich über Werbeanzeigen finanzieren, also nicht nur ein reines Hobby-Projekt sind, haben das Problem, dass ein Artikel, der über RSS gelesen wird, keine Klickzahlen bringt. Also gehen hier Einnahmen verloren, wenn auf der Seite Anzeigen geschaltet sind, die nach Views oder Klicks bezahlt werden.

Es ist auch schwer, RSS-Leser in Statistiken zu erfassen. Die Anzahl der Besucher und auch die Frage, welche Inhalte am meisten gelesen werden, ist schwer zu messen. Auch hier besteht ein Vorteil, wenn die Leserin aus dem Feedreader zum Lesen des ganzen Artikels auf die Seite kommt.

Der Betreiber einer Webseite hat sich bei der Erstellung (hoffentlich) auch Gedanken gemacht, wie sie oder er ihre/seine Inhalte optisch präsentiert. Die Gestaltung der Seite unterstützt auch die Inhalte, die ich vermitteln möchte. Auch kann man Mehrwerte für seine Leser über zusätzliche Informationen und Links auf seiner Webseite anbieten, die im Feedreader so nicht zu sehen sind.

Eine Besonderheit bei Blogs ist die Kommentarfunktion, über die Bloggerinnen und Blogger mit den Lesern in Kontakt treten und über die Beiträge diskutieren können. Viele Blogs haben die Kommentarfunktion allerdings nicht mehr aktiv und verschieben die Diskussion eher auf die sozialen Medien. (Das wäre ein Thema für eine andere Tasse Kaffee an einem anderen Sonntagmorgen.) Im Feedreader sehe ich nicht, ob es eine Kommentarfunktion gibt und muss zunächst auf die Seite wechseln.

Ich kann also verstehen, warum ihr das mit den gekürzten Feeds macht. Ich habe aber bei mir festgestellt, dass ich bei den Blogs mit den gekürzten Feeds weniger Artikel komplett lese. Beim Scrollen durch die Artikel bin ich eher geneigt, einen Artikel als gelesen zu markieren, wenn mich eine Überschrift oder die ersten Sätze nicht sofort packen. Bei vollständigen Artikel im Reader lese ich eher den ganzen Beitrag oder überfliege ihn zumindest.

Ich würde mich freuen, wenn ihr als Blogger eure Feeds nicht kürzt. Das erleichtert die Zugänglichkeit zu euren Inhalten und ich würde (gefühlt) mehr eurer Beiträge ganz lesen. Und zum Kommentieren komme ich dann auch gern rüber.

Ein technischer Anhang: Mittlerweile kann man in vielen Feedreadern Einstellungen vornehmen, die anstatt des gekürzten RSS-Feeds den ganzen Inhalt der Webseite abrufen und entsprechend darstellen. Es gibt auch Dienste, die für Seiten einen RSS-Feed bereitstellen, die eigentlich gar keinen solchen anbieten. Das ist aber für technisch nicht so affine Personen eine Hürde und außerdem würde es ja mein oben geschriebenes Jammern obsolet machen. :-)