本文為翻譯文,不一定是逐字逐句的翻譯,而且中間會加上自己的一點見解,如有理解錯誤的地方,還請大家指出,我定虛心學習。原文見鏈接
其中斜體字是自己的理解,建議和ebtables手冊和iptables手冊一起看。
1.介紹
1.弄清楚br-nf代碼都做了什么,就明白iptables的規則為什么在bridge上也能夠起作用了。
2.這里既然說道iptables只對ip數據包進行過濾,那么,可以這么理解,與ip協議同層的包括arp,802.1q等協議(見linux中/etc/ethertypes列出的),那么這些協議的數據包是不會被iptables過濾的。
應該指出的是,br-nf代碼有時會違反TCP/IP網絡模型。例如在鏈路層內執行IP DNAT。要注意的是,我們完全清楚,幀是用於鏈路層的,而分組是用於網絡層的。但是,當我們談論鏈路層內的IP數據包時,我們將這些數據稱為幀/數據包或數據包/幀。
2.幀如何遍歷ebtables鏈
本節只考慮ebtables,而不是iptables。
首先我們要記住我們在說的是以太網層,也就是tcp/ip模型的1層和2層。
以網橋(工作在以太網層)為目的地的數據包的ip目的地址不一定是網橋所在的計算機。這就是路由器的工作原理(mac目的地址是路由器,ip目的地址才是你想交互的實際的box)。
1.明確一個概念:工作在2層的設備,如網橋,交換機,意味着他們只和數據包的二層的頭交互,並不意味着它一定有mac地址(以前我是這么認為的)。
2.一個幀中的目的mac地址,只是數據幀下一跳的目的地,並不一定是它的最終目的地,最終目的地由目的ip決定。3.box我沒有翻譯,就把它理解為可以接受ip數據包的黑匣子就可以
Figure2a.數據幀穿越網橋的方案

在linux的橋代碼中有6個hook點,BROUTING是專門為ebtables新增的。
Figure2b.以太網橋接的hook點

