Socat は、HTTPやIMAPのような人間が読めるラインベースのプロトコルをインタラクティブにテストするのに最適です。
例えば:
$ socat -d -d READLINE,history=$HOME/s.hist openssl:Host:port,crnl,cafile=some.ca
より適切に分析するには、このようなインタラクティブなセッション、つまり送受信されたバイトをキャプチャする必要があります。
たとえば、ターミナル出力をハードコピーするだけです。 Tux
は十分ではありません。クライアント/サーバーパーツがマークされておらず、「\ t」などの文字が失われるか、サイレントに変換されるためです。
tcpdump
を使用してキャプチャすることは、暗号化されていない接続の場合にのみ役立ちます。
したがって私の質問。
答えはsocatベースである必要はありません。別のツールがそのユースケースに適している場合は、そのツールについて読みたいと思います。
ソリューションのボーナスポイント
私はネットワーク接続を記録するために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
これが通常、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
、<
をI
、O
に変換した後、>
によって提供されます)) 。
text2pcap
の代わりに-ki -
で呼び出されたwireshark
に-r dump.pcap
出力をパイプすることにより、wireshark
でライブトラフィックを確認できますが、wireshark
は古いpcap
のみをサポートしますpcap-ng
の形式ではなく-n
のtext2pcap
オプションを削除する必要があり、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
ゲットースタイルのアプローチの1つは、 ltrace
で 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
次に、共通の文字列を使用して送信/受信バッファを識別する必要があります。
$ 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
は、タイムスタンプ付き出力の複数のオプションもサポートしています。