Linux的brctl addif命令可以將一個接口加入到既有的網橋中,接下來,這個接口就成了brport,屬於一個從屬的接口,然而你還是可以看到它的,並且可以為它添加IP地址,然後route命令會顯示出它的新添加的IP地址的鏈路層路由已經生效,種種跡象都讓人覺得這個brport仍然保有IP語義,然而如果此時你使用該IP(Linux內核會做源地址選擇)去訪問同一網段的其它地址的話,就會發現,不通,反過來從其它同一網段的地址訪問該地址也是不通的,原因何在?聽我分解。
網絡不通的話,一般第一步是通過抓包來分析,發現是在arp這一步出問題的,arp是IPv4的生命源,arp出了問題,什麼都別扯了!懂Linux網絡實現的家伙們其實早就知道為何出錯了,因為作為從屬接口brport,它的一切都要被網橋接口接管,包括arp,也就是說arp期望的接口信息都是關於網橋接口的而不是基於brport的。總的來說是這樣的。
IP地址配置在物理接口brport上,因此鏈路層路由顯示的出口設備就是該brport,發送數據的時候,arp邏輯會將目標IP-Mac映射記錄在該brport門下,然而arp回來的時候,網橋接口接收了它,內核發現網橋接口門下沒有任何待解決的arp請求,因此丟棄之,因此根本不可能從本機訪問和配置在brport上IP在同網段的任何目標。反過來也一樣,arp請求從其它機器過來,被網橋接口接收,可是在arp_process中准備回復reply的時候,反向路由查找由於dev參數而無法通過,dev參數是網橋,而查詢結果卻是brport,因此failed。能分析到這個地步需要你十分精通網絡協議的行為或者Linux內核協議棧。
那麼怎麼解決這個問題呢?easy啊easy,以下一條命令即可:
ebtables -t broute -A BROUTING -p ARP --arp-ip-dst 12.12.12.12 -j redirect --redirect-target DROP
這句話的意思就是,用物理接口,即brport接管arp,而不是用網橋接口。為了不影響網橋的正常流程,特意指定目標IP地址是這個添加到brport的地址。