Mysql: Tunelizando la conexión por medio de SSH

En esta oportunidad vamos a aprender a conectarnos a un servidor remoto de MYSQL utilizando un túnel SSH para maximizar la seguridad del acceso.


Motivaciones

¿Cuántas veces necesitamos utilizar algún cliente de conexión a MySQL como el mysql-client o MySQL Workbench, para poder administrar un servidor Mysql?

Claro, para ello “necesitamos” abrir el puerto tcp 3306 en el servidor, lo que a simple vista no parece una muy buena idea.

Ya se, se preguntarán ¿Por qué no utilizar phpmyadmin y utilizar el web server?

Particularmente prefiero no utilizarlo por una cuestión de seguridad en mis servidores, pero eso es otro tema.

Entonces… ¿cuál podría ser la solución?

Y la respuesta a esta pregunta viene, como muchas veces, de la mano de SSH 🙂

Túnel SSHssh mysql

SSH es un súper protocolo, un protocolo extremadamente versátil y útil para un montón de aplicaciones.

Ya hemos escrito largo y tendido sobre SSH en este blog, algunas de las entradas que pueden ser de interés son:

A grandes rasgos, SSH permite establecer una conexión de contenido cifrado de alta seguridad entre nuestro ordenador y un servidor en la red.

SSH, además de permitirnos armar túneles para proxificar una conexión web, o realizar conexiones invertidas, o montar un sistema de archivos en red, o incluso levantar una VPN, también permite, como es la intención explicar aquí, tunelizar otros protocolos de aplicación sobre SSH… en este caso, MySQL.

Esquema de la comunicación

En la siguiente figura se puede analizar brevemente el esquema de la comunicación a realizar.

mysql tunnel ssh security privacy hack hacking

La idea es dejar oculto el puerto tcp3306 en el servidor (mysql), y solo permitirnos conexión por SSH (¿quien no tiene ya un SSH en el server? :D).

El cliente al establecer la conexión SSH contra el servidor, va a abrir automáticamente en el host local (Cliente) el puerto 3306 para el mysql, pero de una forma en la que el cliente Mysql local, como mysql-client por línea de comandos, o MySQL Workbench, o cualquier otro, se conecten al server remoto apuntándole a la dirección ip local 127.0.0.1.

Todo el tráfico Mysql dirigido a la ip local de localhost será reenviado, automáticamente, al servidor remoto, por medio del túnel cifrado de SSH, así el único acceso al servidor remoto será por SSH.

El tráfico mysql en sí, será cifrado en el cliente, enviado por dentro del túnel de red de SSH, descifrado en el servidor y entregado localmente al server en su puerto tcp 3306 local.

¿Interesante no? Vamos con la práctica.

Configuración SSH – MySQL

Suponiendo que nuestro servidor SSH/mysql está en la dirección ip 11.22.33.44, y queremos abrir el puerto cliente 3306 en el cliente, en la dirección ip de localhost 127.0.0.1, como explicamos en el esquema anterior, solo debemos ejecutar el siguiente comando (previo, por supuesto, ya disponer de cliente y server SSH configurado).

Aquí,

  • -L permite especificar un puerto local que será reenviado al servidor SSH remoto hacia un puerto remoto.
  • 12345: es el puerto local que reenviaremos al servidor remoto.
  • 127.0.0.1 es la dirección ip local en el equipo remoto en la que atiende el servicio. En este caso es la de localhost.
  • :3306 es el puerto remoto que será mapeado y asociado a esta conexión en el puerto local.
  • usuario_ssh es el usuario con el que vamos a conectarnos al SSH remoto.
  • 11.22.33.44 es el servidor remoto que atiende en el puerto de SSH hacia Internet, y que localmente tiene un servidor Mysql escuchando en una ip privada.

