(在详细介绍之前,我以 Apache 和 SSH 为例来介绍这个问题,但这并不特定于 TCP 流量,它与基于 TCP 和 UDP 的协议的问题相同。)
我有一个运行 Ubuntu 9.04 的多链接、多宿主服务器,eth0 连接到外部网络,eth1 连接到内部网络。外部网络呈现给“世界其他地方”,内部网络包含所有开发人员工作站和主力服务器。有防火墙阻止从“世界其他地方”到内部网络的流量,但不阻止传出请求。
$ /sbin/ifconfig
eth0 Link encap:Ethernet HWaddr 00:30:18:a5:62:63
inet addr:xxx.yyy.159.36 Bcast:xxx.yyy.159.47 Mask:255.255.255.240
[snip]
eth1 Link encap:Ethernet HWaddr 00:02:b3:bd:03:29
inet addr:xxx.zzz.109.65 Bcast:xxx.zzz.109.255 Mask:255.255.255.0
[snip]
$ route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
xxx.yyy.159.32 0.0.0.0 255.255.255.240 U 0 0 0 eth0
xxx.zzz.109.0 0.0.0.0 255.255.255.0 U 0 0 0 eth1
0.0.0.0 xxx.yyy.159.33 0.0.0.0 UG 100 0 0 eth0
Apache 监听 80 端口,sshd 监听 22:
$ netstat --tcp -a
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 *:www *:* LISTEN
tcp 0 0 *:ssh *:* LISTEN
[snip]
从我在里面的开发机器,xxx.zzz.109.40,我可以连接到里面的地址,一切都很好。从外部我可以连接到外部地址,一切正常。
但是对于某些类型的测试,我想从我的开发机器连接到外部地址,但服务器拒绝连接请求。我猜它正在查看它的路由表,并且由于传入的数据来自一个应该在 eth1 上但到达 eth0 的地址,因此它正在丢弃它,这可能是出于安全预防措施。
有什么办法可以放宽这个限制吗?
奇怪的是,这曾经在 8.04 上工作,但在 8.10 或 9.04 上不起作用,所以在去年的某个时候,内核正在做一些额外的检查。为了使连接正常工作,返回路径需要与源路径相同,这意味着来自我的开发机器到达 eth0 的消息必须返回到 eth0 才能路由回我的机器。
这是一个图表,任何地方都没有 NAT。
假设您没有任何 iptables 规则可以阻止这种情况,您需要禁用返回路径过滤。您可以使用以下方法执行此操作:
您还可以使用特定的接口名称而不是全部,并且还有一个默认值,这会影响新创建的接口。
从:
您还没有显示您的防火墙配置,但我敢打赌,那里有一条规则在过滤从内部到外部 IP 地址的连接时会做一些不利的事情。一个严重搞砸的 NAT 配置也可能有问题,但我很难想象一次普通的配置尝试会导致如此病态的事情。
也只是为了澄清一点:仅仅因为一个数据包来自一个接口,地址是另一个接口的 IP 地址,不会导致内核拒绝该数据包。无论发生什么,都不是内核的错。
此外,流量的 tcpdump(在服务器的内部和外部接口上以及在客户端上)在诊断上也很有用。
您的开发机器的默认网关是什么?假设第 3 层交换机/路由器的默认网关应该知道如何到达服务器的其他接口。
你应该有类似的东西
这应该使事情正常进行。但如果这还不够,请在机器 xxx.zzz.109.65 上启用 IP 转发,使用
还要编辑 /etc/sysctl.conf 并在那里启用 ip 转发。
确保 xxx.zzz.109.65 上过滤表的 iptables FORWARD 链允许您的开发机器进行数据包转发。
我猜您正在使用该框作为使用 iptables NAT 的 Internet nat 路由器 - 显然,如果不是这种情况,那么这将无济于事,否则您可能需要类似的东西:
这将跳过您为从内部到外部传输的数据包所做的源 natting,这些数据包针对任何发往该服务器的外部 IP 的内容。
只是为了肛门,我不会将上述网络配置称为多宿主。它只是在同一个 AS 内的两个网络之间转发。如今,多宿主实际上意味着连接到两个或多个邻居 (AS),或者至少连接到同一个上游邻居 (AS) 的多条路由,在叶网络具有单个上游连接提供商的情况下。
已经给出了很多有用的想法。我会 a) 仔细检查它不是防火墙/NAT。在你的 REJECT 和 DROP 规则之前添加一个 -j LOG 规则,看看是否有任何可疑的东西被捕获。b) 在两个接口(-i any)上运行 tcpdump 并查找您的数据包。
顺便说一句,“服务器拒绝连接请求”到底是什么意思?您是否看到一些(立即)拒绝消息或连接只是超时?
这一定是您的防火墙规则的问题。盒子自己的外部 IP 很可能与“所有外部流量”混为一谈,因此不允许返回到内部客户端。尝试在该 IP 地址的防火墙规则中设置一个例外;也就是说,明确允许网络服务器的外部 IP 地址向内部网络发送流量。
更多调试将要求您发布防火墙规则。