Pasos para reproducir:

Pasos para reproducir:

¿Por qué OpenSSH_8.4p1 finaliza otras sesiones que comparten la misma conexión cuando se utiliza ProxyCommand? ¿Hay alguna manera de prevenir esto?

Nota: Este comportamiento no parece ocurrir si se omite el argumento ProxyCommand.

Pasos para reproducir:

  1. Elimine cualquier conexión compartida existente con localhost:
ssh -o ControlPath=/tmp/%C -O exit 127.0.0.1 2>/dev/null
ssh -o ControlPath=/tmp/%C -O exit localhost 2>/dev/null
  1. Ejecute el siguiente comando dos veces en paralelo cada una en una terminal diferente:
ssh -F none -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \
  -o ControlMaster=auto -o ControlPath=/tmp/%C -o ControlPersist=1d \
  -o ProxyCommand='ssh -W %h:%p 127.0.0.1' \
  localhost 'sleep 3600'
  1. Interrumpa el primer proceso ssh con SIGINT escribiendo control-C.

Comportamiento esperado

  • Sólo finaliza el proceso SIGINT.
  • Otros procesos continúan ejecutándose sin verse afectados.

Comportamiento real

  • Ambos procesos se dan por finalizados.

Respuesta1

Sólo finaliza el proceso SIGINT.

"Proceso" es una premisa falsa. Ctrl+C envía SIGINTal proceso de primer planogrupode la terminal. Un grupo de procesos puede incluir más de un proceso.

Entonces esto es relevante:

ProxyCommand
Especifica el comando que se utilizará para conectarse al servidor. La cadena de comando se extiende hasta el final de la línea y se ejecuta utilizando la execdirectiva de shell del usuario para evitar un proceso de shell prolongado.
[…]

(fuente)

El comando se ejecuta localmente en el mismo grupo de procesos que el main ssh. En su ejemplo el comando es ssh …pero en general puede ser cualquier cosa. En cualquier caso, el comando no lo conoce ControlMastery ControlPersistlo usó para el main ssh.

Cuando presionas Ctrl+ C, cada proceso en el grupo de procesos de primer plano obtiene SIGINT. El "principal" sshsale sin afectar el socket en el ControlPathporque en caso de que ControlPersistno sea noeste socket es manejado desde el principio poraún otra sshproceso que se genera deliberadamente en su propio grupo de procesos, esto le permite sobrevivir. En este contexto se le puede llamar el verdaderamente principal ssh.

El comportamiento inesperado se debe a que el comando especificado con ProxyCommandse genera en el grupo de procesos de primer plano y se lleva SIGINTbien con el sshque desea interrumpir. El comando reacciona a la señal como lo haría normalmente. En su caso, el comando termina en SIGINT. Y debido a que se suponía que el comando transmitiría todos los datos, la conexión maestra (la verdaderamente principal ssh) ahora es inútil. Termina junto con todos sshlos procesos dependientes.

Por lo tanto, el original sshrealiza un trabajo adicional para garantizar que sshel manejo de la conexión maestra (y el socket) sobreviva Ctrl+ C, pero no lo hace para el comando especificado, ProxyCommandque es igualmente importante. Creo que puedes llamarlo error.

Probablemente sería mejor si el comando especificado en fuera ProxyCommandgenerado por el inmune sshenesgrupo de proceso. No he analizado esto lo suficientemente a fondo. De todos modos, por ahora no es el caso, el comando se genera en el grupo de procesos que es el grupo de procesos en primer plano en el momento en que presionas Ctrl+ C, por lo que obtiene SIGINT.

Una solución alternativa es hacer que el comando sea inmune a SIGINT. Por dentro ProxyCommandno se puede usar trapdirectamente porque ProxyCommandse usa execautomáticamente, exec trap …no tiene sentido y no funciona. Necesitas otro caparazón:

ssh -F none -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \
  -o ControlMaster=auto -o ControlPath=/tmp/%C -o ControlPersist=1d \
  -o ProxyCommand='sh -c "trap \"\" INT; exec ssh -W %h:%p 127.0.0.1"' \
  localhost 'sleep 3600'

Mis pruebas indican que ser inmune a SIGINTno impedirá que este interno sshsalga cuando llegue el momento y la conexión maestra finalice debido a la ControlPersistconfiguración finita.

información relacionada