HOWTO - SSH-Tunnel on demand ============================ !! Achtung !! Der Autor übernimmt keine Haftung für Schäden, die durch dieses HOWTO direkt oder indirekt verursacht wurden. Nutzung der Informationen geschieht auf eigene Gefahr. Vielen Dank für ihre Aufmerksamkeit. 0. Inhalt --------- 1. Worum geht's? 2. Vor-/Nachteile? 3. Namen, Konventionen 4. Was brauche ich? 5. SSH Pubkey Authentifizierung 6. SSH Pubkey testen 7. Zugriff einschränken 8. xinetd/inetd konfigurieren 8.1 xinetd 8.2 inetd 8.3 Test + Fehlersuche 9. Autor, Kontakt 1. Worum geht's? ---------------- Um durch eine Firewall hindurchzukommen braucht man immer mal wieder einen SSH-Tunnel. SSH bietet nämlich ein Feature das sich Portforwarding schimpft. Das blöde an der Geschichte ist, dass man den Tunnel immer erst aufbauen muss (= ssh von Hand starten), bevor man ihn benutzen kann. Dieses HOWTO zeigt, wie man mit Hilfe von SSH und (x)inetd dafür sorgen kann, dass der Tunnel bei Bedarf aufgebaut wird, ohne weiteres zutun. Das HOWTO ist relativ lang für das bisschen Konfiguration aber Profis können den grössten Teil überspringen und nicht-Profis sind wahrscheinlich froh darum :) 2. Vor-/Nachteile? ----------------- Vorteil: - man muss nix mehr tippen - man muss nicht mal mehr dran denken, erst einen Tunnel aufzubauen - funktioniert in allen Fällen, in denen auch ein SSH-Tunnel funktioniert Nachteil: - inetd bzw. xinetd muss laufen - Verbindungsaufbau dauert länger, also nur bedingt geeignet, um viele einzelne HTTP-Requests zu tunneln *gähn*. Für NNTP, POP3, IMAP, SMTP, IRC usw. ist es aber wunderbar. 3. Namen, Konventionen ---------------------- An manchen Stellen muss ein Benutzer- oder Servername angegeben werden. In den Beispielen wird davon ausgegangen, dass der SSH-Server (das ist der, auf dem man sich mit ssh einloggt) "ssh-host.example.org" heisst und der Account auf dem Server den Namen "ssh-user" trägt. Der Newsserver, zu dem man connecten will heisst "news-server.example.org". Die Namen sind wenig kreativ aber leicht merkbar :) 4. Was brauche ich? ------------------- Einen SSH-Account auf dem Server, zu dem getunnelt werden soll. Das muss übrigens nicht der gleiche Rechner sein wie der, zu dem ich eigentlich eine Verbindung aufbauen will; er muss sich lediglich auf der selben Seite der Firewall befinden wie der Zielrechner. [lokal] | [ssh-host] [news-server] H | H | | +==============|==========+ +-------------+ | Firewall === SSH-Tunnel (verschlüsselte Verbindung) --- normale Verbindung (unverschlüsselt) Auf dem Server muss das Programm netcat installiert sein (in manchen Distributionen heisst es netcat (z.B. SuSE), in anderen nc (RedHat, Debian)). Auf der lokalen Seite braucht man den xinetd (bevorzugt) oder inetd (zweite Wahl). Die meisten Distributionen haben einen der beiden schon installiert. SuSE Linux (zumindest bis SuSE 7.x) verwendet standardmässig inetd, RedHat Linux arbeitet mit xinetd. Die Beschreibung geht davon aus, dass auf'm Client und Server jeweils OpenSSH zum Einsatz kommt. Bei anderen Clients und Servern können sich die Konfigurationen und Kommandozeilenparameter unterscheiden, das Prinzip bleibt aber gleich. 5. SSH Pubkey Authentifizierung ------------------------------- Das ist der aufwändigste Teil und deshalb ein bisschen ausführlicher. Wer schon weiss, wie man sich mit SSH auf einem Rechner einloggt, ohne ein Passwort tippen zu müssen, der kann diesen Teil hier überspringen. Wer's noch nicht weiss: SSH bietet nicht nur die Möglichkeit, sich über ein Passwort am Server anzumelden sondern auch mittels eines Schlüssels. Genauer gesagt: mit einem Schlüsselpaar bestehend aus privatem (private key) und öffentlichen Schlüssel (public key). Gleiches Prinzip wie's auch für SSL, PGP und GPG benutzt wird. Wem bei den Begriffen public und private key noch kein Licht aufgeht sollte erstmal eine Suchmaschine bemühen und sich über die Funktionsweise informieren, bevor er weiterliest. Dreh- und Angelpunkt der tunnel-on-demand-Geschichte ist die Authentifizierung ohne Passwort (dafür mit Pubkey ohne Passphrase). Das ist notwendig, weil ssh später nicht-interaktiv als Daemonprozess läuft und daher kein Passwort abfragen kann. Ein paar SSH-Clients kriegen's trotzdem hin, ein Fenster in X aufzumachen und nach dem Passwort zu fragen aber das klappt nicht immer und überall :( Also gut, machen wir uns dran, das zu konfigurieren... Zunächst mal meldet man sich am System als der User an, unter dessen UID der (x)inetd läuft. Meist ist das root. Dann generiert man ein Schlüsselpaar. Mit ssh-keygen -t dsa -f tunnel -N "" erzeugt man zwei Dateien, tunnel und tunnel.pub. Das sind der Private Key und der Public Key. Den Private Key (tunnel) kopiert man sich an eine sichere Stelle, z.B. ins Verzeichnis .ssh/ im Homeverzeichnis des aktuellen Benutzers. Unbedingt drauf achten, dass der Private Key nur vom Benutzer selbst lesbar ist und von sonst niemanden! Den Pubkey kopiert man auf den SSH-Server. Praktischerweise bietet SSH das Programm scp (secure copy) an. scp tunnel.pub ssh-user@ssh-host.example.org: Als nächstes muss ein bisschen was auf dem SSH-Server konfiguriert werden. Und zwar erstellt man dort den Ordner .ssh/ im Homeverzeichnis, falls er nicht schon existiert und kopiert die Datei tunnel.pub hinein. mkdir -m 0700 .ssh/ mv tunnel.pub .ssh/ Im Ordner .ssh/ erstellt man nun die Datei authorized_keys, falls sie noch nicht existiert und kopiert den Inhalt von tunnel.pub hinein bzw. hängt ihn an, wenn authorized_keys schon existiert. Folgendes Kommando macht das in einem Rutsch: cd .ssh cat tunnel.pub >>authorized_keys Sodali, ab hier sollte einloggen ohne Passwort möglich sein. Testen wir's, indem wir uns mit dem Private Key auf dem Server einloggen (siehe nächster Abschnitt). 6. SSH Pubkey testen -------------------- Sagen wir, der im vorangegangenen Abschnitt erzeugte Private Key liegt in /root/.ssh/tunnel und die Konfiguration ist fehlerfrei verlaufen, dann müsste ssh ssh-user@ssh-host.example.org -i /root/.ssh/tunnel einen Shellaccount auf dem Server öffnen, ohne vorher nach einem Passwort zu fragen. Wenn's die erste Verbindung ist, kommt erst noch eine Meldung, ob man den Key vom Server in die Datei known_hosts aufnehmen will. Wichtig: Das Kommando muss unter der User-ID (UID) laufen, unter der es auch später im (x)inetd aufgerufen wird. Wie gesagt, in den meisten Fällen läuft's als User root. Wenn's nicht funktioniert fragt man am besten jemand, der sich damit auskennt, denn es gibt verschiedene Ursachen, woran es liegen kann. Z.B. kann es sein, dass die Datei für den Public Key nicht authorized_keys sondern authorized_keys2 heisst. Oder man hat sie in den falschen Ordner kopiert (richtig: .ssh/ im Homeverzeichnis auf dem Server). Oder Pubkey-Authentifizierung wurde vom Serveradministrator verboten. Oder auf'm Server läuft kein OpenSSH. 7. Zugriff einschränken ----------------------- Die Pubkey Authentifizierung ist ziemlich mächtig. Etwas zu mächtig für unsere Bedürfnisse. Allein der Besitz des Private Keys ermöglicht vollen Zugriff auf den Shellaccount auf dem SSH-Server. Das ist nicht sooo sicher und überhaupt nicht nötig. Deshalb zeigt der Abschnitt, wie man Möglichkeiten auf ein Minimum einschränkt. Auf dem Server muss wie bereits erwähnt das Programm netcat vorhanden sein. Unter RedHat und Debian heisst es nc. SuSE hat es netcat getauft, wahrscheinlich, um's vom Northern Commander zu unterscheiden, der ebenfalls nc abgekürzt wird. Einfach mal nc -h bzw. netcat -h tippen. Wenn eine Liste mit Optionen auftaucht, wie man sich mit einem anderen Rechner verbindet war's wahrscheinlich richtig :) Jetzt brauchen wir den absoluten Pfad von nc: which nc bzw. which netcat Meist isses /usr/bin/nc oder /usr/bin/netcat. Wenn man den Pfad weiss, kann man in authorized_keys auf'm Server folgendes vor den Pubkey in die gleiche Zeile schreiben: command="/usr/bin/nc news-server.example.org nntp",no-port-forwarding Durch ein Leerzeichen getrennt sollte dann ssh-dss, gefolgt von einer langen Reihe wilder Buchstaben und Zahlen kommen. Wie gesagt, alles in eine Zeile (zumindest bei OpenSSH, bei anderen Servern weiss ich nicht, wie das aussehen muss). Der zweite Parameter von nc (hier: nntp) ist übrigens der Port, auf den connected werden soll. Für POP3 gibt man pop3, für IMAP imap und für SMTP smtp an :) Oder wenn man die Portnummer weiss geht auch die. Jetzt kann man nochmal den Abschnitt 6 erklärten Test durchführen. Nur diesmal geht keine Shell auf und stattdessen meldet sich hoffentlich der Newsserver. Kommt doch eine Shell, hat man das Kommando vielleicht vor den falschen Schlüssel geschrieben. Passiert überhaupt nichts bzw. geht die Verbindung gleich wieder zu, dann hat man dem nc vielleicht 'nen falschen Parameter gegeben. Zum Überprüfen auf dem Server das in Anführungszeichen angegebene Kommando ausführen und schauen, ob sich da mehr tut. 8. xinetd/inetd konfigurieren ----------------------------- Wer's bis hierhin geschafft hat, sollte sich mal auf die Schulter klopfen, denn dann kriegt man das bisschen jetzt auch noch geregelt :) Zunächst geben wir dem Tunnel eine Portnummer und einen Namen. Sagen wir mal Port 61023 und als Name nntp-tunnel. Das tragen wir dann auch gleich in /etc/services ein. Eine Zeile der Form nntp-tunnel 61023/tcp # Tunnel zum Newsserver irgendwo zwischenreinschieben. Cool gemacht. An dieser Stelle trennt sich der Weg für diejenigen, die xinetd benutzen von vom Weg für die inetd-Nutzer. 8.1 xinetd ---------- Fehlt nur noch der xinetd. Der hat gleich ein ganzes Konfigurationsverzeichnis: /etc/xinetd.d/. Darin erzeugt man eine neue Datei mit dem Namen unseres Tunnels (hier: nntp-tunnel) mit folgendem Inhalt: # default: on # description: SSH on demand tunnel zum Newsserver service nntp-tunnel { socket_type = stream wait = no user = root server = /usr/bin/ssh server_args = -T ssh-user@ssh-host.example.org -i /root/.ssh/tunnel log_on_success += USERID log_on_failure += USERID disable = no only_from = localhost } Schnell noch lässig dem xinetd Bescheid geben, dass sich die Konfiguration geändert hat und dann war's das auch schon. Naja, fast. Eine kleine Schwierigkeit gibt's noch: Das Kommando zum neuladen ist von Distribution zu Distribution unterschiedlich :( Probier' mal die hier aus, eines wird schon passen... service xinetd reload /etc/init.d/xinetd reload rcxinetd reload service xinetd restart /etc/init.d/xinetd restart rcxinetd restart killall -HUP xinetd 8.2 inetd --------- Der inetd wird über die Datei /etc/inetd.conf gesteuert. In die trägt man irgendwo (z.B. am Schluss) folgende Zeile ein: nntp-tunnel stream tcp nowait root /usr/sbin/tcpd /usr/bin/ssh -T ssh-user@ssh-host.example.org -i /root/.ssh/tunnel Ist das geschehen, muss man noch den inetd neu starten. Wie im vorangegangenen Abschnitt zu xinetd gibt's auch hier mehrere Möglichkeiten, von denen eine schon stimmen wird :) service inetd reload /etc/init.d/inetd reload rcinetd reload killall -HUP inetd 8.3 Test + Fehlersuche ---------------------- Obercool. Ab jetzt kann man eine Verbindung zu localhost Port 61023 aufmachen und wird *zauber-zauber, magie, hex-hex* zum Newsserver durchgereicht. Ok, was tun, wenn doch nicht? In die Logfiles schauen (z.B. /var/log/messages). Immer noch kein Hinweis? Dann jemanden fragen, der sich auskennt, denn auch hier gibt's wieder viele seltsame Fehler, die sich nicht schnell im Howto klären lassen. Ein Fehler könnte sein, dass der Tunnel zum allerersten Mal mit dieser UID aufgemacht wird. Probier's nochmal von Hand unter der UID des Users, mit dem die SSH im (x)inetd gestartet wird. Bei mir hat es sich mal als vorteilhaft erwiesen, den Aufruf von SSH um den Parameter -T zu ergaenzen, also [...] ssh-user@ssh-host.example.org -T -i /root/.ssh/tunnel Wenn das aber auch nichts bringt ist doch Rat von Freunden gefragt. 9. Autor/Kontakt ---------------- Zu erreichen bin ich unter E-Mail: Achim Settelmeier . WWW: http://www.sirlab.de/linux/ IRC: Settel, #gnuher.de (auf deutschen Servern) Ich bin ganz besonders gut zu erreichen für Leute, die trotz oder wegen dem Howto immer noch Probleme haben aber auch für die, die Fehler finden oder Verbesserungsvorschläge anbringen wollen.