Linux

Linux - 兩個子網、一個介面、一個網關 - NAT 附加子網

  • September 21, 2013

我們目前有幾台伺服器都使用同一個 LAN:

Host1: eth0 10.0.0.1/24
Host2: eth0 10.0.0.2/24
Host3: eth0 10.0.0.3/24
Gateway: 10.0.0.254 

我們想在這些伺服器上執行一些虛擬機(VirtualBox)。我們可以將它們設置為橋接到主機的 eth0,但我們不能使用 10.0.0.0/24 範圍內的地址,因為它們將來可能會被分配。

所以我們認為我們會使用不同的子網:

Host1VM: eth0 192.168.0.1/24 (bridge to host eth0)
Host2VM: eth0 192.168.0.2/24 (bridge to host eth0)
Host3VM: eth0 192.168.0.3/24 (bridge to host eth0)

這很好,所有虛擬機都可以相互通信,因為它們位於使用相同物理介面的同一子網上。

我們面臨的問題是我們需要讓這些虛擬機通過 10.0.0.254 網關訪問網際網路。所以我們想為什麼不選擇其中一台主機並將其用作路由器/NAT?

Host1: eth0 10.0.0.1/24, eth0:0 192.168.0.254/24

現在我們可以給虛擬機一個網關 192.168.0.254。然後我們看到的問題是 Host1 似乎沒有正確地進行 NAT。

iptables -t nat -A POSTROUTING -s 192.168.0.0/24 -o eth0 -j SNAT --to 10.0.0.1

我認為這會起作用,我們確實看到它匹配數據包。如果虛擬機 ping 網際網路,我們看到 ICMP 數據包進入主機 1(因為它是路由器),然後主機重新發送 ICMP,因為它是 NAT’ing,網際網路主機響應主機 - 但隨後它死在那裡。我希望主機隨後將數據包轉發回虛擬機,但事實並非如此。

我錯過了什麼,或者這個設置根本不可能?

編輯:澄清一下,我們在 iptables 中沒有拒絕規則,一切都是預設的接受。我們還啟用了 IP 轉發。

更新1-iptables

忽略 virbr0 - 這與 VirtualBox 虛擬機無關

# Completed on Fri Sep 20 16:50:45 2013
# Generated by iptables-save v1.4.12 on Fri Sep 20 16:50:45 2013
*nat
:PREROUTING ACCEPT [171383:10358740]
:INPUT ACCEPT [1923:115365]
:OUTPUT ACCEPT [192:21531]
:POSTROUTING ACCEPT [169544:10254463]
-A POSTROUTING -s 192.168.0.0/24 -o eth0 -j SNAT --to-source 10.0.0.1
COMMIT
# Completed on Fri Sep 20 16:50:45 2013
# Generated by iptables-save v1.4.12 on Fri Sep 20 16:50:45 2013
*filter
:INPUT ACCEPT [96628707:25146145432]
:FORWARD ACCEPT [195035595:22524430122]
:OUTPUT ACCEPT [44035412:304951330498]
-A INPUT -i virbr0 -p udp -m udp --dport 53 -j ACCEPT
-A INPUT -i virbr0 -p tcp -m tcp --dport 53 -j ACCEPT
-A INPUT -i virbr0 -p udp -m udp --dport 67 -j ACCEPT
-A INPUT -i virbr0 -p tcp -m tcp --dport 67 -j ACCEPT
-A FORWARD -d 192.168.122.0/24 -o virbr0 -m state --state RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -s 192.168.122.0/24 -i virbr0 -j ACCEPT
-A FORWARD -i virbr0 -o virbr0 -j ACCEPT
-A FORWARD -o virbr0 -j REJECT --reject-with icmp-port-unreachable
-A FORWARD -i virbr0 -j REJECT --reject-with icmp-port-unreachable
COMMIT
# Completed on Fri Sep 20 16:50:45 2013
# Generated by iptables-save v1.4.12 on Fri Sep 20 16:50:45 2013
*mangle
:PREROUTING ACCEPT [291641356:47665886851]
:INPUT ACCEPT [96628707:25146145432]
:FORWARD ACCEPT [195035595:22524430122]
:OUTPUT ACCEPT [44035838:304951365412]
:POSTROUTING ACCEPT [239078922:327477732680]
-A POSTROUTING -o virbr0 -p udp -m udp --dport 68 -j CHECKSUM --checksum-fill
-A POSTROUTING -o virbr0 -p udp -m udp --dport 68 -j CHECKSUM --checksum-fill
COMMIT
# Completed on Fri Sep 20 16:50:45 2013

更新 2 - tcpdump

16:58:37.189758 IP 192.168.0.2 > 74.125.128.106: ICMP echo request, id 1, seq 2, length 40
16:58:37.189805 IP 10.0.0.1 > 74.125.128.106: ICMP echo request, id 1, seq 2, length 40
16:58:37.194607 IP 74.125.128.106 > 10.0.0.1: ICMP echo reply, id 1, seq 2, length 40
(no final reply back to the VM)

我將回答我自己的問題,因為這就是我解決它的方法。我很確定其他答案在正常情況下非常準確,但我相信由於使用介面別名的錯誤或警告,它們不起作用。

所以認為介面別名導致了這個問題,我尋找其他提供虛擬介面的方法,結果發現有一種稱為 MAC-VLAN 的虛擬介面類型,它本質上將自己作為虛擬介面附加到物理介面,其自己的 MAC 地址。

使用 NAT 第一次完美執行,所以我認為這僅僅是因為 MAC-VLAN 介面在核心中顯示為一個完全獨立的介面,而介面別名在某處引起了一些混亂。

作為參考,創建 MAC-VLAN 的命令很簡單:

ip link add dev macvlan0 link eth0 type macvlan

這是一個非常好的功能,我不敢相信我以前沒有聽說過。

這說明:

16:58:37.189758 IP 192.168.0.2 > 74.125.128.106: ICMP echo request, id 1, seq 2, length 40
16:58:37.189805 IP 10.0.0.1 > 74.125.128.106: ICMP echo request, id 1, seq 2, length 40
16:58:37.194607 IP 74.125.128.106 > 10.0.0.1: ICMP echo reply, id 1, seq 2, length 40

上游路由器 ( 10.0.0.254) 將回復發送回 Host1,因此您的路由和 SNAT 正常工作。問題是 Host1 沒有將該回复傳遞回192.168.0.0/24網路。

您是否載入了適當的連接跟踪核心模組?

確保流量進入連接跟踪表:

grep src=192.168.0.2 /proc/1/net/nf_conntrack

前幾天我看到一個與 TCP 數據包類似的問題,結果證明是由於rp_filter核心造成的。我看不出這會是什麼問題,但它非常相似。您可以從 Host1 發布路由表 ( ip route show) 並檢查您的 rp_filter 設置嗎?( cat /proc/sys/net/ipv4/conf/default/rp_filter)

引用自:https://serverfault.com/questions/540390