(在详细介绍之前,我将以 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。
答案1
假设您没有任何可以阻止这种情况的 iptables 规则,则需要禁用返回路径过滤。您可以使用以下命令执行此操作:
# echo 0 > /proc/sys/net/ipv4/conf/all/rp_filter
您还可以使用特定的接口名称而不是全部,并且还有一个默认值,这会影响新创建的接口。
从:
反向路径过滤器;它是检查对于到达接口的数据包,发送到原始数据包源地址的数据包是否会从该接口发送出去;如果不是,则丢弃到达的数据包。它可以被认为是检测具有欺骗源地址的数据包的尝试。
答案2
您没有显示防火墙配置,但我敢打赌,其中肯定有一条规则在过滤从内部到外部 IP 地址的连接时出现了问题。NAT 配置严重混乱也可能是问题所在,但我无法想象普通的配置尝试会导致如此严重的问题。
还要澄清一点:仅仅因为一个数据包来自一个接口,并且被发送到另一个接口的 IP 地址,不是导致内核拒绝该数据包。无论发生什么,都不是内核的错。
此外,流量的 tcpdump(在服务器的内部和外部接口上以及在客户端上)在诊断上很有用。
答案3
你的开发机器的默认网关是什么?假设第 3 层交换机/路由器的默认网关应该知道如何到达服务器的其他接口。
你应该有类似的东西
ip route xxx.yyy.159.36 netmask 255.255.255.240 gw xxx.zzz.109.65
这应该可以正常工作。但如果这还不够,请使用以下命令在机器 xxx.zzz.109.65 上启用 IP 转发
sysctl net.ipv4.ip_forward = 1
还要编辑 /etc/sysctl.conf 并在那里启用 ip 转发。
确保 xxx.zzz.109.65 上的过滤表的 iptables FORWARD 链允许为您的开发机器转发数据包。
答案4
出于严谨的考虑,我不会将上述网络配置称为多宿主。它只是在同一 AS 内的两个网络之间进行转发。如今,多宿主实际上意味着连接到两个或多个邻居 (AS),或者在具有单个上游连接提供商的叶网络的情况下,至少连接到同一上游邻居 (AS) 的多个路由。