识别审查HTTPS流量的Airtel中间盒

2020-09-29 20:53:52

早在2019年11月,我们就报道过Reliance Jio能够通过深度数据包检测(DPI)技术拦截HTTPS互联网流量。作为回应,一些读者给我们发消息说,他们运行了我们的测试,能够在Airtel移动网络上重现类似的行为。根据TRAI';2019年7月至9月的业绩指标报告,Reliance Jio和Airtel分别为印度约52%和23%的互联网用户提供服务。这基本上意味着,基于SNI检查的审查制度现在影响着印度每4个互联网连接中的3个。

虽然之前的测试能够检测到基于SNI检查的审查制度的存在,但它不是很有洞察力。在这篇文章中,我们深入研究了一个更有信息量的测试,它不仅证实了SNI基于检查的审查制度的存在,而且还帮助我们确定了确切的机制。此外,它还允许我们识别在TLS握手和审查请求中主动检查SNI的中间盒。使用这种方法,我们能够发现注册到Airtel的25个不同的中间盒,这些中间盒正在积极审查HTTPS流量。

复制此实验的所有代码以及我们测试运行的日志都可以在此存储库中找到。感谢IPinfo让我们能够访问他们的IP地址数据集,感谢GurshabadGrover在构思方法和编辑本文时提出的建议。

传输层安全(TLS)是一种用于提供通信机密性和真实性的加密协议,通常用于加密Web流量(如HTTPS中所做的)。通常在TCP上使用TLS,因为它需要可靠的有序数据流。Cloudflare对TLS的快速更新。

先进行TCP握手,然后进行TLS握手。ClientHello是客户端发送的消息,发起TLS握手。此消息可以包含诸如SNI之类的扩展名。映像制作者名单-云耀斑。

服务器名称指示(SNI)首先在RFC4366中定义,然后在RFC6066中定义,是一种TLS扩展,旨在促进在同一IP地址上托管多个HTTPS网站。在发送ClientHello消息(启动安全连接的建立)时,客户端需要使用其希望连接的网站的主机名填写SNI属性。不幸的是,SNI在网络上以明文传输,即网络运营商不仅可以看到您正在访问的网站,还可以根据这些信息过滤流量。

由于SNI是明文形式,因此网络中的任何人都可以根据其值检查和过滤流量。正如在其他国家/地区看到的那样,ISP可以利用这一点来拒绝对某些网站的访问。我们可以通过尝试使用OpenSSL建立TLS连接并监视发往主机的数据包来观察同样的情况。

尝试使用SNI fullhd720.com将TLS连接到103.224.212.222。我们在发送包含SNI的ClientHello消息后立即观察到RST数据包。

例如,使用Airtel,我们可以看到,当客户端尝试连接到被阻止的网站";fullhd720.com";时,它会收到TCP RST数据包。RST数据包似乎源自实际主机,并且是在发送包含SNI的ClientHello消息之后立即接收的。PCAP。

要确认连接终止确实是由SNI引起的,我们可以重新尝试与我们不希望阻止的其他SNI连接(在这种情况下,我们使用facebook.com)。

尝试使用不同的SNI facebook.com将TLS连接到103.224.212.222。在本例中,我们观察到成功的TLS握手。

这一次我们注意到连接成功,表明上一次尝试中的RST确实是由指定的SNI造成的。PCAP。

虽然此测试确实证明存在基于SNI检查的审查,但数据包转储不足以证明RST数据包实际上是由属于ISP的中间盒伪造的。

对于给定的主机,让调用数据包从客户端到达主机所需的最短生存时间(TTL)min_ttl。TTL设置小于min_ttl的任何数据包都将在传输过程中过期,并且永远不会到达主机。理想情况下,数据包的TTL过期的路由器应以ICMP超时(ICMP消息类型11)消息响应。但是,这并不能保证,一些路由器甚至被配置为不发送它们(以便隐藏网络拓扑)。

