2019年1月19日 星期六

pcap 封包擷取過濾式

pcap 封包擷取過濾式 (filter expression) 用在 tcpdumpWireshark (TShark)、Dumpcap 等程式,在擷取階段就篩選封包。其基本表示式 (primitive) 至少會有一個以上前置限定詞 (qualifier),然後可能會有一個數字或名稱的 id。

限定詞可大致分類成通訊協定 (proto)、傳送方向 (dir)、類型 (type) 三種:
  • type:說明 id 是指什麼,未指明預設是 host
    • host host:位址或主機名稱,如果沒指明 proto 是指 IPv4 或 IPv6 的位址或主機名稱。
    • net net [mask netmask] 或 net net/len:IPv4 或 IPv6 位址、subnet,可指明 netmask。
    • port port:TCP 或 UDP 的通訊埠。
    • portrange port1-port2:TCP 或 UDP 通訊埠的範圍。
  • dir:限定方向
    • srcdstsrc or dst (預設)、和 src and dst
    • proto wlan 限定:rataaddr1addr2addr3addr4dir
  • proto:限定協定,有 etheripip6arprarptcpudp 等,未指明則預設所有跟 type 能一致的協定。
此外還有其它特殊 keyword gatewaybroadcast 等,以及算術運算。較複雜的過濾表示用邏輯 and (&&)、or (||)、not (!)、以及「( )」來組合基本表示式。

範例

