cómo ejecutar un túnel en segundo plano como parte de un script de shell

cómo ejecutar un túnel en segundo plano como parte de un script de shell

Yo ejecuto estosdos comandostodo el tiempo para conectarme a mi instancia rds en aws que está protegida detrás de un firewall (por lo que hago un túnel a través de la instancia ec2) de esta manera:

comando 1: abrir el túnel (ejecutar en segundo plano)

ssh -N -L port:host:5432 user@$ip -i ~/.ssh/key.pub &

comando 2: conectarse a la base de datos a través del puerto del túnel:

PGPASSWORD=password psql dbname -U user -h ip_address -p port;

Lo cual es fantástico, pero me gustaría poner ambos en una sola función. Pero nada funcionó conmigo:

intento 1: ejecutar sin elementos de fondo:

function db()
{
    ssh -N -L port:host:5432 user@$ip -i ~/.ssh/key.pub &
    PGPASSWORD=password psql dbname -U user -h ip_address -p port;
}

simplemente me dice esto:

$proddb
[1] 62924
psql: could not connect to server: Connection refused
    Is the server running on host "127.0.0.1" and accepting
    TCP/IP connections on port 6666?

aunque el comando inicial se ejecuta en segundo plano:

ps aux | grep host
(standard input):435:abdullah         62924   0.0  0.0  4315660   5828 s006  S     3:06PM   0:00.03 ssh -N -L port:host:5432 user@$ip -i ~/.ssh/key.pub

y si ejecuto inmediatamente el siguiente comando después... ¡me conecto a la base de datos sin problemas!

PGPASSWORD=password psql dbname -U user -h ip_address -p port;
user=>

¿Cómo hago que esto funcione?

Respuesta1

El primer comando no tuvo tiempo de establecer un túnel cuando se ejecutó el segundo comando, lo que generó un "Conexión rechazada".

Simplemente no uses &, usa en su lugar la opción-f:

-f
Solicita a ssh que pase al fondo justo antes de la ejecución del comando. Esto es útil si ssh va a solicitar contraseñas o frases de contraseña, pero el usuario las quiere en segundo plano. Esto implica -n. La forma recomendada de iniciar programas X11 en un sitio remoto es con algo como ssh -f host xterm.
Si la opción de configuración ExitOnForwardFailure está configurada en "sí", entonces un cliente iniciado con -f esperará a que todos los reenvíos de puertos remotos se establezcan correctamente antes de colocarse en segundo plano.

Juntando todo esto, reemplace la línea ssh en la función con:

ssh -o ExitOnForwardFailure=yes -f -N -L port:host:5432 user@$ip -i ~/.ssh/key.pub

de esa manera, ejecutar la función varias veces no dejará ejecutándose ssh inútil (múltiple-1).

También es posible reemplazarlo -Ncon un breve comando de suspensión remota. De esa manera, no habrá un comando ssh inactivo de larga duración que deba buscarse si es necesario eliminarlo. Ssh seguirá esperando el final del uso del túnel antes de finalizar, por lo que el breve retraso no es un problema:

ssh -o ExitOnForwardFailure=yes -f -L port:host:5432 user@$ip -i ~/.ssh/key.pub sleep 15

Respuesta2

Esta solución de @AB también se puede utilizar para crear un "servidor de salto" entre dmz (internet o puntos finales de borde) y mz (backend) con un túnel de reenvío de puerto ssh a los hosts backend, por ejemplo:

(todos los puertos respectivos deben abrirse usando firewall-cmd)

desthost_ip es la IP de destino para el servicio al que se accede, debe tener un proceso de respuesta vinculado, es decir, Tomcat, webapp, etc.

En el borde dmz:

ssh -o ExitOnForwardFailure=yes -f -L localhost_ip:port:desthost_ip:port user@dest_ip -i xyz.key sleep 15

Entonces, si localhost también tiene una ip pública; suponiendo que desthost tiene un servicio basado en https en ejecución, entonces algo como esto puede funcionar:

https://public_ip_of_localhost:port

Esto debería abrir la página web desthost_ip:port service.

ssh -o ExitOnForwardFailure=yes -f -L 192.168.1.199:8001:192.168.2.10:8081 [email protected] -i xyz.key sleep 15

Y

https://192.168.1.199:8001 

o

https://public_ip_for_192.168.1.199:8001

Aparecerá la página de servicio en 192.168.2.10:8081.

información relacionada