本文是2021年4月时,南科大镜像站遇到的TLS连接重置问题的调试存档。一句话概括情况:在校外向镜像站公网v4地址(116.7.234.220)的TCP 443端口发起的首个HTTPS连接会被中间设备(middlebox)抢答并阻断,镜像站主机根本没有收到这条TCP连接相关的数据包。

简介

在校外向镜像站公网v4地址(116.7.234.220)的TCP 443端口发起的首个HTTPS连接会被中间设备(middlebox)抢答并阻断,镜像站主机根本没有收到这条TCP连接相关的数据包。

在北京时间09:00-24:00这个问题可被重现的概率极高,在凌晨则似乎不易发生。推测与中间设备负载或出口带宽使用率有关。

中间设备似乎在截获一个TLS Client Hello后便会放行该IP随后向443端口发起的TCP连接。此放行规则的超时时间似乎不定,大致为30分钟至一个半小时。

问题影响的范围

最早是在镜像站公网IPv4地址的TCP 443端口上观察到的。公网IPv4地址于TCP 80端口提供的HTTP服务及IPv6地址则不受影响。

随后的测试发现学校电信出口116.7.234.0/24网段下一些IP的443端口同样会受此问题影响,但频率似乎不如镜像站的116.7.234.220高。教育网出口110.65.147.0/24下找到了一个似乎受此问题影响的IP,但在随后申请到的教育网IP上则无法复现。

如何复现

在客户端启动抓包软件。参考命令:tcpdump -i eth0 -n -w /tmp/test.pcap host 116.7.234.220

然后反复执行下方命令,观察抓包记录。

curl http://116.7.234.220:443/ --max-time 5 -v -o /dev/null

可见TCP握手能正常进行,但客户端发出的HTTP请求却一直不被响应:尽管客户端的TCP栈不断尝试重传承载它的PSH,ACK包,但对方始终不发回ACK。

可同时在镜像机器同时抓包确认,此TCP连接相关的数据包没有到达内网中的镜像机。由此推测,此连接被中间设备截获并抢答了。

其后可执行 curl https://116.7.234.220/ -v -o /dev/null

本地抓包记录可见,客户端发出TLS Client Hello后,对方会直接返回RST包终止此条TCP连接。镜像机上未见相关的数据包。

根据观察,RST包被成功触发后,在一段时间内此中间设备便不会再干涉外界与镜像站443端口的通信,能正常建立TLS连接。尝试在443端口进行HTTP请求能正常收到nginx发出的400 Bad Request响应。

调试结论简述

学校使用的边界防火墙由华为提供(USG9500)。在与厂商的技术人员调试的过程中,我们发现根据ACL规则的匹配记录,在问题发生时,外部发往公网443端口的包似乎不能完成NAT并转发至对应的内网IP。

针对80端口的ACL计数规则。可见来机客户端、目的地址为镜像站公网IP的报文数量与目的地址为其内网IP的相等(分别对应rule 5和rule 15)

Advanced ACL 3001, 4 rules ( Reference counter 1 )
Acl's step is 5
 rule 5 permit tcp source <client-public-ip> 0 destination 116.7.234.220 0 destination-port eq www (16 times matched)
 rule 10 permit tcp source 116.7.234.220 0 source-port eq www destination <client-public-ip> 0 (16 times matched)
 rule 15 permit tcp source <client-public-ip> 0 destination <mirror-intra-ip> 0 destination-port eq www (16 times matched)
 rule 20 permit tcp source <mirror-intra-ip> 0 source-port eq www destination <client-public-ip> 0 (16 times matched)

然而针对443端口进行的统计则出现了异常情况,看起来防火墙收到了公网一侧的包,但没有将它发往预想中的镜像站内网IP(见rule 5与rule 15的命中次数差异)

