Mostrando entradas con la etiqueta socat. Mostrar todas las entradas
Mostrando entradas con la etiqueta socat. Mostrar todas las entradas

lunes, octubre 26, 2015

Tunelizar UDP con ssh y socat

Tunelizar UDP con ssh y socat

Hoy me he encontrado con un pequeño problema: Quería mandar un syslog (UDP) sobre Internet a una máquina EC2 con la cual estaba haciendo pruebas en Amazon. Es cierto que podía montar una VPN con OpenVPN o usar stunnel, pero la verdad, no me apetecía estar montando certificados y quería algo rápido. La solución por la que opté fue usar socat para encapsular el tráfico UDP sobre TCP, un reenvío TCP sobre ssh para mandar los datos a la instancia EC2 en Amazon encriptados sobre el canal ssh y de nuevo socat para desencapsular los datos del flujo TCP y lanzarlos sobre el puerto UDP local.

El escenario del que parto es el siguiente:

  • Tengo configurado el daemon de syslog para que mande todo lo que recibe al puerto 5000 de la máquina a través de UDP
  • Voy a redirigir el puerto de la máquina local 4000 al puerto 4000 de la máquina en EC2 a través de un túnel ssh
  • En la máquina local, todo lo que se reciba con protocolo UDP al puerto 5000 se encapsular sobre un flujo TCP y se redirigirá a través del puerto 4000 que es donde está escuchando la redirección de puertos local.
  • En el extremo EC2 todo lo que reciba por el puerto TCP 4000, se dirigirá al puerto UDP 514, que es el syslog daemon local.
  • A modo de ejemplo, asumo que la IP de la máquina de Amazon remota es 10.11.12.13

Para que funcione correctamente hay que dar los siguientes pasos y en orden:

  1. Establecer el tunel TCP con el reenvio de puertos en la máquina local
    $ ssh -L 4000:localhost:4000 -i clave_secreta.pem -l root 10.11.12.13
  2. Realizar con socat la redirección del puerto 4000 TCP al puerto 514 UDP en el servidor EC2
    $ socat -4 TCP-LISTEN:4000 UDP:localhost:514
  3. Por último, en nuestra máquina local, mandar los datagramas UDP que recibimos por el puerto 5000 a través del túnel
    $ socat -4 UDP-LISTEN:5000 TCP:localhost:4000

Decir que en este caso concreto, syslog, podría simplemente no usar UDP y aprovechar las conexiones TCP que también soporta dicho daemon para tunelizar vía ssh directamente los datos, pero trataba de poner un ejemplo de esa encapsulación UDP sobre TCP con socat y ssh.

Otra manera de hacer esta redirección, suponiendo que tengamos credenciales de root en las dos máquinas es esta que me apunta sntg_boff: Se aprovecha las posibilidades de ssh para establecer el túnel TUN/TAP y mandar los datos sobre ssh.

miércoles, junio 24, 2015

Tutorial de socat (I)

socat es una utilidad que permite establecer una comunicación bidireccional entres dos canales. El canal de comunicación puede ser pipes, sockets tcp o udp, conexiones raw, líneas serie o sockets en el sistema de ficheros. Es una navaja suiza para transmitir flujos de bytes.

Cuando se compila socat intentará utilizar las librerias OpenSSL, readline y libwrap si están presentes en el sistema. Para detectarlas se usa el script de configure. En caso de no querer usarse, existen una serie de opciones de configure (--disable-openssl, --disable-readline, --disable-libwrap) para desactivar su uso. Puede verse más información en el README que acompaña al código fuente del programa. Puede compilarse de manera sencilla con:

# Descargar la última versión disponible
# de socat/download
wget http://www.dest-unreach.org/socat/download/socat-1.7.3.0.tar.gz
# Comprobar al suma md5
# (consultar aquí las actuales)
# En el caso del fichero  socat-1.7.3.0.tar.gz es de46e3f726f783271226eb94d5109bf8
md5sum socat-1.7.3.0.tar.gz
# Descomprimir, compilar e instalar
tar zxvf socat-1.7.3.0.tar.gz
cd socat-1.7.3.0
./configure --prefix=/usr/local
make
# Como root instalar
make install

Si el proceso de compilación e instalación terminan correctamente los binarios del programa se habrán instalado en /usr/local/bin.

Para usar el programa:

socat [opciones] [addr0] [addr1]

Tras ejecutar la orden:

  • Analizará las opciones de la línea de comandos.
  • Abrirá los canales de comunicación indicados por las especificaciones de dirección addr0 y luego addr1
  • Pasará la información entre los canales abiertos.

Las especificaciones de dirección tiene la forma de CLAVE:opciones,[opciones,...]: Una palabra clave separada por ":" y las opciones que necesite dicha dirección separada por ",". Ejemplo TCP-LISTEN:5000 va a abrir un puerto TCP en escucha en el puerto 5000, STDOUT o "-" va a usar la salida estándar , TCP:host:port se va a conectar a través de TCP a host:port. Con estos comandos se puede probar la comunicación.Se va a usar dos procesos de socat: uno lee de la entrada estándar, lo envía a través del puerto 5000 TCP a localhost y otro escucha las conexiones, recibe la información y la imprime.

# El servidor
socat -u TCP-LISTEN:5000 STDOUT
# El cliente
socat -u STDIN TCP:127.0.0.1:5000

En el ejemplo anterior, se usa la opción -u porque queremos una comunicación unidireccional desde la addr0 (el socket, la entrada estándar) hacía la otra dirección. Si quisiéramos una comunicación bidireccional, tb se podría hacer, pero ahora vamos a usar STDIO como sustituto de STDION y STDOUT y eliminado la opción -u. Se arranca de nuevo el server, y con independencia de la terminal en la que se escriba, podemos transmitir información entre las dos ventanas.

Como se están usando sockets TCP para la comunicación, cuando el proceso que está escuchando se para, automáticamente termina el proceso hijo.

Otro ejemplo: Supongamos que se desea tener un fichero de logs, por ejemplo, /var/log/system.log (en OS X, este fichero necesita permisos de admin para verse) disponible en un puerto de TCP para poder ver su contenido. Para ello se arranca un server en el puerto 5000 que volcará el contenido y un cliente que leerá el fichero desde el final y lo mandará al server

# El servidor
socat -u TCP-LISTEN:5000 STDOUT
# El cliente socat -u OPEN:/var/log/system.log,rdonly=1,seek-end=0,ignoreeof TCP:localhost:5000

Se abriendo el fichero (OPEN:/var/log/system.log), como sólo lectura (rdonly=1), posicionándose al final del mismo (seek-end=0) e ignorando el fin del fichero (ignoreof). Los datos que se leen se están mandando por TCP a localhost:5000. Básicamente esta orden es el equicalente a un tail -f a través de red en el puerto 5000. Puede verse en la siguiente captura su uso - y algunos errores de las pruebas ;) -.