惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

博客园 - Franky
有赞技术团队
有赞技术团队
宝玉的分享
宝玉的分享
雷峰网
雷峰网
Hugging Face - Blog
Hugging Face - Blog
V
V2EX
大猫的无限游戏
大猫的无限游戏
博客园 - 司徒正美
D
Docker
T
The Blog of Author Tim Ferriss
罗磊的独立博客
博客园 - 叶小钗
酷 壳 – CoolShell
酷 壳 – CoolShell
Blog — PlanetScale
Blog — PlanetScale
月光博客
月光博客
J
Java Code Geeks
Jina AI
Jina AI
博客园 - 【当耐特】
C
Check Point Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
腾讯CDC
Last Week in AI
Last Week in AI
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
V
Visual Studio Blog

Dallas Lu

一些没有意义的事情 博客程序的一次大重构 OpenWRT 使用 udp2raw 对抗 WireGuard 阻断 如何证明你是原创作者 Nginx 泛域名配置的隐患与对策 WISeID S/MIME 证书 V2EX 刑满释放记 使用 Radicale 在 Ubuntu 24.04 中搭建 vCards CardDav 服务 邮件服务的域名成功从 SURBL 黑名单移除 The Domain of Mail successfully removed from SURBL blacklist 网站多语言的设计细节 Website Multilingual Design Details 网站评论系统的目前进展和展望 Current Progress and Outlook of the Website Comment System 在公网使用 iptables 转发端口时保留客户端 IP Retaining Client IP with iptables Port Forwarding on Public Networks 邮件投递平台 Postal 的使用经验 Experience with Using Postal, the Mail Delivery Platform 自建 Postal 完美替代 SendGrid Build Your Own SendGrid: Postal SMTP Server 互联网在崩塌吗,然后呢 Is the Internet collapsing and then what 在 SvelteKit 应用中使用 JSON-LD Using JSON-LD in SvelteKit Applications 网页的打印样式应该怎么写 How to write print styles for web pages “茴字的四种写法”之 IP 与域名 Trivia: Special ways of writing IP and domain names 怎么伪造 Git 提交的时区 How to fake the timezone of a git commit
一次排查诡异的网络问题的经历
达拉斯・卢 · 2024-03-20 · via Dallas Lu

最近一段时间,自建的 Forgejo 总是无法通过 ssh 进行 pull 和 push。总是用着用着,就出问题了,只好切换到其他 IP,立即就正常了。即使置之不理,偶尔也会莫名正常,但在常用的几个工作网络却经常不行。最终,我决心要彻底解决这个问题。

问题现象

假设我需要连接的目标地址是 1.2.3.4:22

连接总是断开

当我在出现问题的网络环境中执行 telnet 1.2.3.4 22 时,会有提示:

Connection closed by foreign host.

但同服务器上还运行着其他服务,均可正常连接。

从其他 IP 可正常连接

尝试过从其他 IP,比如各地云主机、移动网络,几乎都可正常连接。

初步分析

很明显,常用的几个 IP 出了问题,可能是被哪里的房火墙阻断了。但所有的设备都是我一人管理,从来没有配置过限流之类的策略。互联网中的设备也没有道理阻断我连接某台服务器的 22 端口啊。

flowchart LR client["Terminal"] router["OpenWRT"] front["Front Server"] server["Forgejo Server"] client --> router router --> front front --> server

自然,开始排查提供端口转发的 Front Server。使用 tcpdump:

tcpdump -i any port 22 and host 1.2.3.4

再次尝试连接,日志显示:

...
Flags [R.], seq 0, win 0, length 0

嗯,果然和 FrontServer 有关系。

误入崎途

于是开始在 FrontServer 上逐个测试当前的 UFW 配置,一遍一遍不厌其烦地重启防火墙,检查 iptables,查看日志。直到在 syslog 中发现了 ss-server 日志:

ss-server getpeername: Transport endpoint is not connected

日志输出节奏与测试一致。基本上是有关联了。但关掉 ss-server 仍然不起作用。

