ebtables和iptables與linux bridge的交互


本文為翻譯文,不一定是逐字逐句的翻譯,而且中間會加上自己的一點見解,如有理解錯誤的地方,還請大家指出,我定虛心學習。原文見鏈接

其中斜體字是自己的理解,建議和ebtables手冊和iptables手冊一起看。

1.介紹

本文檔描述了iptables和 ebtables過濾表如何在基於Linux的網橋上進行交互。
在2.4.x內核上獲取橋接防火牆包括修補內核源代碼。2.6內核包含ebtables和br-nf代碼,所以不需要修補。由於需求很高,2.4版內核的補丁仍然可以在ebtables主頁上找到。該BR-NF代碼使橋接IP幀/數據包通過iptables的鏈。該BR-NF代碼使橋接IP幀/數據包通過iptables的鏈。ebtables在以太網層進行過濾,而iptables只對IP數據包進行過濾。

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中 使用橋口

希望能夠在iptables規則中使用屬於網橋(網橋端口)的物理設備是可以且有效的。了解輸入的網橋端口對防止欺騙攻擊是必要的。假設br0有端口eth0和eth1。如果 iptables規則只能使用br0,那么除了查看MAC源地址(然后仍然...)之外,無法知道eth0端的一個box何時將其源IP地址更改為eth1端子box的源IP地址。 使用iptables physdev模塊,您可以在iptables規則中使用eth0和eth1 ,因此可以捕獲這些嘗試。 
試想一個場景,網橋兩端各有一個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鏈的 兩種可能方式

由於br-nf代碼的存在,幀/數據包可以通過給定的3個iptables鏈來傳遞2種方式。第一種方式是幀被橋接時,所以 iptables鏈被bridge代碼調用。第二種方式是當數據包被路由時。因此必須特別注意區分這兩者,特別是在iptables FORWARD鏈中。這有一個需要注意的奇怪的例子:
Figure7a. 非常基本的配置 
172.16.1.2和172.16.1.4的默認網關是172.16.1.1。172.16.1.1是端口為eth1和eth2的網橋接口br0。
更多細節:
這個想法是172.16.1.4和172.16.1.2之間的通信被橋接,而其余的通過偽裝被路由。
Figure7b: 示意設置的數據流情況 
以下是在啟動橋/路由器時使用的可能方案:
iptables -t nat -A POSTROUTING -s 172.16.1.0/24 -d 172.16.1.0/24 -j ACCEPT
iptables -t nat -A POSTROUTING -s 172.16.1.0/24 -j MASQUERADE
 
brctl addbr br0
brctl stp br0 off
brctl addif br0 eth1
brctl addif br0 eth2
 
ifconfig eth1 0 0.0.0.0
ifconfig eth2 0 0.0.0.0
ifconfig br0 172.16.1.1網絡掩碼255.255.255.0起
 
echo'1'> / proc / sys / net / ipv4 / ip_forward 
注意第一行。因為 iptables對於橋接數據包和路由數據包都執行代碼,我們需要區分這兩者。我們並不希望橋接幀/數據包被偽裝。如果我們省略第一行,那么一切都會起作用,但事情會以不同的方式發生。比如172.16.1.2 ping 172.16.1.4。網橋接收到ping請求,並在首先偽裝IP地址后通過它的eth1端口發送。所以數據包的源IP地址現在是172.16.1.1,而172.16.1.4將響應這個橋。偽裝會將此響應的IP目標從172.16.1.1更改為172.16.1.4。一切正常。但最好不要有這種行為。因此,我們使用第一行來避免這種情況。

8.iptables PREROUTING鏈中的IP DNAT作用在進入橋端口的幀/數據包上

通過一些常規播放,可以確保(參見/net/bridge/br_netfilter.c)DNAT'ed數據包在DNAT之后具有與它們所來的輸入設備相同的輸出設備(我們想要調用的邏輯橋設備br0)將通過ebtables FORWARD鏈,而不是通過ebtables INPUT / OUTPUT鏈。所有其他的DNAT'ed數據包將被純粹路由,所以不會通過ebtables FORWARD鏈,將通過ebtables INPUT鏈並可能通過ebtables OUTPUT鏈。
如果在iptables的nat PREROUTING鏈執行DNAT的話,那么次數據幀可能出現兩種情況,1.目的MAC地址不是橋地址,如果判定數據包從br0進入而且還是從br0出去的話,那么它將進過ebtables的 FORWARD鏈而不是ebtables INPUT/OUTPUT鏈。2.目的MAC地址是橋地址,將會被路由,所以不會走ebtables的FORWARD鏈。

9.使用iptables的MAC模塊擴展

這里解釋的副作用發生在內核中啟用了netfilter代碼時,IP數據包被路由並且該數據包的輸出設備是邏輯橋設備。在iptables FORWARD鏈中過濾MAC源時會遇到副作用。從前面部分應該清楚,iptables FORWARD鏈的遍歷被推遲到數據包經過橋代碼時。這樣做是為了我們可以在網橋端口輸出設備上進行過濾。這對MAC源地址有副作用,因為IP代碼已將MAC源地址更改為橋接設備的MAC地址。因此在iptables的 FORWARD鏈中過濾源Mac是有問題的且目的Mac是網橋/路由器的計算機的MAC的數據包。如果你真的需要過濾這個MAC源地址,你應該在nat PREROUTING鏈中進行。是的,這非常丑陋,但是如果將可以過濾真正的MAC源地址的功能加在FORWARD鏈中,將涉及非常骯臟的黑客攻擊,這是不值得。這當然會使第6部分的反欺騙言論變得有趣。
還沒來得及細想為什么會涉及黑客攻擊。

10.使用iptables的physdev模塊

2.6標准內核包含一個名為physdev的iptables匹配模塊,該模塊必須用於匹配網橋的物理輸入輸出端口。它的基本用法很簡單(請參閱iptables手冊頁以獲取更多詳細信息):
iptables -m physdev --physdev -in <bridge-port>
iptables -m physdev --physdev-out <bridge-port> 
 
最后是兩幅圖片,比較清晰的指出了IP數據包在Linux bridging firewall上的流轉。 圖1圖2
 

總結:

為什么在br-nf代碼中遍歷iptables的鏈

  1. 在進入bridge前就用進行dnat
  2. 為了能將bridge port作為過濾條件
 
 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM