web-dev-qa-db-ja.com

インタラクティブsocat TCP / TLSセッションを記録する方法は?

Socat は、HTTPやIMAPのような人間が読めるラインベースのプロトコルをインタラクティブにテストするのに最適です。

例えば:

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

より適切に分析するには、このようなインタラクティブなセッション、つまり送受信されたバイトをキャプチャする必要があります。

たとえば、ターミナル出力をハードコピーするだけです。 Tuxは十分ではありません。クライアント/サーバーパーツがマークされておらず、「\ t」などの文字が失われるか、サイレントに変換されるためです。

tcpdumpを使用してキャプチャすることは、暗号化されていない接続の場合にのみ役立ちます。

したがって私の質問。

答えはsocatベースである必要はありません。別のツールがそのユースケースに適している場合は、そのツールについて読みたいと思います。

ソリューションのボーナスポイント

  • タイムスタンプも記録されます
  • インターリーブ録音(クライアント/サーバー側)または個別のファイルへのロギングのいずれかを選択できます
6
maxschlepzig

私はネットワーク接続を記録するためにtcpdumpがとても好きです。あなたは実際にあなたが達成したいもののためにそれを使うことができます。 socat接続でREADLINEエンドポイントを使用する代わりに、あるポートをリッスンするようにします。

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

次に、2番目のsocat接続を使用して、最初のsocatが待機しているローカルポートに接続します。これは暗号化されていません。そして、このポートで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
6
kkeller

これが通常、socat-vおよび-xオプションの目的です。

-vは、CR文字が\rになるように変換してstderrにデータをダンプするので、それを確認できます。

-xは16進ダンプを実行します(ただし、ダンプされたトラフィックがどの方向に流れているかを示すタイムスタンプや指示がないため、あまり役に立ちません)。

-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

以下を使用して、少し後処理した後、text2pcap(wiresharkに付属)を使用してそれをpcapに変換することもできます。

{
  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

カプセル化を使用するそのpcap147。これはリンク層タイプではありませんが、wiresharkはそれをserカプセル化として理解します。

次に、wiresharkにパケットに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<IOに変換した後、>によって提供されます)) 。

text2pcapの代わりに-ki -で呼び出されたwireshark-r dump.pcap出力をパイプすることにより、wiresharkでライブトラフィックを確認できますが、wiresharkは古いpcapのみをサポートしますpcap-ngの形式ではなく-ntext2pcapオプションを削除する必要があり、directionの情報が失われます。

{
  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
4

ゲットースタイルのアプローチの1つは、 ltracesocat を使用することです。

$ 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

次に、共通の文字列を使用して送信/受信バッファを識別する必要があります。

$ 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は、タイムスタンプ付き出力の複数のオプションもサポートしています。

1
maxschlepzig