remote Zugriff auf einen MySQL Server per SSH Tunnel

2010-02-24 - kostaki 2 Kommentare »

Das Standard LAMP System läuft naturgemäß auf einem physischen Server, aber ab einer bestimmten Auslastung lohnt es sich den Webserver vom Datenbank Server zu trennen. Es gibt aber auch andere Anwendungsbeispiele in denen der Zugriff auf einen MySQL Server von einem Remote Server/Client Sinn macht. In dieser Anleitung gehe ich davon aus das auf den MySQL Server übers Internet zugegriffen werden soll, es also um Kommunikation über ein unsicheres Netz geht. Bei mir kommt natürlich auf beiden Seiten ein aktuelles Debian Lenny zum Einsatz, aber es sollte auch in anderen Systemkonstellationen funktionieren.

Die einfachste Lösung ist dem MySQL Server den Netzwerkzugriff zu erlauben und dann über die Access Control von MySQL den Zugriff so weit wie möglich zu beschränken. Man kann hiermit zum Beispiel einem User den Zugriff nur von einer IP aus erlauben und ihn dann auf eine Tabelle oder Datenbank beschränken. Das lässt aber immer noch den MySQL Port offen im Netzwerk und das ist ein Sicherheitsrisiko. Außerdem kommuniziert MySQL standardmäßig unverschlüsselt und das macht das abhören und ggf. das verändern von Daten möglich. Will man diesen Schritt gehen, muss man MySQL auf einem anderen Interface lauschen lassen. Standardmäßig wird MySQL auf 127.0.0.1 gebindet. Damit ist der Zugriff nur von der lokalen Maschine aus möglich. Note: Verbindungen auf den localhost werden dabei aber nicht per TCP aufgebaut, sondern über einen lokalen UNIX Socket.

bind-address = 0.0.0.0 # lauschen auf allen Schnittstellen
bind-address = 127.0.0.1 # Standard nur lokaler Zugriff
bind-address = 84.4.4.123 # lauscht auf genau diesem Interface

Gibt man mehrere Zeilen an, wird die letzte genommen. Man kann dem Server auch die Kommunikation per SSL beibringen. Will man dies aber auf einem Debian System machen, muss man den MySQL Server selbst kompilieren, da aus irgend welchen Lizenzstechnischen Gründen der SSL Support disabled ist. Überprüfen kann man dies mit diesem Befehl.

mysql> SHOW VARIABLES LIKE 'have_openssl';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| have_openssl  | YES   |
+---------------+-------+

Steht dort an Stelle des YES ein disabled bleibt einem nur die neu Kompilierung des MySQL Servers übrig. Wer sich für diesen Weg entscheidet findet hier Informationen.

Eine weitere Lösung ist das verbinden zum MySQL Server über einen SSH Tunnel (Port Forwarding). Dabei wird die Kommunikation übers Netzwerk vom Remote Client zum MySQL Server über eine SSH Verbindung geleitet. Das hat den Vorteil das die komplette Kommunikation verschlüsselt ist und man den MySQL Server nicht um konfigurieren muss, da er immer noch nur lokale Anfragen annimmt (der Port bleibt aus dem Internet nicht erreichbar). Dies ist auch die Lösung für die ich mich schlussendlich entschieden habe und die ich hier etwas ausführlicher beschreiben möchte.

MySQL Remote Zugriff per SSH Tunnel

Hat man OpenSSH installiert, dann hat man eigentlich schon alles was man braucht. In meinem Fall möchte ich den Tunnel dauerhaft aufrecht erhalten und benutze dafür autossh. Nun aber erst mal eine "Von Hand" Lösung zum testen. Ein SSH Tunnel ist nichts anderes als eine Port Weiterleitung eines lokalen Ports über die SSH Verbindung zu einem anderen Port auf dem Remote Server. Das ganze ist nichts MySQL spezifisches, sondern kann für viele andere Anwendungen ebenfalls benutzt werden. Hier die Syntax fürs Port Forwarding. Dies wird auf dem Client ausgeführt.

$ ssh -L localport:host:hostport user@remotehost

