Linux

具有 NAT 和虛擬機橋接的兩個 NIC 的 Linux 路由(LAN 與 Internet)

  • November 21, 2017

我的設置:

此設置中只有一台物理機,即帶有兩個網路適配器的虛擬機 (VM) 主機系統。

一個 NIC (eth0) 連接到內部網路(LAN 子網,例如 10.xxx/24),用於內部流量。

另一個 NIC (eth1) 連接到公共網際網路(它配置了公共可路由 IP)。此連接應用於將公共網際網路流量埠轉發到 VM 的內部 IP(傳入流量),並允許 VM 通過 NAT 訪問公共網際網路(傳出流量)。

虛擬機使用 LAN-Subnet 中的 IP 地址(10.xxx/24,與 eth0 相同)

我為 VM(vnet0、vnet1、…)和 LAN-NIC(eth0)的虛擬網路介面配置了一個橋接設備(br0)。這意味著:

  • br0 在 LAN 子網中有一個 IP 地址 (10.xxx/24)
  • eth0 被添加到網橋
  • vnet0、vnet1、…(由 VM 使用)動態添加到網橋

問題

LAN 內的通信工作正常。此外,VM-Host 可通過公共 IP 訪問並具有 Internet 訪問權限。

我的問題是允許虛擬機訪問公共網際網路的 NAT 配置。

我嘗試使用一個簡單的 (S)NAT 規則:

iptables -t nat -I POSTROUTING -s 10.x.x.x/24 ! -d 10.x.x.x/24 -j SNAT --to-source y.y.y.102

而 yyy102 是第二個 NIC (eth1) 的公共可路由 IP。

我發現我需要啟用“ip_forward”和“bridge-nf-call-iptables”:

echo 1 > /proc/sys/net/ipv4/ip_forward
echo 1 > /proc/sys/net/bridge/bridge-nf-call-iptables

否則 iptables 不會處理橋接包。

現在來自虛擬機的數據包似乎通過以下 iptables 鏈:

  • “FORWARD”(正常)- 我在那裡接受它們(-j ACCEPT,計數器上升)
  • “PREROUTING” (nat) - 我在那裡接受他們(政策接受,計數器上升)
  • “POSTROUTING” (nat) - 它們匹配 SNAT 規則

但由於我目前無法弄清楚的任何原因,並非所有數據包似乎都到達了 PRE/POSTROUTING。

然而,更有趣tcpdump -i eth0的是,tcpdump -i eth1顯示數據包(我試圖從 VM 內 ping 外部 IP)似乎是通過錯誤的介面 eth0(=LAN-NIC)發送的。甚至應用了 NAT 規則,因此源地址更改為另一個 NIC(eth1)的 IP。

問題:

如何配置系統以輸出以公共 IP 作為源地址的 NAT 數據包以通過正確的 NIC (eth1) 發送?

我是否需要以某種方式將 eth1 添加到網橋(br0)?如果是這樣,如何正確分配公共 IP 地址?通常需要在橋接設備上配置 IP。我是否需要為網橋分配別名地址(br0:0 上的公共 IP)?

配置詳情

主機系統上的路由配置:

# ip r
default via y.y.y.126 dev eth1
10.x.x.0/24 dev br0  proto kernel  scope link  src 10.x.x.11
y.y.y.96/27 dev eth1 proto kernel  scope link  src y.y.y.102
  • IP:yyy126 是我們的公共網際網路路由器。
  • IP:yyy102是宿主機的公網IP
  • IP:10.xx11是主機的區域網路IP
  • 子網:10.xx0/24 是區域網路
  • SUBNET:yyy96/27 是公共 IP 子網

網卡配置:

# ifconfig
br0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
       inet 10.x.x.11  netmask 255.255.255.0  broadcast 10.x.x.255
       inet6 ####::###:####:####:####  prefixlen 64  scopeid 0x20<link>
       ether ##:##:##:##:##:##  txqueuelen 0  (Ethernet)
       RX packets 2139490  bytes 243693436 (232.4 MiB)
       RX errors 0  dropped 0  overruns 0  frame 0
       TX packets 29085  bytes 2398024 (2.2 MiB)
       TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
       inet6 ####::###:####:####:####  prefixlen 64  scopeid 0x20<link>
       ether ##:##:##:##:##:##  txqueuelen 1000  (Ethernet)
       RX packets 2521995  bytes 290600491 (277.1 MiB)
       RX errors 0  dropped 0  overruns 0  frame 0
       TX packets 383089  bytes 48876399 (46.6 MiB)
       TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
       device memory 0xdfa60000-dfa7ffff

