Einen OpenVPN-Client per SSH zu einem anderen lassen, ohne den Pool zu öffnen
Lass client-to-client aus, überlass dem Kernel die Weiterleitung eines Flusses, und der Rest des Pools bleibt geschlossen. Zwei Regeln auf dem Server plus eine am Ziel.
Ein Client muss den SSH-Dienst eines anderen Clients erreichen, und der Rest des Pools soll so isoliert bleiben wie heute. Der verlockende Schalter ist client-to-client, der Peer-Zugriff für alle auf einmal aktiviert und die Entscheidung an OpenVPN statt an den Kernel gibt. Eine engere Antwort lässt diesen Schalter aus und überlässt dem Routing und der Firewall des Servers genau einen Fluss.
Der Mechanismus zählt mehr als der Regeltext, weil die beiden Ansätze das Paket an verschiedene Stellen bringen. Zu wissen, welchen man gewählt hat, erklärt sowohl die Regel, die nichts zu tun scheint, als auch den Peer, der ohne sie verbindet.
Wohin client-to-client das Paket verschiebt
Mit aktiviertem client-to-client leitet der Server ein Peer-Paket intern weiter, statt es wieder durch das Tunnelgerät zu schicken, sodass das Paket nie auf den Weiterleitungspfad des Kernels trifft. Das ist bequem, und es bedeutet auch, dass deine Firewall den Fluss nie sieht, den sie eigentlich prüfen soll. Lässt du die Option aus, leitet der Server das Paket über dieselbe Schnittstelle wieder hinaus, was es vor netfilter bringt. Dieselbe Schnittstelle rein, dieselbe raus, und die FORWARD-Kette bekommt die Stimme.
Der Tausch ist ausdrücklich: Du gewinnst einen Richtlinienpunkt und übernimmst die Routing- und Weiterleitungsarbeit, die die Abkürzung für dich erledigt hat. Diese Arbeit ist für einen einzelnen Fluss klein und wächst mit jeder Ausnahme, die du hinzufügst. Zähle die Ausnahmen jetzt, denn im Regelsatz lebt die Peer-Richtlinie tatsächlich.
Der Weg, den ein Peer-Paket tatsächlich nimmt
Nimm einen Linux-Community-OpenVPN-2.6-Dienst an, Userspace-TUN-Verarbeitung statt DCO, Subnet-Topologie, tun0 und einen Pool von 10.44.0.0/24 mit Client A auf 10.44.0.21 und Client B auf 10.44.0.37. Bei Subnet-Topologie decken die Adresse und Netzmaske, die A erhalten hat, den Pool bereits ab, sodass A das Paket ohne eine zusätzliche gepushte Route an das Tunnelgerät schickt. Prüfe die effektive Route auf A, statt eine anzunehmen.
Auf dem Server kommt das Paket an B adressiert an, was keine lokale Adresse ist, also wird es weitergeleitet. IPv4-Weiterleitung muss dafür überhaupt aktiviert sein, und die Routensuche muss das Paket wieder durch tun0 schicken. Die Firewall sieht daher einen weitergeleiteten Fluss mit derselben Schnittstelle auf beiden Seiten, und das ist das Detail, das die meisten Regelsätze übersehen. Hier ist keine Quellübersetzung nötig, und gerade weil A's Adresse unverändert bleibt, kann B seine eigene quellbasierte Regel anwenden.
Zwei Regeln auf dem Server, in dieser Reihenfolge
Drei Regeln tragen die ganze Freigabe: Weiterleitung, die Paar-Ausnahme und ein Standard-Drop für das Tunnelpaar. Die Accept-Regel benennt das Paar und den Dienst, sodass die Freigabe einen wachsenden Pool übersteht. Setze sie vor jede pauschale Ablehnung von Tunnel-zu-Tunnel-Verkehr, denn der erste Treffer gewinnt:
sysctl -w net.ipv4.ip_forward=1
iptables -A FORWARD -i tun0 -o tun0 -s 10.44.0.21 -d 10.44.0.37 -p tcp --dport 22 -j ACCEPT
iptables -A FORWARD -i tun0 -o tun0 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A FORWARD -i tun0 -o tun0 -j DROPDiese Befehle sind illustrativ und gehören in den Mechanismus, mit dem dein Host Regeln dauerhaft speichert; eine Einfügung zur Laufzeit verschwindet beim nächsten Start. Die Stateful-Regel ist es, die B's Antworten und den TCP-Handshake ohne eine zweite, gespiegelte Accept-Regel zurückkommen lässt.
Prüfe danach die Zähler statt der Regelliste, denn eine Regel, die nie trifft, sieht identisch aus wie eine, die funktioniert. Bleiben die Zähler auf null, nimmt das Paket nicht den Weg, den du glaubst.
Was B trotzdem erlauben muss
B betreibt den SSH-Dienst, also entscheidet B, ob etwas auf der Tunneladresse lauscht und ob die eigene Host-Firewall die Quelle akzeptiert. Eine Netzwerkfreigabe auf dem Server ist keine Erlaubnis für irgendein Konto auf B, und Hostschlüsselprüfung und Benutzerauthentifizierung gelten weiterhin wie von überall sonst.
Teste zuerst den Positivfall: eine frische SSH-Verbindung von A zur Tunneladresse von B, angenommen mit dem erwarteten Hostschlüssel. Teste dann einen anderen Peer oder einen anderen Port und bestätige, dass er abgelehnt wird, denn eine Freigabe, die still alles erlaubt, ist von einer funktionierenden nicht zu unterscheiden, bis es darauf ankommt. Beide Hälften dieses Tests sind nötig, und die zweite ist die, die Leute auslassen.
Halte die zugewiesenen Adressen, die effektiven Routen auf beiden Clients und die genauen Regeln auf dem Server und auf B fest. Ein erfolgreicher Ping zum Gateway oder ein offener Port auf dem Server beweist nichts davon, da beides zutreffen kann, während die Peer-Weiterleitung noch blockiert ist. Schreib diese Zahlen auf, solange der Tunnel steht, denn die Adresse, die ein Client nach einer erneuten Verbindung erhält, kann eine andere sein.