微信支付 IPv6 支持问题及排查思路方法论分享

2024-09-09
来源:网络整理

关于作者

林伟浩,网络安全新锐,曾就职于中国电信、网易游戏等数据网络、网络安全、游戏运维等岗位,在运维、虚拟化、网络安全防护等方面有较多研究,目前专注于网络安全自动化检测与防御体系建设。

众所周知,随着“微信红包”等热门应用的火爆,微信支付已经无处不在。今天要分享的是一个关于微信支付面向商户API IPv6支持的问题。重点不只是问题本身,还有排查过程中的一些思路和方法。

故障描述

最近有同事反映在访问微信支付API时出现了奇怪的现象,比如第一次访问URL需要10-30秒才能返回结果,但是连续多次访问后都是毫秒级返回结果。在一段时间没有访问之后,第一次访问就很慢,之后的连续多次访问就很快返回了。因为是比较敏感的应用,这样的响应时间是不能接受的,所以我们决定彻查一下。

故障详情

当发现故障时,处理的第一步通常是重现故障并使用脚本进行测试:

测试结果如下:

可以看到,首次连接耗时超过15秒,后续响应都是毫秒级的,如何定位初始连接时间过长的问题是目前的重点。

过程

节点 1

在出现这个问题之前,我们内部有一个应用也出现过类似的问题,比如第一次访问网页需要10多秒才能加载完成,但是之后访问就很快了。当时我们通过抓包定位到了同网内其他IP对流量进行了劫持,增加了建立连接的时间。后来我们把劫持的源头去除了,就恢复正常了。所以受以往经验的影响,我首先猜测可能是网络问题或者劫持了。按照这个想法,我先检查了发起请求的客户端所在的网络,发现是独立的外网IP,没有NAT等相对复杂的网络环境。同时我切换到其他网络环境进行测试,发现每次请求响应都非常快。测试结果如下:

所以网络问题还是没法彻底解决,于是我决定在curl的同时抓包。

-w 测试.pcap

捕获数据包,打开它,然后查看连接是如何建立的。

发现第一个请求出现了TCP重传,于是怀疑是网络问题,但是从这里又看不出具体原因。于是开始检查客户端所在的服务器环境。

节点 2

在处理过程中,我也想起之前遇到过一个问题,就是因为规则配置不合理,导致梳理数据包的效率低下。所以一开始检查服务器环境的时候,我优先检查了配置规则,发现还挺合理的,没有设置第一次建立连接的标签,也没有对New做特殊的设置。然后我临时清除了所有规则,发现问题依旧,就略过了。

节点 3

此时我开始怀疑DNS解析异常也会导致首次连接建立时间过长的问题。于是我开始检查/etc/.conf。无论是检查配置还是更换DNS服务器,问题都是一样的。不过“种花不善则花开,种柳不善则柳暗花明”,在这个过程中我还是抓到了包,发现IPv6地址解析异常!

可以看出DNS服务器返回的IPv6解析结果为“AAAA”,并且耗时超过5秒,也就是说出现了问题。

节点 4

接下来我们重点排查了微信支付域名IPv6解析问题,发现确实存在,并且复发率很高。

同时指定IPv4解析,发现A的查询很快:

由于确定是IPv6解析有问题,IPv4解析正常,因此修改了相关代码,确认强制域名解析IPv4正常。

原因分析

从DNS原理角度看问题

1. 整个DNS解析过程

如上图所示,当客户端发起DNS解析请求时,会有优先级,按照本地DNS缓存->/etc/中的DNS配置->ISP或本地域名解析缓存服务器->根域名服务器->顶级域名服务器->……->目标站点权威服务器的顺序进行解析。

从这个失败来看,问题应该出在权威服务器上。详情请参见下面的解释。

我们先来看一下对比分析结果:

A. IPv4 解析结果

B. IPv4 解析结果

域名微信业务打开支持什么意思_微信不支持打开非业务域名_域名微信业务打开支持什么协议

C. IPv6解析结果

D. IPv6解析结果

从上面的测试结果可以看出IPv6解析是正常的,IPv6解析失败的原因是因为多了一层:

