[HowTo] Tunneln von Verbindungen mit SSH

Jimini

PCGH-Community-Veteran(in)
Aloha,
nachdem ich einige Tage damit verbracht habe, ein Problem zu lösen, dachte ich mir, dass die Vorgehensweise vielleicht noch jemanden interessieren könnte. Zwar kann das Thema unter jedem Betriebssystem aufgegriffen werden, ich habe das Projekt aber ausschließlich unter Linux (Debian & Gentoo) durchgezogen. Natürlich kann man hierfür auch ein VPN nutzen, dazu benötigt man dann allerdings einen VPN-Zugang - ein SSH-Tunnel hingegen bringt weniger Anforderungen mit, da SSH zur Standardausrüstung eines Linux- / Unix-Systems gehört.

Szenario:
Traffic zu routen ist an sich kein großes Thema. Problematisch wird es, wenn der Traffic unverschlüsselt durch ein fremdes Netz (öffentliches WLAN, Internet...) geleitet werden soll. Bei mir ging es konkret darum, einen bei einem Hoster stehenden Server (im folgenden Alfred) insofern an mein Netzwerk anzubinden, als dass ich a) seinen Logging-Output an meinen bei mir zuhause stehenden Logging-Server (Bert) leiten und zudem b) den auf dem Server laufenden Zabbix-Client (auf Alfred) mit meinem Zabbix-Server (auf Bert) beobachten will. Ich werde das Tunneln anhand des Remote Loggings erklären.
Letztendlich kann man diese Methode aber durchaus dazu verwenden, um beispielsweise eine Firewall zu umgehen - man benötigt aber in jedem Fall einen Rechner außerhalb des eigenen Netzwerks, denn irgendwo muss der Tunneleingang ja erreichbar sein.

Hinweis: das Tunneln ist nur mit TCP-Verbindungen möglich!

Vorbereitungen:

Ich habe mich dazu entschieden, zum Aufbauen und Verwalten der Tunnels autossh zu nutzen, dieses Programm bringt die Fähigkeit mit, einen Tunnel bei einem Verbindungsabbruch selbständig wieder aufzubauen, so dass die Verbindung gewährleistet ist.
Man kann das ganze zwar auch mit ssh machen, das eignet sich dann allerdings nicht für den dauerhaften Betrieb.

Ein kurzer Testlauf ergab zunächst, dass es ohne Tunnel problemlos möglich ist - allerdings möchte ich nicht, dass Infos über mein System unverschlüsselt durchs Internet flattern.

1) Anpassen der Config von syslog-ng
Zunächst muss die Config des auf Alfred laufenden syslog-ng dahingehend angepasst werden, dass Alfred nicht mehr lokal, also nach /var/log/, loggt, sondern an ein entferntes System:
Code:
@version: 3.1

options {
        chain_hostnames(no);
        mark_freq(0);
        stats_freq(0);
};

source src { unix-stream("/dev/log"); internal(); };
destination remote      { tcp("127.0.0.1" port(5140)); };
filter f_messages       { level(info..emerg); };

log { source(src); filter(f_messages); destination(remote); };
Wie man unschwer erkennen kann, sollen alle Meldungen an 127.0.0.1:5140 geschickt werden. Warum aber an localhost? Man könnte hier natürlich auch direkt die Adresse des Zielsystems angeben - dann würde syslog-ng seine Meldungen allerdings quer durchs Internet schicken. Wir wollen den ganzen Kram aber tunneln - und da der Tunnel-"Eingang" sich auf Alfred befindet, muss auch dahin geloggt werden.

