2008-11-21 47 views
18

Me gustaría establecer un túnel ssh sobre ssh en mi servidor mysql.Conectarse a un servidor MySQL a través de SSH en PHP

Idealmente, devolvería un puntero mysqli db como si me estuviera conectando directamente.

Estoy en un host compartido que no tiene las bibliotecas SSH2, pero podría instalarlas localmente usando PECL.

Si hay una forma de utilizar comandos nativos que sería genial.

Estaba pensando algo como esto, pero sin esas bibliotecas no funcionará.

$connection = ssh2_connect('SERVER IP', 22); 

ssh2_auth_password($connection, 'username', 'password'); 

$tunnel = ssh2_tunnel($connection, 'DESTINATION IP', 3307); 

$db = new mysqli_connect('127.0.0.1', 'DB_USERNAME', 'DB_PASSWORD', 
         'dbname', 3307, $tunnel) 
    or die ('Fail: ' . mysql_error()); 

¿Alguien tiene alguna idea? Estoy ejecutando un host de CentOS linux compartido en liquidweb.

¿Alguna idea de hacer que el túnel sea persistente? ¿Es posible establecerlo con otro script y solo aprovecharlo en PHP?

Gracias.

+0

Te das cuenta de que todos los demás en ese host compartido también podrán hacer conexiones a tu base de datos, ¿verdad? – Zoredache

+0

Todavía requeriría un nombre de usuario y contraseña válidos para conectarse, pero es un riesgo definitivo. ¿Sería ese el caso si el túnel fuera creado por ejecución en php? –

+0

Eliminé mi respuesta anterior, ya que al leer la documentación me di cuenta de que estaba mucho más involucrado de lo que pensaba para que mysqli utilizara SSL. – Powerlord

Respuesta

0

Eric,

creo que usted está fuera de suerte en este caso. Puede usar la extensión ssh en su código PHP o, si tiene acceso al servidor, puede intentar crear un túnel ssh en la línea de comandos.

Probablemente necesites permisos especiales para hacerlo. También parece que no tienes acceso ssh a esta cuenta de hosting.

--Joao

1

creo que la mejor opción es encontrar un proveedor de alojamiento diferente; Sugiero una solución VPS (Servidor Virtual Privado) que le da control total sobre su servidor web. De esta forma, si no te gusta la configuración predeterminada, puedes actualizarla tú mismo.

14

Usaría la herramienta autossh para crear un túnel ssh persistente en su base de datos mysql. Entonces todo lo que tienes que hacer en tu código PHP es dirigirlo a localhost.

Puede probar esto (sin reinicio automático) haciendo:

ssh -L 3306:localhost:3306 [email protected] 

instalación de una clave SSH de manera que no es necesario utilizar contraseñas, y modificar el archivo .ssh/authorized_keys en el sistema de MySQL solo permitir que se use para el reenvío de puertos.

Para obtener más información sobre los trucos de ssh, consulte Brian Hatch's series excelentes sobre SSH y reenvío de puertos.

+0

Esta respuesta me puso en el camino correcto. Finalmente lo descubrí aquí: http://stackoverflow.com/questions/464317/connect-to-a-mysql-server-over-ssh-in-php#comment65229024_16138417 – Ryan

2

Es es posible, pero ¿por qué? Es más complicado de lo que debe ser y propenso a errores.

¿No puede ejecutar la base de datos localmente? Si no es así, ¿no puede usar algo como SQLite, archivos XML u otra cosa que no requiera un servidor demonio por separado?

Usted realmente no desea inicializar el túnel dentro de los scripts de PHP. Inicializar un túnel SSH lleva mucho tiempo (puede ser fácilmente un segundo o dos), por lo que significa que cada página que se conecta a la base de datos tendrá un retraso de 2 segundos mientras se carga.

Si tiene que hacer esto (que recomiendo en contra), el mejor método sería tener un guión que mantiene la conexión en el fondo ..