Ethernet 信頭
  • ether dst|src|host ehost:Ethernet 目的或來源位址是 ehostehost 可以是來自 /etc/ethers 的名稱或十六進位數字表示的 MAC 位址 (會忽略中間參雜的「:」、「.」、和「-」)。
  • ether ehost:錯誤。
  • [ether] broadcast:Ethernet 廣播封包。ether 可省略。
  • [ether] multicast:Ethernet 群播封包。ether 可省略。相當於 ether[0] & 1 != 0
  • [ether protoprotocol:Ethernet 的 Ether Type 是 protocolprotocol 可以是數字或名稱 ipip6arprarpatalkaarpdecnetscalatmopdlmoprcisostpipx、或 netbeui。註:由於這些名稱也是保留字,所以需要 backslash (\) 跳脫。
  • vlan [vlan_id]:
  • pppoed
  • pppoes [session_id]:
  • wlan ra|ta|addr1|addr2|addr3|addr4 ehost
  • [type wlan_type] [subtyp wlan_subtype]:
  • dir dir:
IP 位址或主機名稱
  • [ip|arp|rarp|ipv6] [dst|src] host hosthost 是 IPv4/IPv6 位址或主機名稱。前面可加協定限制、方向限制。ip host host 相當於 ether proto \ip and host host
  • gateway host:使用 host 作為 gateway 的封包,也就是使用 host 的 Ethernet 位址,但不是 host 的 IP 位址。host 的 IP 位址和 MAC 位址需要查得到。相當於 ether host ehost and not host host。
  • [dst|src] net net [mask netmask]:
  • [dst|src] net net[/len]:
  • ip broadcast
  • [ip|ip6] multicast
  • [[ip|ip6] proto] tcp|udp|icmp:協定是 tcp、ucp、或 icmp 封包。註:tcp, udp, and icmp 也是 keyword,所以需要 backslash (\) 跳脫。註:不能 chase the protocol header chain。
  • [ip|ip6] proto protocol:IPv4 或 IPv6 protocol type 是 protocol。protocol 可以是數字或名稱 icmp6, igmp, igrp, pim, ah, esp, or vrrp。註:不能 chase the protocol header chain.
  • [ip|ip6] protochain protocol:IPv4 或 IPv6 protocol chain 中含有 protocol。產生的 BPF 程式碼較複雜,且 kernel 不支援。
  • [tcp|udp] [dst|srcport port
  • [tcp|udp] [dst|srcportrange port1-port2
算術
  • expr relop exprrelop 是比大小 ><>=<==!= 之一。expr 可能是某個值、封包長度 len、或封包資料和正整數的 +-*/&|<<>>%^ 運算。(註:Linux 3.7 以後在 kernel 才能算 %^。) 封包資料用 proto[expr[:size]] 表示,指特定 proto 協定的 expr byte offset 的 size byte。size 可以是 1、2、4,預設是 1。特定 offset 或欄位可以用名稱表示,例如 tcp[tcpflags]。特定值可以用名稱表示,例如 tcp-syntcp-fin 等。
  • less|greater length:封包長度。相當於 len <= length 和 len >= length
其它

這些過濾描述會先編譯成 BPF 虛擬機器的指令碼,才給 BPF 執行。

參考來源

  1. Manpage of PCAP-FILTER
延伸閱讀
  • 顯示過濾式

2019年1月16日 星期三

pcapsipdump

pcapsipdump 基於 libpcap,將網路界面或 pcap 檔的封包以每個 SIP session (包括 RTP 或 T38 media) 儲存成不同的檔案。封包除了用 BPF 先行過濾外,可以用正規表示式過濾出需要的電話號碼或 SIP Method。另外,在每個 session 開始或結束時可以指定執行 shell 指令。

編譯

需要 libpcap-dev、libbsd-dev 等。
git svn clone --stdlayout https://svn.code.sf.net/p/pcapsipdump/code pcapsipdump
cd pcapsipdump
make
sudo make install

指令格式

pcapsipdump [-fpU] [-i interface | -r file] [-d output_directory] [-P pid_file]
            [-v level] [-R filter] [-m filter] [-n filter] [-l filter]
            [-B size] [-T limit] [-t trigger:action:param] [expression]
參數
  • -f:不 fork,也就是不成為 daemon
  • -p
  • -U
  • -i interface 或 -r file:必須指定網路界面或檔案
  • -d:指定輸出目錄和檔名,不然預設是 ... 
    • %f %t %i
  • -P:
  • -v:
  • -R:
  • -m filter:Method 過濾,預設是「^(INVITE|OPTIONS|REGISTER)$」。
  • -n:電話號碼過濾 (正規表示式)
  • -l:
  • -B:
  • -T:
  • -t:
  • expression:BPF 過濾表示式

使用範例

pcapsipdump ; 顯示使用說明
pcapsipdump -f -r test.pcapng -m '^INVIT$' -d ./%Y%m%d-%H%M%S-%f-%t.pcap

程式

main() @pcapsipdump.cpp
  1. 取得參數,剩下的部份是額外的 BPF 表示式。
  2. ...
  3. 使用 pcap_create() 或 pcap_open_offline() 取得網路界面或 pcap 檔的 pcap_t handle。
  4. 用 pcap_compile() 和 pcap_setfilter() 編譯和設定 BPF 過濾。預設過濾式「udp or vlan」,指令參數之外剩餘的部份就是 BPF 表示式。
  5. pcap_datalink() 查看 datalink 類型,換算出 IP 信頭位置。
  6. 可以 fork() 為 daemon。
  7. pcap_next_ex() 處理每個封包
    1. 每封包時間 15 秒檢查是否 session 過長應該結束
    2. fragment 封包:看是否需要儲存,然後處理下個封包。
    3. 如果是要儲存的 RTP 封包,儲存然後處理下個封包。
    4. 如果是 SIP 封包的話
      1. 檢查號碼是否符合儲存然後處理下個封包。
      2. 新 callid:檢查 Method 符合後產生輸出檔名。
      3. BYE
      4. 解析 SDP
      5. 是否有 fragment
    5. 其它封包:可開顯示
  8. 結束所有 session
  9. 結束 pcap_t
  10. 等候子行程
讀取封包需要取得 pcap_t
  • 從網路界面:pcap_create() → 設定選項 → pcap_activate()。pcap_findalldevs() 列出界面,然後 pcap_freealldevs() 釋出。pcap_lookupdev() 取得第一個非「loopback」的界面。
  • 從檔案:pcap_open_offline() 或 pcap_fopen_offline()。
  • 「假」的:pcap_open_dead()
  • 讀取封包:pcap_dispatch(), pacp_loop(), pcap_next(), pcap_next_ex()。
  • 結束取得封包:pcap_close()
過濾:pcap_compile() ...
寫 pcap 檔:pcap_dump_open() -> pcap_dump() -> pcap_dump_close()。
送出封包:pcap_inject()、pcap_sendpacket()

參考

2019年1月15日 星期二

primitive

primitive 是原始的、遠古的、早期的意思,含有不是從其它東西衍生出來的意思,也隱含有簡陋的、未分化的意思。
原始人叫 primitive man

primitive 也可以當名詞,就是原始人的意思,用在計算機科學的函數是指基本的原始函數,可翻作「原函數」、「原始函數」、「基元函數」

參考

Firefox 網頁轉成 PDF 檔的擴充

PDF Mage:支援本地檔案 (如 .md) 產生的網頁,可正確產生含有超連接的 PDF 檔。可設定頁寬 (Web page width) 1024px 以下或 Firefox 視窗不要開太大,避免字太小。

其它大多不支援本地檔案產生的網頁 (如 Save as PDFWeb to PDFPDF CreatorPrint Friendly & PDF) 或只跟內建的 Print 一樣沒有超連接 (如 Print to PDFWebsite to PDF)。

SIP header Via

所有 SIP 訊息 都要有 Via,縮寫 v。一開始的 UAC 和後續途經的每個 proxy 都會疊加一個 Via 放傳送的位址,依序作為回應的路徑。 格式 sent-protocol sent-by [ ;branch= branch ][ ; 參數 ...] s...