| 0.1 | 10-Ene-04 | Partes incompletas o no revisadas, explicación de forwarding. |
| 0.2 | 13-Ene-04 | Correcciones ortográficas, de formato. Se completa
parte
del Apéndice I. |
| 0.3 | 15-Ene-04 | Menos errores de tipeo (thx Fedex!). Arreglo de links rotos. Validación W3Consortium para HTML 4.01 Transitional. Optimización de los png (thx Sismo!). |
| 0.4(current) | 22-Ene-04 | Se hacen las pruebas de seguridad del forwarding. Se agregan
los créditos de Dia y de Gimp. Se agregan subsecciones en
"(In)Seguridad en el forwarding". Se completan las capturas de pantalla
incompletas. |
| El autor no se hace responsable de los daños o perdida de datos producidos por la libre aplicación de la información contenida en este documento. De hecho, nadie se hace responsable. Que a mi me haya funcionado no significa que respondo por los resultados. |
Para un mejor seguimiento de cambios de este documento sugiero que quien lo modifique me avise, así toda la comunidad puede hacer uso de ellos. Los créditos de los cambios serán respetados, como también los créditos originales del autor. Si quiere hacer referencia a este documento o si quiere tener una copia en su página ruego también se me avise.
El autor suele castellanizar palabras del inglés como "tunelear" (por "tunneling"), espero esto sea útil y no moleste a nadie, pero hay palabras anglosajonas que no tienen su equivalente en el español. Tal vez, con el tiempo, haga un pequeño glosario para los no argentinos.
Los dibujos están hecho en Dia y retocados con TheGimp se pueden
agrandar haciendo un click sobre ellos.
Este documento intenta ser una humilde guía práctica de OpenSSH, así como también un manual de referencia para consultas rápidas. Críticas, preguntas o mejoras son bienvenidas y agradecidas.
Si el segundo número de la versión es distinto a 0 es porque hay cosas no probadas, porque se hace referencia a secciones que todavía no se escribieron o porque hay secciones incompletas. Cuando se agregen nuevas secciones del nivel más alto, el primer número aumentará. Para detalles sobre los cambios en las versiones puede seguir el "Tablero de cambios", en la parte superior de este documento
La jerarquía de títulos es la correspondiente a la etiqueta <h*> del código HTML.
Los nombres de host se escriben en italic. Por ejemplo: imap.utn.edu.ar. Los nombres de los archivos en courier. Por ejemplo: /etc/ssh/sshd_config. Los comandos y salidas de terminales se expresan con letras gruesas blancas sobre fondo negro, y sus comentarios con letras finas. En bold irán las palabras claves o los conceptos que merezcan ser resaltados. Los canales seguros (o sea, encriptados por la sesión SSH) se representan con una flecha de color gruesa. Los números de puertos a los que se hace referencia son todos TCP, a menos que se aclare lo contrario.
Secure Shell es una solución basada en software que mantiene seguros los datos de la red. Muchos usuarios de telnet, rlogin, ftp y otros programas parecidos, no se dan cuenta que sus contraseñas se están transmitiendo sin cifrar a través de la red. SSH cifra todo el tráfico (incluidas las contraseñas) para eliminar de un modo efectivo las "escuchas", los secuestros de las conexiones y otros ataques a nivel de red. Además, SSH ofrece amplias posibilidades para la creación de túneles seguros, aparte de una variedad de métodos de autenticación. Parece cosa de locos, pero Secure Shell no es un shell. No es un interprete, historial de comandos, ni demás.
Pero sí hace cosas muy útiles por la seguridad de un sistema en entornos poco confiables. Algunas "features":
De la página de OpenSSH: «OpenSSH es una versión LIBRE del paquete de herramientas de comunicación segura del protocolo SSH/SecSH para redes, una solución de seguridad que está ganando la confianza de un número cada vez mayor de usuarios de Internet.[...] Está desarrollado principalmente por el Proyecto OpenBSD, y su primera integración en un sistema operativo fue en OpenBSD 2.6. Estos programas se desarrollan fuera de los EE.UU., usando código desarrollado en unos 10 países distintos. Este código es de libre utilización bajo la licencia BSD.
La gestión de la distribución de OpenSSH está dividida entre dos equipos. Un equipo sólo lleva a cabo el desarrollo basado en OpenBSD, y su objetivo es el de producir un código que sea tan limpio, simple y seguro como sea posible. Estamos convencidos de que el sacrificio de la portabilidad en favor de la simplicidad permite un mejor control de calidad y facilita la revisión del código. El otro equipo toma la versión "pura" y la convierte en una versión portable, para que pueda funcionar en muchos otros sistemas operativos (estas versiones se conocen como "versiones p", y se distinguen por nombre como OpenSSH 3.7p1). Esta es la lista de Sistemas Operativos donde OpenSSH está portado:
Esta guía se basará en OpenSSH por ser LIBRE y por que muchos sistemas operativos y productos lo tienen integrado al sistema base. Aunque la mayoría de los conceptos son igual de aplicables a las implementaciones propietarias.
SSH no solo provee un login remoto de manera segura. También permite generar conexiones de servicios inseguros (como ser http, imap, pop entre otros) sobre sesiones de SSH de manera (casi) transparente para ellos. Esto es lo que se llama "Port Forwarding".

Pero... ¿por qué forwardear conexiones?
| Antes
de poner en práctica el forwarding de puertos sugiero leer las implicaciones de seguridad que las distintas
técnicas
conllevan. Si los conceptos ya se conocen la sección "Resumen de Referencia" puede ser útil como ayuda memoria. |
Cuando se genera una sesión SSH se puede hacer que ciertas aplicaciones pasen por el túnel encriptado que se generó. Para las aplicaciones superiores es (casi) transparente y segurizar de esta manera es mucho menos engorroso que levantar una VPN. Pero solo permite que aplicaciones TCP pasen por el túnel, ya que son orientadas a conexión. UDP no maneja sesiones, por lo que este sistema no funciona para servicios como DHCP, NFS, NetBIOS y TFTP entre otros. Tampoco se pueden forwardear protocolos no basados en IP, como AppleTalk o IPX. Para resumir, solo TCP/IP está permitido, como ser: Telnet, HTTP, SMTP, HTTPS (HTTP con encriptación SSL), POP, IMAP, ciertas características de DNS, SSH en sí mismo y FTP, este último con algunas consideraciones /*que explicaré luego(ref!)*/.
Como ejemplo de forwarding voy a usar el servicio de IMAP. La situación es la siguiente: tengo, tras un firewall, un servidor (que llamaremos "imap.utn.edu.ar") de IMAP (corriendo en el puerto 143/tcp) y de OpenSSH (en el 22/tcp). En otra punta de InterNet (atravesando redes inseguras) está mi computadora (que llamaremos home, con conexión y los cliente correspondientes de ambos servicios.

Si yo me conecto directamente tanto el nombre de usuario como la contraseña se transmiten en texto plano. Pero al usar port forwarding la comunicación en su totalidad será encriptada. Cabe aclarar que esto no me dará seguridad para la conexión extremo a extremo de los correos, ya que antes de llegar a mi servidor atravesaron otros servidores, de los cuales desconfío (¿no seré demasiado paranoico?). Si quiero seguridad desde el remitente necesito usar algún sistema como GPG (la implementación GNU de PGP) o algún otra encriptación aplicada desde la generación del correo mismo.
Este método es el más sencillo de entender en un principio. Y es cuando el servidor y el cliente de la aplicación a forwardear son también los extremos de la sesión SSH, como en nuestro caso.
Volviendo al ejemplo, en home tendré que tipear el siguiente comando:
| home:~$ ssh -L 10143:localhost:143 imap.utn.edu.ar |
Analicemos los modificadores (para ver como guardar los parámetros de una sesión consultar "configuración del cliente"(ref: todavía no escrita):
Así, cuando dé "intro", tendré un login en el servidor SSH donde habré de autenticarme. Una vez que me identifique, un shell estará a mi disposición. Ahora tengo que reapuntar mi cliente IMAP hacia la entrada del túnel (es decir, localhost:10143 y no imap.utn.edu.ar:143). Cuando dé la orden de sincronizar mis correos el paquete se dirigirá al puerto 10143 de home, ahí el cliente SSH lo encriptará y lo enviará al servidor SSH en donde los desencriptará y lo mandará a localhost (o sea él mismo) en el puerto 143. De esta manera la comunicación viajará segura.

Veamos algunas pruebas de lo que acabó de pasar (la salida se modificó levemente para facilitar el ejemplo). Estos son lo puertos que se generaron en home:
| home:~$ netstat -na | awk '{ if
(/22/ || /10143/ ) print $0; }' tcp 0 0 127.0.0.1:10143 0.0.0.0:* LISTEN tcp 0 0 home:<RandomPortA> imap.utn.edu.ar:22 ESTABLISHED |
Nótese el puerto 10143 que escucha en localhost y la conexión al 22 de imap.utn.edu.ar. Por otro lado, en el shell que generamos en imap.utn.edu.ar se puede ver que el servidor IMAP y SSH están a la escucha, además de la conexión establecida con home:
| imap:~$ netstat
-an | awk '{ if (
/22/ || /143/ ) print $0; }' tcp 0 0 0.0.0.0:143 0.0.0.0:* LISTEN tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN tcp 0 0 imap.utn.edu.ar:22 home:<RandomPortA> ESTABLISHED Las siguientes linea solo se ven mientras se sincronizan los correos tcp 0 0 127.0.0.1:<RandomPortB> 127.0.0.1:143 ESTABLISHED tcp 0 0 127.0.0.1:143 127.0.0.1:<RandomPortB> ESTABLISHED |
Las dos últimas lineas son la conexión final del servidor a sí mismo.
Algo raro: Si hacemos el túnel con Putty
e intentamos realizar la experiencia de estos netstat antes de que
nuestro
cliente IMAP sincronice los correo no veremos nada, no así
cuando el cliente es OpenSSH, que levanta el puerto junto con la
sesión SSH.
Vayamos complicando el ejemplo. Este es el nuevo escenario: El servidor IMAP no tiene servicio de SSH por alguna razón. Pero puede pasar que el firewall o que alguna otra máquina dentro de mi DMZ tenga servidor de SSH. Así, si mi servicio de IMAP está solo disponible para la red interna puedo usarlo igual, ya que será el una máquina interna quien realice la conexión.
Esta situación sería parecida si lo que quiero es usar el servidor SMTP de mi empresa, cuyo relay está abierto solo a la red interna

