Lo hice y lo entendí

El blog de Vicente Navarro
13 jun

Reenvío dinámico de puertos / montar un servidor SOCKS con SSH

En la entrada anterior, Creando túneles TCP/IP (port forwarding) con SSH: Los 8 escenarios posibles usando OpenSSH, vimos todas las posibilidades que tenemos a nuestra disposición para el reenvío de puertos (port forwarding)… pero para el reenvío de puertos estático. Es decir, allí sólo vimos casos en los que queríamos acceder únicamente a un puerto de otro sistema encauzándolo por dentro de la conexión SSH.

Sin embargo, en aquella entrada nos dejamos en el tintero el reenvío dinámico de puertos y varios lectores lo echaron de menos, de modo que esta entrada tratará de complementar a aquélla (muchas gracias a todos por la sugerencia).

Cuando hablamos de hacer dynamic port forwarding con SSH, de lo que estamos hablando exactamente es de convertir el SSH en un servidor SOCKS. ¿Y qué es un servidor SOCKS?

¿Sabes para qué sirve un proxy web? Probablemente sí, muchas empresas usan uno. Se trata de un sistema directamente conectado a Internet que permite que los clientes de una intranet sin acceso a Internet puedan navegar por la web si configuran sus navegadores para que hagan sus peticiones a través del proxy (aunque también hay proxies transparentes). Un proxy web, además de permitir la salida a Internet, también cacheará las páginas, imágenes, etc. ya descargadas por algún cliente para no tener que descargarlas para otro cliente. Además, permite filtrar los contenidos y monitorizar la actividad de los usuarios. Sin embargo, su función básica es la de reenviar tráfico HTTP y HTTPS.

Un servidor SOCKS le daría un servicio similar a la intranet de una empresa que el que proporciona un servidor proxy pero no está limitado a HTTP/HTTPS, sino que permite reenviar cualquier trafico TCP/IP (con SOCKS 5 también UDP).

Por ejemplo, imaginemos que queremos usar nuestro correo usando POP3 o ICMP y SMTP con Thunderbird desde una intranet sin acceso directo a Internet. Si sólo tenemos un proxy web disponible, la único sencillo que nos quedaría sería usar algún webmail (aunque si es un webmail también podríamos usar la extensión Webmail de Thunderbird). También podríamos aprovecharnos del proxy montándonos un túnel por HTTP. Pero lo más sencillo sería que la red tuviera un servidor SOCKS disponible que nos permitiera usar POP3, ICMP y SMTP a través de él sin ningún inconveniente.

Aunque hay mucho software para configurar servidores de SOCKS muy especializados, montar uno con OpenSSH podría ser tan sencillo como:

clientessh $ ssh -D 1080 usuario@servidorssh

o podríamos mejorarlo un poco con:

clientessh $ ssh -fN -D 0.0.0.0:1080 usuario@servidorssh

Donde:

  • La opción -D es similar a las opciones -L y -R del reenvío estático de puertos. Como aquéllas, con esta podemos hacer que el cliente escuche sólo las peticiones locales o las que lleguen desde otros nodos, dependiendo de a qué dirección se asociemos la petición:

    -D [bind_address:]port

    Mientras que en el reenvío estático de puertos vimos que podíamos hacer reenvío inverso de puertos con la opción -R, con el reenvío dinámico no es posible. Sólo podemos crear el servidor SOCKS en el lado del cliente SSH, no en el lado del servidor SSH.

  • 1080 es el puerto típico de los servidores SOCKS, igual que el 8080 es el típico de los servidores proxy web.

  • La opción -N evita que realmente se lance una sesión interactiva de shell remota. Es útil cuando sólo hacemos el ssh para establecer este túnel.

  • La opción -f hace que el ssh se quede en segundo plano y se desasocie de la shell actual, de modo que el proceso se convierte en un demonio. No funciona sin la opción -N (o sin especificar un comando), ya que de otro modo habría una shell interactiva incompatible con que el proceso esté en segundo plano.

Usando PuTTY también es muy sencillo redirigir puertos. El equivalente a un “ssh -D 0.0.0.0:1080” sería usar esta configuración:

PuTTY SOCKS

Para que una aplicación pueda acceder a otra red a través de un servidor SOCKS, es conveniente (aunque no necesario) que la aplicación lo soporte específicamente, al igual que los navegadores soportan usar un servidor proxy. Los navegadores, como Firefox o Internet Explorer, son ejemplos de aplicaciones preparadas para usar un servidor SOCKS para acceder a otra red:

Firefox SOCKS

Internet Explorer SOCKS

Nota: La captura ha sido obtenida usando IEs 4 Linux: ¡Muy recomendable si necesitas Internet Explorer y usas Linux!

Sin embargo, no son precisamente los navegadores los que más suelan precisar un servidor SOCKS, ya que normalmente se arreglan mejor con el servidor proxy.

Pero por ejemplo, el Thunderbird también lo permite y eso sí que es útil:

Thunderbird SOCKS

Otro ejemplo: el cliente de Spotify soporta también SOCKS:

Spotify SOCKS

Algo a tener en muy cuenta es la resolución de nombres. A veces nos encontraremos que en la red actual no podemos resolver los nombres de los sistemas a los que queremos acceder del otro lado del servidor SOCKS. SOCKS 5 nos permite también tunelizar las peticiones DNS (como es UDP el SOCKS 5 nos lo permite) y enviarlas al otro extremo: Es posible especificar si queremos resolver localmente o remotamente (o tal vez probar ambos). Las aplicaciones que soporten esto también tienen que tener esto en cuenta. Por ejemplo, Firefox tiene el parámetro network.proxy.socks_remote_dns (en el about:config) que nos permite especificar que se resuelva remotamente. Por defecto se resuelve localmente.