. 600 IN .,那么AAAA解析返回是错误的,这里权威服务器处理失败。

为什么客户端解析了AAAA,但是又缓存回去查询AAAA呢?

这是因为记录 .600 IN . 被缓存了,导致所有后续查询都查询相应的记录。

接下来我们来对比分析一下,看看在权威服务器层面上有何不同。

这里的AAAA解析返回有问题,是SOA,按照协议还是应该返回记录的,通过对比解析结果可以发现,后者才是返回的SOA。

我们会记下这个值,如果返回的是 none,那么根据 RFC 2308 2.2(#-2.2)这是一个 NO DATA 返回,表明这是一个指示返回(比如根权限返回顶级权限 NS)或者域名记录不存在(比如查询 AAAA)。

从上面可以看出, . 其实是一层 NS,虽然还没有真正授权过( . 上没有 SOA 记录),但是缓存认为已经授权了一层,返回的 SOA 是不正确的。因此缓存服务器无法判断返回的类型,所以认为返回不合法,最终导致一直返回 和 的 AAAA 记录。因此缓存服务器会尝试继续解析,导致第一次解析时间很长。后续解析成功后,使用本地缓存,所以解析很快。当缓存失效时,问题又会再次出现。

2.关于curl的DNS解析顺序

一般来说,如果服务器开启了 IPv6,curl 默认会优先进行 IPv6 解析,如果对应域名没有 IPv6,则会等待 IPv6 DNS 解析失败后再照常查找 IPv4。DNS 服务都支持 IPv6 解析,如果没有设置 IPv6 解析,则查询结果为空。

3.关于dig的工作原理

不同的操作系统和dig的工作方式不同,例如Win7对每个IPv4请求生成两个A记录请求,而Win XP对每个IPv4请求只生成一个A记录请求,因此在抓包分析时需要根据不同操作系统的应用特点进行区分。

微信已经有解决方案

关于这个问题,微信官方文档

答案已经给出。

商户接入微信支付

商户端使用(主)和(备)两个支付API域名接入微信支付,这两个域名的功能是完全一样的。

这两个域名分别配备了两个131开头的策略IP,用于绑定专线访问微信,api和api2分别绑定电信和联通的具体IP,商户可以自行测速后决定。

商户端访问支付接口的代码逻辑,必须有访问失败时通过更换域名进行重试的机制。即访问不成功的话,会进行重试。

商户接入微信支付时,若两条专线都不可用,必须能切换回公网,若公网不可用,商户需注意相关风险。

可能的解决方案

1.使用来验证IPv6是否已启用:

2.检查服务监听的IP地址,验证IPv6是否启用:

3.使用来验证IPv6是否已启用:

禁用IPv6:修改/etc/.conf,添加以下两行,然后重新启动系统。

net-pf-10 关闭

IPv6 关闭

启用IPv6:默认支持IPv6,因此只需在/etc/.conf中注释掉上述两条指令即可。

按照下面的格式进行配置,但是如果指定的服务器出现故障,业务也会受到影响,这不是很安全的方法。

183.3.235.18

例如,PHP:

经验教训

在学习技术知识的时候,很多人喜欢用搜索引擎找别人的博客或者问题解答作为知识学习的切入点。其实这里就存在一个问题,博客或者问题解答已经被别人消化了,一方面提高了可读性,但是也引入了偏见和误解,也不能保证完整性。另一方面,官方的用户文档,特别是外语的文档,虽然阅读难度相对较大,但是却非常权威全面,包括了很多细节。但是很多人不愿意认真阅读用户文档,而是通过网上碎片化的知识去学习,这样难免会有疏漏。比如这次我们使用微信支付API的时候,在用户文档里就没有看到这部分,走了一圈,增加了学习成本。所以,在学习或者使用新的系统、技术的时候,阅读用户文档其实是一个非常基础的地方。

从上面的处理流程我们可以看出,由于之前处理类似问题的经验,我最初尝试将问题定位在网络或者劫持的方向上,但并没有带来太大的效果。很多时候,相关经验至少可以提供思路,这是一种优势。有时候,过于看重经验会导致思维僵化,没有充分收集基础信息再进行定性定位,就会事倍功半。

分享