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