hook是網絡代碼中的特定位置,其它代碼可以將自己綁定到該位置,從而處理通過該位置的分組/幀。例如,內核模塊負責將ebtables的FORWARD鏈綁定掉橋的FORWARD點。這是模塊被加載到內核或者啟動時完成的。
請注意,ebtables的BROUTING和PREOUTING鏈在橋接決定之前被遍歷,因此這些鏈設置會看到橋會忽略的幀。使用此鏈時應考慮到這一點。另外要注意的是,這些鏈不會看到進入非轉發網橋端口的幀。
如何理解最后一句的non-forwarding bridge port,應該是有一個開關負責打開bridge的forwarding功能,就像ip_forward。然而我並沒有找到此配置。僅僅找到了/proc/sys/net/bridge/bridge-nf-call-iptables和CONFIG_BRIDGE_NETFILTER,但是感覺應該不是這里的non-frowarding。
橋對一個幀的決策可能是以下情況之一:
- 橋接,條件是:目的Mac地址在橋的另一端端口
- 從橋的所有端口廣播此幀,條件是:橋不知道擁有此目的Mac地址的box
- 將此幀傳遞至更高協議棧,條件是:幀的目的Mac是橋的Mac或者是橋某個端口的Mac
- 忽略此幀,條件是:幀的目的Mac地址在橋的同側,和幀入口在同側
圖2b中,有幾點問題,
1. 圖中第一個Routing做了什么,之后呢?
2. FORWARD是依據什么作為判決條件的?
3. BRIDGING為什么是一個判斷框,而又沒有N(否定情況)?
4. 這里的BRIDGING是通過橋口將數據幀發出去的意思嗎?下面我會對這幾個問題作答。
Figure2c 橋接表ebtables遍歷過程
Ebtables有三個表:filter,nat和broute,如圖2c,每個表有各自的鏈。
注:filter和nat表的OUTPUT鏈是分離的,並有不同的用法。
圖2b和2c給出了清晰地ebtables的鏈是如何附加到橋的hook點的。
當被綁定到橋上的網卡接收到幀時,幀會首先經過BROUTING鏈。在這個特殊的鏈,你可以選擇路由或者橋接此幀,使你成為一個brouter(橋路器)。與在互聯網上找到的關於brouter是什么的定義有些不同。下一個定義很好地描述了使用BROUTING鏈的brouting能力:
“brouter是橋接一些幀/分組(即基於鏈路層信息的轉發)並路由其他幀/分組(即基於網絡層信息的轉發)的設備。橋/路徑決策基於配置信息。”
我覺得這里體現出了文章介紹部分說明的情況“br-nf代碼有時會違反TCP/IP網絡模型”,本身bridge和ebtables都處於第二層,然而這里竟然會去根據三層的信息決定是路由還是橋接。
例如,可以使用brouter作為2個網絡之間IP流量的普通路由器,同時橋接這些網絡之間的特定流量(NetBEUI,ARP,無論什么)。IP路由表不使用網橋邏輯設備,而是將IP地址分配給物理網絡設備,這些設備也恰好是網橋端口(網橋受限網卡)。
這里說的IP路由表不使用網橋邏輯設備,box將ip地址分配給物理網絡設備,也正好是網橋接口。不太理解,為什么說IP路由表不使用網橋邏輯設備,其次,當網卡被橋接后,其ip地址是訪問不到的,我做過試驗,同時也有理論證明。見鏈接。
BROUTING鏈中的默認決定是橋接。
默認是ACCEPT,在BROUTE表中,ACCEPT的含義略有不同,就是橋接的意思,這個可以從ebtables的用法中找到。而DROP的含義是讓幀被路由。還有一個決策時redirect,它相當於做了目的Mac地址轉換,並將橋口的Mac地址作為目的Mac。這個redict的作用和DROP的作用效果一樣,都會讓幀走到三層,去做路由抉擇,區別在於,DROP並沒有進行目的Mac地址轉換。
redirect可以用在broute表的BROUTING鏈和nat的PREROUNTING鏈,只是它們更換的Mac不一樣,nat中使用的橋的的Mac地址(linux中橋設備默認有一個Mac地址,是橋口的某一個設備Mac地址)
接下來,幀通過PREROUTING鏈。在此鏈中,你可以更改幀的目標MAC地址(DNAT)。如果該幀通過該鏈,則橋接代碼將決定幀的發送位置。網橋通過查看目的MAC地址來實現這一點,它不關心網絡層地址(例如IP地址)。
在此回答剛才的問題1,2,3,4:
1. 到了三層,根據路由表查看數據包下一跳應該發送到哪里(如果有iptables相關策略,就會去遍歷iptables的鏈點)
2. 依據目的Mac地址是否是自己或者是廣播包(應該說是不是bridge的Mac地址,應該不是bridge.port地址,這里也是個疑問。)
3. 否定時通過路由
4. 數據包的出口還是橋的接口,判斷框里應該寫BRIDGING/ROUTING,但是經過routing后的幀還是有可能會經過ebtables的OUTPUT和POSTROUTING。
如果網橋決定這個幀的目的地是本機,這個幀就會經過INPUT鏈。在這個鏈你可以過濾目的是bridge box的幀。遍歷過INPUT鏈后,這個幀將會被傳送上網絡層(IP相關的代碼中)。因此,一個被路由的IP數據包會經過ebtables的INPUT鏈,而不會經過ebtables的FORWARD鏈。這是符合邏輯的。
Figure2d 傳入幀遍歷的鏈
Figure2e 轉發幀遍歷的鏈
橋接決定后,本地始發的幀將遍歷nat OUTPUT,過濾器OUTPUT和nat POSTROUTING鏈。nat OUTPUT鏈允許改變目的地MAC地址,並且過濾器OUTPUT鏈允許過濾來自橋接盒的幀。請注意,在橋接決策后,nat OUTPUT鏈會被遍歷,所以這實際上太晚了。我們應該改變這一點。nat POSTROUTING鏈與上面描述的一樣。
1.還是不理解這個橋接決定到底是什么意思呢。難不成就是數據包出去是否要通過這個橋。先簡單這么理解吧。2.為什么說,橋接決策后,nat表的OUTPUT鏈會被遍歷,這實際上太晚了。因為nat OUTPUT鏈允許進行DNAT,但是此時橋接決策已做,意味着數據包從哪個網卡出去已經確定了,此時再做DNAT的有可能變換后的目的地址其實不應該從這個口出去的,但是已經晚了。
Figure2f 傳出幀遍歷的鏈
當目標設備是邏輯橋設備時,需要被路由幀也可能通過這三條鏈。
這個容易理解,目的MAC為邏輯橋設備,被路由決策后,封裝后的幀的源MAC地址為橋的Mac。
3.一個用做橋梁和路由器的設備(而不是橋路器)
Figure3a IP代碼hooks
下面是iptables數據包遍歷方案
Figure3b 路由表(iptables)遍歷過程
請注意,iptables nat OUTPUT鏈位於路由決策之后。正如前一節所述(討論ebtables時),這對於DNAT來說已經太晚了。這是通過重新路由IP數據包,如果它已被DNAT解決,在繼續之前。為了清楚起見:這是Linux內核的標准行為,不是由我們的代碼引起的。
在nat OUTPUT鏈上既可以做snat也可以做dnat,為什么說dnat在這里做太晚了呢,因為,此時路由決策已經做了,數據包其實已經卻從哪個口出到達下一跳了,但是轉換后的目的地址並不一定可以從此口可以到達的。
圖3a和3b給出了iptables鏈連接到IP hook的清晰視圖 。在內核中啟用bridge代碼和netfilter時,iptables鏈也會連接到橋接代碼的鈎子上。但是,這並不意味着它們不再附加到他們的標准IP代碼鈎子上。對於與橋接代碼接觸的IP數據包,br-nf代碼將決定iptables 鏈將在網絡代碼的哪個位置被遍歷。很明顯,這就確保沒有鏈被同一個數據包遍歷兩次。所有不與網橋代碼接觸的數據包都會以標准方式遍歷iptables的鏈,如圖3b所示。
除了別的之外,以下各節還將嘗試解釋br-nf代碼的功能以及它為什么執行此操作。
可以看到一個IP數據包/幀可能會遍歷 nat PREROUTING,filter NPUT,nat OUTPUT,filter OUTPUT和nat POSTROUTING ebtables鏈。
這是在當網橋也用作路由器時,可能會發生這種情況。包含該IP數據包的以太網幀將具有網橋的目標MAC地址,而目標IP地址不是網橋。包括 iptables鏈,這是IP數據包如何通過網橋/路由器。
Figure3c 橋梁/路由器 路由數據包到一個橋接口(簡單視圖)
這里是假設路由決定發送幀到橋接口。如果路由決定發送數據包到非橋接口,是下面這種情況:
Figure3d 橋梁/路由器 路由數據包到一個橋接口(簡單視圖)
這兩幅圖如何理解呢:比如一條linux服務器,三個網卡,eth0,eth1,eth2,eth0和eth1被橋接為br0,接受到的數據包從br0的某一個端口進來,經過路由判定后,該數據包需要從eth2口送出(例如數據包的目的地址和網橋地址不一個子網,或者網橋沒有地址,而恰巧和eth2在一個子網,或者默認路由是通過eth2才能到達的)。
圖3c和3d假定IP數據包到達橋端口。這里顯然是“不協調”的是 在ebtables INPUT鏈之前遍歷iptables PREROUTING 鏈,但是這不能在不犧牲功能的情況下得到幫助。請參閱下一節。
4.對被橋接的數據包進行目的地址轉換。
取一個橋接收到的IP數據包。我們假設我們想在它上面做一些IP DNAT。更改數據包的目標地址(IP地址和MAC地址)必須發生在網橋代碼決定如何處理幀/數據包之前。
因為等網橋代碼處理完成后,幀已經不是遠來的幀了,黃花菜都涼了,如果要在網橋代碼里做DNAT的話,那么,這必須是同一個人寫的代碼,但是即使這樣也違背了linux模塊分離的特性)
所以,這個IP DNAT必須在網橋代碼之前發生。即在橋代碼實際上做任何事情之前。這與ebtables nat PREROUTING鏈將被遍歷的地方是一樣的(出於同樣的原因)。這應該解釋圖3c和3d中遇到的不協調。
我們也應該注意到,橋接決策的幀成為上述列表中的第四項(例如忽略幀)將在ebtables和iptables的PREROUTING鏈中看到 。
前面三個是指broute的BROUTING,mangle的PREROUTING和nat的PREROUTING。
5.被橋接的數據包遍歷鏈的過程
橋接數據包永遠不會到第1層(鏈路層)之上的任何網絡代碼。所以,橋接的IP數據包/幀將永遠不會輸入IP代碼。因此,所有iptables鏈將被遍歷是因為IP數據包會經過網橋的代碼。鏈遍歷看起來像這樣:
這里圖中沒有畫mangle表,包括mangle PREROUTING、mangle FORWARD和mangle POSTROUTING。
6.在iptables中 使用橋口
試想一個場景,網橋兩端各有一個pc終端,ip分別為192.168.1.11和192.168.1.12,他們的默認網關是橋,現在需要限制1.12地址訪問外網,那么如果沒有網橋端口參數(--physdev-in)的話,1.12很容易通過偽裝ip(手動修改或者snat)來逃脫此限制。
6.1 iptables想要使用網橋目的端口
為了使這成為可能,必須在網橋代碼決定幀需要發送的位置(eth0,eth1或兩者)之后,才能遍歷iptables鏈。這對第3部分提出的方案有一定影響(所以我們在這里查看路由過程,從橋某一端口進入box)。它實際上看起來像這樣(在圖3c的情況下)
Figure6a 路由時遍歷鏈的過程(橋和netfilter代碼已經編譯到了內核中)
注意此圖和圖3c的區別,iptables的NAT POSTROUTING被移動到了最后面,晚於ebtables的各個鏈。
所有的鏈是在bridge代碼中被遍歷的。這都是br-nf代碼做的工作。顯然這並不意味着被路由的IP數據包不會進入IP代碼。而是他們在IP代碼中時不會經過iptables的鏈而已。
這個做法是如何實現的呢,有待看內核源碼分析。
6.2 IP DNAT作用於本地生成的數據包(因此在 iptables nat OUTPUT鏈中)
本地生成的數據包的通常將通過的鏈是這樣的:
Figure6c:
這里iptables的nat POSTROUTING之所又在前面了,原因應該不考慮br-nf代碼
從6.1中我們知道實際情況應該是這樣的(因為br-nf代碼)
Figure6d:
請注意,當數據包在IP代碼中時,iptables nat OUTPUT鏈被遍歷,並且當數據包通過橋接決定時,iptables的filter OUTPUT鏈被遍歷。這使得可以對另外的設備在nat OUTPUT鏈執行DNAT,並讓我們在filter OUTPUT鏈中使用網橋端口作為現在。
這一句“This makes it possible to do DNAT to another device in the nat OUTPUT chain”,應意思是說在nat OUTPUT鏈執行完DNAT后,數據包可能會用另一個設備(網口)將此幀發送出去。不知道這么理解是不是對的:)
7.幀/數據包通過iptables PREROUTING,FORWARD和POSTROUTING鏈的 兩種可能方式
8.iptables PREROUTING鏈中的IP DNAT作用在進入橋端口的幀/數據包上
如果在iptables的nat PREROUTING鏈執行DNAT的話,那么次數據幀可能出現兩種情況,1.目的MAC地址不是橋地址,如果判定數據包從br0進入而且還是從br0出去的話,那么它將進過ebtables的 FORWARD鏈而不是ebtables INPUT/OUTPUT鏈。2.目的MAC地址是橋地址,將會被路由,所以不會走ebtables的FORWARD鏈。
9.使用iptables的MAC模塊擴展
還沒來得及細想為什么會涉及黑客攻擊。
10.使用iptables的physdev模塊
總結:
為什么在br-nf代碼中遍歷iptables的鏈
- 在進入bridge前就用進行dnat
- 為了能將bridge port作為過濾條件
