Comando socat: relays, túneis e TLS no Linux

Terminal com o comando socat a ligar dois endereços — um TCP-LISTEN e um TCP — num laboratório de rede

Chegar a um serviço que só escuta na rede interna, ver o que uma aplicação envia, cifrar um protocolo antigo: três problemas, uma ferramenta. O socat (SOcket CAT) liga quaisquer dois «endereços» — o teclado, uma ligação TCP ou UDP, um socket UNIX, um ficheiro, um programa, uma porta série, o TLS — e copia os bytes entre eles, nos dois sentidos. Há quem lhe chame o netcat com esteroides.

Seguimos a ordem do vídeo e fechamos com o ângulo defensivo. Regra para tudo o que se segue: use o socat só em sistemas seus ou com autorização explícita.

Veja o guia em vídeo

Prefere ver antes de experimentar? No canal HJFR-IT no YouTube mostramos o socat opção a opção, com o resultado de cada comando no ecrã — narrado em português e com legendas.

socat — o canivete suíço dos sockets: relays, túneis e listeners — canal HJFR-IT no YouTube. Se o áudio não arrancar em português, abra as definições do vídeo (ícone da roda dentada) → Faixa de áudio → Português.

O que faz o socat

Damos-lhe dois endereços; abre ambos e copia o que chega a um para o outro, nos dois sentidos, até um lado fechar. Cada endereço tem um tipo, parâmetros e, após vírgulas, opções; antes deles vêm as opções globais.

socat [opções-globais] ENDEREÇO1 ENDEREÇO2
ENDEREÇO = TIPO:parâmetros[,opção[,opção=valor]...]

$ socat - TCP:srv-web01:80       # teclado ↔ porta 80

O - é atalho para STDIO. A lista completa de tipos e opções sai de socat -hhh.

Opções globais: ver, cronometrar e registar

  • -v e -x — escrevem no stderr tudo o que passa, em texto ou em hexadecimal. Poupam horas.
  • -d, até quatro vezes — avisos, notas (-d -d, o recomendado), informação e depuração; -D mostra os descritores; -lf FICHEIRO grava o registo.
  • -u/-U — modo unidirecional, só num sentido.
  • -t SEG — espera depois de um lado fechar; -T SEG — tempo máximo de inatividade.
  • -b (bloco), -s (sloppy), -4/-6 (IPv4 ou IPv6) e -L/-W (ficheiros de bloqueio).

Endereços de fluxo e redirecionamento de portas

A primeira família é a dos endereços orientados à ligação: STDIO, TCP e TCP-LISTEN (variantes TCP4/TCP6), UNIX-CONNECT e UNIX-LISTEN, SCTP e — os mais importantes para nós — OPENSSL e OPENSSL-LISTEN, TCP dentro de TLS.

O uso clássico é o redirecionamento de portas: o socat escuta na 8080 e encaminha cada ligação para a porta 80 interna. Essenciais: fork, um processo filho por ligação, e reuseaddr, que deixa reiniciar o serviço sem esperar pela porta. Com -v, o mesmo relay vira proxy de depuração.

$ socat TCP-LISTEN:8080,fork,reuseaddr TCP:10.0.0.20:80 &
$ curl -s http://localhost:8080/ | head -1
$ socat -v TCP-LISTEN:9000,fork,reuseaddr TCP:10.0.0.30:80   # proxy de depuração

Transferir ficheiros

Com -u, o socat serve um ficheiro numa porta e o outro lado grava-o com creat — um scp sem SSH, cifrado se trocar TCP por OPENSSL.

aluno@hjfr:~$ socat -u FILE:backup.tar.gz TCP-LISTEN:9100,reuseaddr
aluno@srv-web01:~$ socat -u TCP:192.0.2.25:9100 OPEN:backup.tar.gz,creat
$ sha256sum backup.tar.gz        # o mesmo valor dos dois lados

Datagramas e sockets UNIX

A segunda família trata datagramas e sockets de baixo nível: UDP, UDP-LISTEN, as variantes UDP-SENDTO, UDP-RECVFROM, UDP-RECV e UDP-DATAGRAM (broadcast e multicast), datagramas UNIX, sockets abstratos do Linux, IP em bruto e o genérico SOCKET. Em UDP não há ligação: o UDP-LISTEN responde ao remetente do último pacote, e o multicast serve a descoberta de serviços.

$ socat UDP-LISTEN:9200,fork PIPE &               # eco UDP
$ echo "olá por UDP" | socat - UDP:127.0.0.1:9200

