使用兩個 NIC(LAN 與 Internet)的 Linux 路由,以及 NAT 和虛擬機器橋接

使用兩個 NIC(LAN 與 Internet)的 Linux 路由,以及 NAT 和虛擬機器橋接

我的設定:

此設定中只有一台實體機,即具有兩個網路介面卡的虛擬機 (VM) 主機系統。

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

另一個 NIC (eth1) 連接到公共互聯網(配置了公共可路由 IP)。此連接應用於將公共互聯網流量連接埠轉送到虛擬機器的內部 IP(傳入流量),並允許虛擬機器透過 NAT 存取公共網際網路(傳出流量)。

虛擬機器使用 LAN 子網路中的 IP 位址(10.xxx/24,與 eth0 相同)

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

  • br0 在 LAN 子網路 (10.xxx/24) 中有一個 IP 位址
  • eth0已新增至網橋
  • vnet0、vnet1...(由虛擬機器使用)動態新增至網橋

問題

區域網路內的通訊工作正常。此外,VM 主機可透過公用 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顯示封包(我嘗試從虛擬機器內 ping 外部 IP)似乎是透過錯誤的介面 eth0(= LAN-NIC)發送的。即使套用了 NAT 規則,因此來源位址也變更為另一個網路卡 (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是主機的LAN IP
  • 子網路:10.xx0/24 是 LAN
  • 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 封包(來自虛擬機器的 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

  1. 檢查您的虛擬機器的 IP 位址是否為 10.xxx/24(網路遮罩 255.255.255.0)

  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
    

答案2

iptables -t nat -I POSTROUTING -s 10.xxx/24 ! -d 10.xxx/24 -j SNAT --到來源 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 隧道上的橋接連結。

答案3

Silvio 的貼文幫助我實現了類似的配置。除了他的帖子之外,我還需要做一些事情。

  1. 在較新版本的 Linux 核心(例如 Redhat 7)中,您需要啟用橋接核心模組:

    modprobe br_netfilter
    

然後為了使該變更在伺服器重新啟動後保持不變,請將同一行新增至名為 /etc/modules-load.d/.conf 的檔案中

  1. 啟用 br_netfilter 後,我還必須啟用虛擬機器的 iptable 轉送規則,例如:

    iptables -I FORWARD -d 10.x.x.x/24 -j ACCEPT
    iptables -I FORWARD -s 10.x.x.x/24 -j ACCEPT
    
  2. 我沒有使用 SNAT,而是使用了偽裝規則,因為我只需要伺服器託管設施內的單一路由。

    iptables -t nat -A POSTROUTING -s <single-local-vm-ip>/32 -d <my-destination-subnet>/24 -p tcp -j MASQUERADE --to-ports 1024-65535
    

相關內容