2) Öffnen des Tunnels auf Alfred
autossh -N -M55555 -L 5140:127.0.0.1:514 -f user@bert
Hiermit wird auf Alfred ein Tunnel zu Bert geöffnet. Auf Alfred lauscht der Tunnel fortan auf Port 5140. Wenn also syslog-ng etwas an 127.0.0.1:5140 schickt, nimmt der Tunnel den Traffic entgegen und schickt ihn an Bert, wo der Traffic dann auf Port 514 herauskommt und vom syslog-ng-Server entgegengenommen wird.
Zu den Parametern:
-N = kein Login auf dem Zielsystem
-M = Monitoringport, auf diesem Port überwacht autossh die Verbindung (kann beliebig gewählt werden, sollte aber keinem sonstigen verwendeten Port entsprechen)
-L = der Tunnel wird lokal geöffnet (dazu später mehr)
-f = nach dem Öffnen des Tunnels verschwindet das Programm im Hintergrund. Ich empfehle, diesen Parameter zuerst wegzulassen, damit man etwaige Fehler direkt in der Shell ausgegeben bekommt.
Hinweis: der root-Login via SSH sollte generell deaktiviert sein (in /etc/ssh/sshd_config "PermitRootLogin" auf "no" setzen). Privilegierte Ports (1-1023) können allerdings nur von root verwaltet werden, weswegen ich einfach einen höheren Port gewählt habe.
Hinweis: zum Testen eignet sich wunderbar das weit verbreitete Programm netstat:
Code:
root@alfred:/# netstat -tlpn | grep 5140
tcp        0      0 127.0.0.1:5140          0.0.0.0:*               LISTEN      9355/sshd: user
tcp6       0      0 ::1:5140                :::*                    LISTEN      9355/sshd: user
Man sieht, dass der SSHd auf Alfred auf Port 5140 auf Verbindungen wartet.
Man kann ebenfalls das kleine Programm "logger" nutzen, mit welchem man Meldungen direkt an den Logging-Daemon übergeben kann. Ein "logger test" sollte also "test" in den Logs ausgeben.
3) Öffnen eines Remote-Tunnels von Bert aus:
Das Problem bei mir war jetzt aber, dass der Logging-Server nicht direkt aus dem Internet erreichbar ist, da er hinter einer routenden Firewall sitzt. Ich hatte also zwei Möglichkeiten:
Entweder baue ich einen Tunnel von Alfred auf den Router und von da aus einen weiteren Tunnel zu Bert. Das Prinzip ist das selbe wie bei einem Tunnel. Oder ich baue den Tunnel von Bert aus auf, wofür dann nur ein einziger Tunnel benötigt wird. Da dies die weniger komplexe Lösung ist und ich ohnehin möglichst wenig Löcher in meine Firewall reißen möchte, habe ich mich für die zweite Variante entschieden. Hierzu muss der obige Befehl nur leicht abgeändert und diesmal auf Bert ausgeführt werden:
autossh -N -M55555 -R 5140:localhost:514 -f user@alfred
Statt "-L" wird hier nun der Parameter "-R" (remote) verwendet. Ich baue also auf Bert den Tunnel auf, wobei der Eingang nicht lokal, sondern auf Alfred geöffnet wird.

Fertig!

4) Schließen von Tunneln
Man kann die Tunnel natürlich schließen, indem man "killall autossh" ausführt. Damit werden alle Tunnel beendet. Möchte man allerdings nur einen Tunnel beenden, so sucht man sich mittels "netstat -tlpn" den entsprechenden Tunnel heraus und killt ("kill -KILL 12345") dann beispielsweise den Prozess mit der ID 12345.

Exkurs: SSH-Login ohne Passwort
Da es umständlich ist, bei jedem Tunnel das Passwort eingeben zu müssen oder wenn man beispielsweise einen Tunnel schon beim Systemstart bereitstellen will, empfiehlt es sich, mit Keyfiles zu arbeiten.

1) Erstellen des Keyfiles:
Zunächst muss man mit dem User (fred), der die Verbindung aufbauen soll, ein Keyfile erstellen, dies geschieht mittels "ssh-keygen". Möchte man kein Passwort eingeben, so lässt man dieses leer.

2) Kopieren des Public Keys auf den Zielrechner:
Als nächstes muss der Public Key (in der Regel im jeweiligen Homeverzeichnis unter ~/.ssh/id-rsa.pub) auf dem Zielsystem in ~./ssh/authorized_keys des jeweiligen Users (hans) kopiert werden.
Von nun an sollte sich fred via SSH als hans auf dem Zielsystem einloggen, ohne ein Passwort eingeben zu müssen.

MfG Jimini
 
Zuletzt bearbeitet:
Zurück