我是一名程序员,被推到服务器管理岗位,我遇到了一个让我很困惑的问题。缺乏知识无疑是罪魁祸首,所以如果你可以的话请教我。:)
问题简介:两台物理服务器由同一个专用托管服务托管。一台服务器上的 Web 服务器(在虚拟机中运行)无法被另一台服务器访问,但互联网上任何其他尝试访问的人都可以访问。
设置:
我们有两台由 ServerBeach 托管的服务器。两台服务器都运行 Debian,其中一台运行 VMWare Server 2,带有两台虚拟机 - 每台虚拟机也运行 Debian。每台虚拟机都运行 Apache 并提供网站服务。一些伪造的为清晰起见,IP 如下:
服务器 #1 (eth0): 10.0.1.1
服务器 #2 (eth0): 11.0.0.1
服务器 #2 辅助 IP (eth0:1) - 用于 VM #1: 10.0.2.1
服务器 #2 辅助 IP (eth0:2) - 用于 VM #2: 10.0.2.2
服务器 #2 上的虚拟机通过仅主机网络连接到主机:
服务器 #2(vmnet1):192.168.0.1
虚拟机 #1:192.168.0.2
虚拟机 #2:192.168.0.3
... 服务器 #2 上的 iptables 规则将发往这些辅助 IP 的互联网流量修改为目标 IP 以前往虚拟机,并将从虚拟机发往互联网的流量修改回原点:
-A PREROUTING -d 10.0.2.1 -i eth0 -p tcp -m tcp --dport 80 -j DNAT --to-destination 192.168.0.2:80
(...)
-A POSTROUTING -s 192.168.0.2 -o eth0 -j SNAT --to-source 10.0.2.1
这是可行的。互联网上的计算机可以将其浏览器指向http://10.0.2.1并使 Web 服务器在 VM 上运行。这种设置(其中辅助 IP 是主机上的别名,而不是 VM 本身)是 ServerBeach 坚持的 VMWare 设置应配置方式。它确实做到了。
唯一奇怪的是,当服务器 #1 尝试像互联网上任何其他客户端一样访问服务器 #2 VM 时,它会超时。(我通过 SSH 登录到服务器 #1,并使用链接尝试浏览该站点,甚至在端口 80 上进行 telnet)
如果我在 VM #1 上运行 tshark,我会看到 SYN 数据包从服务器 #1 通过服务器 #2 到达 VM:
4.607664 10.0.1.1 -> 192.168.0.2 TCP 44983 > http [SYN] Seq=0 Win=5840 Len=0 MSS=1460 TSV=318986 TSER=0 WS=7
52.596287 10.0.1.1 -> 192.168.0.2 TCP 44983 > http [SYN] Seq=0 Win=5840 Len=0 MSS=1460 TSV=330986 TSER=0 WS=7
(etc...)
SYN 数据包不断涌来,但虚拟机从不发回 SYN-ACK。
现在,如果我跳到任何其他计算机并在浏览器中转到该 URL,我会看到 SYN、SYN-ACK 和 ACK,当然还有随后的流量(我们将这个其他系统称为 170.0.0.1):
8.456176 170.0.0.1 -> 192.168.0.2 TCP 16945 > http [SYN] Seq=0 Win=65535 Len=0 MSS=1460 WS=1 TSV=972883011 TSER=0
8.456243 192.168.0.2 -> 170.0.0.1 TCP http > 16945 [SYN, ACK] Seq=0 Ack=1 Win=5792 Len=0 MSS=1460 TSV=718068724 TSER=972883011 WS=4
8.522374 170.0.0.1 -> 192.168.0.2 TCP 16945 > http [ACK] Seq=1 Ack=1 Win=66608 Len=0 TSV=972883012 TSER=718068724
(... let the GETs begin! ...)
VM #2 上也发生了同样的事情。每个人都可以访问并与 Web 服务器通信除了服务器 #1。
当然,服务器#1可以访问互联网上的任何其他网站。
编辑:如果我从服务器 #1 运行 nmap -sS 10.0.2.1,端口 80(以及服务器 #2 设置为传递给虚拟机的任何其他端口)将显示为已过滤。但是,如果我从任何其他机器执行相同的 nmap,端口将显示为打开。
我知道这个问题可能很难理解,我当然不希望任何没有动手能力的人当场想出答案。但我确实想知道是否有人可以回答... VM #1 从服务器 #1 获得 SYN 数据包,但没有尝试发送 SYN-ACK 回来的原因可能是什么?我认为问题可能与主机有关,但 SYN 显然确实到达了 VM,它似乎在到达那里后忽略了它们 - 但它会立即响应来自任何其他客户端的 SYN。
只是在这里寻找线索。
编辑#2:按照 kubanskamac 的建议,我可能发现了问题。
在 VM #1 上,netstat -rn 提供:
Destination Gateway Genmask Flags MSS Window irtt Iface
192.168.0.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0
10.0.0.0 0.0.0.0 255.0.0.0 U 0 0 0 eth0
0.0.0.0 192.168.0.1 0.0.0.0 UG 0 0 0 eth0
因此,如果我没有看错的话,VM 发往 10.xxx 的任何内容都不会发往 192.168.0.1(VMWare 主机的适配器,也是 VM #1 通向外界的唯一路径)。
那么我该如何让虚拟机 #1 至少通过 192.168.0.1 网关路由发往 10.0.1.x 的数据包呢?查看服务器 #2 的 netstat -rn,我认为如果服务器 #2 收到数据包,它会正确路由该数据包。
编辑#3:已解决!
编辑 #2 的线索是正确的。我使用“route”命令回答了我自己的问题:
路由添加-net 10.0.2.0 网络掩码 255.255.255.0 gw 192.168.0.1
最后一个问题:如何使上述命令永久生效?
答案1
Server1 似乎与 Server2 的接口 eth0:1 位于同一子网,但您没有提供网络掩码,所以我不确定。
您的 POSTROUTING 规则仅在 Server2 决定通过 eth0 或 eth0:1 或 eth0:2 发送数据包后才会启动。要发送数据包,Server2 需要找出哪个 MAC 地址是目标(它使用 ARP 来查找 MAC)。如果 Server1 位于不同的子网上,则应将数据包发送到默认网关的 MAC。如果 Server1 位于同一个 IP 子网上(看起来如此),则无需打扰默认网关,Server2 独自尝试将 IP 解析为某个可用的 MAC。如果不成功,则无法发送数据包 - 它无处可去。
arp -a # (on Server2) print known MACs
netstat -rn # (on Server2 and VM1) print table for IP routing decisions
答案2
您的 NAT 妨碍了您的工作。具体来说,返回数据包的原始源地址是目标地址,因此不会通过 NAT 设备进行解除 NAT。
答案3
您知道只有 10.xxx 可以正常使用,而 11.xxx 不行吗?其他可用的 IP 是 172.16-32.xx 和 192.168.xx 170.xxx 不可用。您提到给出的 IP 是假的,所以这可能没用。
服务器 #1 的 IP 是否列在虚拟机或其主机的 /etc/hosts.deny 文件中?
我假设您已经检查了虚拟机的防火墙规则以确保它没有被丢弃。