Me he aficionado bastante a los proxy inversos HTTP en nuestro entorno de desarrollo y he encontrado que el proxy inverso de host virtual basado en DNS es bastante útil. Tener solo un puerto (y el estándar) abierto en el firewall hace que la administración sea mucho más fácil.
Me gustaría encontrar algo similar para hacer conexiones SSH pero no he tenido mucha suerte. Prefiero no usar simplemente túneles SSH, ya que eso requiere abrir rangos de puertos distintos al estándar. ¿Hay algo por ahí que pueda hacer esto?
¿Podría HAProxy hacer esto?
ssh
reverse-proxy
ahanson
fuente
fuente
Respuestas:
No creo que SSH basado en nombres sea algo que sea posible dado cómo funciona el protocolo.
Aquí hay algunas alternativas.
Lo que podría hacer es configurar el host que responde para que el puerto 22 actúe como puerta de enlace. Luego puede configurar el servidor ssh para reenviar solicitudes al interior según la clave. Ejemplo de SSH Gateway con claves
Puede ajustar su cliente para usar ese host como proxy. Es decir, enviaría ssh al host de la puerta de enlace y luego usaría ese host para establecer una conexión con el host interno. Proxy SSH con configuración del cliente .
También puede configurar un proxy HTTP simple en el borde. Luego use eso para permitir conexiones entrantes. SSH a través del proxy HTTP .
Obviamente, con todo lo anterior, es muy importante asegurarse de configurar y bloquear correctamente la puerta de enlace.
fuente
He estado buscando una solución para este problema por intervalos durante los últimos 16 meses. Pero cada vez que miro, parece imposible hacer esto con el protocolo SSH como se especifica en RFC relevantes e implementado por implementaciones importantes.
Sin embargo, si está dispuesto a usar un cliente SSH ligeramente modificado y está dispuesto a utilizar protocolos de una manera que no fue exactamente cuando se diseñaron, entonces es posible lograrlo. Más sobre esto a continuación.
Por qué no es posible
El cliente no envía el nombre de host como parte del protocolo SSH.
Puede enviar el nombre de host como parte de una búsqueda de DNS, pero puede almacenarse en caché, y la ruta del cliente a través de resolvers a servidores autorizados no puede cruzar el proxy, e incluso si lo hiciera, no existe una forma sólida de asociar búsquedas de DNS específicas con clientes específicos de SSH.
Tampoco hay nada lujoso que pueda hacer con el protocolo SSH. Debe elegir un servidor sin siquiera haber visto el banner de la versión SSH del cliente. Debe enviar un banner al cliente, antes de que envíe algo al proxy. Las pancartas de los servidores podrían ser diferentes, y no tienes ninguna posibilidad de adivinar cuál es la correcta para usar.
Aunque este banner se envíe sin cifrar, no puede modificarlo. Cada bit de ese banner se verificará durante la configuración de la conexión, por lo que estarías causando una falla de conexión un poco más adelante.
La conclusión para mí es bastante clara, uno tiene que cambiar algo en el lado del cliente para que esta conectividad funcione.
La mayoría de las soluciones están encapsulando el tráfico SSH dentro de un protocolo diferente. También se podría imaginar una adición al protocolo SSH en sí mismo, en el que el banner de versión enviado por el cliente incluye el nombre de host. Esto puede seguir siendo compatible con servidores existentes, ya que parte del banner se especifica actualmente como un campo de identificación de forma libre, y aunque los clientes generalmente esperan el banner de la versión del servidor antes de enviar el suyo, el protocolo permite que el cliente envíe su banner. primero. Algunas versiones recientes del cliente ssh (por ejemplo, la de Ubuntu 14.04) envía el banner sin esperar el banner del servidor.
No conozco ningún cliente que haya tomado medidas para incluir el nombre de host del servidor en este banner. He enviado un parche a la lista de correo de OpenSSH para agregar dicha función. Pero fue rechazado por el deseo de no revelar el nombre de host a nadie que esté husmeando en el tráfico SSH. Dado que un nombre de host secreto es fundamentalmente incompatible con la operación de un proxy basado en nombres, no espere ver una extensión SNI oficial para el protocolo SSH en el corto plazo.
Una solución real
La solución que mejor funcionó para mí fue usar IPv6.
Con IPv6 puedo tener una dirección IP separada asignada a cada servidor, por lo que la puerta de enlace puede usar la dirección IP de destino para averiguar a qué servidor enviar el paquete. Los clientes SSH a veces se pueden ejecutar en redes donde la única forma de obtener una dirección IPv6 sería mediante el uso de Teredo. Se sabe que Teredo no es confiable, pero solo cuando el extremo nativo de IPv6 de la conexión está utilizando un relé público de Teredo. Uno simplemente puede poner un relé Teredo en la puerta de enlace, donde ejecutaría el proxy. Miredo se puede instalar y configurar como un relé en menos de cinco minutos.
Una solución alternativa
Puede usar un host de salto / host de bastión. Este enfoque está destinado a casos en los que no desea exponer el puerto SSH de los servidores individuales directamente a Internet público. Tiene el beneficio adicional de reducir la cantidad de direcciones IP externas que necesita para SSH, por lo que es utilizable en este escenario. El hecho de que sea una solución destinada a agregar otra capa de protección por razones de seguridad no le impide usarla cuando no necesita la seguridad adicional.
Un truco sucio para que funcione si la solución real (IPv6) está fuera de tu alcance
El truco que estoy a punto de describir solo debe usarse como el último recurso absoluto. Antes de siquiera pensar en usar este truco, le recomiendo obtener una dirección IPv6 para cada uno de los servidores a los que desea que se pueda acceder externamente a través de SSH. Use IPv6 como su método principal para acceder a sus servidores SSH y solo use este truco cuando necesite ejecutar un cliente SSH desde una red solo IPv4 donde no tenga ninguna influencia en la implementación de IPv6.
La idea es que el tráfico entre el cliente y el servidor debe ser un tráfico SSH perfectamente válido. Pero el proxy solo necesita comprender lo suficiente sobre el flujo de paquetes para identificar el nombre de host. Dado que SSH no define una forma de enviar un nombre de host, puede considerar otros protocolos que ofrecen esa posibilidad.
HTTP y HTTPS permiten que el cliente envíe un nombre de host antes de que el servidor haya enviado datos. La pregunta ahora es si es posible construir una secuencia de bytes que sea simultáneamente válida como tráfico SSH y como HTTP y HTTPS. HTTP es prácticamente un no iniciador, pero HTTP es posible (para definiciones suficientemente liberales de HTTP).
¿Te parece SSH o HTTP? Es SSH y completamente compatible con RFC (excepto que algunos de los caracteres binarios se alteraron un poco por la representación SF).
La cadena de versión SSH incluye un campo de comentario, que en el anterior tiene el valor
/ HTTP/1.1
. Después de la nueva línea SSH tiene algunos datos de paquetes binarios. El primer paquete es unMSG_SSH_IGNORE
mensaje enviado por el cliente e ignorado por el servidor. La carga útil a ignorar es:Si un proxy HTTP es lo suficientemente liberal en lo que acepta, la misma secuencia de bytes se interpretaría como un método HTTP llamado
SSH-2.0-OpenSSH_6.6.1
y los datos binarios al comienzo del mensaje de ignorar se interpretarían como un nombre de encabezado HTTP.El proxy no entendería ni el método HTTP ni el primer encabezado. Pero podría entender el
Host
encabezado, que es todo lo que necesita para encontrar el backend.Para que esto funcione, el proxy debe diseñarse según el principio de que solo necesita comprender suficiente HTTP para encontrar el backend, y una vez que se ha encontrado el backend, el proxy simplemente pasará el flujo de bytes sin procesar y dejará la terminación real de la conexión HTTP que debe realizar el backend.
Puede parecer un poco exagerado hacer tantas suposiciones sobre el proxy HTTP. Pero si estaba dispuesto a instalar un nuevo software desarrollado con la intención de admitir SSH, entonces los requisitos para el proxy HTTP no suenan demasiado mal.
En mi propio caso, encontré que este método funciona en un proxy ya instalado sin cambios en el código, la configuración u otros. Y esto fue para un proxy escrito con solo HTTP y sin SSH en mente.
Prueba de concepto cliente y proxy . (Descargo de responsabilidad de que el proxy es un servicio operado por mí. Siéntase libre de reemplazar el enlace una vez que se haya confirmado que cualquier otro proxy admite este uso).
Advertencias de este truco
fuente
the gateway can use the destination IP address to find out which server to send the packet to
la solución IPv6?-J
, por lo que puede usar: ssh -J user1 @ front user2 @ targetNo creo que esto sea algo posible, al menos de la forma en que lo describiste, aunque me encantaría que me demuestren lo contrario. No parece que el cliente envíe el nombre de host al que desea conectarse (al menos en claro). El primer paso de la conexión SSH parece ser configurar el cifrado.
Además, tendría problemas con la verificación de la clave del host. Los clientes SSH verificarán las claves en función de una dirección IP y un nombre de host. Tendría varios nombres de host con diferentes claves, pero la misma IP a la que se está conectando.
Una posible solución sería tener un host 'bastión', donde los clientes pueden ingresar a esa máquina, obtener un shell normal (o restringido si lo desea), y luego pueden ingresar en hosts internos desde allí.
fuente
Hay un nuevo chico en la cuadra. SSH piper enrutará su conexión en función de nombres de usuario predefinidos, que deben asignarse a los hosts internos. Esta es la mejor solución en el contexto de proxy inverso.
SSh piper en github
Mis primeras pruebas confirmadas, SSH y SFTP funcionan.
fuente
debug1: Sending subsystem: sftp
. Resulta que el frente de la camisa no admite subsistemas. ¿Soportas dobladillo en SSh piper?Me pregunto si Honeytrap (el honeypot de baja interacción) que tiene un modo proxy no podría modificarse para lograrlo.
Este honeypot puede reenviar cualquier protocolo a otra computadora. Agregar un sistema vhost basado en nombres (como lo implementa Apache) podría convertirlo en un proxy inverso perfecto para cualquier protocolo, ¿no?
No tengo las habilidades para lograrlo, pero tal vez podría ser un gran proyecto.
fuente
A medida que aumenta la cantidad de puertos / hosts a los que desea acceder detrás de un firewall, aumenta la conveniencia de las VPN.
Sin embargo, no me gustan las VPN.
fuente
debido a cómo funciona ssh, creo que no es posible. Similar a https, tendría que tener diferentes direcciones IP (externas) para diferentes hosts, porque la puerta de enlace no sabe a dónde desea conectarse porque todo en ssh está encriptado
fuente