UDP-Verkehr durch SSH-Tunnel

66

Der Titel bringt es auf den Punkt. Ich möchte UDP-Verkehr über einen SSH-Tunnel senden. Insbesondere muss ich in der Lage sein, UDP-Pakete durch den Tunnel zu senden, und der Server muss sie auf der anderen Seite an mich zurücksenden können. Ich weiß, wie man das für TCP-Verbindungen macht. Ist das mit UDP möglich?

heavyyd
quelle

Antworten:

36

In diesem kleinen Handbuch erfahren Sie, wie Sie UDP-Datenverkehr über SSH mit den Standardtools (ssh, nc, mkfifo) der meisten UNIX-ähnlichen Betriebssysteme senden.

Durchführen eines UDP-Tunnels über eine SSH-Verbindung

Schritt für Schritt Öffnen Sie mit Ihrer SSH-Verbindung einen TCP-Forward-Port

Stellen Sie auf Ihrem lokalen Computer (lokal) über SSH mit der zusätzlichen Option -L eine Verbindung zum entfernten Computer (Server) her, sodass SSH mit TCP-Portweiterleitung:

local# ssh -L 6667:localhost:6667 server.foo.com

Auf diese Weise können TCP-Verbindungen über die Portnummer 6667 Ihres lokalen Computers über den sicheren Kanal an die Portnummer 6667 auf server.foo.com weitergeleitet werden. Richten Sie die TCP / UDP-Weiterleitung auf dem Server ein

Auf dem Server öffnen wir einen Listener auf dem TCP-Port 6667, der Daten an den UDP-Port 53 einer bestimmten IP weiterleitet. Wenn Sie wie ich DNS-Weiterleitungen durchführen möchten, können Sie die IP des ersten Nameservers verwenden, die Sie in /etc/resolv.conf finden. Aber zuerst müssen wir ein FIFO erstellen. Das FIFO ist für die bidirektionale Kommunikation zwischen den beiden Kanälen erforderlich. Eine einfache Shell-Pipe überträgt nur die Standardausgabe des linken Prozesses an die Standardeingabe des rechten Prozesses.

server# mkfifo /tmp/fifo
server# nc -l -p 6667 < /tmp/fifo | nc -u 192.168.1.1 53 > /tmp/fifo

Auf diese Weise kann der TCP-Verkehr auf dem Port 6667 des Servers an den UDP-Verkehr auf dem Port 53 von 192.168.1.1 weitergeleitet werden und die Antworten können zurückgegeben werden. Richten Sie die UDP-zu-TCP-Weiterleitung auf Ihrem Computer ein

Jetzt müssen wir das Gegenteil von dem machen, was oben auf dem lokalen Rechner gemacht wurde. Sie benötigen privilegierten Zugriff, um den UDP-Port 53 zu binden.

local# mkfifo /tmp/fifo
local# sudo nc -l -u -p 53 < /tmp/fifo | nc localhost 6667 > /tmp/fifo

Auf diese Weise kann UDP-Datenverkehr auf Port 53 des lokalen Computers an TCP-Datenverkehr auf Port 6667 des lokalen Computers weitergeleitet werden. Viel Spaß mit Ihrem lokalen DNS-Server :)

Wie Sie jetzt wahrscheinlich erraten haben, wird eine DNS-Abfrage auf dem lokalen Computer, z. B. auf dem lokalen UDP-Port 53, an den lokalen TCP-Port 6667, dann an den TCP-Port 6667 des Servers und dann an den DNS-Server des Servers weitergeleitet UDP-Port 53 von 192.168.1.1. Um DNS-Dienste auf Ihrem lokalen Computer nutzen zu können, geben Sie in Ihrer /etc/resolv.conf die folgende Zeile als ersten Nameserver ein:

nameserver 127.0.0.1
John T
quelle
28
Diese Lösung ist nicht sicher. Es kann nicht garantiert werden, dass TCP-Streams Nachrichtengrenzen beibehalten. Daher kann ein einzelnes UDP-Datagramm in Teile aufgeteilt werden, wodurch jedes Protokoll verletzt wird.
Juho Östman
2
Es könnte auch schön sein, Port 1153 anstelle von 6667 (aus dem man-SSH-Beispiel) zu verwenden, der vom IRC verwendet wird.
phil pirozhkov
1
@ JuhoÖstman Danke, dass du auf diese Falle aufmerksam gemacht hast. Sich des Problems bewusst sein ... haben Sie eine Lösung gefunden? Wären ausreichend kleine Nachrichten eine Möglichkeit, um die Funktionsfähigkeit zu erhöhen?
HumanityANDpeace
4
Die Lösung besteht darin, jedem Paket eine Länge voranzustellen, bevor es über den TCP-Stream gesendet wird, und die ursprünglichen Pakete daraus zu rekonstruieren. Es wäre einfach, ein C-Skript dafür zu schreiben, aber ich bin nicht sicher, ob es eine sofort verfügbare Lösung gibt. In der Praxis scheint das TCP in diesem Fall normalerweise die Nachrichtengrenzen beizubehalten, es können jedoch jederzeit seltsame Fehler auftreten.
Juho Östman
Ich hatte damit ein weiteres Problem: Pipe und Fifo sind gepuffert, sodass Frame-Grenzen verloren gehen. So viele UDP-Frames können zu einem TCP-Frame verkettet werden.
Julio Guerra
26

In diesem Beispiel (ich glaube, Johns Antwort zeigt dasselbe an einer anderen Stelle) wird beschrieben, wie über eine TCP / SSH-Verbindung auf die UDP / DNS-Dienste eines anderen Computers zugegriffen wird.

Wir leiten den lokalen UDP / 53-Verkehr an TCP weiter, dann den TCP-Verkehr mit dem Portweiterleitungsmechanismus von SSH an den anderen Computer und dann TCP an UDP / 53 am anderen Ende.
Normalerweise können Sie dies mit openvpn tun.
Aber hier machen wir es mit einfacheren Tools, nur mit openssh und netcat.

Am Ende dieser Seite befindet sich ein weiterer Kommentar mit einem Verweis auf ' socat'.
Derselbe UDP / DNS-Zugriff erfolgt mit,

Serverseite: socat tcp4-listen:5353,reuseaddr,fork UDP:nameserver:53
Clientseite:socat udp4-listen:53,reuseaddr,fork tcp:localhost:5353

Siehe socat Beispiele für mehr.

nik
quelle
3
Dieser scheint mir viel nützlicher zu sein als die akzeptierte Antwort. Ich brauchte eine unidirektionale Umleitung von Video - Stream (TS / UDP) ... ssh orig_strm_src socat udp4-listen:4003,reuseaddr,fork STDOUT| socat STDIN udp-sendto:localhost:4003
nhed
FWIW, ich habe auf meiner Homepage eine detailliertere Anleitung geschrieben, die beschreibt, wie Sie socat over SSH für die UDP-Weiterleitung einrichten. Es verwendet SNMP als Beispiel.
Peter V. Mørch
20

SSH (mindestens OpenSSH) unterstützt einfache VPNs. Mit der Option -woder Tunnelim sshClient können Sie tunan beiden Enden ein Gerät erstellen , mit dem jeder IP-Verkehr weitergeleitet werden kann. (Siehe auch Tunnelin der Handbuchseite von ssh_config(5).) Beachten Sie, dass hierfür an beiden Enden OpenSSH (und möglicherweise Root-Rechte) erforderlich sind.

