Как записывать сеанс TCP / TLS в societ socat?

Socat отлично подходит для интерактивного тестирования линейных человеческих читаемых протоколов, таких как HTTP или IMAP.

Например:

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

Для лучшего анализа мне нужно зафиксировать такой интерактивный сеанс – то есть полученные и отправленные байты.

Просто печатать вывод терминала через, например, tux недостаточно, поскольку части клиент / сервер не отмечены, а символы типа «\ t» теряются / преобразуются молча.

Использование tcpdump для захвата помогает только для незашифрованных соединений.

Таким образом, мой вопрос.

Ответ не обязательно должен быть основан на социуме. Если другой инструмент лучше подходит для этого случая использования, я хотел бы прочитать об этом.

Бонусные баллы за решение, где

  • отметки времени также записываются
  • можно выбирать между чередованием записи (сторона клиент / сервер) или протоколирование для разделения файлов

Мне очень нравится tcpdump для записи сетевых подключений. Вы действительно можете использовать его для того, чего хотите достичь. Вместо того, чтобы использовать конечную точку READLINE в вашем соединении socat, попробуйте прослушать какой-то порт.

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

Затем вы используете второе соединение для подключения к локальному порту, где слушает первый сомат. Это незашифрованное. И на этом порту вы можете запустить 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 

Это типично для вариантов -v и -x для socat .

-v выгружает данные в stderr с некоторым преобразованием, так как символ CR становится \r чтобы вы могли его увидеть.

-x делает шестнадцатеричный дамп (не очень полезный, хотя, поскольку нет метки времени или указание того, в каком направлении проходит сбрасываемый трафик).

При объединении -v и -x вы получаете hd тип дампа с меткой времени и направлением:

 > 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 [...] 

Если вы хотите, чтобы он сбрасывался в файл, вы можете перенаправить stderr в файл, а выход отладки перенаправлен на stdout с помощью:

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

Вы также можете преобразовать это в pcap с text2pcap (который поставляется с wirehark) после небольшой постобработки, используя:

 { 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 

Это pcap с использованием инкапсуляции 147. Это не тип ссылочного уровня, но wirehark понимает его как инкапсуляцию пользователя .

Затем мы можем сказать wirehark, что пакеты содержат HTTP-трафик, например:

 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 

(здесь также изменяются отображаемые столбцы, так как нет адреса, но у нас есть направление движения (предоставлено text2pcap -D после того, как мы преобразуем < , > в I , O )).

Вы можете видеть трафик в прямом эфире с помощью text2pcap вывод text2pcap в text2pcap называемый с -ki - вместо -r dump.pcap , но затем wireshark поддерживает только старый формат pcap , а не pcap-ng что означает, что нам нужно отказаться от -n опции text2pcap и мы теряем информацию о направлении :

 { 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 

Один вид подхода в стиле гетто – использование ltrace на socat :

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

Затем вам нужно определить буферы отправки / получения, используя общую строку:

 $ 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 

Эти адреса затем могут использоваться для разделения клиентских / серверных частей сообщения:

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

(печатает сторону клиент / отправитель – для серверной стороны используется другой указатель)

С положительной стороны, ltrace также поддерживает несколько параметров для timestamped output.