Thunderbird también soporta el parámetro network.proxy.socks_remote_dns, pero como no tenemos una barra de direcciones donde poner about:config, podemos cambiarlo, como leemos en MozillaZine: about:config, en Tools → Options → Advanced → General → Config Editor (button).

Las aplicaciones que no soporten específicamente SOCKS las podemos “socksificar”. Esto funcionará bien con muchas aplicaciones que usen TCP/IP sin problemas, pero no con todas. “socksificar” consiste en cargar una librería adicional que detecte peticiones a la pila TCP/IP y modificarlas para redirigirlas a través del servidor SOCKS, de forma que la comunicación vaya por él sin que la aplicación se haya tenido que programar específicamente con soporte de SOCKS.

Hay “socksificadores” para Windows y para Linux.

Para Windows tenemos por ejemplo el SocksCap, un producto cerrado pero gratuito para uso no comercial que yo he usado muy satisfactoriamente durante mucho tiempo. El SocksCap lo hacía una empresa llamada Permeo que fue la empresa que creó la tecnología de referencia de SOCKS. Permeo fue comprada por Blue Coat y ésta descontinuó el SocksCap. Aún se puede encontrar muy bien buscando el archivo sc32r240.exe en Internet. También para Windows, y de código libre, existe el FreeCap, de apariencia y uso muy, muy parecido al SocksCap. Sin embargo, funciona bastante peor y lleva años sin mantenimiento. Parece que su autor ha preferido dedicar sus esfuerzos a un nuevo producto esta vez de pago, el WideCap.

Este es el aspecto del SocksCap cuando hemos “socksificado” varias aplicaciones. Estas aplicaciones accederán a la red a través del servidor SOCKS cuando las lancemos desde aquí:

SocksCap

En el diálogo de configuración veremos que si elegimos el protocolo SOCKS 5, podemos elegir dónde se tienen que resolver los nombres, localmente o remotamente:

SocksCap settings

En Linux, como siempre, tenemos muchas alternativas a un sólo comando de distancia. En Debian/Ubuntu, la salida del comando:

$ apt-cache search socks

nos mostrará muchas de ellas

Las más conocidas para mí son el tsocks y el proxychains. Funcionan de forma muy parecida: Sólo hay que lanzar la aplicación que queremos “socksificar” con ellas y ya está. Un ejemplo usando proxychains y wget:

$ proxychains wget http://www.google.es
ProxyChains-3.1 (http://proxychains.sf.net)
--19:13:20--  http://www.google.es/
Resolving www.google.es... 
|DNS-request| www.google.es
|S-chain|-<>-10.23.37.3:1080-<><>-4.2.2.2:53-<><>-OK
|DNS-response| www.google.es is 72.14.221.147
72.14.221.147
Connecting to www.google.es|72.14.221.147|:80... 
|S-chain|-<>-10.23.37.3:1080-<><>-72.14.221.147:80-<><>-OK
connected.
HTTP request sent, awaiting response... 200 OK
Length: unspecified [text/html]
Saving to: `index.html'

    [  <=>                                                       ] 6,016       24.0K/s   in 0.2s

19:13:21 (24.0 KB/s) - `index.html' saved [6016]

Para que esto funcione, hay que especificar el servidor proxy que queremos usar en /etc/proxychains.conf:

[ProxyList]
socks5 clientessh 1080

También podemos decirle que las peticiones de DNS se hagan remotamente:

# Proxy DNS requests - no leak for DNS data
proxy_dns

Además, en la salida anterior, hemos visto varios mensajes informativos propios del proxychains, no de wget en líneas marcadas con las cadenas |DNS-request|, |S-chain| o |DNS-response|. Si no quisiéramos verlos, también podemos ajustarlo en la configuración:

# Quiet mode (no output from library)
quiet_mode

:wq

Entradas relacionadas

7 Comentarios a “Reenvío dinámico de puertos / montar un servidor SOCKS con SSH”

  • alidhaey dice:

    Completo artículo, ya no te podremos dar la vara diciendo que te falta algo.

    Un saludo.

  • inedit00 dice:

    Muy buen articulo. Increible todas las posibilidades de OpenSSH.
    Para continuar con la saga de SSH el siguiente artículo podría ser sobre SSHFS.

    A seguir asi! Un saludo.

  • Andrés Pemán dice:

    Buen artículo.

  • Ringmaster dice:

    ¡Gracias por no abandonarlo de todo! Siempre es agradable leer una mente tan preclara como la tuya… ;-)

    Por otro lado, he visto que, para evitar trabajo extra, las entradas se cierran a los comentarios pasados un mes o dos de su publicación… ¿no? Porque en la entrada sobre la resolución de 2 seg. del FAT no he podido, jeje

    Un saludo!

    • ¡Muchas gracias! ;-)

      Y sí, me temo que como no puedo prestar suficiente atención a los comentarios he preferido que se cierren solos al cabo de un tiempo. No es lo que más me gusta, pero prefiero que sea así que que haya multitud de comentarios sin atender :-(

Trackbacks y pingbacks:

Tema LHYLE09, creado por Vicente Navarro