In diesem Beispiel wird ein Tunnel vom Lokalen Client aus auf einen Remote Server erstellt. Es wird nicht der Standardport 3306 von MySQL benutzt, da auf beiden Rechnern MySQL Server laufen. Im Anschluss ist es möglich auf den lokalen MySQL Server per Port 3306 zu connecten und auf den MySQL Server auf dem Remote Server unter Verwendung des Ports 3307. Am besten öffnet man 2 Consolen Fenster auf dem lokalen Rechner, da das eine zum erstellen des Tunnels benutzt wird und man vom zweiten aus die Verbindung testen kann. Es wird außerdem ein alternativer SSH Port benutzt (-p 12345). Sollte der sshd auf dem Standardport 22 laufen kann man dies weglassen.

$ ssh -L 3307:localhost:3306 -p 12345 user@remotehost

Nachdem Fingerprint akzeptieren und der Eingabe des Passworts hat man eine Verbindung zum Remote Server erstellt und ein Port Forwarding vom Local Port 3307 auf Remote Port 3306 aufgebaut. So lange man diese Verbindung offen lässt, kann man den Tunnel benutzen und auf beide MySQL Server connecten. Standardmäßig kann man den Tunnel nur vom localhost (127.0.0.1) aus benutzen. Will man von weiteren Rechnern im Netzwerk den Tunnel benutzen, muss man diesen bei der Erstellung als global kennzeichnen.

-g      Allows remote hosts to connect to local forwarded ports.

Testen des SSH Tunnels

Steht einem Telnet zur Verfügung kann man es damit testen.

$ telnet 127.0.0.1 3306 # Verbindung zum lokalen MySQL Server
$ telnet 127.0.0.1 3307 # Verbindung zum remote MySQL Server

Sieht man ein paar Kryptische Zeichen, dann hat die Verbindung funktioniert. Note: Telnet verlässt man mit quit. Einen weiteren Test kann man mit dem Client Tool mysql machen. Hierbei ist wichtig zu verstehen das die MySQL Client Library bei Verbindungen zum localhost keine TCP Verbindung erzeugt, sondern einen lokalen UNIX Socket benutzt, was in unserem Fall nicht erwünscht ist, da der lokale Socket nichts mit unserem Tunnel anfangen kann. Es muss also bei der Verbindung zum Remote Server als Host 127.0.0.1 angegeben werden und nicht localhost.

$ mysql -h 127.0.0.1 -P 3306 -uuser -ppassword #lokaler MySQL Server
$ mysql -h 127.0.0.1 -P 3307 -uuser -ppassword #remote MySQL Server

Wenn die Verbindung geklappt hat, sollte man sich vergewissern ob man wirklich auf dem richtigen Server ist. Das macht man durch ein einfaches show databases;.

Automatisches erstellen und aufrecht erhalten des SSH Tunnels

Für kurze Checks reicht das oben beschriebene vollkommen aus, aber was macht man wenn man eine dauerhafte Verbindung zu einem MySQL Server haben will und diese auch nach einem Neustart/Netzunterbrechung automatisch gestartet werden soll? Hierfür gibt es das in C geschriebene Tool autossh, das als Debian Paket mit geliefert wird. autossh erstellt die Verbindung, beobachtet ob sich etwas am Status ändert und startet dann wenn nötig den Tunnel neu. Wie man mit Hilfe von autossh einen dauerhaften Tunnel betreiben kann, wird im Artikel MySQL SSH Tunnel mit autossh beschrieben.

Related Links

  1. 2 Kommentare

  2. Stan
    schrieb am 27.04.2010 um 08:44 Uhr

    Man kann den Zugriff auch aus dem Netzwerk zulassen und dann per iptables einschränken. So hat man zwar keine verschlüsselte Übertragung, aber trotzdem eine gewisse Sicherheit.

  3. harivolker
    schrieb am 23.12.2011 um 04:59 Uhr

    Ist zwar schon ein bischen älterer Artikel, aber der Vollständigkeit halber… :-)
    Verwendung von SSL geht mit den debian-Paketen aus lenny und squeeze auch ohne Rekompilierung:
    Einfach des Wort ‘ssl’ der my.cnf hinzufügen. Näheres gibt’s unter http://www.howtoforge.com/how-to-set-up-mysql-database-replication-with-ssl-encryption-on-debian-lenny.

Kommentar schreiben

*

*