A fines prácticos es lo mismo si el servidor SSH está en el firewall o en un host interno. En nuestro ejemplo llamaremos bastion.utn.edu.ar a quien corra el demonio SSH en el puerto 22/tcp. Este sería el comando a correr en home:
| home:~$ ssh -L 10143:imap.utn.edu.ar:143 bastion.utn.edu.ar |
Lo que genera un esquema de conexiones así:

Los primeros pasos de la conexión son muy semejantes a los del caso anterior. El cliente IMAP de home se conecta a localhost:10143 ahí se encripta sobre la sesión SSH hasta bastion.utn.edu.ar. Hasta acá igual, pero esta vez bastion.utn.edu.ar se conecta a imap.utn.edu.ar:143. Este último tramo no será encriptado, por lo que un sniffer en nuestra DMZ verá pasar nuestra clave en texto plano.
Ahora se empieza a poner más lindo. Esto es lo que se conoce como "off-host port forwarding". En mi casa, home es el gateway de una pequeña red hogareña. Tengo dos máquinas más, espiralito y tuxboy. Estas dos máquinas tienen clientes IMAP.

Con mirar el siguiente dibujo se pueden dilucidar algunos evidentes problemas de seguridad. El más obvio es que dos de las tres conexiones son no encriptadas. Pero hay más, la sección "(In)Seguridad en el forwarding" trata estos temas.