Luego de ejecutar este comando, podremos ver el puerto 3306 en nuestra ip local esperando conexiones, y por supuesto, podremos utilizar cualquier cliente de Mysql para conectarnos al servidor “127.0.0.1” o “localhost” con el puerto TCP 12345.

Por supuesto, no necesariamente tienen que ser estos puertos, podemos abrir cualquier puerto en el cliente, y que este puerto mapee contra el servidor en el 3306, simplemente reemplazando el primer “12345” en el comando anterior, por cualquier otro.

Además, suponiendo que en nuestra LAN tengamos mas de un equipo que quiera conectarse al mismo servidor, no es necesario que conecte SSH también, podemos especificar la ip de nuestra LAN antes del puerto local (192.168.x.y idealmente), o incluso * para permitir conectar a cualquier ip local de la LAN.

El comando quedaría así:

Como nota adicional cabe aclarar que MySQL Workbench ya dispone de la lógica para permitir conexión a un server Mysql remoto por medio de un túnel SSH… pero en mi caso necesitaba, además, abrir el puerto para permitir conexiones de otros equipos virtualizados locales 🙂

Ejemplo

Si ejecutamos:

Y nos autenticamos contra el servidor, luego podremos conectar, por ejemplo, nuestro cliente mysql por línea de comandos de esta forma:

mysql -h 127.0.0.1n -P 12345 -u usuario_mysql -p

¿Y si nuestro cliente es Windows?

Si el equipo cliente es Window$, podemos simplemente instalar Putty, el genial cliente SSH para sistemas EXE, y ejecutarlo.

En los datos de conexión debemos colocar el usuario y host del equipo servidor remoto:

Luego, ir a la sección Connection -> SSH -> Tunnels, y crear un túnel local automático con un puerto origen determinado, 3306 en este caso, y socket destino ip:port del servidor remoto de mysql:

Al dar clic en Add / Agregar, veremos lo siguiente:

Esto indica que se ha configurado correctamente… solo debemos dar clic en “Open/Abrir” y typear nuestra contraseña SSH contra el servicio remoto, que si loguea, ya tendremos en la ip 127.0.0.1:3306 el servicio Mysql remoto corriendo y atendiendo en forma local 🙂

¡Espero que les sea de utilidad!


Video complementario

