Como gravar uma sessão do protocolo TCP / TLS?

5
O

Socat é ótimo para testar de forma interativa os protocolos legíveis baseados em linhas humanas, como HTTP ou IMAP.

Por exemplo:

$ socat -d -d READLINE,history=$HOME/s.hist openssl:host:port,crnl,cafile=some.ca

Para melhor análise, preciso capturar uma sessão interativa, ou seja, os bytes recebidos e enviados.

Basta copiar a saída do terminal por meio de, por exemplo, tux não é suficiente, porque as partes do cliente / servidor não estão marcadas e caracteres como '\ t' são perdidos / convertidos silenciosamente.

Usar tcpdump para capturar ajuda apenas para conexões não criptografadas.

Assim, minha pergunta.

A resposta não precisa ser baseada em socat. Se outra ferramenta for mais adequada para esse caso de uso, eu gostaria de ler sobre isso.

Pontos de bônus para uma solução em que

  • os carimbos de hora são gravados também
  • pode-se escolher entre gravação intercalada (lado cliente / servidor) ou registro em arquivos separados
por maxschlepzig 04.03.2014 / 20:36

3 respostas

6

Eu gosto bastante do tcpdump para gravar conexões de rede. Você realmente pode usá-lo para o que você deseja alcançar. Em vez de usar o endpoint READLINE na sua conexão social, faça-o ouvir alguma porta.

remote server with ssl
     ^
     |       (ssl-encrypted)
   socat
     |       (not ssl-encrypted)
     v
local port   <-- run tcpdump here
     ^
     |       
   socat
     |
     v
 your terminal

Você então usa uma segunda conexão socat para conectar-se à porta local, onde a primeira socat está ouvindo. Isso não é criptografado. E nessa porta você pode rodar o tcpdump.

$ # easiest to use a separate terminal window for each command
$ socat TCP-LISTEN:9000,reuseaddr openssl:host:port,cafile=some.ca
$ tcpdump -i lo -w /tmp/tcpdump.output port 9000
$ socat READLINE,history=$HOME/.socat.hist TCP:localhost:9000
    
por 04.03.2014 / 22:42
4

Normalmente, são as opções -v e -x de socat .

-v envia os dados para stderr com alguma transformação, como o caractere CR se torna \r para que você possa vê-lo.

-x faz um dump hexadecimal (não é muito útil, já que não há registro de data e hora ou indicação de em que direção o tráfego descartado está fluindo).

Com -v e -x combinados, você recebe um tipo de dump hd com timestamp e direção:

> 2014/03/08 08:46:23.370824  length=4 from=0 to=3
 61 64 73 0a                                      ads.
--
< 2014/03/08 08:46:23.398666  length=1371 from=0 to=1370
 48 54 54 50 2f 31 2e 30 20 34 30 30 20 42 61 64  HTTP/1.0 400 Bad
 20 52 65 71 75 65 73 74 0d 0a                     Request..
 43 6f 6e 74 65 6e 74 2d 54 79 70 65 3a 20 74 65  Content-Type: te
[...]

Se você quer que seja despejado em um arquivo, você pode redirecionar o stderr para um arquivo e a saída de depuração redirecionada para stdout com:

socat -d -d -lf /dev/stdout -x -v 2> dump.txt \
   "READLINE,history=$HOME/s.hist" \
   openssl:host:port,crnl,cafile=some.ca

Você também pode convertê-lo em um pcap com text2pcap (que vem com o wireshark) depois de um pouco de pós-processamento, usando:

{
  socat -d -d -lf /dev/stdout -x -v 2>&1 >&3 3>&- \
    "READLINE,history=$HOME/s.hist" \
    openssl:host:port,crnl,cafile=some.ca |
    awk '/^[<>]/{a=0;print $1 == "<" ? "I" : "O", $2, $3; next}
         {$0 = substr($0, 1, 48);printf "%.4x %s\n",a,$0;a+=NF}' |
    text2pcap -l 147 -Dnqt '%Y/%m/%d %H:%M:%S.' - dump.pcap
} 3>&1

Esse pcap usando o encapsulamento 147. Esse não é um tipo de camada de link, mas o wireshark entende isso como um encapsulamento usuário .

Em seguida, podemos dizer ao wireshark que os pacotes contêm tráfego HTTP, por exemplo:

wireshark -o 'uat:user_dlts:"User 0 (DLT=147)","http","0","","0",""' \
  -o 'gui.column.format:"No.","%m","Time","%Yt",
    "Direction","%Cus:frame.packet_flags_direction:0:R","Protocol","%p",
    "Length","%L","Information", "%i"' -r dump.pcap

(aqui também modifica as colunas exibidas também, já que não há endereço, mas temos a direção do tráfego (fornecida por text2pcap -D depois de convertermos o < , > to I , O )).

Você pode ver o tráfego ao vivo com wireshark canalizando a saída text2pcap para wireshark com -ki - em vez de -r dump.pcap , mas wireshark suporta apenas o formato antigo pcap , não pcap-ng , o que significa que precisamos descartar a opção -n de text2pcap e perderemos as informações da direção :

{
  socat -d -d -lf /dev/fd/3 -x -v 2>&1 >&3 3>&- \
    "READLINE,history=$HOME/s.hist" \
    openssl:host:port,crnl,cafile=some.ca |
    awk '/^[<>]/{a=0;print $1 == "<" ? "I" : "O", $2, $3; next}
         {$0 = substr($0, 1, 48);printf "%.4x %s\n",a,$0;a+=NF}' |
    text2pcap -l 147 -Dqt '%Y/%m/%d %H:%M:%S.' - - |
    wireshark -o 'uat:user_dlts:"User 0 (DLT=147)","http","0","","0",""' \
      -o 'gui.column.format:"No.","%m","Time","%Yt",
        "Direction","%Cus:frame.packet_flags_direction:0:R","Protocol","%p",
        "Length","%L","Information", "%i"' -ki -
} 3>&1
    
por 08.03.2014 / 10:09
1

Um tipo de abordagem no estilo do gueto é usar ltrace em socat :

$ ltrace -s $((100*1024)) -e [email protected]'*' -o s.log \
    socat -d -d READLINE,history=$HOME/.socat.hist \
      openssl:host:port,crnl,cafile=some.ca

Em seguida, você precisa identificar os buffers de envio / recebimento usando uma string comum:

$ grep -i logout s.log
libssl.so.10->memcpy(0xd3bd30, "a5 logout\r\n", 11)               = 0xd3bd30
libssl.so.10->memcpy(0xd32230, "a5 OK Logout completed.\r\n", 25) = 0xd32230

Esses endereços podem ser usados para separar as partes cliente / servidor da comunicação:

$ grep 0xd3bd30 s.log | \
    sed 's/^[^(]\+([0-9a-fx]\+. \(".*"\), [0-9]\+) *= [0-9a-fx]\+$//'

(imprime o lado do cliente / envio - para o lado do servidor, use o outro ponteiro)

No lado positivo, ltrace também suporta várias opções de saída com registro de data e hora.

    
por 04.03.2014 / 23:21