BPF 過濾器(BPF filter)
/ B-P-F /
當你接入一個繁忙的網路,封包以百萬計地飛過,而你幾乎從不想要全部——你只想要對你的問題重要的那少數幾個。BPF 過濾器(BPF filter)就是你給系統的精確指令,說「只保留像這樣的封包;其餘的丟掉」。這就像告訴收發室「只把這位寄件人、標示緊急的信轉給我」,而不是把每一個信封都倒在你桌上。BPF 是 Berkeley Packet Filter(柏克萊封包過濾器)的縮寫,得名自它被設計出來的那所大學。
美妙之處在於過濾發生的地點。BPF 過濾器會被編譯成一個微小的程式,在作業系統核心內執行,就在封包抵達之處、在它們被複製上傳給你的工具之前。所以當你寫下「tcp port 443 and host 10.0.0.5」時,核心會拿每個封包對照那個測試,只把通過的那些往上交。這遠比把每個封包都複製到使用者空間再丟掉大多數來得省,也正是它讓 tcpdump 與 Wireshark 能篩過一條 10 Gbps 連結而不被淹沒的原因。過濾器用 host、port、tcp、udp、and、or、not 這些字把欄位與條件組合起來——例如「udp port 53」擷取 DNS,而「icmp」擷取 ping 與 traceroute 的回覆。
兩點值得分清楚的釐清。第一,擷取時的 BPF 過濾器(決定核心保留什麼)和顯示過濾器(決定工具從已擷取的集合中顯示什麼給你)不是同一回事;令人困惑的是,Wireshark 前者用 BPF 語法,後者用它自己的語法。第二,BPF 這個名字如今也指一項範圍大得多的核心內技術 eBPF,被用於追蹤、安全與遠超封包擷取的網路用途;用於過濾的傳統 BPF 是它小小的、最初的祖先。
你不全部擷取,而是執行「tcpdump 'tcp port 443 and host 10.0.0.5'」。核心對每個抵達的封包評估那個 BPF 運算式,只把往返於 10.0.0.5 的 HTTPS 流量往上交——於是少數相關封包到達你的螢幕,而不是洪水般湧入。
BPF 過濾器是在封包被複製上傳之前、於核心內執行的微小測試——只保留符合的,讓高速擷取仍負擔得起。
擷取過濾器(BPF,決定核心保留什麼)不是顯示過濾器(決定工具從已擷取的資料中顯示什麼)。Wireshark 前者用 BPF 語法、後者用它自己的語法——一個典型的混淆點。