En nuestro canal de youtube hemos publicado un video con la explicación de este artículo, esperamos sea interesante y ameno!

  • kabeza

    Buenisimo el dato. Consulta: en este caso tanto cliente como servidor tienen *nix como S.O., pero el cliente podria ser bien un Windows o cualquier cosa, no?

    • Hola! Si, si se puede configurando el túnel en Putty (el cliente SSH para Windows).
      Ahí actualicé el artículo y agregué esta info, es simplemente configurar un túnel SSH local automático contra el servcio remoto para que levante el puerto local.
      Espero te sirva!

  • Oscar Gallench

    me estoy volviendo loco, el putty parece que si accede al servidor, ya que me accepta el pass, pero luego intento acceder al phpmyadmin pero no abre…

    • Hola Oscar! Hay una confusión ahí. El artículo habla sobre cómo tunelizar conexiones de MYSQL sobre SSH, no http/https. Si el Putty te aceptó la password, significa que en tu ordenador vas a tener el puerto 3306 abierto para establecer conexiones contra el mysql remoto, por lo que con un cliente mysql deberías poder conectarte, como mysql desde línea de comandos, o mysql workbench apuntándole al localhost:3306 para acceder al servidor remoto.
      PHPmyadmin es un cliente web de mysql, que corre en un servidor web y atiende en el puerto 80/443, y el phpmyadmin internamente accede a los datos del mysql utilizando la conexión al puerto 3306.
      Esto significa que, si tenés el phpmyadmin instalado en tu máquina, éste debería acceder al server mysql remoto apuntándo a 127.0.0.1:3306.
      Si tenés el phpmyadmin en la máquina remota que hostea al mysql, y tenés acceso web a esa máquina, entonces deberías entrar con un navegador a la ip/nombre de la máquina remota, puerto 80/443.

      Conclusión, con el tunel ssh estás “trayendo” el puerto 3306 de la máquina remota a la tuya, de modo que puedas acceder al mysql remoto apuntándo a tu ip local, puerto 3306.
      Si de la misma forma querés acceder al phpmyadmin remoto, deberías hacer un trabajo similar para “traerte” el puerto 80/443 de la máquina remota a la tuya, y poder acceder al phpmyadmin apuntándo a tu dirección local.

      Espero que se haya entendido (algo, está rebuscado jaja).

      Cualquier duda quedo a disposición! Escribime que no es molestia.

      Saludos!! Diego

      • Oscar Gallench

        Buf…te cuento mi caso por si me puedes/quieres ayudar.
        Mi hermano me ha cedido una base de datos alojada en 1and1.com
        Lo que queremos conseguir es que yo pueda acceder mediante phpmyadmin sin usar el portal 1and1 y asi no usar sus credenciales.
        He seguido varios tutoriales, y mas o menos todos llegan al mismo sitio, pero en mi caso, no puedo entrar entrando en 127.0.0.1:3306/phpmyadmin, me aparece “Got packets out of order”, pero el caso es que en mi pc tengo tambien una base de datos montada con appache en red local que es donde hago las pruevas antes de subirlo al servidor online. Tambien acabo de provar de entrar con mysql worckbench configurando la conexion como tcp/ip over ssh pero parece que tampoco responde…sale un error que dice “lost connection to mysql server at ‘reading initial communication packet’, system error:0
        Podrias guiarme un poco?? Muchas gracias!

        • Oscar! Algunos datos a tener en cuenta:
          Si vas a usar mysqlworkbench, como bien decís, tiene la opción de conectarse via “tcp/ip over ssh”… si usás esa configuración, NO es necesario tunelizar la conexión mysql por ssh como describo en mi artículo, puesto que el workbench en este caso hace el mismo trabajo… deberías poder conectarte usando la ip/puerto/user/password del SSH remoto, y en la configuración del mysql apuntarle a 127.0.0.1:3306, debería salir andando solo.

          Por otro lado, si estás tunelizando como describo en mi artículo, y querés usar mysqlworkbench, deberías conectarte usando la conexión “standard tcp/ip”, no la que va sobre SSH, ya que la parte del ssh ya la resolviste… ahí deberías poner el server 127.0.0.1:3306 como base de datos, con user/pass de acceso que tenés configurado en el mysql remoto.

          Finalmente, como te dije en el otro comentario, no vas a poder entrar al phpmyadmin usando 127.0.0.1:3306/phpmyadmin, el puerto 3306 es de protocolo mysql, NO web, por lo que el navegador no puede interpretarlo.
          Si tenés acceso web a la máquina del mysql, simplemente deberías entrar al phpmyadmin usando http://ip_del_server_mysql/phpmyadmin.

          Si NO tenés acceso web y solo tenés acceso ssh, deberías “traerte” el puerto 80 del server mysql a tu equipo local, un trabajo similar al que hago en el artícuo, pero utilizando el puerto 80 en vez del 3306… el artículo explica cómo “traerse” el puerto 3306 de mysql desde un server remoto a tu equipo local para conectarte localmente, pero el mecanismo es perfectamente válido para cualquier puerto.

          Así, si querés traerte el puerto 80 del server mysql al equipo local, podrés hacer algo similar a esto:

          ssh -L 11111:127.0.0.1:80 usuario_ssh@11.22.33.4

          Y luego conectar al phpmyadmin desde un browser usando http://127.0.0.1:11111/phpmyadmin

          Es “parecido” al que no te funcionó a vos, con la diferencia de que el puerto 11111 en este caso está enlazado al puerto 80 remoto, no al 3306.

          Espero te aclare un poco los tantos! Escribime cualquier duda!