openclash 开启后端口转发失效

openclash 开启后端口转发失效

💡 原文中文,约7300字,阅读约需18分钟。
📝

内容提要

最近发现服务器访问日志中的IP都是内网IP,经过排查发现是socat工具导致的。尝试使用iptables解决,但发现不行。关闭openclash后一切正常,增加iptables规则后可以正常响应http请求,但获取的来源IP变成了宿主机的内网IP。经过分析发现是openclash内核导致的。尝试让流量不经过内核,成功解决问题。但后续发现内部服务无法访问,解决办法是增加NAT回环规则。总结使用socat进行端口转发会导致http server无法正确获取来源IP,在部署了openclash的内网NAT环境下,正确使用iptables进行端口映射需要配置不经过内核的源端口流量,并增加端口转发规则和NAT回环规则。

🔎

延伸解读

socat 转发为何丢失真实源 IP

文章指出,使用 socat 进行端口转发时,HTTP 服务器获取到的源 IP 始终是 pve 宿主机的内网地址 100.100.0.1。这是因为 socat 作为用户态代理,会以自身身份重新发起连接,从而改变了原始来源地址。若需要保留客户端真实 IP,应改用 iptables 的 DNAT/SNAT 规则进行内核级转发,而非依赖 socat。

openclash 内核如何干扰端口映射

在 openwrt 作为网关且启用 openclash 的环境中,所有出站流量都会经过 clash 内核处理。当使用 iptables 做 DNAT 后,流量进入 openclash 时,内核可能因连接跟踪不一致而返回 RST 包,导致握手成功后连接被强制关闭。tcpdump 抓包显示客户端与服务端握手正常,但随后收到来自服务端的 RST,说明问题出在 openclash 对流量的处理逻辑上。

绕过内核与 NAT 回环的配合

解决方案是在 openclash 的访问控制中,将 80、443 等源端口设置为不经过内核,使这些流量直接由 iptables 处理,从而恢复真实源 IP。但这样会导致内网机器无法通过公网 IP 访问内部服务,因此还需在宿主机添加 NAT 回环规则:对目标为公网 IP 的流量做 DNAT,并对来自内网网段的流量做 MASQUERADE,确保内部访问也能正确转发。

❓

Q&A

socat工具如何影响HTTP服务器的IP获取?

socat工具会改变来源的端口IP,导致HTTP服务器无法正确获取真实的来源IP。

关闭openclash后,问题有什么变化?

关闭openclash后,HTTP服务器能够正常获取真实的来源IP。

如何使用iptables解决socat导致的问题?

需要配置iptables规则,确保流量不经过openclash内核,并增加NAT回环规则。

为什么增加iptables规则后来源IP变为宿主机内网IP?

因为流量经过openclash内核处理,导致返回的来源IP被替换为宿主机的内网IP。

如何配置不经过内核的源端口流量?

在openclash的访问控制中设置不经过内核的源端口流量,例如80和443端口。

NAT回环规则的作用是什么?

NAT回环规则确保内部服务能够正常访问外部IP,避免流量被错误处理。

🏷️

标签

➡️

继续阅读