eth1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
       inet y.y.y.102  netmask 255.255.255.224  broadcast y.y.y.127
       inet6 ####::###:####:####:####  prefixlen 64  scopeid 0x20<link>
       ether ##:##:##:##:##:##  txqueuelen 1000  (Ethernet)
       RX packets 2681476  bytes 597532550 (569.8 MiB)
       RX errors 0  dropped 130  overruns 0  frame 0
       TX packets 187755  bytes 21894113 (20.8 MiB)
       TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
       device memory 0xdfa00000-dfa1ffff

網橋配置:

# brctl show
bridge name     bridge id               STP enabled     interfaces
br0             8000.002590eb1900       no              eth0
                                                       vnet0

和 iptables 規則:

# iptables -vnL
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target     prot opt in     out     source               destination
 723  106K DROP       udp  --  *      *       y.y.y.0/24           0.0.0.0/0            udp spt:5404
 586 40052 ACCEPT     all  --  *      *       0.0.0.0/0            0.0.0.0/0            state RELATED,ESTABLISHED
   5   420 ACCEPT     icmp --  *      *       0.0.0.0/0            0.0.0.0/0
   0     0 ACCEPT     all  --  lo     *       0.0.0.0/0            0.0.0.0/0
   0     0 ACCEPT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            state NEW tcp dpt:22
   2   458 LOG        all  --  *      *       0.0.0.0/0            0.0.0.0/0            LOG flags 0 level 4
   2   458 REJECT     all  --  *      *       0.0.0.0/0            0.0.0.0/0            reject-with icmp-host-prohibited

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target     prot opt in     out     source               destination
1343  173K ACCEPT     tcp  --  *      *       10.x.x.2             0.0.0.0/0            tcp spt:3389
1648  127K ACCEPT     tcp  --  *      *       0.0.0.0/0            10.x.x.2             tcp dpt:3389
  18  1040 LOG        all  --  *      *       0.0.0.0/0            0.0.0.0/0            LOG flags 0 level 4
  18  1040 ACCEPT     all  --  *      *       0.0.0.0/0            0.0.0.0/0

Chain OUTPUT (policy ACCEPT 525 packets, 84016 bytes)
pkts bytes target     prot opt in     out     source               destination


# iptables -vnL -t nat
Chain PREROUTING (policy ACCEPT 13 packets, 1218 bytes)
pkts bytes target     prot opt in     out     source               destination

Chain INPUT (policy ACCEPT 5 packets, 420 bytes)
pkts bytes target     prot opt in     out     source               destination

Chain OUTPUT (policy ACCEPT 13 packets, 880 bytes)
pkts bytes target     prot opt in     out     source               destination

Chain POSTROUTING (policy ACCEPT 14 packets, 920 bytes)
pkts bytes target     prot opt in     out     source               destination
   5   300 SNAT       all  --  *      *       10.x.x.0/24          !10.x.x.0/24           to:y.y.y.102

這裡是 LAN 介面卡上擷取的 NAT 數據包(來自 VM 的 ping):

# tcpdump -i eth0
12:53:55.243350 IP y.y.y.102 > y.y.y.110: ICMP echo request, id 2, seq 5, length 40

“ip 規則”的輸出:

# ip rule
0:      from all lookup local
32766:  from all lookup main
32767:  from all lookup default
  1. 檢查您的虛擬機是否在 10.xxx/24(網路遮罩 255.255.255.0)上有 IP 地址
  2. 將 10.xx11(br0 ip 地址)設置為 VM 的預設網關
  3. 在物理主機上啟用 ip 轉發
  4. 啟用 SNAT:
iptables -t nat -A POSTROUTING -s 10.x.x.x/24 -o eth1 -j SNAT --to y.y.y.102

iptables -t nat -I POSTROUTING -s 10.xxx/24 !-d 10.xxx/24 -j SNAT –to-source yyy102

這必須更改為

iptables -t nat -I POSTROUTING --out-interface eth1 -j SNAT --to-source y.y.y.102

根據您的第一條規則,只有目的地為 10.xxx 的包必須被處理。那麼,從外部到您的網路的流量呢?(來源 - 來自世界各地,目的地是您的公共 IP :)

如何配置系統以輸出以公共 IP 作為源地址的 NAT 數據包以通過正確的 NIC (eth1) 發送?

閱讀以上部分。只需更改 NAT 規則。

我是否需要以某種方式將 eth1 添加到網橋(br0)?如果是這樣,如何正確分配公共 IP 地址?通常需要在橋接設備上配置 IP。我是否需要為網橋分配別名地址(br0:0 上的公共 IP)?

除非你知道你這樣做是什麼以及為什麼這樣做。保持內部和外部介面分開。只允許路由。

我已經描述了你配置現場(生產)超過 5 年。3 台主機伺服器和 25 台虛擬機順利工作,包括 openvpn 隧道上的橋接連結。

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