Reenviar conexiones ssh al contenedor acoplable por nombre de host

10

Me he metido en una situación muy específica y, aunque hay otras formas de hacerlo, estoy un poco obsesionado con esto y me gustaría encontrar una manera de hacerlo exactamente así:

Antecedentes

Digamos que tengo un servidor que ejecuta varios servicios escondidos en contenedores acoplados aislados. Como la mayoría de esos servicios son http, estoy usando un proxy nginx para exponer subdominios específicos a cada servicio. Por ejemplo, un servidor de nodo se está ejecutando en un contenedor acoplable con su puerto 80vinculado al 127.0.0.1:8000host. Voy a crear un host virtual en nginx que los proxies todas las solicitudes de myapp.mydomain.coma http://127.0.0.1:8000. De esa manera, no se puede acceder al contenedor de Docker desde afuera, excepto a través de myapp.mydomain.com.

Ahora quiero iniciar un contenedor de gogs docker de tal manera que gogs.mydomain.comapunte al contenedor de gogs. Así que comienzo este contenedor de gogs con el puerto 8000vinculado al 127.0.0.1:8001host. Y un sitio nginx que envía solicitudes gogs.mydomain.coma http://127.0.0.1:8001y funciona bien ...

Sin embargo, como gogs es un contenedor de git, también me gustaría acceder a los repositorios, [email protected]:org/repopero eso no funciona con la configuración actual. Una forma de hacer que eso funcione sería vincular el puerto 22del contenedor al puerto 0.0.0.0:8022en el host, y luego la URL de git ssh puede ser algo así [email protected]:8022/repo.

(Eso no parece funcionar; cuando llego a un origen con uri como esa, git exige la contraseña para el usuario giten gogs.mydomain.comlugar de) gogs.mydomain.com:8022, pero eso es probablemente algo que estoy haciendo mal y fuera del alcance de esta pregunta, sin embargo, Agradecería cualquier diagnóstico para eso también)

Problema

Mi principal preocupación es que quiero que el puerto ssh <gogs container>:22sea ​​proxy al igual que proxys puertos http usando nginx; es decir, cualquier conexión ssh para gogs.mydomain.compasar al puerto del contenedor 22. Ahora no puedo vincular el puerto ssh del contenedor al puerto ssh del host porque ya hay un sshd ejecutándose en el host. Además, eso significaría que cualquier conexión *.mydomain.comse pasará al sshd del contenedor.


Quiero cualquier conexión ssh a:

  • mydomain.com host.mydomain.com o la dirección IP de mydomain para ser aceptada y reenviada al sshd en el host
  • gogs.mydomain.como git.mydomain.comser aceptado y transmitido al sshd en el contenedor de gogs
  • *.mydomain.com(donde *hay algo más que las posibilidades anteriores) para ser rechazado

Si fuera http, fácilmente podría hacer que eso funcione a través de nginx. ¿Hay alguna manera de hacer eso para ssh?


(También me gustaría ponerme nervioso y preguntar: ¿hay alguna manera de lograrlo con algún servicio de TCP en general?)

Cualquier idea sobre la forma en que estoy tratando de hacerlo aquí también es bienvenida. No me importa que me digan cuando lo que intento hacer es completamente estúpido.


Lo que ya tengo en mi mente:

¿Tal vez podría compartir el socket sshd en el host con el contenedor como un rovolumen? Eso significaría que el sshd dentro del contenedor podría recoger todas las conexiones *.mydomain.com. ¿Podría haber una manera de hacer que el sshd dentro del contenedor rechace todas las conexiones que no sean gogs.mydomain.como git.mydomain.com? Sin embargo, el sshd en el host recogerá todas las conexiones de *.mydomain.comtodos modos, incluyendo gogs.mydomain.com; entonces habría un conflicto. No sé, en realidad no lo he probado. ¿Debería intentarlo?

Zia Ur Rehman
fuente

Respuestas:

2

Hacer esto "por nombre de host" simplemente no está dentro del alcance de ssh. El protocolo ssh en sí mismo no admite alojamiento virtual basado en nombres (de hecho, HTTP es la excepción de la regla aquí).

El SSHd en el lado receptor nunca puede saber a qué nombre de host le pidió a su cliente que se conecte ya que esta información no se pasa dentro del protocolo.

Si solo necesita algunos clientes para trabajar con esto, puede configurar cada cliente para que se conecte a su servidor y luego saltar al contenedor acoplable de la siguiente manera:

Host yourcontainer
        Hostname internal.ip.of.your.container
        ProxyCommand ssh your.docker.host nc %h %p

De esta manera, ssh invocará el comando proxy que abrirá una sesión ssh a su host y llamará netcatpara establecer una conexión a su contenedor. De esta manera, realmente no necesita exponer el puerto ssh de sus contenedores al mundo exterior.

Andreas Rogge
fuente
0

Las versiones recientes de OpenSSH tienen la directiva ProxyJump y el indicador -J:

ssh -J proxyuser@jumphost user@target
ptman
fuente