大家好,我是飛哥!今天聊聊大家工作中經(jīng)常用到的
tcpdump。在
網(wǎng)絡(luò)包的發(fā)送和接收過程中,絕大部分的工作都是在
內(nèi)核態(tài)完成的。那么問題來了,我們常用的運行在用戶態(tài)的程序 tcpdump 是那如何實現(xiàn)抓到
內(nèi)核態(tài)的包的呢?有的同學(xué)知道 tcpdump 是基于 libpcap 的,那么 libpcap 的工作原理又是啥樣的呢。如果讓你裸寫一個抓包程序,你有沒有思路?按照飛哥的風格,不搞到最底層的原理咱是不會罷休的。所以我對相關(guān)的源碼進行了深入分析。通過本文,你將徹底搞清楚了以下這幾個問題。
- tcpdump 是如何工作的?
- netfilter 過濾的包 tcpdump 是否可以抓的到?
- 讓你自己寫一個抓包程序的話該如何下手?
借助這幾個問題,我們來展開今天的探索之旅!
一、網(wǎng)絡(luò)包接收過程
在
圖解Linux網(wǎng)絡(luò)包接收過程一文中我們詳細介紹了網(wǎng)絡(luò)包是如何從網(wǎng)卡到達用戶進程中的。這個過程我們可以簡單用如下這個圖來表示。
找到 tcpdump 抓包點
我們在
網(wǎng)絡(luò)設(shè)備層的代碼里找到了 tcpdump 的抓包入口。在 __netif_receive_skb_core 這個函數(shù)里會遍歷 ptype_all 上的協(xié)議。還記得上文中我們提到 tcpdump 在 ptype_all 上注冊了虛擬協(xié)議。這時就能執(zhí)行的到了。來看函數(shù):
//file:?net/core/dev.c
static?int?__netif_receive_skb_core(struct?sk_buff?*skb,?bool?pfmemalloc)
{
????......
????//遍歷?ptype_all?(tcpdump?在這里掛了虛擬協(xié)議)
????list_for_each_entry_rcu(ptype,?