Advanced ACL 3001, 4 rules ( Reference counter 1 )
Acl's step is 5
 rule 5 permit tcp source <client-public-ip> 0 destination 116.7.234.220 0 destination-port eq https (3 times matched)
 rule 10 permit tcp source 116.7.234.220 0 source-port eq https destination <client-public-ip> 0 (0 times matched)
 rule 15 permit tcp source <client-public-ip> 0 destination <mirror-intra-ip> 0 destination-port eq https (0 times matched)
 rule 20 permit tcp source <mirror-intra-ip> 0 source-port eq https destination <client-public-ip> 0 (0 times matched

当443端口的重置行为被客户发来的TLS Client Hello包触发后,防火墙上针对443端口的统计信息也恢复正常。此现象与443端口的重置问题发生的时机似乎有很强的相关性。

到此(3月25日下午),华为的驻场工程师已经认识到了问题,并将它反馈给他们内部了。

3月31日上午,华为的驻场工程师表示他在查防火墙日志时发现一个机制的行为有些可疑,将其关闭后经测试443端口的问题消失。他与学校信息中心老师协商后决定将此功能的阈值调大,经过一些测试,镜像站目前的流量规模似乎不会触发中间人问题了。

问题似乎已经解决,然而我们暂未得知此功能的具体名称以及预期行为(比如它为什么会对TLS连接进行截获TLS Client Hello的攻击)。尚不清楚未来若镜像站的对外带宽提升,是否会再次受类似的问题影响,

调试杂项记录

在外界对116.7.234.220发起traceroute,发现对于ICMP包和UDP包最后一个返回ICMP Time Exceeded消息的路由器IP为183.56.64.2或183.56.64.10。推测此跳为深圳电信接入侧的路由器,记它的跳数为N。

若对TCP 80端口及正常状态下的TCP 443端口使用TCP SYN包进行traceroute测试,可测得响应的SYN ACK包来自第N+3跳,且N+1与N+2跳均不会返回ICMP Time Exceeded消息。

在问题发生时,TTL为N+1的SYN包即可触发中间设备返回SYN ACK包。此外还可以通过指定socket的TTL值确认

可使用nmap提供的nping工具构造TCP包并traceroute,如:nping --tcp --traceroute --dest-ip 116.7.234.220 -p 443 --flags syn

nping在TCP Probe(而非TCP connect)模式下会直接通过raw socket发送已构造的TCP包,内核的TCP栈不会参与。为了避免内核的TCP栈发送RST包干扰中间设备的状态机,在开始测试前可使用iptables规则丢弃发往被测IP的RST包。

iptables -I OUTPUT -p tcp -d 116.7.234.220 --tcp-flags RST RST -j DROP

另外可通过调整socket选项构造出具有特定TTL的TLS Client Hello包,以精确触发问题中间设备的重置行为。使用Python的一个例子:

import socket
import ssl

hostname = '116.7.234.220'
context = ssl.create_default_context()
N=17

with socket.create_connection((hostname, 443)) as sock:
    sock.setsockopt(socket.IPPROTO_IP, socket.IP_TTL, N+1)
    with context.wrap_socket(sock, server_hostname=hostname) as ssock:
        print(ssock.version())

值得一提的是,由于运营商可能会在中间路由使用ECMP等负载均衡策略,拥有不同五元组的包在跳数上可能有差异,因此尝试使用TTL定位问题时应当确认中间路由拓扑层级的稳定。


我们于3月21日按照前述方法进行了测试(使用http协议请求南科大所有对公网开放的服务的443端口,预期情况应为返回400 bad request,如果出现了之前所反馈的问题,请求将一直超时,不过由于我们设置了5秒的timeout时间,因此在请求结果中,请求时间大于5秒的数据,均可以被认为是被学校的防火墙设备干扰了):

结果如下如图/表所示(测试每10分钟进行一次,分别从深圳阿里云,深圳电信和香港宽频发起,3月21日大约进行了约700次测试):

IP重置次数服务性质(猜测)
116.7.234.143461网站群服务
116.7.234.50380VPN
116.7.234.220291镜像站
116.7.234.158211健康申报
116.7.234.3116官网
116.7.234.18438Blackboard
110.65.147.16413Blackboard
116.7.234.9710
110.65.147.1636
116.7.234.245
116.7.234.2093
116.7.234.942
总计1536

根据华为驻场工程师的说法:

由于你们的公网只有一个IP,都指向了443端口,流量大了后,会触发防火墙的攻击防范机制,超过了攻击防范机制的默认数值,所以导致了丢弃的情况

工程师现已调大了攻击防范机制的阈值,链接被重置的情况应该会有较为显著的改善。

我们将持续跟踪此问题。