編寫乙個Linux虛擬網絡卡來實現類NVI

2021-09-21 02:38:01 字數 1718 閱讀 8488

我們可以在linux上使用loopback介面來模擬兩個階段的路由抉擇,第乙個階段是走一遍pre/post routing流程,將nat實施完畢,第二階段完成單純路由**。然而需要在netfilter上掛鉤子,以便取消關聯在skb上的路由項,並且取消關聯在skb上的conntrack資訊,因為在第二階段的單純路由流程裡面,我不希望再有什麼基於conntrack的動作,因此如果需要有基於conntrack的操作,務必在第一階段內和nat一併完成。

回過頭來看loopback的實現,不是那麼完美,因為像在netfilter上掛載鉤子完成的這種事完全可以在虛擬網絡卡的xmit操作中完成,因此有必要重新寫乙個虛擬網絡卡,之所以最終還是考慮重新寫,是因為這個模組超級簡單,基本可以照搬loopback.c的實現,所不同的是xmit的操作:

static netdev_tx_t nvi_xmit(struct sk_buff *skb,

struct net_device *dev)

else

return netdev_tx_ok;

}

對nvi介面的註冊也非常簡單:

dev = alloc_netdev(0, "nvi", nvi_setup);
為何可以使用skb的mark來儲存入介面index呢?實際上在32位的機器上它完全可以儲存原始入網絡卡dev的位址,強轉成net_device型別指標即可。我並不是一開始就直接把入網絡卡的index儲存在mark中了,因為可能netfilter鉤子還要用這個mark,我也沒有使用mark的掩碼掩去一些位來儲存index,因為不知情者可能會誤用。我採用的方式是在「確認不可能有netfilter鉤子使用mark的時候再將其覆蓋成入網絡卡的index,那麼何時合適呢?精通netfilter的都知道,在postrouting的最後做這件事比較合適,因此我就把這個hook安置於postrouting的nf_confirm之後。是否會有流控用到mark我不管,畢竟流控是在物理網絡卡上做的,和第一輪的路由無關。然而問題是,到了postrouting的時候我還能取到原始的入網絡卡的index嗎?oh,no!:

int ip_output(struct sk_buff *skb)

所以,到了postrouting,就再也取不到原始網絡卡的index了!那麼變通的辦法就是將linux協議棧的這段**改了:

int ip_output(struct sk_buff *skb)

return nf_hook_cond(pf_inet, nf_inet_post_routing, skb, orig_dev, dev,

ip_finish_output,

!(ipcb(skb)->flags & ipskb_rerouted));

}

我個人覺得,對於將linux作為路由box來用的人來講,對於forwarding的資料報,在postrouting的時候能取到資料報從哪個網絡卡進入,可以實施更多的控制策略,這難道不更好嗎?好吧,如果非要說這樣改不好,我還有更加標準的做法,那就是在conntrack結構體中註冊乙個新的extend,其實就是乙個結構體,將原始的入網絡卡作為乙個字段放進去,在nvi介面的xmit中,conntrack重置為nf_conntrack_untracked之前,取出這個網絡卡,呼叫eth_type_trans介面即可,這樣好了吧,我沒有觸動linux kernel的主協議棧,還是基於netfilter來做擴充套件!事實上,netfilter的擴充套件能力是無限的!

編寫乙個Linux虛擬網絡卡來實現類NVI

我們可以在linux上使用loopback介面來模擬兩個階段的路由抉擇,第乙個階段是走一遍pre post routing流程,將nat實施完畢,第二階段完成單純路由 然而需要在netfilter上掛鉤子,以便取消關聯在skb上的路由項,並且取消關聯在skb上的conntrack資訊,因為在第二階段...

linux增加乙個虛擬網絡卡

linux虛擬網絡卡配置 作用 一塊真實網絡卡配置多個ip引數,可同時和多個網路通訊 實現步驟 1.cd etc sysconfig network scripts 進入網絡卡配置檔案所在目錄 2.cp ifcfg eth0 ifcfg eth0 0 複製真實網絡卡配置檔案為第一塊虛擬網絡卡配置檔案...

linux增加乙個虛擬網絡卡

linux虛擬網絡卡配置 作用 一塊真實網絡卡配置多個ip引數,可同時和多個網路通訊 實現步驟 1.cd etc sysconfig network scripts 進入網絡卡配置檔案所在目錄 2.cp ifcfg eth0 ifcfg eth0 0 複製真實網絡卡配置檔案為第一塊虛擬網絡卡配置檔案...