MySQL SSH Tunnel mit autossh
Warum ein SSH Tunnel eine gute Wahl ist um von einem Remote Client auf einen MySQL Server zuzugreifen habe ich in diesem Artikel beschrieben. Jetzt möchte ich zeigen wir man einen dauerhaften SSH Tunnel erstellt und ihn aufrecht erhält. Zum Monitoring des Tunnels kommt autossh zum Einsatz und die Authentifizieren geschieht per PublicKey. Das System ist bei mir seit ca. 1 Monat im Einsatz und läuft seit dem Start problemlos. Auf beiden Servern wird ein unprivilegierter User für SSH Tunnel angelegt. In diesem Beispiel werden die folgenden beiden Server:
Webserver (Alice)
Alice ist der Initiator des Tunnels und möchte den MySQL Server auf Bob benutzen.
MySQL Server (Bob)
Dieser MySQL Server soll unter dem Port 3307 von Alice aus dauerhaft erreichbar sein.
MySQL Server auf Bob
Auf Bob wird ein neuer User angelegt und der sshd so konfiguriert das dieser User sich per PublicKey Authentication anmelden kann.
$ adduser ssh-tunnel $ nano /etc/ssh/sshd_config AllowUsers ssh-tunnel PubkeyAuthentication yes $ /etc/init.d/ssh restart
Webserver auf Alice
Als erstes wird autossh installiert, dann wird ein neue User angelegt. Da man vielleicht mehrere Tunnel aufbauen möchte, lohnt es sich schon jetzt Gedanken über die Namen der User und Scripte zu machen. Bei mir folgen die Namen diesem Muster "tunnel-zielservername-dienst". Da ich für jeden Tunnel einen eigenen User anlege, heißt das Script also genauso wie der zum Einsatz kommende User.
$ aptitude update && aptitude safe-upgrade $ aptitude install autossh $ adduser tunnel-bob-mysql
Jetzt loggt man sich als tunnel User ein und testet die Verbindung.
$ su tunnel-bob-mysql $ cd ~ $ /usr/bin/autossh -M 20009 -N -L 3307:127.0.0.1:3306 -p SSHPORT ssh-tunnel@bob
Der autossh Aufruf endet nach dem -M 20009 (setzt den Monitoring Port auf 20009). Alles was folgt ist der ganz normale SSH Tunnel Aufruf. Für das Überwachen der Verbindung bietet autossh 2 Möglichkeiten. Bei der ersten Lösung wird eine zweite Verbindung aufgebaut über den per -M angegebenen Port und bei der zweiten wird ein Echo Service benutzt. Da der Echo Service einen inetd benötigt den ich nicht habe, kommt bei mir die erste Lösung zum Einsatz. Wenn alles funktioniert hat man nun einen SSH Tunnel aufgebaut und kann in einem anderen Consolen Fenster die MySQL Verbindung testen. Der zu verwendende Port ist in diesem Beispiel 3307!
$ mysql -h 127.0.0.1 -P 3307 -uMYSQL-USER -pMYSQL-PASSWORT mysql> SHOW DATABASES;
Nun kümmern wir uns um den PublicKey zum anmelden ohne Passwort.
$ mkdir ~/keys $ ssh-keygen -t dsa -b 1024 -f ~/keys/tunnel-key (Passphrase leer lassen) $ cd keys $ ls -1 tunnel-key (private key) tunnel-key.pub (public key)
MySQL Server auf Bob
Der Public Key von Alice muss jetzt in die authorized_keys Datei auf Bob eingetragen werden. Da bei mir alles per Putty läuft, kopiere ich den Key in die Zwischenablage und füge ihn dann in die Datei auf Bob ein. Wie man es macht ist aber auch egal. Auf Bob loggen wir uns als ssh-tunnel User ein.
$ cd ~ $ if [ ! -d .ssh ]; then mkdir .ssh ; chmod 700 .ssh ; fi $ cd .ssh/ $ if [ ! -f authorized_keys ]; then touch authorized_keys ; fi $ chmod 600 authorized_keys $ vi authorized_keys
Webserver auf Alice
Jetzt noch einmal die Verbindung per PublicKey testen.
$ /usr/bin/autossh -M 20009 -N -L 3307:127.0.0.1:3306 -p SSHPORT \ -i /home/tunnel-bob-mysql/keys/tunnel-key ssh-tunnel@bob $ mysql -h 127.0.0.1 -P 3307 -uMYSQL-USER -pMYSQL-PASSWORT mysql> SHOW DATABASES;
Funktioniert alles, kann man mit dem autossh Parameter -f den SSH Tunnel in den Hintergrund legen. Will man den Tunnel beenden, kann man dies ganz normal über kill + PID machen oder wenn man killall hat mit killall -u tunnel-bob-mysql (deshalb lege ich für jeden Tunnel einen eigenen User an)
$ /usr/bin/autossh -M 20009 -f -N -L 3307:127.0.0.1:3306 -p SSHPORT \ -i /home/tunnel-bob-mysql/keys/tunnel-key ssh-tunnel@bob
Eine Lösung für ein Crontab Start/Check gibt es hier. Bei mir kommt ein Init Script zum Einsatz, damit der SSH Tunnel automatisch gestartet wird. Es basiert auf dem hier veröffentlichten Init Script.
#!/bin/sh
#
### BEGIN INIT INFO
# Provides: autossh
# Required-Start:
# Required-Stop:
# Should-Start:
# Should-Stop:
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Start and stop a autossh tunnel
# Description: Creates a SSH Tunnel
### END INIT INFO
#
# config
AUTOSSH="/usr/bin/autossh -M 20009 -f"
TUNNEL="-N -L 3307:127.0.0.1:3306 -p SSHPORT -i ~/keys/tunnel-key ssh-tunnel@bob";
USER="tunnel-bob-mysql"
# script
# check if autossh is installed
test -x /usr/bin/autossh || exit 0
# autossh config
export AUTOSSH_GATETIME=30
export AUTOSSH_POLL=15
case "$1" in
start)
echo "Starting autossh tunnel"
su $USER -c "$AUTOSSH $TUNNEL"
;;
stop)
echo "Stopping autossh tunnel"
killall -u $USER
;;
restart)
$0 stop && sleep 2 && $0 start
;;
*)
echo "Usage: $0 {start}" >&2
exit 3
;;
esac
exit 0
$ nano /etc/init.d/tunnel-bob-mysql && chmod 755 /etc/init.d/tunnel-bob-mysql $ update-rc.d tunnel-bob-mysql defaults $ /etc/init.d/tunnel-bob-mysql start
Wer so wie ich mehrere Tunnel haben will und Wert auf die Stop/Restart Logik im Script legt, muss für jeden Tunnel einen eigenen User anlegen, da zum Stoppen einfach alle Prozesse des angegebenen Users beendet werden. Es gibt sicher eine elegantere Lösung, aber diese geht schnell und einfach. Tipps sind natürlich willkommen.
Entfernen eines SSH Tunnels
Auf Alice:
$ update-rc.d -f tunnel-bob-mysql remove $ rm /etc/init.d/tunnel-bob-mysql $ deluser --remove-home tunnel-bob-mysql
Auf Bob:
$ deluser --remove-home ssh-tunnel
Oder man nimmt nur den Key aus den authorized_keys.
Related Links
- Sicherheit: Weiteres einschränken der Tätigkeiten
- Offizielle AutoSSH Webseite
- Init Script von mopsy aus dem debianforum
- MySQL Forum Sammlung zum Thema SSH Tunnel
- Eine gute Engische Anleitung