OpenSSH: SSH Tunnel on Demand (DE)
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 bischen 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 bischen 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 bischen 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 bischen 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 <sshtunnelhowto@sirlab.de>.
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.