现在,很自然地会产生一个问题,如果我们能做到将 HTTP 连接重定向到本地端口的这些便捷操作,那么我们是否可以对远程服务器执行相同的操作呢?(例如,运行 Squid 的机器与运行 iptables 的机器不是同一台机器)。 答案是肯定的,但这需要一些不同的“诀窍”。 如果你只想重定向到本地服务器(通常情况),请跳过本节。
为了示例命令的目的,我们假设我们有两台机器,分别称为 squid-box 和 iptables-box,并且它们在本地网络 local-network 上。 在下面的命令中,将这些字符串替换为您机器和网络的实际 IP 地址或名称。
我将在这里介绍两种不同的方法。
首先,我们需要运行 Squid 的机器,即 squid-box。 您不需要在这台机器上安装 iptables 或任何特殊的内核选项,只需 Squid 即可。 但是,您*将*需要如上所述的 'http_accel' 选项。(本 HOWTO 的早期版本建议您不需要这些选项。那是个错误。很抱歉给人们造成了困惑......)
现在,是运行 iptables 的机器,即 iptables-box。 您需要按照上面第 3 节中的描述配置内核,但您不需要 REDIRECT 目标支持)。 现在,对于 iptables 命令。 您需要三个:
第一个命令将数据包从 iptables-box 发送到 squid-box。 第二个命令确保回复通过 iptables-box 发回,而不是直接发送到客户端(这非常重要!)。 最后一个命令确保 iptables-box 将转发适当的数据包到 squid-box。 它可能不是必需的。 YMMV(您的里程可能会因情况而异)。 请注意,我们指定了 '-i eth0',然后是 '-o eth0',这分别代表输入接口 eth0 和输出接口 eth0。 如果您的数据包在不同的接口上进入和离开,您将需要相应地调整命令。
将这些命令添加到 /etc/rc.d/ 下的适当启动脚本中。
(感谢 Giles Coochey 帮助撰写本节)。
我们的第一种方法效果很好,但存在一个小的缺点,即没有 Host 标头的 HTTP/1.0 连接无法正确处理。 完全或部分符合 HTTP/1.1 标准的连接可以正常工作。 由于大多数现代 Web 浏览器都发送 Host 标头,因此对于大多数人来说这不是问题。 但是,一些小型程序或嵌入式设备可能只发送非常简单的 HTTP/1.0 请求。 如果您想支持这些,我们需要做更多的工作。 也就是说,在 iptables-box 上,除了上面指定的选项外,我们还需要在内核中启用以下选项:
您还需要 iproute2 工具。 您的发行版可能已经安装了它们,但如果没有,请查看 ftp://ftp.inr.ac.ru/ip-routing/。
您需要在 iptables-box 上使用以下命令集:
接下来,是 squid-box。 使用此命令,它应该与我们之前见过的命令非常相似。
以下是对此工作原理的简要说明:在第一种方法中,我们使用网络地址转换来将数据包发送到另一台服务器。 这样做的结果是数据包被更改。 这种更改是导致上面提到的一些类型的客户端失败的原因。 在第二种方法中,我们使用一种称为策略路由的神奇技术。 我们做的第一件事是选择我们想要的数据包。 因此,端口 80 上的所有数据包,除了来自 squid-box 本身的数据包外,都被标记(MARKed)。 然后,当内核进行路由决策时,标记的数据包不会使用您使用 ``route'' 命令访问的正常路由表进行路由,而是使用一个特殊的表。 这个特殊的表只有一个条目,即指向 squid-box 的默认网关。 因此,数据包顺利地发送出去,而没有被更改过。 因此,即使是 HTTP/1.0 连接也可以完美处理。(感谢 Michal Svoboda 建议并帮助撰写本节)
如果 iptables-box 位于动态 IP 地址上(例如,拨号 PPP 连接,或来自有线调制解调器的 DHCP 分配的 IP 地址等),那么您需要对上述命令进行一些小的更改。 将第二个命令替换为以下命令:
此更改避免了在命令中指定 iptables-box 的 IP 地址。 由于它会经常更改,您必须更改您的命令以反映它。 这将为您节省很多麻烦。