背景
家里的一些服务从外部访问出错了,日常用的Nextcloud等都无法连接。表现为从公司或腾讯云等无法建立连接(通过域名加端口方式访问),但是从内部访问一切正常。这个服务是从Unifi的路由器USG中做了端口转发到达的。
诊断过程
k3s集群问题乎?
查看对应转发服务日志,可看到TLS handshake error
和tls: client using inappropriate protocol fallback
。
|
|
这个服务是部署在k3s集群内的。日志中10.42.2.1是哪个IP?它既非pod IP也非svc IP,和GPT4交谈后,提醒了我:
虚拟网络接口的 IP 地址:若你使用的网络插件(如 Flannel, Calico)为每个 Pod 创建了虚拟网络接口,那么
10.42.2.1
可能是某个虚拟网络接口的 IP 地址。
经查证发现是CNI0的IP,10.42.2.98是目标Pod IP,但是SSL会话出错了,可能是什么原因?因为最近集群出过一点问题,作为k3s的master节点在一台NUC上挂了一次。故第一反应是集群网络层异常了。尝试重启k3s server和agent,问题旧。这也不能证明集群没有问题,为此我设想建立一个不在集群的内部服务并对外提供服务,如果它能复现此问题,说明多半和集群无关?
说干就干,可以基于docker快速部署一个带证书的Nginx,直接叫GPT给我相关的nginx.conf配置文件以及docker-compose就好,分分钟起来。然后在路由上配置好对应的端口转发,同样的问题再次出现!!
到这一步,大概说明此非集群问题。
防火墙问题乎?
为了搜索更多线索,使用curl发起对应HTTPS调用:
|
|
看起来SSL失败了,GPT建议使用openssl来调试一下,依据建议执行:
|
|
我把上面的结果和GPT聊了一下,它提供如下建议,我觉得挺有道理。
Tip
根据你提供的信息,从内部网络可以正常访问Service,但从外部访问时无法建立安全连接。同时,从外部使用openssl诊断时,提示没有可用的peer证书。这可能是由以下几个原因导致的:
- USG防火墙规则配置问题:请检查USG的防火墙规则,确保外部流量已正确转发至Service所在的VLAN。同时,请检查是否允许了外部到Service的HTTPS流量(端口6443)。
- SSL证书配置问题:请检查Service(如Nginx)的SSL证书配置,确保已正确配置了证书文件(包括证书链、私钥等)。此外,请确保证书文件的权限设置允许Service读取。
- NAT配置问题:请检查USG的NAT(网络地址转换)配置,确保外部IP地址(<家公网IP>)已正确映射到内部Service的IP地址和端口(6443)。
- 路由配置问题:请检查内部网络的路由配置,确保Service和USG之间的通信路径是正确的。这可能涉及到VLAN间路由和子网掩码的配置。
诊断思路:
- 首先,检查USG的防火墙规则和NAT配置,确保外部流量能正确转发到Service所在的VLAN,且允许了外部到Service的HTTPS流量(端口6443)。
- 其次,检查Service(如Nginx)的SSL证书配置,确保已正确配置了证书文件(包括证书链、私钥等),并检查证书文件的权限设置。
- 最后,检查内部网络的路由配置,确保Service和USG之间的通信路径是正确的。这可能涉及到VLAN间路由和子网掩码的配置。
GPT认为可能是防火墙配置问题,可是我最近几个月没有操作防火墙的任何设置,为什么会出现这个情况呢?但是内部能访问从外部又失败,确实这个承担外部流量入口的USG又是有重大嫌疑的。
看了几遍防火墙配置没有线索,通过SSH进入USG的后台,抓包看看:
|
|
一个个看这个包还有点麻烦,试了一下GPT能否快速从中提炼有效信息,它果然可以。从后端服务机器上也抓了包,表现上类似,GPT给的回复是:
Tip
从你的数据包捕获中,我们看到了一些有趣的事情。在这里,我们可以明确地看到服务器对 PSH, ACK
包的回应。这个包通常用于开始TLS握手。
此外,我们也看到了一个 RST
包。令人惊讶的是,来自客户端的 ACK
包被服务器正确地响应后,随即就发送了 RST
包。这种行为可能表明服务器遇到了错误,无法处理这个连接,因此它选择将其重置。
以下是一些可能的原因:
- 服务端故障或配置问题:后端服务器(10.42.2.98)上运行的软件可能在尝试处理请求时遇到错误。例如,它可能没有正确配置,或者它不支持客户端尝试使用的特定TLS版本或密码套件。请检查后端服务器的日志以获取更多信息。
- 网络设备干扰:服务端和USG设备之间的某个网络设备可能正在尝试修改或拦截流量,而这可能导致了上述行为。例如,某些类型的网络设备(如IPS、IDS或代理服务器)可能会阻止特定类型的TLS流量。请检查这些设备的配置并确保它们不会影响TLS流量。
建议你进一步检查服务端的设置以及与服务端之间的网络路径,看看是否存在可能导致这种行为的任何问题。
为了快速排查是否防火墙问题,借助于Unifi的定期备份,很方便的将配置恢复到了一个月前(期间我也没改过配置,并且可以肯定当时服务等肯定是正常的)。问题依旧!! 我还是不死心,觉得不是它还会是谁呢?于是查看其iptables规则,放通各种限制等尝试,都没有解决。
比如,在UBNT终端,查看iptables规则(没错:GPT也懂iptables,并且能从一堆规则中分析所关注的内容):
sudo iptables -L -n -v
也在Unifi Controller中开启了相关规则的日志记录,查看连接日志:
sudo tail -f /var/log/messages
端口转发没有问题,也没有包被丢弃等(看iptables表的统计数据)。问题到底在哪里?这可太神奇了吧!以至于凌晨2点了还没困意oO_Oo。星期天的白天除了带娃,一有空也继续看看此问题。找不到其它想法,求助于技术群的小伙伴,可能上下文关联太多描述不清,没有特别的线索出现。
不经意的联想
突然想起来因为旁路由的设置,我的机器网关设置的都是OpenWRT的IP地址。最近因为玩chatGPT插件等,将代理切换到openclash以便使用一些规则。莫不是这家伙在捣蛋?
赶紧停掉openclash,果不其然,问题消失了!切换到Pa**wall好像也没出现此问题(以前一直用它)。有点欣喜又有点无奈,我怎么忘记最近网络的变动,它也算是一环呢!
查看规则列表,我们确实会定义对于局域网的一些不走代理:
|
|
不过我理解这只是目标地为这些IP的命中后直连,我的场景中目地IP应该是外部发起连接的IP。但连接应该是外部主动发起,为什么openclash会将被动连接建立的回包发给了代理呢,难道不区分主动/被动?这个目前我仍旧无法解释,有懂openclash的同学欢迎给出解释。
但是既然知道是它,做法就比较简单了,只需要如下两个开关选择其一就可以解决问题。
- 既然我用的是非标端口,那放通常用端口也就OK。
- 既然因为回包错误被代理,那使其绕过XXIP地址也是一个选项。
题外话:有时在想,国内程序员经常因为某种能力和网络作斗争也是件悲哀的事:( 不过倒是能学点网络知识,只能这么想聊以慰藉啦。
尾声
“事出反常必有妖”。这个事情的出现在近几天,我的定位过程还是走了一些弯路。因为人的记忆力有限,不能快速将一些事情作关联,像在查此问题时,完全忘记了前几天修改过openclash,改后它运转的好好的,你就忘记这事了,没想到带来了如此的副作用。
早上开车上班路上,我在想若能把基础设施完全声明式,可能能有效解决哪里变动不自知的问题。这包括:
- 路由器的配置。基于EdgeOS的USG是很容易做到这一点的,但要打通自动化更新路由还有点路要走。
- OpenWRT系统及插件声明式。插件的配置或许不经意间被改错了,以往一般从旧的快照恢复,然而不知道具体哪些修改引入的?
声明式的Linux系统我知道有一个NixOS了,最近打算学习一下。那么,声明式的路由在哪里?(所有插件的版本,参数均是声明的?)好像还有很长的路要走哩。
PS:本次诊断大量借助AI辅助,在效率上有所突破,诊断问题很少因某知识点不够完备受阻,但能否解决问题,思路上比较看人。