tcpdump
残念ながら、キャプチャでUnicodeでエンコードされたテキスト(特にUTF-8)を検出して表示する方法はないようです。 Unicodeテキストを通常のバイナリデータとして処理し、点として表示します。アプリケーションをデバッグするには、この機能が必要です。
具体的には、tmux
Gnome TerminalのリモートSSHセッションでtcpdump 4.3.0を実行しています。オペレーティングシステムはDebian 7です。
tcpdump
これを使用するか、他のLinuxコマンドと組み合わせてライブネットワークキャプチャでUnicodeテキストを表示できますか?
答え1
次のTXR Lispプログラムは、pcap.tl
次のように呼び出されます。
$ tcpdump -s 1024 -w - | ~/txr/txr pcap.tl
pcap形式の出力を解析し、-w
次の出力を生成します。
192.168.1.102 --> 192.168.1.146
ether hdr: #S(eth-header dst-mac #(8 0 39 249 113 4) src-mac #(0 30 79 164 102 184) eth-type ETH_IPV4)
ipv4 hdr: #S(ipv4-header ihl 5 ver 4 ecn 0 dscp 0 len 101 ident 7434 fragoffs-hi 0 flags 2
fragoffs-lo 0 ttl 64 proto 6 hdr-sum 39232 src-ip 3232235878
dst-ip 3232235922)
ipv4 payload as text: P��.;;�.�+i�.6�...
KK-?9rrt2b
春が来た (Haru-ga Kita/Spring has Com
このコードは、FFIタイプ宣言を使用して、pcapファイルとパケットフォーマット、イーサネットヘッダー、およびipv4ヘッダーに対応する構造タイプを定義します。 ipv4ヘッダはビットフィールドに依存するため、ビッグエンディアンとリトルエンディアンシステムの2つの異なる方法で定義されます。
IPv4ペイロード全体をUTF-8データにインポートしてデコードし、制御文字をドットに置き換えて印刷します。
2022年5月24日編集:新しいコードはTXR 276のエンディアンビットフィールドサポートを利用します。ビットフィールドはエンディアンタイプに基づいている可能性があるため、エンディアンに基づくbe-uint16
2つの方法でIPv4ヘッダー構造の所有者を宣言する必要はなくなりました。
(typedef ll-t (enumed uint32 ll-t
DLT_NULL DLT_EN10MB))
(typedef eth-t (enumed be-uint16 eth-t
(ETH_IPV4 #x0800)
(ETH_ARP #x0806)
(ETH_IPV6 #x08DD)))
(typedef pcap-header (struct pcap-header
(magic uint32)
(majver uint16)
(minver uint16)
(tzoffs uint32)
(tzprec uint32)
(snaplen uint32)
(lltype ll-t)))
(typedef pkt-header (struct pkt-header
(tsec uint32)
(tfrac uint32)
(trunclen uint32)
(origlen uint32)))
(typedef eth-header (struct eth-header
(dst-mac (array 6 uint8))
(src-mac (array 6 uint8))
(eth-type eth-t)))
(typedef ipv4-header (struct ipv4-header
(ver (bit 4 be-uint16))
(ihl (bit 4 be-uint16))
(dscp (bit 6 be-uint16))
(ecn (bit 2 be-uint16))
(len be-uint16)
(ident be-uint16)
(flags (bit 3 be-uint16))
(fragoffs-hi (bit 5 be-uint16))
(fragoffs-lo uint8)
(ttl uint8)
(proto uint8)
(hdr-sum be-uint16)
(src-ip be-uint32)
(dst-ip be-uint32))))
;; Look for IPv4 packets and print headers
(defun decode-packet (phdr buf)
(let ((eh (ffi-get buf (ffi eth-header))))
(unless (eq eh.eth-type 'ETH_IPV4)
(return-from decode-packet))
(let* ((ih (ffi-get buf (ffi ipv4-header) (sizeof eth-header)))
(hdrsz (+ (sizeof eth-header) (sizeof ipv4-header)))
(len (- (length buf) hdrsz))
(body (carray-buf buf (ffi char) hdrsz))
(rawtext (carray-get body))
(text (mapcar (iffi [andf chr-iscntrl [notf chr-isspace]] (ret #\.))
rawtext)))
(put-line `@(str-inaddr ih.src-ip) --> @(str-inaddr ih.dst-ip)`)
(put-line ` ether hdr: @eh`)
(put-line ` ipv4 hdr: @ih`)
(put-line ` ipv4 payload as text: @text`))))
;; main program
(let ((*stdin* (open-fileno (fileno *stdin*) "rbu")) ;; binary, unbuffered
(hdr (new pcap-header))
(hdr-buf (make-buf (sizeof pcap-header)))
(phdr (new pkt-header))
(phdr-buf (make-buf (sizeof pkt-header)))
(pay-buf (make-buf 65536)))
;; read pcap file header
(when (< (fill-buf hdr-buf) (sizeof pcap-header))
(return))
;; decode to structure
(ffi-in hdr-buf hdr (ffi pcap-header) t)
(unless (eq hdr.lltype 'DLT_EN10MB)
(put-line "can only deal with Ethernet frames")
(exit nil))
;; read and decode packets
(while t
(when (< (fill-buf phdr-buf) (sizeof pkt-header))
(return))
(ffi-in phdr-buf phdr (ffi pkt-header) t)
(buf-set-length pay-buf phdr.trunclen)
(when (< (fill-buf pay-buf) phdr.trunclen)
(return))
(decode-packet phdr pay-buf)))
body
イーサネットおよびIPV4ヘッダーを転送するために、変位はネストされたオブジェクトcarray
にバインドされます。要素型はヘッダの後ろのバッファ全体を占めます。buf
hdrsz
char
これにより、(carray-get body)
外部値全体がLisp文字列に変換されます。 UTF-8変換は、要素タイプが次のとおりであるため開始されますchar
。配列の特別な動作char
。型がある場合は、bchar
バイトを文字1:1として扱います。型がある場合、wchar
配列はwchar_t
文字になり、それに応じて文字列に変換されます。文字列の代わりに数値バイトベクトルを取得するには、要素タイプをまたはuchar
に設定できますuint8
。
このプログラムは、TCP、UDP、IPv6など、必要なすべてを処理するために簡単に拡張できます。特定のヘッダーフィールドで特定の一致を探します。