迭代网络跟踪;我们发送具有递增TTL的ClientHello消息。在这种情况下,所需的最小TTL是9。审查请求的中间盒即使在TTL小于9的情况下也会发回经过审查的响应。图像信用-Yadav等人。

因此,如果收到的RST是由中间盒伪造的,即使我们发送了TTL小于min_ttl的ClientHello消息,我们也应该收到它。这种方法称为迭代网络跟踪(INT),以前曾用于确定印度是否存在审查DNS和HTTP流量的中间盒[Yadav等人]。和中国徐等人。与这些研究类似,我们使用INT来检测TLS流量的审查(在方法论部分进一步解释)。

我们使用一份可能被屏蔽的网站(PBW)列表(PBW)来运行我们的测试,该列表是从泄露的法院和政府命令中挑选出来的。列表和与之相关的更多信息可以在这里找到。

使用Google的DNS over HTTPS(DoH)服务,每个主机名都被解析为其正确的IP地址。在这里使用DoH很重要,因为它可以确保基于DNS的审查不会干扰测试。这产生了大约5000个(主机名、IP)对。接下来,我们选择一个随机子集,检查端口443到每个IP的TCP连接(因为并非所有IP都支持HTTPS流量),将我们的列表过滤到1370对。

对于这些测试点中的每一个,我们都使用RESOLUTED_IP建立TCP连接,并发送SNI设置为CORRECT_HOSTNAME的TLS ClientHello。我们嗅探并保存这些ClientHello数据包(仅SSL层)以供稍后使用。同样,我们将SNI设置为facebook.com的ClientHello数据包保存。这些嗅探过的数据包可以在这里找到。

测试的输入是一个2元组,(正确的主机名,解析的IP)。我们希望了解中间盒在观察到包含其希望拦截的网站的SNI的ClientHello消息时的行为。

首先,我们计算给定测试点的min_ttl。我们首先使用RESOLUTED_IP建立TCP连接。

导入套接字随机导入。所有导入*RESOLUTED_IP=";103.224.212.222";dport=443TLS CONNECTION SPORT=随机.randint(1024,65535)#随机源portdef CREATE_CONNECTION(RESOLUTED_IP):s=socket.socket(socket.AF_Packet,socket.SOCK_RAW)s.bind((";usb0";,0))#正在使用系留移动连接进行实验IP_PACKET=IP(dst=RESOLUTED_IP)SEQ=RESOMANDINT(12345,67890)#随机初始序列号SYN=tcp(SPORT=SPORT,DPORT=DPORT,FLAGS=";S";,SEQ=SEQ)SYNACK=SR1(IP_PACKET/SYN)ACK=TCP(SPORT=SPORT,DPORT=DPORT,FLAGS=";A";,seq=seq+1,ack=SYNACK.seq+1)发送(IP_PACKET/ACK)返回IP_PACKET,ACK。

注意:当Linux内核特性将TCP数据包发送到未知套接字时,它会将RST发送回发起方。因为我们将创建我们自己的原始套接字,所以在运行实验之前,我们需要使用iptables从内核抑制这些出站RST。

一旦TCP连接建立,我们将在更新底层IP报头中的TTL(Probe_Ttl)之后发送ClientHello消息(在SNI中包含facebook.com)。我们在SNI中指定facebook.com,这样中间盒就不会尝试终止连接。Min_ttl将是我们从主机接收TLS ServerHello或TLS警报的最小TTL。

#使用open(";tls_client_hellos/facebook.com";,';rb';将主机名损坏的ClientHello加载到SNI中(之前已嗅探,读取数据准备)max_ttl=35def find_min_ttl(已解析_IP)。)as fp:tls_client_hello_facebook_com_sni=fp.read()for be_ttl in range(1,max_ttl):IP_PACKET,ACK=CREATE_CONNECTION(RESOLLED_IP)IP_PACKET.ttl=Probe_ttl del IP_PACKET.chksum#将在TTL更新Resp,_=sr(ip_Packet/ACK/TLS_CLIENT_HELLO_Facebook_COM_SNI,超时=2,重试=0,MULTI=True)for_,分别为:TLS_ALERT=ans_Packet.get(tls.TLS,{}).get(tls.TLSAlert)TLS_SERVER_HELLO=ans_Packet.get(tls.TLS,{}).get(tls.TLSHandshakes,{}).get(tls.TLSServerHello)如果TLS_ALERT或TLS_SERVER_HELLO:返回PROBE_tl#min_ttl find!