# multicast: juntar-se ao grupo 239.1.1.1 na eth0
$ socat -u UDP4-RECV:5000,ip-add-membership=239.1.1.1:eth0 -

Os sockets UNIX servem bases de dados ou o Docker; a ponte para TCP é clássica, mas expor o /var/run/docker.sock dá acesso de root a quem lá chegar.

$ socat UNIX-LISTEN:/tmp/eco.sock,fork PIPE &
$ echo olá | socat - UNIX-CONNECT:/tmp/eco.sock

Programas, ficheiros e terminais

A terceira família liga o socat a programas e ficheiros. EXEC corre um programa diretamente, sem shell — mais rápido e seguro; SYSTEM entrega a linha a uma shell, com pipes e variáveis e o risco correspondente. Há ainda PTY, PIPE (eco), OPEN, CREATE e GOPEN (sockets e FIFO incluídos), FD e READLINE.

Um programa interativo precisa de pty no EXEC — sem pseudoterminal, vi ou sudo portam-se mal —, além de stderr, setsid e sigint. Já o PTY com link deixa um atalho no sistema de ficheiros: a forma mais simples de partilhar uma porta série pela rede.

$ socat -,raw,echo=0 EXEC:top,pty,stderr,setsid,sigint,sane
$ socat -u GOPEN:/var/log/nginx/access.log,ignoreeof -     # como tail -f
$ socat TCP-LISTEN:8000,reuseaddr,fork SYSTEM:'echo HTTP/1.0 200 OK; echo; echo olá'

aluno@srv-web01:~$ socat TCP-LISTEN:4001,reuseaddr FILE:/dev/ttyUSB0,b115200,raw,echo=0
aluno@hjfr:~$ socat PTY,link=/tmp/ttyV0,raw,echo=0 TCP:192.0.2.10:4001

Variantes: SCTP-LISTEN/SCTP-CONNECT funcionam como os TCP; para IPv6, TCP6 ou o global -6; e bind fixa o endereço local, essencial com várias interfaces.

Proxies, túneis e reconexão

A quarta família atravessa proxies e cria túneis: SOCKS4/SOCKS4A passam por um servidor SOCKS, PROXY usa o HTTP CONNECT dos proxies empresariais, TUN cria uma interface de rede virtual e INTERFACE dá acesso aos pacotes de uma placa.

$ socat - PROXY:10.0.0.3:ssh.example.org:22,proxyport=3128,proxyauth=aluno:"$PROXY_PASS",retry=5,interval=2

# VPN de laboratório: uma interface TUN em cada ponta, dentro de TLS
aluno@hjfr:~$ sudo socat OPENSSL-LISTEN:4443,cert=lab-server.pem,cafile=lab-client.crt TUN:10.9.0.1/24,up
aluno@srv-web01:~$ sudo socat OPENSSL:192.0.2.25:4443,cert=lab-client.pem,cafile=lab-server.crt,commonname=lab-server TUN:10.9.0.2/24,up

O proxyauth passa as credenciais (visíveis no ps, cuidado), o resolve decide quem resolve o destino e retry, interval e forever repetem uma ligação falhada — o que torna um túnel resistente a quebras. No TUN, up ativa a interface e um ping 10.9.0.1 já viaja dentro do TLS.

Opções de endereço

Para escutar e aceitar, além de fork, reuseaddr e bind, há range (só clientes de uma rede), tcpwrap (respeita o hosts.allow e o hosts.deny), backlog e max-children.

$ socat -d -d TCP-LISTEN:7000,bind=10.0.0.5,range=10.0.0.0/24,fork,reuseaddr PIPE
... W refusing connection from AF=2 10.0.8.15:50412 due to range option

Há ainda ctty no EXEC, append, nonblock e cool-write em ficheiros e as termios raw e echo=0. As opções seguem o endereço separadas por vírgulas; se o comando de um EXEC tiver uma vírgula, proteja-a, senão o socat lê-a como separador (unknown option). No socat 1.8 do Debian 13 confirmámos que duplicá-la não chega; use \, ou aspas:

$ socat - 'EXEC:"sort -t, -k2"' < vendas.csv
$ socat - 'EXEC:sort -t\, -k2',stderr < vendas.csv

TLS com OPENSSL: certificados e autenticação mútua

As opções TLS: cert (certificado e chave num PEM, obrigatório no servidor), key (chave à parte), cafile/capath (autoridades em que confiamos), verify (validação do outro lado, ligada por omissão), commonname (nome exigido) e cipher, dhparams, compress e method para afinar.

