Linux 多重網路介面,多重路由表 === 本文主要介紹在使用多個網路介面時,一張路由表可能無法做到複雜的封包路由功能,透過多重路由表搭配路由規則、iptables,讓封包使用不同的路由表,使用不同的介面轉送。 [TOC] ## Context ![Network Topology](https://i.imgur.com/1G7OAqj.png) 圖1:環境拓樸 如上圖,`web server`上有兩個網路介面,`eth0`連接內部私人網路;`eth1`直接連接 internet 提供對外存取服務。因為公司 IT 政策的關係,web server 自身產生的任何流量(系統更新、套件下載等...)都必須經過內部網路的邊界伺服器( Edge Router ),而 `eth1` 則是作為專線,用來服務由外對內的網頁伺服器流量。以此做到讓服務網路與管理網路分離。 Web Server 網路介面說明: ``` eth0: (default route) address 192.168.0.10 netmask 255.255.255.0 gateway 192.168.0.1 eth1: address 100.10.10.10 netmask 255.255.255.255 gateway 100.10.10.254 (ISP gateway) ``` ## Problem 預設情況當 Client 要連接至 `100.10.10.10` 存取 `Web Server` 上的資源時封包的路徑如下: 1. client 連接到 web server 封包會走上方路線 `client -> (eth1)100.10.10.10`, 2. response 給 client 的封包會走 `(eth0) 192.168.0.10 -> 192.168.1.1 -> 100.0.0.1 -> client` 因為 web server 的預設路由,所有封包流量都會走 `eth0` 介面出去,導致request的封包與response的封包走了不同的路徑,進而造成 client 收到的封包 IP address 不同。 ## Solution 這問題會發生在一台 Server 有多個不同的網路介面,而且經過這兩個網路介面出去的封包Public IP Address不一樣的時候。解決方法為將封包上標記( mark ),並且透過`多重路由表`與`路由規則`讓封包使用不同的路由表走不同的介面。實際操作方式如下。 ### 1.安裝 iproute2 套件 需要使用進階的路由表與路由規則,因此需要新的管理套件,此套件於 Debian 8.4 已經預設安裝了 指令:安裝 iproute2 進階網路管理工具 `apt install iproute2` ### 2.新增一張專屬於 100.10.10.10 網頁伺服器服務的路由表 指令:新增一個路由表web,編號為100 `echo "100 web" >> /etc/iproute2/rt_tables` Linux 2.2 以後支援最多 252 個額外的路由表 ( 系統內建了 4 個路由表了 ),所以路由表的編號可以從 1~252,而後面接的是路由表的名稱。 ### 3.新增 iptables rule 至 mangle table 的 OUTPUT chain中 根據 linuxhomenetworkiing 網站中所提供的 [Iptables Packet Flow Diagram](http://www.linuxhomenetworking.com/wiki/index.php/Quick_HOWTO_:_Ch14_:_Linux_Firewalls_Using_iptables#.WCoH_mt96Uk%20Figure%2014-1%20Iptables%20Packet%20Flow%20Diagram) 圖中可以得知,當程式處理完產生出來的response封包會先經過 mangle Table OUTPUT Chain,因此我們在此階段新增一個規則,為封包加上標記( mark ),最後在封包比對路由表要出去的時候,就能根據 mark 選擇不同的路由表。 ![](https://i.imgur.com/iFENoMY.png) 指令:新增一條規則到 mangle table 的 OUTPUT chain中,比對模式為封包的protocol為tcp,且source port為80 port。(因為client是這個response packet的destination) 而要做的target為 MARK,並且設定一個mark為0x1。 `iptables -t mangle -A OUTPUT -p tcp --sport 80 -j MARK --set-mark 1` 指令執行成功後可以使用`iptables -t mangle -L -v`觀看規則 ``` /etc/iptables [root@web] [2:57] > iptables -t mangle -L -v Chain PREROUTING (policy ACCEPT 176K packets, 25M bytes) pkts bytes target prot opt in out source destination Chain INPUT (policy ACCEPT 72262 packets, 6965K bytes) pkts bytes target prot opt in out source destination Chain FORWARD (policy ACCEPT 0 packets, 0 bytes) pkts bytes target prot opt in out source destination Chain OUTPUT (policy ACCEPT 11164 packets, 774K bytes) pkts bytes target prot opt in out source destination 202 223K MARK tcp -- any any anywhere anywhere tcp spt:http MARK set 0x1 Chain POSTROUTING (policy ACCEPT 11164 packets, 774K bytes) pkts bytes target prot opt in out source destination ``` ### 4.新增封包路由規則 接著我們需要新增路由規則,讓電腦看到這個0x1的mark,將該封包套用不同的路由表(本文中為web路由表) 指令: 新增一條rule,只要fwmark為0x1 就使用web這張路由表 `ip rule add fwmark 1 table web` 可以使用`ip rule ls` 查看新增結果 ``` /etc/network/if-up.d [root@web] [3:01] > ip rule ls 0: from all lookup local 32765: from all fwmark 0x1 lookup web 32766: from all lookup main 32767: from all lookup default ``` ### 5.新增 web 路由表的預設路由規則 最後我們只要在web 這張路由表上寫一條預設路由,將所有使用這張路由表的封包從 eth1 (100.10.10.10出去即可) 指令:新增一條預設路由規則到web路由表,下一跳為100.10.10.254(通常為介面的gateway),透過eth1這個device出去 `ip route add default via 100.10.10.254 dev eth1 table web` 最後使用 `ip route show table web`指令就可以看到新增的路由規則了 ``` /etc/network/if-up.d [root@web] [3:05] > ip route show table web default via 140.124.183.254 dev eth1 ``` ## Conclusion Linux 內建強大的防火牆功能:iptables,內建三種以上不同的table可以使用,分別為專門進行封包過濾用的filter表,進行nat封包網址轉換用的nat表,與進行封包修改用的mangle表。搭配上Linux 2.2/2.4以上提供的XTables功能,可以依造不同的rule選擇不同的routing table,達到不同的封包客製化不同的路由表。如果此功能搭上子介面,或是tunnel interface等,即可玩出很多不同的花樣,實在是很強大阿。 本篇文章示範了一個特別的網路環境下,如何透過多重路由表與iptables的功能,對封包進行標記、分類、套用不同的路由規則,讓封包走我們想要他走的介面,而不是根據預設路由表亂走。 ###### tags: `linux`, `network`, `iptables`, `iproute`, `iproute2`, `ip route`, `routing table`, `ip rule`