我在使用 iptables 防火墙的服务器后面使用 virsh 的访客上遇到了问题。此访客托管网站,其中一个是使用反向代理的 mattermost。
一切运行良好。然后我安装了合作在线 1:https://www.collaboraoffice.com/code/。打开文档超级酷,而且它们有一个插入最重要的是
我从运行 mattermost 的远程服务器测试了这个插件,该服务器可以访问我 iptables 后面的本地框,并且它运行正常。但是,当我从客户本地服务器本身测试这个插件时,它在 iptables 后面,所以基本上是 NAT,它无法找到自己。我超时了。
因此,我的 iptables 后面的客户端设置了适当的规则来传递流量,拥有 mattermost 和 CollaboraOnline,但如果我将 mattermost 的公共 URL 指向获取 CollaboraOnline,则两个 localhost 都无法找到对方。我无法在插件中执行 localhost:9980 或 127.0.0.1:9980(这是 CollaboraOnline 所在的位置),它不喜欢地址中的端口...
如果我确实卷曲https://CollaboraOnline.domain.ca我可以看到它超时了。
如果我将 localhost 服务器上的 /etc/hosts 文件编辑为127.0.0.1 CollaboraOnline.domain.ca
,则 curl 可以工作,mattermost-plugin 确实可以找到 CollaboraOnline,但它仍然无法工作,因为我最终遇到了像这样的 SSL 类型验证错误。
AH02032:通过 SNI 提供的主机名和通过 HTTP 提供的主机名没有兼容的 SSL 设置如何绕过
所以现在我已经没有什么好主意了。我有另一个公共盒子,不在带有 iptables 的 virsh 后面,如果我对它的一个本地主机进行 curl 操作,一切都很好。这只能让我相信 iptables 可能需要一条规则,以便我的运行 mattermost 和 CollaboraOnline 的客户端能够在请求它自己服务的公共 URL 时循环回到自己?!?
有人对此有什么想法吗?
我的客户虚拟机是 192.168.122.126,托管 Vrish 客户机和 iptables 的父服务器是 192.168.122.1
以下是 iptables 规则(删除了一些混乱的内容,例如 fail2ban 内容)
iptables -L
Chain FORWARD (policy ACCEPT)
target prot opt source destination
ACCEPT all -- anywhere 192.168.122.126 state NEW,RELATED,ESTABLISHED
ACCEPT all -- anywhere 192.168.122.0/24 ctstate RELATED,ESTABLISHED
ACCEPT all -- 192.168.122.0/24 anywhere
ACCEPT all -- anywhere anywhere
REJECT all -- anywhere anywhere reject-with icmp-port-unreachable
REJECT all -- anywhere anywhere reject-with icmp-port-unreachable
iptables -L -t nat
Chain PREROUTING (policy ACCEPT)
target prot opt source destination
DNAT tcp -- anywhere 148.59.149.79 tcp dpt:9980 to:192.168.122.126:9980
DNAT tcp -- anywhere 148.59.149.79 tcp dpt:12000 to:192.168.122.126:12000
DNAT tcp -- anywhere 148.59.149.79 tcp dpt:11000 to:192.168.122.126:11000
DNAT tcp -- anywhere 148.59.149.79 tcp dpt:submission to:192.168.122.126:587
DNAT tcp -- anywhere 148.59.149.79 tcp dpt:imap2 to:192.168.122.126:143
DNAT tcp -- anywhere 148.59.149.79 tcp dpt:smtp to:192.168.122.126:25
DNAT tcp -- anywhere 148.59.149.79 tcp dpt:webmin to:192.168.122.126:10000
DNAT tcp -- anywhere 148.59.149.79 tcp dpt:4443 to:192.168.122.126:4443
DNAT udp -- anywhere 148.59.149.79 udp dpt:10000 to:192.168.122.126:10000
DNAT tcp -- anywhere 148.59.149.79 tcp dpt:http to:192.168.122.126:80
DNAT tcp -- anywhere 148.59.149.79 tcp dpt:https to:192.168.122.126:443
答案1
这里的罪魁祸首是错误/不完整的 NAT 规则。在 TCP 连接期间,每个端点都有固定的源/目标 IP,如果在此端口上收到具有不同源/目标 IP 的 IP 数据包,则该数据包将被丢弃。对于两个端点都是如此:客户端 ( curl ) 和服务器。
为了理解这个问题,我将跟踪数据包流,从客户端开始:
- VM 内部的 curl 向公共 IP 地址发送数据包。源 IP:192.168.122.126,目标 IP:148.59.149.79
- VM 的内核检查其路由表,并将 IP 数据包发送到其默认网关,即 192.168.122.1
- 主机的内核接收数据包并将其传递给 iptables 链(记住哪个链首先被遍历 - PREROUTING 在 POSTROUTING 之前)
- 在 PREROUTING 链中,目标 IP 被替换为 192.168.122.126
- 这里,POSTROUTING 链将被遍历。
- 由于目标 IP,数据包返回到虚拟机
- 在服务器套接字处,IP 数据包到达。目标 IP 和源 IP 均为 192.168.122.126。目前没有问题。
- 服务器套接字发送答复 - 这一次,由于目标 IP 是其自己的接口,因此主机的 NAT 规则将不会应用。
- 客户端套接字收到来自 192.168.122.126 的回复 - 这不是客户端套接字发送连接请求的 IP,因此数据包被丢弃。
解决方案是以某种方式更改源 IP 地址,使得来自 VM 服务器套接字的回复必须通过主机 NAT 规则:
iptables -t nat -I POSTROUTING 1 -s 192.168.122.126 -d 192.168.122.126 -j SNAT --to-source 192.168.122.1
请记住,SNAT 目标仅适用于 POSTROUTING 链内 - 因此,PREROUTING 链中的 DNAT 已经应用。
使用此规则,虚拟机内的服务器套接字将接收来自 192.168.122.1 的传入连接请求 - 发送回复,并且该回复将在到达主机后立即反向应用 SNAT / DNAT 规则:源为 192.168.122.126,目标为 148.59.149.79。
此答复与初始连接请求相匹配,并且连接尝试成功。