$ openssl req -new -x509 -newkey rsa:2048 -nodes -keyout lab-server.key \
    -days 365 -subj "/CN=lab-server" -out lab-server.crt
$ cat lab-server.key lab-server.crt > lab-server.pem    # formato do cert=

$ socat OPENSSL-LISTEN:8443,reuseaddr,fork,cert=lab-server.pem,verify=0,dhparams=dh2048.pem,cipher=HIGH:!aNULL,min-version=TLS1.2 TCP:10.0.0.20:80 &
aluno@srv-web01:~$ socat - OPENSSL:hjfr:8443
... W SSL_connect(): error:0A000086:SSL routines::certificate verify failed
aluno@srv-web01:~$ socat - OPENSSL:hjfr:8443,cafile=lab-server.crt,commonname=lab-server

O servidor dá a sua identidade com cert; o verify=0 dispensa apenas o certificado do cliente. Os parâmetros Diffie-Hellman garantem sigilo futuro, e cipher e min-version recusam cifras fracas e versões antigas (no Debian 13, method deu lugar a min-version). O primeiro erro do cliente é boa notícia — a validação funciona; com o certificado do servidor no cafile, passa.

Na autenticação mútua, o servidor exige também o certificado do cliente (cafile=lab-client.crt,verify=1) e o cliente apresenta o seu com cert=lab-client.pem; quem não o tiver é recusado no handshake. E o nome importa: o socat compara o nome do certificado com o anfitrião (commonName does not match hostname), e o commonname impõe outro. Com -x, uma sessão em claro mostra tudo legível; por TLS, só registos cifrados.

socat em cibersegurança

Dupla utilização, só com autorização. O socat que cifra um protocolo antigo serve também a quem queira manter acesso a uma máquina. O vídeo distingue dois padrões: na bind shell, a máquina comprometida abre uma porta à escuta, que uma firewall de entrada trava; na shell reversa, é ela que liga para fora, contornando as regras de entrada. Com TLS, o canal escapa à deteção por conteúdo — na defesa, interessa o rasto, não a receita.

Detetar pelo processo, não pelo conteúdo. O sudo ss -tlnp mostra as portas à escuta e o processo dono: um socat numa porta que ninguém pediu é alarme (Send-Q 5 é o backlog por omissão). O sudo lsof -nP -c socat -a -i junta as ligações de saída e o utilizador, e o ps --forest revela um socat com uma shell como filho. Restrinja e registe o tráfego de saída.

Responder sem destruir provas. Antes de terminar o processo, registe as saídas, guarde o /proc/<PID>/cmdline, capture memória e tráfego e só depois isole a máquina — um canal em claro pode revelar comandos e credenciais.

Experimente no simulador interativo

O simulador recria a máquina de laboratório hjfr (192.0.2.25 e 10.0.0.5). À esquerda, os dois endereços em cartões, as opções em etiquetas e o fluxo de bytes entre eles; por baixo, os sockets da máquina, com duas linhas a laranja que ninguém lançou. No terminal, as linhas com barra dourada são o outro lado da ligação. Demonstrar tudo percorre os exemplos pela ordem do vídeo, Anterior/Seguinte avançam ao seu ritmo e Repor estado volta ao início.

Erros comuns e boas práticas

  • Esquecer o pty: programas interativos portam-se mal. Junte pty, stderr e setsid.
  • Caracteres a dobrar no ecrã: falta -,raw,echo=0 no terminal.
  • A porta presa (Address already in use): resolve-se com reuseaddr.
  • Deixar verify=0 no cliente: deita fora a confiança do TLS. Use cafile e confirme o nome.
  • Esquecer o fork: o servidor morre após o primeiro cliente; e um fork esquecido deixa o listener aberto.
  • Vírgulas no EXEC: proteja-as com \, ou aspas e prefira EXEC a SYSTEM.

Conclusão

O socat resume-se a uma ideia — dois endereços ligados — e daí saem relays, redirecionamento de portas, cópias de ficheiros, ecos UDP e UNIX, portas série, túneis e TLS com autenticação mútua. Escreve-se mais do que o netcat (nc), mas faz muito mais. Use-o só onde tem autorização e confira com o comando ss o que fica à escuta. Para o acesso remoto do dia a dia, continua a valer o ssh e scp.

Workshop — Linha de Comandos Linux

Quer passar da leitura à prática, com exercícios reais e acompanhamento? No workshop Linha de Comandos Linux da HJFR trabalha estes e outros comandos da série — da administração do dia a dia à resposta a incidentes.

Este artigo faz parte da série «Comandos Linux, um a um» do blog HJFR — fique atento aos próximos comandos.