作者 青鸟

为了避免不必要的误会,本文中不会提供具体的方法,有兴趣的朋友可以自行baidu,本文只是对SNI技术的分析,以及其衍生问题的讨论。文中以pixiv来举例分析。

本文可能会有一些不严谨的地方,欢迎大家指出。

谢绝以任何形式的传播!!!

一些专业名词的介绍

HTTP(Hyper Text Transfer Protocol)

超文本传输协议,日常浏览的各种网页都是通过HTTP协议传输,但是它的传输过程没有加密,不安全。 目前所说的支持HTTP一般是指HTTP和HTTPS功能都可以实现,而不是单单支持HTTP。

TLS(Transport Layer Security)

安全传输层,它的前身是SSL,它实现了将报文加密后再交由TCP进行传输的功能。即HTTP + TLS = HTTPS

SNI(Server Name Indication)

服务器名称指示。SNI是为了解决一个服务器使用多个域名和证书的SSL/TLS的一个拓展,它允许服务器在同一个IP地址和TCP端口下支持多张证书,从而允许多个HTTPS,或其他服务在TLS的网站,可以在同一个IP地址下请求不同的服务。

简单来说,是用于在一台服务器的相同端口上部署不同证书的方法。服务器根据收到请求中的SNI域名来处理相应的请求,如果SNI域名为空,会按照预先设置好的默认域名处理请求。

CDN(Content Delivery Network)

内容分发网络,各个地区部署的服务器在一起形成的高速网络拓扑,用户在每个地区都能实现快速访问。CDN通过SNI响应不同的网站,同时也保护根服务器的安全。

Nginx

主流的高性能开源HTTP反向代理工具,主要用于反向代理、负载均衡和动静态资源分离。

反向代理

在根服务器前部署一台外层服务器做为网关,用户只能访问到外层服务器,从而保护内网服务器不被暴露。做为网关,也可以对报文分析和修改。

代理服务器和根服务器部署在一台主机上称为本地反代。

目前的主流屏蔽技术

这里粗略的讲一下技术至于更详细的,请自行百度一下

在目前的生活中,GFW屏蔽违规网站主要有两种方法:1.DNS污染,2.TCP重置攻击。

DNS污染

主要是检查HTTP报文中的关键字来拦截相应网站中的内容,浏览器访问时会出现ERR_CONNECTION_TIMED_OUT的错误,因为DNS会被指向一个不可访问的地址,访问也就超时了。DNS查询可以到达DNS服务器,但是如果和请求禁止的关键字匹配,**防火墙将在合法DNS回复之前注入虚假的DNS回复。对于这个问题的解决方法是在本地做好解析,通过修改本地的Hosts文件使用ip直连。

但是,在目前的生活中,使用DNS污染的方法在大型网站的屏蔽中已经很少见了,其主要原因是HTTPS会对浏览内容进行加密,报文检测关键字的方法也就失效了。

SNI审查方法

在正常情况下,TLS握手需要以下几个阶段

在最开始的Clint Hello阶段,双方还没有商量好约定的加密方式,在报文中采用的是明文状态,其中的Extension字段中包含了SNI信息,也就是当前正在请求的域名,而这个信息可通过抓包得到。

在正常的情况下,服务端根据SNI中包含的域名,对客户端发送相应的域名证书,进行接下来的握手步骤,在协商结束后,开始通讯加密。

但是在这个过程中,GFW可以通过截获SNI中的域名,来判断客户端请求的网站的合法性,并进行检测和阻断,阻断的方式是TCP重置攻击。这个手段被称为基于深度数据包检测的 SNI 阻断。

TCP重置攻击是使用一个单一的数据包来执行。攻击者制作并发送一个伪造的TCP重置包来干扰用户和网站的连接,欺骗通信双方终止TCP连接。 目前GFW会抢先发送RST报文,来中断这种连接。这个技术也被称之为TCP关键字阻断

一种可行的解决方案

SNI是在一个服务器的相同端口上部署不同证书的方法,我们熟知的 Cloudflare 在启用 CDN 后提供的证书就是基于 SNI 部署的。 实现 SNI 的重要过程之一,就是在客户端与服务器建立连接的时候就发送要连接的域名,以便服务器可以返回一张颁发给指定域名的证书。

这个过程中,如果用户请求了一个不存在的域名后,服务器会发送一张默认证书给客户端以便连接能够继续

而这种通过混淆 Server Name 来绕过阻断的方法叫做域前置(Domain fronting)。简单来说就是在Client Hello阶段不携带SNI或者携带无效的SNI,隐藏真实的连接网站来规避互联网审查。

目前对Steam、Pixiv、Github等大型网站都有效.

Domain fronting的工作原理