继续测试除 22 外的其他端口,凡是 FrontServer 本地没有监听、用 iptables 做的端口转发,竟然也都被 RST 了。搜遍网络,也没有找到有人遇到相似的案例。

跟 GPT4 的对话已经有一万五千字,仍然一无所获。

柳暗花明

最终,无奈放过了 FrontServer,决定到 OpenWRT 上看一看。关闭了 OpenWRT 的防火墙服务,突然一切正常了。

It works! But why?

切换到备用路由器,也同样正常。再复现一下,切回 OpenWRT,打开防火墙——仍然正常。问题竟然不能复现了!

防火墙做了什么?

此前用 nftables 给 OpenWRT 加了一些规则1,通过 Shadowsocks 连接到 FrontServer,FrontServer 上配置了一个住宅 IP 的分流策略2,这样就可以方便地使用住宅 IP 访问各种服务。

防火墙重启后,会重置 nftset。这样就不会将 1.2.3.4 的流量转发到 Front Server 上的 ss-server,这也解释了为何 ss-server 会有对应日志。

问题原理

  • OpenWRT 上有一个用于分流到位于 Front Server 上的 ss-server 的 nftset
  • Front Server 的 IP 1.2.3.4 不知为何进入了 nftset 中。
  • 当在本地尝试连接 1.2.3.4:22 时,OpenWRT 通过 Shadowsocks 将流量转发到位于 1.2.3.4 的 ss-server 上
  • ss-server 将流量发往 1.2.3.4:22
  • 1.2.3.4:22 实际上是一个端口转发(FORWARD),并不处理 FrontServer 本机发出的流量

验证与解决

在另一个环境中,也有着同样的问题。在另外一个 OpenWRT 中,验证 1.2.3.4 是否加入了代理名单中:

nft list table inet fw4 | grep 1.2.3.4

果然存在。手动将其移除:

nft delete element inet fw4 gfwlist { 1.2.3.4 }

当然也可使用 UFW 额外添加一条 OUTPUT 规则,让 ss-server 也能访问到转发的端口3

最后一块拼图

1.2.3.4 为何会出现在 nftset 中呢?

此前在 OpenWRT 上部署了测试用的将 gfwlist 的域名用 dnsmasq 在访问时自动添加到此 nftset 的规则。而 Front Server 的 IP 是怎么被加入 nftset 的呢?我使用过的域名都不在 gfwlist 中,我也没有为我拥有的域名写过任何 dnsmasq 的配置。

我排查了我的所有域名的所有 A 记录,发现仅有几条是直接指向 1.2.3.4 的,其中一个是 EU.org 的免费域名4。马上检查 gfwlist,果然,eu.org 位列其中。

结语

flowchart LR client["Terminal"] server["Forgejo Server"] subgraph OpenWRT router["router"] firewall["Firewall"] ipset{"IP Set"} dnsmasq["Dnsmasq"] gfwlist{GFW List} ssclient[SS Client] end subgraph FrontServer[Front Server] ssserver["SS Server"] farward["Port Farward"] ssserver -->|Failed | farward end client -.->|DNS: my '.eu.org'| dnsmasq client -->|Request| firewall dnsmasq -.-> gfwlist gfwlist -.->|Yes: add to| ipset firewall --> ipset ipset --> |Yes: Redirect| ssclient ipset --> router ssclient --> ssserver router --> farward farward --> server

每当我在本地网络,访问我的指向 1.2.3.4 IP 的域名后,后续的流量就会通过 Shadowsocks 发送,继而导致问题。但排查时需要细心仔细,要相信,计算机是没有错误的;所有奇怪的现象,背后一定有原因。


  1. Dallas Lu. 在 OpenWRT 23 中使用 nftset 配置 Shadowsocks 规则. ISSN 2770-7288. 2024 ↩

  2. Dallas Lu. 访问 ChatGPT 终极方案:IPRoyal 美国家宽 IP. ISSN 2770-7288. 2023 ↩

  3. Andy. Answer to 'iptables port redirect not working for localhost'. serverfault. 2013. ↩

  4. Dallas Lu. EU.org 免费域名的注册与使用. ISSN 2770-7288. 2023 ↩