Grawity
quelle
Dies erfordert Root-Rechte auf dem Remotecomputer, auch für das UDP-Tunneln von nicht privilegierten Ports, und PermitRootLogin, das nicht auf 'no' gesetzt ist. Schade.
phil pirozhkov
@grawity Vielen Dank für den Hinweis auf diese Option, die auch, wie von Philpirozhkov darauf hingewiesen, den erforderlichen Root-Login. Ich frage mich, ob es einen Weg geben kann, die Wurzel nicht zu brauchen?
HumanityANDpeace
4
@humanityANDpeace: Sie können die Tun / Tap-Geräte vorab erstellen und sie einem bestimmten Benutzer zuweisen ip tuntap add.
Grawity
Hi @grawity. Ich mag Ihre Lösung, kann sie aber nicht zum Laufen bringen. Ich precreated das tunGerät wie folgt: sudo ip tuntap add mode tunaber wann immer die Verwendung von -wOption wie folgt aus : ssh $Server -w $portIch bekomme Tunnel device open failed. Could not request tunnel forwarding.Was mache ich falsch?
Lucas Aimaretto
16

Oder Sie können einfach ssf (das für diesen Anwendungsfall entwickelt wurde) mit einem einfachen Befehl verwenden:


Client Seite:

#>./ssfc -U 53:192.168.1.1:53 server.foo.com

Dieser Befehl leitet den lokalen Port 53 (DNS) über einen sicheren Tunnel zwischen localhost und server.foo.com zu 192.168.1.1 Port 53 um.


Sie benötigen einen SSF-Server (anstelle oder neben Ihrem SSH-Server):

#>./ssfs

Übrigens arbeiten sowohl die Client- als auch die Serverseite von ssf unter Windows / Linux / Mac. Dies ist eine Userland-Anwendung, sodass Sie weder Tun / Tap noch VPN benötigen.

Um Port 53 umzuleiten, benötigen Sie Administratorrechte - unabhängig vom verwendeten Tool.

Für weitere Informationen, Details, Anwendungsfälle oder Download: https://securesocketfunneling.github.io/ssf/

SSF-Entwickler
quelle
Bitte seien Sie vorsichtig und antworten Sie mit "Hier ist mein Produkt", es ist Borderline-Spam. Ich empfehle, die Richtlinien in der Hilfe zu lesen und zu befolgen .
Heavyd
7
Es ist höchstens ein schamloser Stecker. Die Lösung passt auf jeden Fall zu Ihrer Anfrage. Übrigens ist SSF OpenSource und gemeinnützig.
SSF-Entwickler
11
@heavyd: Wenn er eine Reihe von Hacky-Skripten posten würde, wäre das akzeptabel, aber weil er ein ausgereiftes Open-Source-Tool erstellt hat, ist es nicht so? Es beantwortet die ursprüngliche Frage perfekt.
Synthead
Ich muss widerwillig zugeben, dass dies genau das Werkzeug ist, nach dem ich gesucht habe, auch wenn es ein schamloser Stecker war.
Therealrootuser
9

Ich konnte nicht ncmit SNMP arbeiten, da SNMP-Clients weiterhin einen neuen Quell-UDP-Port auswählen und mehrere gleichzeitig aktiv sein können.

Stattdessen habe ich socatin diesem Blog-Beitrag einen Beitrag geschrieben , in dem die Vorgehensweise am Beispiel von SNMP beschrieben wird. Im Wesentlichen mit zwei Terminals, beginnend mit einer Übersicht:

Überblick

Terminal eins:

client$ ssh -L 10000:localhost:10000 server
server$ socat -T10 TCP4-LISTEN:10000,fork UDP4:switch:161

Dadurch wird die SSH-Weiterleitung von TCP-Port 10000 erstellt und socat auf dem Server ausgeführt. Beachten Sie, wie die IP-Adresse des Switches in der socat-Befehlszeile als "switch" angegeben wird.

Terminal zwei:

client$ sudo socat UDP4-LISTEN:161,fork TCP4:localhost:10000

Das setzt socat auf dem Klienten fest. Das sollte es tun.

Peter V. Mørch
quelle
Das hat bei mir funktioniert :)
Paul Fenney
4

Ein VPN ist eine bessere Lösung, wenn Sie Zugriff auf einen UDP-Port haben.

Wenn Sie nur Zugriff auf den TCP-SSH-Port haben, ist ein SSH-Tunnel so gut wie ein VPN, zumindest für Ping und Packet Backtracking.

Michael
quelle