| home:~$ ssh -g -L 10143:imap.utn.edu.ar:143 bastion.utn.edu.ar |
El modificador -g permite que tanto tuxboy como espiralito redireccionen sus clientes a home:10143 para entrar en el túnel. Esto también puede hacerse agregando la linea en el archivo de configuración del cliente (el default es "no"):
| ~/ssh/ssh_config GatewayPorts yes |
En todos nuestros casos en modificador que usamos fue -L para Forwarding Local. Pero existe otro tipo de forwarding, menos usado: Forwarding Remoto. Sería algo parecido a lo que es el Call-Back en un servidor dial-up.
El Forwarding Remoto es igual al Local, pero al revés. El servidor de la aplicación es quien inicia la sesión SSH hacia el cliente de la aplicación. Veamos el esquema de nuestro ejemplo:

Si estubieramos logueados en imap.utn.edu.ar, y home fuese "resolvible" (que se puede resolver a una IP, sino hay que poner la IP) por él, se puede generar el túnel inverso así:
| imap:~$ ssh -R 10143:localhost:143 home |
Las opciones tienen una interpretación levemente diferente:
| Si el servidor es OpenSSH (debería ;-)) soporta la opción GatewayPorts y se aplica globalmente a todos los forwarding remotos establecidos por él.(check!) |
Al principio puede ser algo confuso, o simplemente no entender en que situación usar cual. Esta puede ser una buena regla práctica:
De entrada el forwarding remoto puede parecer inútil, pero hay casos en donde puede sacarnos las papas del fuego. En el Apéndice I se puede leer acerca de un caso de estudio puntual con MS Windows, pero es cuestión de imaginación para crear nuevos escenarios útiles.
El forwardeo de sistemas X es todo un tema aparte. Por el momento espero sirva esto:
| ssh -X <usuario>@<host> |
Si me deslogueo de la sesión que generó el túnel! guarda con ventanas cortas.(como http adif de SSH)
Para generar un túnel TCP/IP sobre la sesión SSH primero hay que abrir la sesión. Después de la autenticación el cliente nos dará un shell para correr comandos en el host remoto. La opción -f
Me cansé de decirlo: El forwarding puede ser inseguro, por eso se debe estar consiente de que se provoca cuando se levanta un túnel y como solucionar estos problemas según el entorno donde se lo aplicó. Incluso si en un entorno no se usa Forwarding es bueno leer esta sección, sobre todo el primer punto. A continuación se enumerarán los casos y consejos, si leyendo se te ocurren otro podes mandármelos para agregarlos a la lista
Primero lo primero, puede que como sysadmins no queramos que se haga forwarding en los servidores de nuestra DMZ. Deshabilitar el forwarding si no se usa debería ser lo segundo después de prohibir el acceso de root por SSH. Por otro parte, si solo usas tu servidor SSH para correr shells, te recomiendo que también lo deshabilites, ya que si alguna cuenta de usuario está comprometida pueden utilizarte de trampolín para otros ataques a tu red o a otra.
| ~/ssh/sshd_config AllowTcpForwarding no |
En casos de forwarding off-host se hizo referencia a la inseguridad en ciertos tramos de la conexión end-to-end. Si no se confía en las redes internas de las puntas y el servidor o cliente final no tienen SSH, entonces el túnel puede no dar toda la seguridad que se pretende. En este caso hay dos opciones:
De cualquier manera que siempre será más seguro usar forwarding que no usarlo, pero estar consiente de los tramos no encriptados nos ayudará a evitar una falsa sensación de seguridad.
Cuando abrimos un túnel se abre un puerto en localhost. Este puerto puede ser accedido por cualquier usuario con cuenta en el equipo. En la mayoría de los casos esto no es un problema, o porque la aplicación forwardeada tiene su propio sistema de autenticación o porque los usuarios del sistema suelen ser una cantidad manejable.
¡Este es un problema terrible para el forwarding
off-host! Cuando habilitamos la opción GatewayPorts (o su equivalente -g) estamos levantando un nuevo
puerto en nuestro host. Veamos este netstat
de home.utn.edu.ar, cliente
de la sesión SSH iniciada con -g:
| home:~$ netstat
-an | grep 10143 tcp 0 0 *.10143 *.* LISTEN |
Importantísimo recalcar el asterisco (*), ya que significa que está escuchando en todas las interfaces.Es decir cualquiera puede usar este puerto para conectarse al servidor imap.utn.edu.ar conectándose a la IP de home en su puerto 10143. Basca con imaginarse que, por ejemplo, se esté forwardeando smtp. ¡Se dejaría un relay abierto para el mundo!
La solución es un filtro de puertos en home, lo que sería más que lógico teniendo en cuenta que es un host en el borde de nuestra red. En las reglas hay que poner que no se permiten conexiones desde InterNet a los puertos altos.
Resumen del uso del forwarding. (a completar)
| ~/ssh/sshd_config SyslogFacility AUTH LogLevel INFO |
Para que root no pueda loguarse a través de una sesión SSH hay que deshabilitar esta opción, así los usuarios tendrán que hacer su para ejecutar comandos con privilegio.:
| ~/ssh/sshd_config PermitRootLogin no |
En host_destino hay que permitir X Forwarding
| ssh -X <host_destino> |
Cuando solo se quiere ejecutar un comando sin necesidad de un shell interactivo.
| ssh <user>@<host_destino> <comando> |
PuTTY es un cliente de SSH/Telnet para plataformas MS Windows de 32 bits, creado por Simon Tatham de Gran Bretaña. Es bastante intuitivo de usar y, además, es libre (licencia MIT, similar a la BSD).
Esta sección no intenta llegarle ni a los talones a la documentación oficial pero sí intenta ser una referencia para casos puntuales. Los screenshots son de la versión 0.53b, la última a la fecha de escritura de esta sección.
En la sección "Tuneleando conexiones" se explico la teoría de su funcionamiento y su uso en el cliente de OpenSSH. Con PuTTY se puede hacer forwardeo de puertos TCP/IP y de X desde la opción Connection -> SSH -> Tunnels. Este panel se divide en dos: "X11 forwarding" y "Port forwarding".

