使用 KVM 进行 NAT 的 Iptables 配置

使用 KVM 进行 NAT 的 Iptables 配置

我有一台具有公共 IP(142.0.0.142)的服务器。此服务器托管一个 KVM 虚拟机(192.168.100.10),并将 HTTP/S 流量重定向到此 VM。我遵循那些指令配置“基于自定义 NAT 的网络”。当我使用公共 IP142.0.0.142执行 HTTP 请求时,它运行正常,流量被重定向到虚拟机。但是,当我使用公共 IP 从主机或客户机执行 HTTP 请求时,连接失败。

以下是 的内容/etc/iptables/rules.v4

*mangle
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
# DHCP packets sent to VMs have no checksum (due to a longstanding bug).
-A POSTROUTING -o virbr10 -p udp -m udp --dport 68 -j CHECKSUM --checksum-fill
COMMIT

*nat
:PREROUTING ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]

# Modify the destination address of packets received on ports 80 and 443.
-A PREROUTING -d 142.0.0.142/32 -p tcp -m tcp --syn -m multiport --dports 80,443 -j DNAT --to-destination 192.168.100.10

# Do not masquerade to these reserved address blocks.
-A POSTROUTING -s 192.168.100.0/24 -d 224.0.0.0/24 -j RETURN
-A POSTROUTING -s 192.168.100.0/24 -d 255.255.255.255/32 -j RETURN

# Masquerade all packets going from VMs to the LAN/Internet.
-A POSTROUTING -s 192.168.100.0/24 ! -d 192.168.100.0/24 -p tcp -j MASQUERADE --to-ports 1024-65535
-A POSTROUTING -s 192.168.100.0/24 ! -d 192.168.100.0/24 -p udp -j MASQUERADE --to-ports 1024-65535
-A POSTROUTING -s 192.168.100.0/24 ! -d 192.168.100.0/24 -j MASQUERADE

COMMIT

*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]

# Allow basic INPUT traffic.
-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -p icmp --icmp-type 8 -m conntrack --ctstate NEW -j ACCEPT

# Accept SSH connections.
-A INPUT -p tcp -m tcp --syn -m conntrack --ctstate NEW --dport 22 -j ACCEPT

# Accept DNS (port 53) and DHCP (port 67) packets from VMs.
-A INPUT -i virbr10 -p udp -m udp -m multiport --dports 53,67 -j ACCEPT
-A INPUT -i virbr10 -p tcp -m tcp -m multiport --dports 53,67 -j ACCEPT

# Reject everything else.
-A INPUT -m conntrack --ctstate INVALID -j DROP
-A INPUT -p tcp -m tcp -j REJECT --reject-with tcp-reset
-A INPUT -j REJECT --reject-with icmp-port-unreachable

# Allow established traffic to the private subnet.
-A FORWARD -d 192.168.100.0/24 -o virbr10 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT

# Allow outbound traffic from the private subnet.
-A FORWARD -s 192.168.100.0/24 -i virbr10 -j ACCEPT

# Allow traffic between virtual machines.
-A FORWARD -i virbr10 -o virbr10 -j ACCEPT

# Allow packets that have been forwarded to particular ports on the VM.
-A FORWARD -d 192.168.100.10/32 -o virbr10 -p tcp -m tcp --syn -m conntrack --ctstate NEW -m multiport --dports 80,443 -j ACCEPT

# Reject everything else.
-A FORWARD -i virbr10 -j REJECT --reject-with icmp-port-unreachable
-A FORWARD -o virbr10 -j REJECT --reject-with icmp-port-unreachable

COMMIT

答案1

对于虚拟机故障,这是因为NAT 发夹结构必须使用它来避免服务器 LAN 中的系统获得直接非 NAT 回复流量(包括服务器将其自己的源地址视为传入流量):它会失败。

因此,对于系统 LAN 中的虚拟机(包括服务器本身),请执行 NAT harpinning。只要源 IP 地址与目标 LAN 位于同一 LAN,并且 DNAT 已经发生,就会更改源 IP 地址,如 conntrack 状态中所述,可使用以下方法检索-m conntrack --ctstate DNAT-d 192.168.100.0/24既不需要又不够,所以没有添加):

iptables -t nat -A POSTROUTING -m conntrack -s 192.168.100.0/24 --ctstate DNAT -j SNAT --to-source 142.0.0.142

实际上,任何经过或到达主机的源 IP 地址都可以:142.0.0.142、192.168.100.1 或任何虚构地址(例如 192.0.2.1),只要它可以通过虚拟机的默认路由访问即可。甚至可以将 LAN 中的源地址映射到另一个(可能是虚构的)LAN 中的另一个源地址,例如 192.168.101.0/24(NETMAP在 nat/POSTROUTING 中改变了源):

iptables -t nat -A POSTROUTING -m conntrack -s 192.168.100.0/24 --ctstate DNAT -j NETMAP --to 192.168.101.0/24

因此,可以在 192.168.100.10 的虚拟机上运行的应用程序日志中区分来自 192.168.100.0/24 的客户端直接调用(任何地方的地址均未更改)、相同调用公共地址(源变为 192.168.101.x)以及作为客户端的主机直接调用 192.168.100.10(任何地方的地址均未更改)。


对于调用公共地址的主机本身,不涉及路由,因此 nat/PREROUTING 不会对初始流量发生,也不会发生任何重定向。相反,nat/OUTPUT 会发生。有时必须将 nat/PREROUTING 规则复制到 nat/OUTPUT 并进行轻微更改(这里似乎不需要更改):

  iptables -t nat -A OUTPUT -d 142.0.0.142/32 -p tcp -m tcp --syn -m multiport --dports 80,443 -j DNAT --to-destination 192.168.100.10

相关内容