为什么 apache 使用外部域时会记录内部 IP?

为什么 apache 使用外部域时会记录内部 IP?

我有一台正在运行的 Raspberry Pi,我们在办公室使用它来执行一些我们不想在主开发服务器上运行的小型测试项目。它运行的是 Apache。DNS 通过 Cloudflare 处理,但处于 DNS Only 模式。目前,在我测试时没有 IP 限制。的 A 记录mysite.domain.tld指向我的静态 IP 地址123.123.123.123,并且 Internet 和 Pi 之间只有一个标准的商用光纤路由器/调制解调器。

mysite.domain.tld例如,当我使用没有 Wi-Fi 的手机访问时,手机运营商 IP 就会显示出来。当我wget使用远程服务器访问时,它是'IP 显示在日志中。一切如预期。

mysite.domain.tld但是,当我从 Pi 所在的同一网络内进入时,apache 会记录路由器网关 IP 192.168.1.1。我希望看到我的公共 IP 地址,因为我与域名的连接通过 Cloudflare 解析为公共 IP。但我在日志中看到的是本地网络 IP。

/etc/hosts路由器上没有设置任何内容(我使用的是 macOS),只有端口 443 的连接的端口转发才会路由到同一端口上的 Pi - 任何地方都没有提到域名。当我 ping 时mysite.domain.tld,它给了我CloudflareIP 地址,这正是我所期望的。

似乎在链条的某个地方,我的 IP 地址和 Pi 的公共 IP 地址被匹配,因此它用内部网关 IP 覆盖了 IP。这里究竟发生了什么?我不头脑就其本身而言,我只是想确保192.168.*在防火墙上设置 IP 限制时,我可以依赖 IP 是可信的事实。

注意:Cloudflare 不会在此处发送 CF-Connecting-IP 和类似标头,我推测这种情况仅在非 DNS Only 模式下才会发生。似乎仅当我使用与 Pi 相同的网络连接时才会发生。

答案1

您的路由器运行的是 Linux,这种行为在任何现有的 Linux 发行版上都很容易实现。我可以猜测路由器的防火墙中必须存在哪些规则才能使其正常工作。但请注意,这只是一种推测,我们不知道规则在现实中究竟是什么样子。

当您将端口转发到 Web 服务器时,它会添加一条特定的 DNAT 规则,该规则可能如下所示:

iptables -t nat -A PREROUTING -p tcp -d <your-external-address> --dport 443 -j DNAT --to-destination <raspberry-pi-address>

换句话说,这意味着:“在决定此数据包是否发往设备或必须转发之前,请检查数据包目标地址是否是您的外部地址,目标端口是否是 443。如果匹配,则将目标地址更改为 Raspberry Pi 的 LAN 地址”。请注意,此规则不会按接口进行过滤。

而且它肯定有 SNAT 类型的规则(用于为 LAN 提供互联网访问),可能看起来像这样:

iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -j MASQUERADE

换句话说,在路由器决定数据包必须发送到哪里之后,在发送数据包之前,它会将其源地址更改为出站接口的地址(如果数据包是从 LAN 发送的)。同样,接口不会过滤任何内容。

现在考虑您的 HTTPS 连接。您在浏览器中指定主机名,对吗?您将其设置为将其解析为路由器的外部地址,该地址将成为目标地址。您的源地址在 LAN 内部。因此,这两条规则似乎都适用于您的连接的数据包。

在处理这些数据包时,路由器首先遇到 DNAT 规则,检查目标地址和端口,并决定将目标地址更改为树莓派的地址。然后,它发现数据包必须通过的接口是 LAN 接口。然后,它根据第二条规则检查部分转换的数据包,并发现源地址来自 LAN。因此,它将数据包的源地址替换为 LAN 接口的地址 192.168.1.1。这就是你的树莓派看到的。

NAT 操作是有状态的,也就是说,它还维护一个表记录,该记录说明哪些被替换了,以及如何检测后续的转发和回复数据包,因此它可以正确地转换所有数据包。是的,事实证明 Linux 可以在同一个流中同时执行 DNAT 和 SNAT。

你能相信这种行为吗?我不知道。如果路由器的固件是开源的,我们就有机会检查。没有源代码,我们就不能确定。当源代码关闭时,情况总是如此,这就是为什么如果你担心安全问题,就必须避免使用闭源产品。

相关内容