我有一台带有公共 ip ( ) 的服务器142.0.0.142
。此服务器托管 KVM 虚拟机 ( 192.168.100.10
) 并将 HTTP/S 流量重定向到此 VM。我按照这些说明配置了“基于 NAT 的自定义网络”。当我使用公共 ip142.0.0.142
执行 HTTP 请求时,它工作正常并且流量被重定向到 VM。但是,当我使用公共 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
对于虚拟机故障,这是因为必须使用 NAT 发夹来避免服务器 LAN 中的系统获得直接的非 NAT-ed 回复流量(包括服务器将其自己的源地址视为传入流量):它会失败。
所以对于系统局域网中的VM,包括服务器本身,做NAT harpinning。每当源 IP 地址来自与预期目标的 LAN 相同的 LAN 并且 DNAT 已经发生时,请更改源 IP 地址,如 conntrack 的状态中所记忆的那样,并且可以使用
-m conntrack --ctstate DNAT
(-d 192.168.100.0/24
既不需要又不足,因此不添加)进行检索:实际上,任何可以通过或到达主机的源 IP 地址都可以:142.0.0.142、192.168.100.1 甚至任何虚构的地址,例如 192.0.2.1,只要它可以通过 VM 的默认路由访问。甚至可以将 LAN 中的源地址映射到另一个(可能是虚构的)LAN 中的另一个源地址,例如 192.168.101.0/24(
NETMAP
在 nat/POSTROUTING 中更改源):因此,可以在 192.168.100.10 VM 上运行的应用程序日志中区分客户端与 192.168.100.0/24 直接调用(任何地方都没有地址更改),同样调用公共地址(源变为 192.168.101.x),主机作为客户端直接调用 192.168.100.10(任何地方都没有地址变化)。
对于调用公共地址的主机本身,不涉及路由,因此初始流量不会发生 nat/PREROUTING 并且根本不会发生重定向。相反,nat/OUTPUT 确实发生了。有时必须将 nat/PREROUTING 规则复制到 nat/OUTPUT 并稍作更改(此处似乎不需要更改):