用户使用合法的域名向DNS请求CDN的IP,然后向CDN发起请求。因为在处理HTTPS请求时,CDN会首先将它解密,并根据HTTP Host的值做请求转发,所以用户想要访问一个非法网站,可以使用一个CDN上的合法的域名作为SNI,然后使用作为HTTP Host与CDN进行HTTPS通信。由于HTTP Host只能被转发看到,而审查者是看不到的,故CDN会放过这条请求,并将HTTP请求根据HTTP Host重新封装,发往实际请求的服务器。这种情况下,客户端实际通信的对象是不怎么合法的网站,但在流量监控设备看来,客户端是在与合法网站通信,即客户端将流量成功伪装成了合法通信的流量。

这种方法在被封锁的站点与无害站点为同一个大型服务提供商时较为可行,例如由内容分发网络提供的服务。此时审查者通常很难区分被伪装流量与合法流量的特点,迫使审查者选择放行所有看似无害的流量,或者选择彻底封锁此域的流量。而彻底封锁可能带来显著的附加损害。

相应的方法

这种阻断方式只是普通的封锁,我们依旧可以ping到相应网站的服务器主机,因此,我们可以通过本地反向代理来绕过相应的审查。

具体的方法为了本博客的安全,不再放出,可以参考这个文章。下面只给出这篇文章所采用的技术的理论分析。

我们讲PIXIV相关的域名添加到Hosts文件中并且指向本地的localhost,这里的localhost作为一个本地安全跳板,供Nginx正常监听的同时还能防止流量外泄。Nginx讲监听到的数据中的SNI信息去除,再发送CDN的IP,使用IP而不使用域名是为了防止DNS污染,这样子既实现了完整的通讯又不会被审查到。

整个通信过程必须使用HTTPS加密协议,这是为了避免审查机构的报文关键字检测。

作为本地反代服务器,Nginx将监听的报文头处理后再发送给CDN,但是此时的Nginx服务器在宿主机看来是“不可信”的,除非强制让其可信,也就是在主机安装CA根证书,同时HTTPS反代也需要部署中间证书。

这里是一个自签证书的教程

之后当我们启动nginx时,当我们请求服务时,监听端口检测到通往上述域名的流量时,会送往一个合法的相同CDN的主机,理论上只要和目标网站在同一家CDN运营商的服务器都是可行的。请求到相应的服务器时,nginx服务器默认返回第一个server的证书来和客户端进行校验。

下面给出一个Nginx参数示例:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
server {# 部署一个虚拟主机
        listen localhost:443 ssl;# 监听localhost的443端口
        server_name steamcommunity.com;# 添加要监听的域名,与Hosts文件里的域名一致
        server_name www.steamcommunity.com;
        server_name store.steampowered.com;
        server_name api.steampowered.com;

        ssl_certificate ca-certificates/steamcommunity.crt;# 设置证书,这里使用了相对路径,绝对路径也行
        ssl_certificate_key ca-certificates/steamcommunity.key;# 设置与证书匹配的密钥,同上

        location / {# 当监听的端口检测到通往上述域名的流量时,执行下列操作
                proxy_pass https://223.119.248.24/;# 将流量送往223.119.248.24主机,理论上任何一个Akamai服务器IP都可以
                proxy_set_header Host $http_host;# 务必要加上,否则会报错URL非法
        }
}

如果不配置证书或证书不可信,如果在是浏览器访问,会提示连接不安全。

相关的法律说明

《国际联网暂行规定》第六条规定:“计算机信息网络直接进行国际联网,必须使用邮电部国家公用电信网提供的国际出入口信道。任何单位和个人不得自行建立或者使用其他信道进行国际联网。”Nginx 本地代理和服务器代理(代理服务器位于广州)使用的都是“公用电信网提供的国际出入口信道”,从国外服务器到国内用户电脑/代理服务器的流量,使用的是正常流量通道,其间未对流量进行任何额外加密(仅有网页原有的 SSL 加密,用户和代理人并不掌握该 SSL 密钥,区别于 VPN 的流量加密),而 Nginx 获取到网页数据之后发生的整个代理过程完全在国内,不再适用国际互联网相关之规定。

(网上找的,不知道真假,有错误的地方欢迎指出)。

最后的话

如果你有自己的服务器的话,可以搭建镜像站,虽然难度不大,但是都有自己服务器了何不直接自建 VPN 呢?而且这显然是不合法的,自己悄悄用就好了。教程

最后的最后,本文只是一篇技术分析文章,单纯的对技术做相应的分析,不涉及任何敏感信息。

参考文章:

从Steam社区屏蔽分析绕过方法及ASF安全部署

从 pixiv 免代理直连看 SNI 阻断及其绕过方法——域前置

一文搞明白域前置(Domain Fronting)技术

Blocking-resistant communication through domain fronting

维基百科

TCP 重置攻击的工作原理

[Pixiv] Nginx 真·反代P站

PIXIV网页版及客户端访问恢复指南

OpenSSL 自签 CA 及 SSL 证书