Advertisement
Advertisement

More Related Content

Advertisement
Advertisement

a little more about CaptureFilter

  1. CaptureFilter の仕組みに ちょっと踏み込んでみた ~ BPF を読んだら分かったこと~ 2015/04/27 #pakeana 27 @otsuka752 (@twovs)
  2. agenda • CaptureFilter と DisplayFilter • CaptureFilter の中身 → BPF/Berkeley Packet Filter→ BPF/Berkeley Packet Filter • 巨大な(5000+行) CaptureFilter を使ってみた • まとめ • 参考
  3. about me • @otsuka752 (@twovs) • ネコ1人+奥さん1人+可愛い娘 • 無線LAN装置の開発(1999~2004)• 無線LAN装置の開発(1999~2004) • オンラインゲームのシステム管理者(2004~) • ただし,ゲームには全く興味無し • http://tcpreplay.jp/ やってます
  4. CaptureFilter と DisplayFilter キャプチャする時 表示・解析する時 高速 低速 低機能 高機能 カーネルの中 カーネルの外 (ユーザランド) tcpdump/libpcap でも使える wireshark/tshark (など)だけで使える
  5. CaptureFilter と DisplayFilter フィルタの例 ip ip icmp icmp ip6 ipv6 icmp6 icmpv6 port 80 http portrange 80-90 tcp.port >= 80 and tcp.port <= 90
  6. CaptureFilter と DisplayFilter フィルタの例 ip ip icmp icmp ip6 ipv6 icmp6 icmpv6 port 80 http portrange 80-90 tcp.port >= 80 and tcp.port <= 90 (注)左右で意味が異なる!!!
  7. CaptureFilter と DisplayFilter フィルタの例 ip[0]&0xf = 0x14 ip.hdr_len == 0x14 tcp[((tcp[12:1] & http.request.methodtcp[((tcp[12:1] & 0xf0) >> 2):4] = 0x47455420 http.request.method == "GET" N/A tcp.stream == 0
  8. CaptureFilter の中身(BPF) • Wireshark Capture -> Options -> Capture Filter:(filter-expression)-> Capture Filter:(filter-expression) -> Compile selected BPFs Compile selected BPFs This button allows you to compile the capture filter into BPF code and pop up a window showing you the resulting pseudo code. This can help in understanding the working of the capture filter you created. The Compile Selected BPFs button leads you to Figure 4.5, "The "Compile Results" dialog box".
  9. CaptureFilter の中身(BPF) • tcpdump/dumpcap $ tcpdump -d (filter-expression) $ dumpcap -d (filter-expression) $ man tcpdump -d Dump the compiled packet-matching code in a human readable form to standard output and stop. $ man dumpcap -d Dump the code generated for the capture filter in a human- readable form, and exit.
  10. BPF/フィルタ無し $ sudo tcpdump -d (000) ret #65535 ret Returnret Return 65535[Byte] キャプチャする (フレーム/パケット全体をキャプチャ)
  11. BPF/フィルタ無し(snaplen 指定) $ sudo tcpdump -d -s 100 (000) ret #100 # 100[Byte] キャプチャ $ sudo tcpdump -d -s 0 (000) ret #65535 # 65535[byte] キャプチャ $ sudo tcpdump -d (000) ret #96 # tcpdump-4.0.0 まで $ sudo tcpdump -d (000) ret #65535 # tcpdump-4.1 から
  12. (参考) tcpdump-4.0.0/interface.h /* * The default snapshot length. This value allows most printers to print * useful information while keeping the amount of unwanted data down. */ #ifndef INET6 #define DEFAULT_SNAPLEN 68 /* ether + IPv4 + TCP + 14 */ #else #define DEFAULT_SNAPLEN 96 /* ether + IPv6 + TCP + 22 */ #endif
  13. (参考) tcpdump-4.1/netdissect.h /* * Maximum snapshot length. This should be enough to capture the full * packet on most network interfaces. * * XXX - could it be larger? If so, should it? Some applications might * use the snapshot length in a savefile header to control the size of * the buffer they allocate, so a size of, say, 2^31-1 might not work * well. */ #define MAXIMUM_SNAPLEN 65535 /* * The default snapshot length is the maximum. */ #define DEFAULT_SNAPLEN MAXIMUM_SNAPLEN
  14. (参考) libpcap-1.7.2/pcap-int.h /* * Maximum snapshot length. * * Somewhat arbitrary, but chosen to be: * * 1) big enough for maximum-size Linux loopback packets (65549) * and some USB packets captured with USBPcap: (snip) * 2) small enough not to cause attempts to allocate huge amounts of * memory; some applications might use the snapshot length in a * savefile header to control the size of the buffer they allocate, * so a size of, say, 2^31-1 might not work well. * * We don't enforce this in pcap_set_snaplen(), but we use it internally. */ #define MAXIMUM_SNAPLEN 262144
  15. 1.ip(IPv4) $ sudo tcpdump -d ip (000) ldh [12] (001) jeq #0x800 jt 2 jf 3 (002) ret #65535 (003) ret #0 ldh Load Half Word (2Byte) jeq Jump Equal (jt:Jump if True, jf:Jump if False) (000) 12[Byte]ずれた後の 2[Byte]を読み込む(Etherヘッダの Type を読み込む) (001) 0x800 なら (002)に/それ以外なら (003) に (002) 65535[Byte]キャプチャ=全てキャプチャ (003) 0[byte]キャプチャ=キャプチャしない
  16. 2.ip6(IPv6) $ sudo tcpdump -d ip6 (000) ldh [12] (001) jeq #0x86dd jt 2 jf 3 (002) ret #65535 (003) ret #0 ldh Load Half Word (2Byte) jeq Jump Equal (jt:Jump if True, jf:Jump if False) (000) 12[Byte]ずれた後の 2[Byte]を読み込む(Etherヘッダの Type を読み込む) (001) 0x86dd なら (002)に/それ以外なら (003) に (002) 65535[Byte]キャプチャ=全てキャプチャ (003) 0[byte]キャプチャ=キャプチャしない
  17. (参考) Ethernet Header +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Source MAC Address | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-| | | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | Destination MAC Address | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Type | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 12[Byte]
  18. 3.icmp(ICMPv4) $ sudo tcpdump -d icmp (000) ldh [12] (001) jeq #0x800 jt 2 jf 5 (002) ldb [23] (003) jeq #0x1 jt 4 jf 5 (004) ret #65535 (005) ret #0 ldb Load Byte(1Byte) (000) 12[Byte]ずれた後の 2[Byte]を読み込む(Etherヘッダの Type を読み込む) (001) 0x800 なら (002)に/それ以外なら (005) に (002) 23[Byte]ずれた後の 1[Byte]を読み込む(IPヘッダの Protocol) (003) Protocol が 0x1(ICMP)なら (004)に/それ以外なら(005)へ (004) 65535[Byte]キャプチャ=全てキャプチャ (005) 0[byte]キャプチャ=キャプチャしない
  19. (参考) IP Header +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |Version| IHL |Type of Service| Total Length | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Identification |Flags| Fragment Offset | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Time to Live | Protocol | Header Checksum | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Source Address | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Destination Address | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Options | Padding | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ https://www.ietf.org/rfc/rfc791.txt 14+9[Byte]
  20. 4.icmp6(ICMPv6) $ sudo tcpdump -d icmp6 (000) ldh [12] # Type (001) jeq #0x86dd jt 2 jf 8 # IPv6 (002) ldb [20] # NextHeader (003) jeq #0x3a jt 7 jf 4 # ICMPv6 (004) jeq #0x2c jt 5 jf 8 # Fragment Header (005) ldb [54] # NextHeader (006) jeq #0x3a jt 7 jf 8 # ICMPv6 (007) ret #65535 # capture (008) ret #0 # don't capture 0x3a = 58 => ICMPv6 0x2c = 44 => Fragment Header for IPv6 NextHeader が Fragment Header の場合, 40[Byte]の IPv6 Header のすぐ後に(Fragment された) NextHeader がくる
  21. (参考) IPv6 Header +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |Version| Traffic Class | Flow Label | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Payload Length | Next Header | Hop Limit | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ (snip) 14+6[Byte]+ Source Address + (snip) +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ (snip) + Destination Address + (snip) +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 14+6[Byte]
  22. (参考) IPv6 (NextHeader = fragment) +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |Version| Traffic Class | Flow Label | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Payload Length | 0x2c = 44 | Hop Limit | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ (snip) 14+6[Byte]+ Source Address + (snip) +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ (snip) + Destination Address + (snip) +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Next Header | Reserved | Fragment Offset |Res|M| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Identification | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 14+6[Byte] 14+20 14+40[Byte] 2015/05/09 修正
  23. 5.port 80(80番ポート) $ sudo tcpdump -d port 80 (000) ldh [12] (001) jeq #0x86dd jt 2 jf 10 (002) ldb [20] (003) jeq #0x84 jt 6 jf 4 (004) jeq #0x6 jt 6 jf 5 (005) jeq #0x11 jt 6 jf 23 (006) ldh [54] (007) jeq #0x50 jt 22 jf 8 (008) ldh [56] (009) jeq #0x50 jt 22 jf 23 (010) jeq #0x800 jt 11 jf 23 (011) ldb [23] …
  24. 5.port 80(80番ポート) ... (012) jeq #0x84 jt 15 jf 13 (013) jeq #0x6 jt 15 jf 14 (014) jeq #0x11 jt 15 jf 23 (015) ldh [20] (016) jset #0x1fff jt 23 jf 17 (017) ldxb 4*([14]&0xf) (018) ldh [x + 14] (019) jeq #0x50 jt 22 jf 20 (020) ldh [x + 16] (021) jeq #0x50 jt 22 jf 23 (022) ret #65535 (023) ret #0 ※ 長いので後回しに…
  25. 6.ip and port 80 $ sudo tcpdump -d ip and port 80 (000) ldh [12] # Type (001) jeq #0x800 jt 2 jf 14 # IPv4 (002) ldb [23] # Protocol (003) jeq #0x84 jt 6 jf 4 # SCTP (004) jeq #0x6 jt 6 jf 5 # TCP (005) jeq #0x11 jt 6 jf 14 # UDP (006) ldh [20] # offset(IP Header) (007) jset #0x1fff jt 14 jf 8 # IP Header Length (008) ldxb 4*([14]&0xf) # TCP Header Length (009) ldh [x + 14] # SrcPort (010) jeq #0x50 jt 13 jf 11 # 0x50 = 80 (011) ldh [x + 16] # DstPort (012) jeq #0x50 jt 13 jf 14 # 0x50 = 80 (013) ret #65535 # capture (014) ret #0 # don't capture
  26. 6.ip and port 80 $ sudo tcpdump -d ip and port 80 (000) ldh [12] # Type (001) jeq #0x800 jt 2 jf 14 # IPv4 (002) ldb [23] # Protocol (003) jeq #0x84 jt 6 jf 4 # SCTP (004) jeq #0x6 jt 6 jf 5 # TCP IPヘッダ長を計算して x に代入 TCPヘッダ長を計算して x と足し算 → TCPペイロードの先頭までの offset を計算(005) jeq #0x11 jt 6 jf 14 # UDP (006) ldh [20] # offset(IP Header) (007) jset #0x1fff jt 14 jf 8 # IP Header Length (008) ldxb 4*([14]&0xf) # TCP Header Length (009) ldh [x + 14] # SrcPort (010) jeq #0x50 jt 13 jf 11 # 0x50 = 80 (011) ldh [x + 16] # DstPort (012) jeq #0x50 jt 13 jf 14 # 0x50 = 80 (013) ret #65535 # capture (014) ret #0 # don't capture → TCPペイロードの先頭までの offset を計算
  27. (参考) IP Header +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |Version| IHL |Type of Service| Total Length | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Identification |Flags| Fragment Offset | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Time to Live | Protocol | Header Checksum | 14+6[Byte] +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Source Address | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Destination Address | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Options | Padding | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ https://www.ietf.org/rfc/rfc791.txt 14+9[Byte]
  28. (参考) TCP Header +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Source Port | Destination Port | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Sequence Number | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Acknowledgment Number | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Data | |U|A|P|R|S|F| | | Offset| Reserved |R|C|S|S|Y|I| Window | | | |G|K|H|T|N|N| | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Checksum | Urgent Pointer | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Options | Padding | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | data | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  29. 5.port 80(80番ポート) again $ sudo tcpdump -d port 80 (000) ldh [12] # Type (001) jeq #0x86dd jt 2 jf 10 # IPv6 (002) ldb [20] # NextHeader(IPv6) (003) jeq #0x84 jt 6 jf 4 # SCTP (004) jeq #0x6 jt 6 jf 5 # TCP (005) jeq #0x11 jt 6 jf 23 # UDP (006) ldh [54] # SrcPort (007) jeq #0x50 jt 22 jf 8 # 0x50=80 (008) ldh [56] # DstPort (009) jeq #0x50 jt 22 jf 23 # 0x50=80 (010) jeq #0x800 jt 11 jf 23 # IPv4 (011) ldb [23] # Protocol(IPv4) …
  30. 5.port 80(80番ポート) again ... (012) jeq #0x84 jt 15 jf 13 # SCTP (013) jeq #0x6 jt 15 jf 14 # TCP (014) jeq #0x11 jt 15 jf 23 # UDP (015) ldh [20] # flags + offset (016) jset #0x1fff jt 23 jf 17 # offset IPヘッダ長を計算して x に代入 TCPヘッダ長を計算して x と足し算 → TCPペイロードの先頭までの offset を計算 (017) ldxb 4*([14]&0xf) # Length of IP Payload (018) ldh [x + 14] # SrcPort (019) jeq #0x50 jt 22 jf 20 # 0x50=80 (020) ldh [x + 16] # DstPort(SrcPort + 2) (021) jeq #0x50 jt 22 jf 23 # 0x50=80 (022) ret #65535 # capture (023) ret #0 # don't capture
  31. 巨大な(5000+行) CaptureFilter • 5772行の BPF で tcpdump してみた ### compile(BPF を生成) $ sudo tcpdump -d port 1 or port 2 or port 3 or … or port 1000 | wc -l$ sudo tcpdump -d port 1 or port 2 or port 3 or … or port 1000 | wc -l 5772 ### tcpdump(パケットをキャプチャ) $ sudo tcpdump -n port 1 or port 2 or port 3 or … or port 1000 (snip)
  32. 5000+行の CaptureFilter • 5772行の BPF で tcpdump して 時間とメモリ量を測定 ※ 0-300行を拡大 ※ 普通はこの辺(でしょ?)
  33. 5000+行の CaptureFilter • tcpdump が開始された後は パケットの取りこぼしや動作不良は観測されず (観測できなかっただけかも???)(観測できなかっただけかも???)
  34. まとめ • BPF(Berkeley Packet Filter)を読むと プロトコルの理解が進んで面白い(!) • フィルタの見た目の複雑さと動作は異なる • (メモリ以外は)パフォーマンスに影響無さそう
  35. BPF 利用例 ${RANDOM}.www.example.jp の query を iptables で DROP するには… $ sudo iptables -A 'INPUT|FORWARD' -j DROP -p udp --dport 53 ¥ -m bpf --bytecode "18,177 0 0 0,0 0 0 20,12 0 0 0,7 0 0 0,80 0 0 0,12 0 0 0,4 0 0 1,7 0 0 0,64 0 0 0,21 0 7 58161015,64 0 0 4,21 0 5 124090465,64 0 0 8,21 0 3 1836084325,64 0 0 12,21 0 1 40529920,6 0 0 1,6 0 0 0,"
  36. 参考 The BSD Packet Filter: A New Architecture for User-level Packet Capture http://www.tcpdump.org/papers/bpf-usenix93.pdf Linux Socket Filtering aka Berkeley Packet Filter (BPF) https://www.kernel.org/doc/Documentation/networking/filter.txt tcpdump cheat-sheets http://packetlife.net/media/library/12/tcpdump.pdf how to defend DNS authoritative server against DNS WaterTorture http://www.slideshare.net/twovs/how-to-defend-dns-authoritative-server-against-dns-watertorture iptables BPF module 効果測定 DROP! the ${RANDOM} queries http://www.slideshare.net/twovs/iptables-bpf-module
  37. ENDEND
Advertisement