Los números rojos son para luego hacer referencia a esas partes de la pantalla durante la explicación, poniendolo [entre corchetes]. Por ejemplo: [1] para referirse al checkbox de "Enable X11 forwarding".
Veamos como hacer forwarding de secciones TCP/IP, cuya teoría se explicó aquí. Se aplicará el mismo ejemplo del servicio IMAP que se usó anteriormente, con la única diferencia que ahora home es un Win32, cosa que nunca pasará ;-).
Para un forwarding local hay que seleccionar la opción [10] (para forwarding remoto la opción es la [11]), colocar el puerto donde el tunel empieza en [7] (donde hay que redirigir el cliente IMAP, para nuestro ejemplo) y en [9] el servidor de imap seguido de dos puntos y el puerto. Queda algo así:

Después, con el botón [8], se lo agrega en la lista de
puertos a forwardear [6]. Se lo pueden agregar múltiples puertos
para forwardear en una sesión. Incluso algunos pueden ser
locales y otros remotos. Si queremos borrar alguno se lo selecciona de
la lista [6] y con el botón [5] se lo borra. Cuando esten todos
por puertos (y si completamos la opción "Session" con los datos
del servidor SSH) se puede dar la opción "Open" y el túnel
quedará formado. Todas estas opciones pueden guardarse en
"Session".
Resulta que por esas vueltas del destino tengo un Internet Information Server en una red privada con un desarrollo web para un cliente de la empresa a la cual trabajo. Este servidor es de pruebas y no está público en InterNet, pero necesito mostrarle las versiones beta del desarrollo al cliente en cuestión, quien es inteligente y tiene un Unix-like (en este caso es un FreeBSD) en su red. ¿Cómo puede ayudarme el forwarding del PuTTY?
Si en mi servidor web pongo el PuTTY (no necesita instalación ni privilegios de administrador) puedo generar un forwarding remoto contra el servidor de SSH que tiene el cliente. De esta manera él se conecta a su servidor en el puerto forwardeado y entra en el tunel que da a mi puerto 80. Sin VPN ni ambientes complejos, todos gracias a un programita de menos de 350 K.
| Ver. 0.4 Luciano Bello luciano (arr@ba) linux.org.ar La última versión está disponible en http://www.lucianobello.com.ar/openssh/ |
![]() |