接下来,我们在TTL从1增加到min_ttl-1的SNI中发送包含正确主机名的ClientHello消息。如果没有中间盒干扰连接,则所有此类请求都应该收到超时的ICMP响应,或者根本没有响应。如果我们在任何时候收到似乎源自RESOLUTED_IP的RST数据包,我们可以肯定地说该数据包是由中间盒伪造的。

MIN_TTL=FIND_MIN_TTL(RESOLUTED_IP,TLS_CLIENT_HELLO),带open(";tls_client_hellos/fullhd720.com";,';RB';)as fp:tls_client_hello_right_sni=fp.read()for be_ttl in range(1,min_ttl):ip_Packet,ACK=CREATE_CONNECTION(RESOLUTED_IP)IP_PACKET.ttl=Probe_ttl del IP_PACKET.chksum#将在TTL更新Resp,_=sr(IP_Packet/ACK/TLS_CLIENT_HELLO_CORUTE_SNI,超时=2,重试=0,MULTI=TRUE)后强制SIGY重新计算校验和。分别为:ICMP_PACKET=ANS_PACKET.GET(ICMP)中的ANS_PACKET如果ICMP_PACKET不是NONE:PRINT(";找到%d";%(ans_Packet[ICMP].type)类型的ICMP消息。如果TCP_PACKET和(TCP_Packet>;>;2)%2==1,则CONTINUE TCP_PACKET=ans_Packet.get(TCP)%2==1:打印(";在跃点%d";%(Probe_Ttl)找到RST)。

使用我们的方法,我们为测试列表中的每个点挖掘以下信息:

Min_ttl:响应以`facebook.com`为SNI的ClientHello的TLS ServerHello/TLS警报接收(如果有)的最小TTL。

MIN_CORRECT_SNI_RST:响应具有CORRECT_SNI的ClientHello的RST接收(如果有的话)的最小TTL。

MIN_CORRECT_SNI_TLS:响应具有CORRECT_SNI的ClientHello时接收TLS ServerHello/TLS警报(如果有)的最小TTL。

可以在此处找到运行此测试的脚本。可以在此处找到每次测试运行的日志。此Python笔记本中提供了从日志中挖掘上述信息的代码。

在我们的1370个可能被阻止的网站列表中,有1058个实例接收到RST数据包,以响应带有CORRECT_SNI的ClientHellos。在所有这些情况下,RST似乎起源于RESOLUTED_IP,并且MIN_CORRECT_SNI_RST小于MIN_TTL。这意味着存在故意终止连接的中间盒。

此外,在170个案例中,我们还在接收RST数据包的同一Probe_ttl处收到ICMP超时警报。进一步分析,我们发现这些RST数据包来自25个唯一的中间盒。与ipinfo.io的核对显示,其中16个注册在airtel.com,9个注册在bhartitelesonic.com。有关这些中间盒的更多信息可以在这个Python笔记本中找到。

在290个案例中,我们收到了TLS ServerHellos/TLS Alerts响应,表明没有网络干扰。这是意料之中的,因为我们一开始就列出了可能被屏蔽的网站。

除此之外,还有一些由于连接问题导致的测试失败,我们没有进一步调查。

光明从何而来:分析印度的网络审查机制。IMC 2018。Tarun Kumar Yadav,Akshat Sinha,Devashish Gosain,Piyush Kumar Sharma和Sambudho Chakravarty。PDF格式。

中国的互联网审查:过滤发生在哪里?PAM2011年。首页--期刊主要分类--期刊细介绍--期刊题录与文摘--期刊详细文摘内容。PDF格式