0、前情摘要
在一次飞行途中,我司客户遭遇到了得物App在飞机上的WiFi网络访问异常的问题。这让我们意识到在特定场景下,用户可能面临无法使用得物App的困扰。经过SRE团队与无线团队、网络团队联合全力排查与优化,最终成功解决了这一问题,并同时挖掘出全网防火墙设备在各个C端用户工作生活场景访问不到得物App的问题。为得物er稳定访问得物提供保障,同时也输出类似疑难问题排查模板。
1、知识速递
1.1 什么是空中WiFi技术?
目前机载 WiFi 服务主要有两大解决方案:地空宽带(ATG)无线通信系统和机载卫星通信系统(SATCOM)。
- 地空宽带(ATG)无线通信系统采用定制的无线收发设备,沿飞行航路或特定空域架设地面基站和对空天线,形成 地空通信链路。
- 机载卫星通信系统由利用卫星、飞机、卫星地面站三者进行数据通讯
两者的技术优劣势对比如下:
指标 | ATG | SATCOM |
时延 | <100ms | 较高,10-700ms,取决于卫星类型和轨道高度 |
覆盖范围 | 地面基站覆盖的区域,主要在陆地上,最大半径300km | 全球范围,包括远离陆地和海洋上的区域 |
网络连通性 | 地面基站之间可能存在信号盲区 | 通过卫星信号传输,具有更高的连通性 |
可靠性 | 可能受地形和基站分布影响 | 受卫星信号强度和可用卫星数量影响 |
适用场景 | 主要适用于陆地上的飞行 | 适用于全球范围内的飞行,包括跨洋航线 |
马斯克搞的星链服务用的是近轨卫星群,距离地表在550公里范围左右,时延基本在20ms以内,而我国目前用于客舱通信的卫星基本是同步卫星,离地距离36000公里,时延基本在500ms以上
1.2 电商业务为什么会普遍使用TCP协议
当今互联网主流通信协议使用的TCP/UDP协议,遵守TCP/IP的4层网络模型,其中TCP协议相比UDP提供了可靠的、面向连接的通信:
- 三次握手
在TCP协议下,数据传输之前,通信双方需要先建立连接,建立连接时会进行一系列的握手过程,确保数据传输前通信双方的状态和能力都是正常的
- 包确认机制(ACK)
在数据传输时,TCP协议会将数据分成多个包进行传输,并且会对每个包进行校验和确认,确保数据能够正确无误地传输。
- 拥塞及流量控制
TCP协议提供了拥塞控制和流量控制等机制,能够自适应地调整传输速率,防止网络拥塞和数据丢失
基于以上TCP协议保证数据的可靠性和完整性,因此在电商应用中广泛使用TCP协议。
2、天地协同排查
2.1 方案制定
了解了空中WiFi实现技术后,如何定位排查问题便是我们SRE专家思考的问题。对于任务疑难杂症,永远的三板斧:模拟复现问题,抓包,分析完整请求链路。本次麻烦的是场景特殊,需要在空中WiFi环境上才能复现,同时抓包又是一个技术活,只能我们技术团队亲自出马了。这里要特别表扬无线平台的客户端同学,为了完全复现场景,特地早上7点乘指定班机来回测试,收集重要抓包数据。
2.2 测试方案&工具确认
因复现场景苛刻(必须万米高空WiFi才会开启),必须制定好完整的测试方案完成尽可能多的数据收集。无线平台团队和SRE团队协同准备好了测试工具包,可进行网路层面测试包含ping和traceroute,APP层面的请求测试,单域名访问测试等。并准备好抓包工具,在测试时留存所有抓包数据。SRE在公司同步值班抓取服务端请求包,做双向对比。
下面是我们的SRE老司机梳理的各协议段排查工具,大家可收藏:
尽管TCP协议具有面向连接、可靠性高等优点,但是在实际的网络环境中,由于网络的复杂性、拓扑结构、应用缺陷等因素,会导致各种网络问题, 以下我们将排障工具和4层模型做了一个归类:
我们排障一般按从下往上逐层排除可疑点这个思路来时,日常工作会少走一些弯路
2.3 问题复现&测试抓包
客户端测试同学在飞机巡航状况下,连上飞机WiFi后,打开得物App,的确存在访问不了得物App的情况。于是,客户端同步地下值班人员开启测试。
(1)打开得物App,浏览不同页面并截图,确保影响范围
(2)进行网络测试包含(ping、traceroute等)
(3)在浏览器单独访问典型接口,如主接口、社区接口、图片链接等
(4)测试其它电商平台,观察其访问情况。
以上所有访问保留截图、日志、抓包数据等
值班SRE同等时间抓取相同时间的接口的入口请求包,保存下来,后做对比分析。
2.4 数据整理
2.4.1 链路诊断
网络链路层测试:用ping/traceroute等工具对app.dewu.com/m.dewu.com相关域名进行了拔测,均显示网络层正常
这里简单介绍一下ping/traceroute工具工作原理
(1)ping工具
ping是一种基于icmp协议开发的网络诊断工具,工作于第3层,其工作原理是向目标主机发出一个icmp的echo request数据包,并等待接收echo response数据包,然后程序自动估算丢包率和数据包的rtt,因此主要用于网络连通性和网络时延的诊断
此工具原始作者是Mike Muuss,于1983年开发,后面macos/win/linux相继实现各自版本,以下没有特殊说明的情况下,所有相关参数或叙述主要是针对linux版本展开的
- ping工具集成在iputils包中,开源项目https://github.com/iputils/iputils
- 一个基于icmp协议的ping包格式
上图中红色标注的属于ip和icmp协议头中较关键的字段:
协议 | 字段 | 取值 | 含义与作用 |
IP | Identification | 1-65535 | 数据包唯一标识符,另外功能用于ip分片,当一个ip包的负载超过1480时,ip包要分成多片,且多片的identification保持一样 |
IP | Flags | 3个bit位 | 用于指示IP数据包是否允许分片和每个分片的位置,它的三个bit分别是:
|
IP | TTL | 1-255 | 主要控制网络中出现回路时,避免IP包无休止的在网络上转发,每经历一个路由器时,此值会减1; 小诀窍:Linux的网络中默认一般为64,因此在服务侧抓包看到的ttl值后,64-当前ttl值,即可知道此包经历过多少路由器 |
IP | Protocol | 1/2/6/17 | 代表承载的上层协议: 1:ICMP, 2:IGMP, 6:TCP, 17:UDP |
ICMP | Type | 0-18 | 节选部分解释: 回复应答(ICMP类型0):ping命令用到该类型的数据包以测试TCP/IP连接; 目标不可达 (ICMP类型3):用以指示目标网络、主机或者端口不可达; 回复请求(ICMP类型8):ping命令用该类型的数据包测试TCP/IP连接; |
ICMP | Identifier | 随机/指定值 | Identifier 字段在 Echo Request 和 Echo Reply 消息中都存在,作用是帮助区分不同的 ICMP 会话。在发送 Echo Request 消息时,发送方会随机地生成一个16位的标识符,然后在接收响应包的时候,通过比较响应报文中的标识符,来确认响应报文是否是自己发送的响应 |
ICMP | SequanceNumber | 1-65535 | 当一个 ICMP Echo(ping)请求消息被发送给目标主机时,Sequence Number 字段的值通常从0开始计数,每发送一个 ICMP Echo 请求就会递增一个。而当目标主机收到 ICMP Echo 请求后,会将它的 Sequence Number 值复制到 ICMP Echo Reply(ping回应)消息中,以便请求端确认它所接收到的回应消息是对相应请求的响应 |
ICMP | TimeStamp | 时间戳 | 主要用于测量RTT,当一个主机收到一个 ICMP Timestamp 请求时,它会记录返回的 ICMP Timestamp 回应消息中的当前时间戳,并计算出请求和回应之间的时间差 |
- ping的部分参数默认值
参数 | Linux 默认值 | 说明 |
-t | 64 | 指定ttl数值 |
-c | 发送无限数量的 ICMP 数据包 | 指定发送 ICMP 数据包的次数 |
-s | 56 字节 | 指定 ICMP 数据包的大小 |
-W | 10秒 | 指定每个响应包超时时间,单位为秒 |
-i | 1 秒 | 指定发送 ICMP 数据包的时间间隔 |
- ping的例外
从开头描述的ping的原理可以看出,目标设备必须回复echo response才能判断网络连通性和时延,因此如果目标设备设置了类似“net.ipv4.icmp_echo_ignore_all=0”禁止或者防火墙设置了丢弃icmp包策略,此测试结果基本失效,此时需要其它工具如telnet/nc/curl等工具配合测试了
特别有意思的一点:在s20190709版本和此前版本,Identifier取值使用是当前ping进程的pid,如下图所示:
ping当前进程pid是2570,16进制值是0xa0a,因此在包中第25和26字节中展示出来是0xa0a,之后的版本考虑不安全,因此全部改为随机值了
ping_common.c
//s20190709版本和此前的版本
if (sock->socktype == SOCK_RAW)
ident = htons(getpid() & 0xFFFF);
//之后的版本
if (sock->socktype == SOCK_RAW && rts->ident == -1)
rts->ident = rand() & IDENTIFIER_MAX;
(2)traceroute
- 功能与作用
用于查找数据包从源到终点所需要的网络路径,并识别这些路径上的瓶颈和故障
- 工作原理
它发送一份TTL字段为1的IP数据包给目的主机,处理这份数据包的第一个路由器将TTL值减1,丢弃该数据包,并发送一份超时ICMP报文。这样就得到了该路径中的第一个路由器的地址。然后traceroute 在发送一份TTL=2的数据包,这样我们就能得到第二个路由器的地址, 继续这个过程直至该数据包到达目的地主机
这个数据包承载的上层协议可以是ICMP/UDP/TCP
- 工具发展历程
最初是在1987年,由Van Jacobson主导实现,后面macos/win/linux/bsd等也都实现了各自版本,主流linux发行版基本使用的是这个项目https://traceroute.sourceforge.net/提供的
- 配置初始值
//代码配置节选
#define MAX_HOPS 255 //最大跳数,限制 traceroute 能够追踪到的最远节点的数量
#define MAX_PROBES 10 //每个路由节点的最大探测次数
#define DEF_HOPS 30 //默认的最大跳数
#define DEF_NUM_PROBES 3 //默认的每个节点的探测次数
#define DEF_WAIT_SECS 5.0 //默认的等待每个节点响应的时间
#define DEF_DATA_LEN 40 //IP包上的负载默认大小
#define MAX_PACKET_LEN 65000 //最大的包长度,默认为 65000 字节
#ifndef DEF_AF
#define DEF_AF AF_INET // 默认的地址族,一般设置为 AF_INET,表示 IPv4
static const char *module = "default"; //默认使用udp进行探测
static tr_module default_ops = {
.name = "default",
.init = udp_default_init,
.send_probe = udp_send_probe,
.recv_probe = udp_recv_probe,
.expire_probe = udp_expire_probe,
.header_len = sizeof (struct udphdr),
};
#define DEF_START_PORT 33434 /* udp探测时启始探测端口 */
- 包格式分析
从抓包可以验证代码实现逻辑,以及整个探测过程(tcpdump host 1.1.1.1 -Nn -w 保存文件名.pcap)
从两个工具的介绍和测试数据来看,说明网路层面是正常的。
2.4.2 应用层测试
空中侧从ios/android终端,https/http等维度对我司后台服务接口进行了测试验证,同时也对友商的app进行了购物体验,只有得物App的接口返回异常(https/http),且使用浏览器测试时返回带有拦截提示的页面;
2.4.3 网络抓包
空中侧对ios端进行了抓包,地面侧在高防入口进行了抓包,从client/server侧角度看,双方都认为对方发起了强制断开(reset)信令:从手机端看认为是高防(服务端)先断开的,从高防侧看认为是手机(客户端)先断开的
ios端:
高防端:
tcpdump是一个超级好用的开源的抓包工具,一直是我们SRE最重要的工具之一,这里给大家分享一下:
tcpdump是一个功能强大的命令行网络数据包截获工具。
通过使用 tcpdump,可以捕获和分析网络中的数据包流量,从而能够诊断网络问题、监视网络行为、进行网络安全审计等操作。
tcpdump也是作为学习网络协议和数据包结构的非常好的工具,用于对网络数据包进行分析和解码。
- tcpdump工作在数据链路层
- 工作原理
- 网络数据包截获:通过调用 libpcap 库捕获从指定网络接口传输的数据包。具体来说,libpcap 库利用操作系统提供的原始套接字(Socket)接口来截获网络数据包,然后通过回调机制将数据包传递给tcpdump进程。
- 数据包过滤:tcpdump可以根据用户设置的过滤规则对捕获到的数据包进行过滤。过滤规则利用 BPF (Berkeley Packet Filter) 过滤器来实现,这是一个基于指令集的过滤器,它能够对数据包的各个字段进行匹配和过滤,过滤出符合条件的数据包。
- 数据包解析:一旦通过过滤器选定了要截获的数据包,tcpdump就会对这些数据包进行解析和格式化,展示其中的各个字段和属性。数据包解析过程的关键是数据包格式的识别和解码,tcpdump和 libpcap 库可以识别和处理多种数据包格式,包括以太网、IPv4/IPv6、TCP/UDP、DNS、HTTP 等等。
- 数据包展示:最后,tcpdump将解析后的数据包内容输出到标准输出或者用户指定的文件中,供用户进行查看和处理。用户可以对输出内容进行进一步处理,比如进行过滤、排序、统计等操作,以更好地理解网络数据流量,分析网络协议和应用行为,发现问题和优化性能等。
2.5 数据包分析
- 从网络链路层测试数据结果看,网络层上端口是正常通行的,包括tcp三次握手。那说明整个网络链路是通畅的。不存在网络不通的情况。(从友商可正常访问来看也能印证这个问题)
- 从网络抓包数据来看,从client/server侧角度看,双方都认为对方发起了强制断开(reset)信令:从手机端看认为是高防(服务端)先断开的,从高防侧看认为是手机(客户端)先断开的
- 从应用层上截图来看,貌似受到类似acl的拦截
综合结论:最有可能是受到类似防火墙之类的中间层设备拦截
2.6 模拟复现
从如下截图来看,可能和我司的防火墙同一厂商,于是迅速和网络同学组织了一次模拟验证:
将某一终端IP在防火墙上开启“禁用访问网站/软件下载”策略,
然后在浏览器上请求https://app.dewu.com,发现命中此策略
同时也从client端及防火墙出口同时进行了抓包:
电脑client侧:
防火墙出口侧:
基于上面的证据链,基本可以确认防火墙的策略误判了公司得物App的域名为下载类网站
2.7 厂商沟通
将我司复现的问题反馈给厂家后,厂商的策略工程师确认此“访问网站/软件下载”策略存在bug,并在沟通中的过程也确认了此航司与我司都是使用同一厂商的防火墙。
2.8 进展同步
4/18,厂商进行了全网策略发布
4/19,我司ac设备自动进行了策略更新
4/21,请朋友帮忙在同一航班验证得物App使用流畅,验证通过
3、网络技术点回顾
3.1 traceroute
从本次的traceroute数据中我们可以确定一点:
- 空中WiFi到国内电商主要域名的时延基本都在600ms以上,此数据也进一步确认空中WiFi使用的SATCOM方式(高延迟)
3.2 ip包头
- ip包头中的ttl正常情况下每经过一个路由器,TTL的值就会减1,直到服务器接收时不再变化,也就是正常情况下client和server的包中的值不应该有变化,如果有较大变化都基本是中间设备篡改
- ip包头中另外一个字段identifcation用于标识IP数据报的唯一性,如果一个ip包需要分片(MTU超过1460),则每个分片的ip包中的identifcation数值一样; 同时RFC791规范并没有规定Identification字段的取值方式,但实际情况下我们看到的依次增长(MTU超过1500字节加1),如果有跳变很大,基本也是中间设备篡改
3.3 AC设备网络管理
AC(Access Controller)是一种中央控制的网络设备,用于管理多个AP(Access Point)的上网行为。AC 设备上网行为管理功能可以帮助管理员对用户的上网行为进行监控和管理,包括以下方面:
- 认证和授权管理:AC 设备可以实现多种认证方式,如无线局域网安全性协议(WPA、WPA2)、802.1X 认证等,确保用户的合法身份,并授权其访问网络。
- 流量控制:AC 设备可以对接入的用户进行流量控制,限制其上行和下行的带宽、流量总量等参数,以避免网络拥堵和单个用户占用过多带宽资源。
- 上网行为过滤:AC 设备可以对用户的网络访问进行过滤,禁止用户访问某些不适宜的网站或应用,确保网络的安全和稳定。
- 用户管理和监控:AC 设备可以对所有接入用户进行统一管理和监控,包括用户的身份、设备类型、MAC 地址、IP 地址、上网时长等,帮助管理员了解用户的上网习惯和行为特征,发现和处理异常行为。
功能实现:
用户认证,可以基于用户和用户组来管理用户的登陆,可以配置本地认证也可以AAA认证等等
URL过滤,运用HTTP识别技术就是获取到HTTP请求时带有的host字段来获知用户想要访问的网站,以此来达到过滤网站目的(本次出问题就是此功能上)
HTTP:三次握手后,HTTP发出请求,带有host字段,从这里得知访问网站
HTTPS:三次握手后会建立SSL加密通道,在SSL第一次握手时客户端发出client hello报文时,会有个server name字段(SNI),从这里获知后进行相应的过滤
参考资料:
1)中国民航网
2)东航官网
3)通信世界
4)中兴通讯5G地空通信白皮书2020