網橋呼叫iptables規則的善後處理

2021-08-20 12:06:31 字數 2583 閱讀 1724

linux網橋在br_nf_pre_routing hook點的處理上,有兩個主要的執行流程:第一執行ebtables在此hook點新增的規則,第二如果proc檔案bridge-nf-call-iptables為真,執行iptables在hook點nf_inet_pre_routing配置的ipv4或ipv6協議相關規則。由於iptables的dnat規則會改變資料報的目的ip位址(包括重定向到本機的報文),而網橋只會依據mac**表傳送資料,目的ip位址改變將導致資料報不能送達正確的目的地。

所以,網橋**在執行iptables規則返回之後,呼叫函式br_nf_pre_routing_finish進行了善後的處理。

static inline bool

br_nf_ipv4_daddr_was_changed(const struct sk_buff *skb, const struct nf_bridge_info *nf_bridge)

如已改變,則需要重新確定改變後目的ip位址所對應的二層mac位址。mac位址的確定分為兩種情況,見**中注釋(簡單翻譯):

* there are two cases to consider:

* 1. the packet was dnat'ed to a device in the same bridge

*    port group as it was received on. we can still bridge

*    the packet.

* 2. the packet was dnat'ed to a different device, either

*    a non-bridged device or another bridge port group.

*    the packet will need to be routed.

考慮以下兩種情況:

1. 資料報dnat後的目的出口裝置與其入口裝置在同一網橋上,資料報仍可通過二層橋**。

2. 資料報dnat到乙個不同的裝置上,可能是乙個非網橋裝置,或者是另一網橋下的裝置。此時資料報需要走路由**。

所以,問題是如何從現有dnat之後的目的ip位址,去獲得出口裝置呢?此時函式ip_route_input該上場了,通過路由查詢可得到入口路由,進而得到路由裝置即出口裝置(注意雖然是查詢入口路由,但是得到的仍然是出口裝置,詳見ip_route_input函式)。

但是ip_route_input函式也有可能會失敗,我們看一下失敗的幾種情況:

1)錯誤ehostunreach,入口裝置沒有開啟**功能;

2)錯誤einval,非法的火星位址(源ip位址或者目的ip位址);或者沒有到此目的ip的路由;

3)其它錯誤。

if ((err = ip_route_input(skb, iph->daddr, iph->saddr, iph->tos, dev)))
如上的判斷**,對於錯誤2)和錯誤3),即如果err錯誤碼不等於ehostunreach,釋放skb結束處理;對於錯誤1),即err等於ehostunreach,這裡又有兩種情況:

a)如果入口裝置開啟了**(in_dev_forward(in_dev)),釋放skb結束處理;

b)如果是由於入口裝置未開啟**導致的ehostunreach錯誤,繼續查詢出口裝置。

在情況b)發生後是否要繼續,還是也釋放skb結束呢?由於核心中dnat不需要入口裝置開啟**功能,所以可繼續查詢出口裝置。此時就需要ip_route_output函式幫忙了。因為出口路由的查詢不會判斷入口裝置的**是否開啟,參見以下**,查詢函式引數中的源ip位址和入口裝置都傳空,ip_route_output會當做是乙個本地主機產生的報文處理:

rt = ip_route_output(net, iph->daddr, 0, rt_tos(iph->tos), 0);

如果還是找不到出口裝置,只有釋放skb結束處理了。如果找到的話,比較一下找到的路由所指向的出口裝置是否與資料報入口裝置所屬的網橋相同:

i) 如果相同,dnat後的出口裝置在同一網橋下,此資料報可通過網橋**(br_nf_pre_routing_finish_bridge),查詢fdb表即可得到其mac位址;

ii)不相同,需要上層路由**。將資料報的目的mac位址更換為本機網橋的mac位址,pkt_type設定為packet_host,最終由函式br_handle_frame_finish將資料報送往本機上層處理(br_pass_frame_up)。

ether_addr_copy(eth_hdr(skb)->h_dest, dev->dev_addr);

skb->pkt_type = packet_host;

前面講的都是ip_route_input函式查詢失敗的情況,來看一成功返回的處理。ip_route_input查詢到路由,找到出口裝置。接下來的處理與從ip_route_output一致,參見i)和ii)。另外,對於重定向的報文,in_route_input返回路由指向本地loopback介面,同ii)與網橋裝置也不相同,送往上層協議棧處理。

處理流程圖

iptables規則的關係

iptables規則的關係,是自上而下進行過慮的。所以新增規則時,要通過檔案進行新增,這樣的話,可以控制其順序。a機器 root www netstat an grep 6100 tcp 0 0 0.0.0.0 6100 0.0.0.0 listen tcp 0 0 192.168.5.140 61...

iptables 生產規則

bin bash etc init.d iptables stop iptables a input p tcp dport 80 j accept iptables a input p tcp dport 21 j accept iptables a input s 192.168.17.0 24...

IPTABLES 清空規則

iptables f 然後重新啟用的話 bin iptables.sh root ctc wh 1 176 iptables l chain input policy accept target prot opt source destination chain forward policy acc...