instalación de un SSH keypair. Luego, usando autossh, o un script simple que ejecutará el comando SSH requerido, espere hasta que el proceso se apague y vuelva a iniciarlo. Podría ser más inteligente e intentar ejecutar un comando cada 10-20 segundos, reconectando si falla.

Usando el par de llaves SSH, no tendría que codificar la contraseña de los usuarios remotos en la secuencia de comandos. Recomendaría limitar lo que el usuario remoto puede hacer (utilizando un usuario de túnel dedicado y dándole un shell restringido, consulte la pregunta this)

En resumen, le sugiero que pruebe primero SQLite, luego vea qué tan factible almacene los datos usando archivos XML, luego intente molestar a su servidor web para obtener un servidor MySQL local, y luego busque en la opción de túnel SSH.

+1

¿recomendaría SSL sobre SSH si se trata de una conexión cifrada? ¿necesario? – csi

+0

@ChristopherIckes Sí, SSL sería mucho más apropiado – dbr

6

Lo intenté haciendo SSH por credenciales de raíz y par de clave privada pública. Me permite conectarme a través de la línea de comandos pero no a través del código PHP.

También intenté creando un túnel (mediante el uso de funciones SSH2) y ejecutando comandos de shell desde código PHP (system, exec, etc.); nada funcionó.

Por último, me trataron función SSH2 para ejecutar comandos shell, y finalmente funcionó :)

Aquí está mi código, si se le ayuda a:

$connection = ssh2_connect($remotehost, '22'); 
if (ssh2_auth_password($connection, $user,$pass)) { 
    echo "Authentication Successful!\n"; 
} else { 
    die('Authentication Failed...'); 
} 


$stream=ssh2_exec($connection,'echo "select * from zingaya.users where id=\"1606\";" | mysql'); 
stream_set_blocking($stream, true); 
while($line = fgets($stream)) { 
    flush(); 
    echo $line."\n"; 
} 

intente hacer esto si desea utilizar las funciones de PHP específicamente.

6

El túnel debe mantenerse abierto durante el curso de la (s) acción (es) SQL. El siguiente ejemplo de RJMetrics explica:

Ésta es la sintaxis de comandos SSH genérico:

ssh -f -L bind-ip-address:bind-port:remote-ip-address:remote-port \ 
[email protected] [command] >> /path/to/logfile 

Así es como para establecer con seguridad una conexión de base de datos remota en sólo 2 líneas de código PHP:

shell_exec("ssh -f -L 127.0.0.1:3307:127.0.0.1:3306 [email protected] sleep 60 >> logfile"); 
$db = mysqli_connect("127.0.0.1", "sqluser", "sqlpassword", "rjmadmin", 3307); 

Nosotros use la función shell_exec() para crear el túnel con una ventana de apertura de 60 segundos, y luego use la función mysqli_connect() para abrir una conexión de base de datos usando el puerto reenviado. Tenga en cuenta que debemos usar la biblioteca "mysqli" aquí porque mysql_connect() no nos permite especificar un puerto y las funciones mysql_* están en desuso.

sleep 60: cuando se trata de conexiones de túnel, básicamente tenemos dos opciones: dejar la conexión abierta todo el tiempo o abrirla y cerrarla según sea necesario. Preferimos este último y, como tal, no especificamos la opción -N al establecer un túnel, que lo dejaría abierto hasta que el proceso se mate manualmente (lo que es malo para la automatización). Como no se especifica -N, nuestro túnel se cerrará tan pronto como su sesión SSH no se utilice para nada. Este es un comportamiento ideal, excepto por los pocos segundos entre cuando creamos el túnel y cuando tenemos una conexión MySQL en funcionamiento a través del túnel.Para comprarnos algo de tiempo durante este período, emitimos el inofensivo comando sleep 60 cuando se crea el túnel, lo que básicamente nos compra 60 segundos para hacer que algo más atraviese el túnel antes de que se cierre. Siempre que se establezca una conexión MySQL en ese marco de tiempo, estamos todos listos.

+0

Esto pregunta por la contraseña de ssh ¿cómo manejarlo? –

Cuestiones relacionadas