Pregunta (TL; DR)
Al asignar puertos dinámicamente para el reenvío remoto (también conocido como -R
opción), ¿cómo puede un script en la máquina remota (por ejemplo, procedente de .bashrc
) determinar qué puertos fueron elegidos por OpenSSH?
Antecedentes
Utilizo OpenSSH (en ambos extremos) para conectarme a nuestro servidor central, que comparto con muchos otros usuarios. Para mi sesión remota (por ahora) me gustaría reenviar X, cups y pulseaudio.
Lo más trivial es reenviar X, usando la -X
opción. La dirección X asignada se almacena en la variable de entorno DISPLAY
y a partir de eso puedo determinar el puerto TCP correspondiente, en la mayoría de los casos de todos modos. Pero casi nunca necesito hacerlo, porque Xlib lo honra DISPLAY
.
Necesito un mecanismo similar para tazas y pulseaudio. Existen los conceptos básicos para ambos servicios, en forma de variables ambientales CUPS_SERVER
y PULSE_SERVER
, respectivamente. Aquí hay ejemplos de uso:
ssh -X -R12345:localhost:631 -R54321:localhost:4713 datserver
export CUPS_SERVER=localhost:12345
lowriter #and I can print using my local printer
lpr -P default -o Duplex=DuplexNoTumble minutes.pdf #printing through the tunnel
lpr -H localhost:631 -P default -o Duplex=DuplexNoTumble minutes.pdf #printing remotely
mpg123 mp3s/van_halen/jump.mp3 #annoy co-workers
PULSE_SERVER=localhost:54321 mpg123 mp3s/van_halen/jump.mp3 #listen to music through the tunnel
El problema está configurando CUPS_SERVER
y PULSE_SERVER
correctamente.
Usamos muchos reenvíos de puertos y, por lo tanto, necesito asignaciones de puertos dinámicas. Las asignaciones de puertos estáticos no son una opción.
OpenSSH tiene un mecanismo para la asignación dinámica de puertos en el servidor remoto, al especificar 0
como puerto de enlace para el reenvío remoto (la -R
opción). Al usar el siguiente comando, OpenSSH asignará dinámicamente puertos para tazas y reenvío de pulsos.
ssh -X -R0:localhost:631 -R0:localhost:4713 datserver
Cuando uso ese comando, ssh
imprimiremos lo siguiente para STDERR
:
Allocated port 55710 for remote forward to 127.0.0.1:4713
Allocated port 41273 for remote forward to 127.0.0.1:631
¡Ahí está la información que quiero! En definitiva quiero generar:
export CUPS_SERVER=localhost:41273
export PULSE_SERVER=localhost:55710
Sin embargo, los mensajes de "Puerto asignado ..." se crean en mi máquina local y se envían a los STDERR
cuales no puedo acceder desde la máquina remota. Curiosamente, OpenSSH no parece tener medios para recuperar información sobre reenvíos de puertos.
¿Cómo obtengo esa información para ponerla en un script de shell para configurar adecuadamente CUPS_SERVER
y PULSE_SERVER
en el host remoto?
Callejones sin salida
Lo único fácil que pude encontrar fue aumentar la verbosidad de la sshd
información hasta que se pueda leer la información de los registros. Esto no es viable ya que esa información revela mucha más información de la que es razonable hacer accesible para usuarios no root.
Estaba pensando en parchear OpenSSH para admitir una secuencia de escape adicional que imprima una buena representación de la estructura interna permitted_opens
, pero incluso si eso es lo que quiero, todavía no puedo acceder a las secuencias de escape del cliente desde el lado del servidor.
Debe haber una mejor manera
El siguiente enfoque parece muy inestable y está limitado a una sesión SSH por usuario. Sin embargo, necesito al menos dos sesiones simultáneas y otros usuarios aún más. Pero lo intenté ...
Cuando las estrellas están alineadas correctamente, después de haber sacrificado una gallina o dos, puedo abusar del hecho de que sshd
no se inicia como mi usuario, sino que elimina los privilegios después de iniciar sesión correctamente, para hacer esto:
obtener una lista de números de puerto para todos los enchufes de escucha que pertenecen a mi usuario
netstat -tlpen | grep ${UID} | sed -e 's/^.*:\([0-9]\+\) .*$/\1/'
obtener una lista de números de puerto para todos los sockets de escucha que pertenecen a procesos que mi usuario inició
lsof -u ${UID} 2>/dev/null | grep LISTEN | sed -e 's/.*:\([0-9]\+\) (LISTEN).*$/\1/'
Todos los puertos que están en el primer conjunto, pero no en el segundo conjunto tienen una alta probabilidad de ser mis puertos de reenvío, y de hecho restando los rendimientos de los conjuntos
41273
,55710
y6010
; tazas, pulso y X, respectivamente.6010
se identifica como el puerto X usandoDISPLAY
.41273
es el puerto de tazas, porquelpstat -h localhost:41273 -a
regresa0
.55710
es el puerto de pulso, porquepactl -s localhost:55710 stat
regresa0
. (¡Incluso imprime el nombre de host de mi cliente!)
(Para hacer la substracción del conjunto I sort -u
y almacenar la salida de las líneas de comando anteriores y usar comm
para hacer la substracción).
Pulseaudio me permite identificar al cliente y, para todos los efectos, esto puede servir como un ancla para separar las sesiones SSH que necesitan separarse. Sin embargo, no he encontrado una manera de vincular 41273
, 55710
y 6010
al mismo sshd
proceso. netstat
no divulgará esa información a usuarios no root. Solo recibo un -
en la PID/Program name
columna donde me gustaría leer 2339/54
(en este caso particular). Tan cerca ...
netstat
no le mostrará el PID para los procesos que no posee o que son kernel-space. Por ejemplo