Cierre el túnel ssh sin root y sin eliminar todas las demás conexiones ssh

Cierre el túnel ssh sin root y sin eliminar todas las demás conexiones ssh

Tengo un túnel ssh escuchando en un puerto local, digamos 8888, abierto desde una máquina remota con ssh -R 8888:localhost:80 myuser@myhost. Necesito escribir un script para "myuser" en "myhost" que cerrará este túnel.

El script será ejecutado por "myuser" en "myhost". No será ejecutado por el root ni podrá sudo.

Un enfoque sería encontrar el PID del proceso que escucha en 8888 usando lsof o netstat y luego finalizar el proceso. Sin embargo, tanto lsof como netstat se niegan a darme el PID sin hacer sudo. Con netstat obtengo -en lugar de "PID/nombre de programa" sin sudo.

¿Hay alguna manera de averiguar el PID del proceso que escucha en un puerto determinado sin los privilegios de root? El proceso que escucha en este puerto se ejecuta con el mismo usuario que nosotros. ¿O hay alguna otra forma de cerrar el túnel ssh desde fuera?

Tenga en cuenta que usar la secuencia de escape ssh para restablecer la conexión no es una solución como estamosnoen el túnel. Nuestro script debe ejecutarse por separado del túnel en el mismo host por parte del mismo usuario.

También tenga en cuenta que simplemente ejecutar killall sshdno es una solución, ya que eliminará todas las demás conexiones ssh, no solo esta.

Esta pregunta no es un duplicado de muchas preguntas similares, porque todas las respuestas aceptadas que he encontrado requieren privilegios de root o simplemente eliminan todas las conexiones ssh.

El host "myhost" ejecuta Ubuntu 12.04.5.


Editar: resumen de la discusión según lo solicitado por @Jakuje:

  • @Patrick sugirió un enfoque para usar setuido modificar /etc/sudoerspara permitir al usuario ejecutar el script con privilegios de root sin tener sudo completo. Aunque setuidnecesitaríamos escribir un binario en lugar del script. Sin embargo, permitir que el usuario ejecute el script con privilegios de root podría suponer un riesgo potencial para la seguridad. Y aún así, esta solución no cubre el caso de que el usuario no tenga ningún acceso de root, por lo que no puede modificar /etc/sudoers. Si @Patrick escribe esto como respuesta, definitivamente lo votaré, pero todavía no lo marcaré como aceptado.

  • @EricRenouf descubrió que sshd asigna el socket al usuario, por lo que el usuario no puede utilizarlo /proc/*/fdpara encontrar el proceso que tiene el socket. Probablemente por eso ni lsof ni netstat lo muestran.

Más ideas:

Como descubrió @EricRenouf, probablemente no haya forma de obtener el PID de sshd mediante el número de puerto del socket abierto ni el inodo. Pero tengo curiosidad por saber si no hay algún otro truco sobre cómo encontrar este PID sshd o cómo decirle que cierre la conexión. Quizás de alguna manera directamente con sshd.

Por ejemplo, si habilité el modo de depuración sshd sshd -d, registraría qué proceso sshd abrió un túnel hacia qué puerto /var/log/auth.loges legible por el usuario. Entonces el script podría analizar el registro y encontrar el PID allí. Pero ejecutar un sshd en modo de depuración no es una buena idea. En realidad hay unparche simple para sshdpara registrar túneles abiertos incluso sin el modo de depuración. Pero tampoco estoy seguro de que ejecutar un sshd parcheado sea una buena idea.

¿Hay algún otro truco?

Respuesta1

Comience configurando una clave SSH personalizada para conectarse a "myhost". Luego, edite su archivo .ssh/authorized_keys en "myhost" para que el PID principal del shell se escriba en un archivo:

command="echo $PPID > tunnel.pid; bash" ssh-rsa AAA...

Es posible que desee modificar algunas otras configuraciones de seguridad y/o escribir un script personalizado para simplemente escribir el PID y colgarlo. El principio es el mismo en ambos sentidos.

Una vez que tenga el PID del proceso que mantiene abierta la sesión SSH, es sólo cuestión de escribir un script...

kill `cat tunnel.pid`

...para finalizar el proceso, cerrando así la sesión SSH.

Tenga en cuenta que puede usar la -ibandera del sshcomando para especificar una clave privada para usar en la conexión.

Editar: eliminar el proceso de shell no cerrará el túnel si hay conexiones activas, por lo que eliminamos el proceso SSH principal.

Editar: aunque mi primera inclinación con cualquier conexión SSH automatizada es usar claves SSH, el mismo proceso podría emularse con:

ssh -R 8888:localhost:80 myuser@myhost 'echo $PPID > tunnel.pid; for ((;;)); do sleep 1; done'

También puede sustituirlo por un script que compruebe otros criterios para decidir cuándo finalizar. Probablemente sea una forma más limpia de manejar esto.

información relacionada