目录
一、XTLS 深入浅出
XTLS 的核心逻辑在于使用真实的 TLS 将代理流量隐藏于互联网最常见的流量之中。
对于普通 TLS 代理协议(比如原版 Trojan),用户的代理客户端与代理服务器建立一个真实的 TLS 连接,通过这个加密的隧道,应用程序(比如浏览器)再与目标服务器(比如 Google)建立一个 TLS 连接。这时浏览器与 Google 服务器就是端对端加密,任何人(包括代理服务)不能解密或者伪装发送信息,这就是所谓的 e2e。
浏览器 —- 代理客户端 ==== 代理服务器 —- Google
代理数据经过审查者的时候其实经过了2次加密,而 RPRX 敏锐的发现在这个过程中 99% 的流量其实是不需要做额外加密的。因为经过 TLS 1.3 加密的数据在外观上是完全一致的,审查者无法分辨。也就是说代理逻辑只需要:
- 建立一条真实 TLS 链接
- 在加密隧道内,跟踪浏览器与 Google 之间的通信,识别当前的通信是否为 TLS 1.3
- 如不是,则使用普通 TLS 代理方法,继续使用加密隧道
- 如是,则等待两端开始传输加密数据,代理客户端在第一个内层加密包中插入 UUID,指示代理服务端:我们准备裸奔了!
- 从第二个内层加密包之后,XTLS 就不再对数据包做任何操作,只是单纯拷贝
这就是 xtls-rprx-vision
我们可以发现
- 代理发起的外层 TLS 是真实的,所以审查者无法破解
- 裸奔的流量在代理方面只做单纯拷贝,如果审查者进行任何破坏,将会得到浏览器与 Google 服务器的正常 alert 响应,与一般访问无异
- 裸奔的信号是 UUID,此信号是代理私有信息,以避免类似 关于 23 3 3 判断部分的 代码特征的利用漏洞 Go#17 的漏洞
二、近乎完美
10月3日开始大规模识别和封锁 TLS 代理,透过一些相关讨论及内幕信息,我们知道审查者使用了海量资源以及机器学习的方法。众所周知,机器学习的特长在于从海量数据中提取统计学特征。
引用 klzgrad 的话,普通 TLS 代理的一个重要弱点就是加密套娃。上面讨论提及,虽然加密包的外观对于审查者无法分辨,但加密套娃无可避免的一点就是在每个包都会增加一个数据包头,加密层数越多,包头就会越重。
这个增量虽然不大,但对于小数据(比如应答包)可能比较明显,而且会有一些包长超过网络底层的 MTU 限制。最重要的,由于每个包都增加了相同长度,它可能具有某些统计学特征。
RPRX 当年发明 XTLS 主要原因是为了减少额外加密,我们现在推出新流控 Vision,则是因为 XTLS 在对抗审查者有独特的能力。可以说,当传输 TLS 1.3 数据时 XTLS 99% 的数据包,拥有几乎完美的流量特征。因为它是原始数据,没有经过任何代理加工。
三、TLS in TLS
为什么说 99% 的数据包都是原始数据?那 1% 究竟是什么?
我们需要继续探索一个典型的代理在遇到内部 TLS 1.3 流量的时候,最开始是几个包究竟在干什么。
形象的看,当加密通道建立以后:
第一个包 代理客户端 -> 代理服务器 "你好 本次代理访问的目标地址是 Google 这里是我的 UUID" 第二个包 代理客户端 <- 代理服务器 "你好 收到了你的代理请求 请开始发送数据" 第三个包 浏览器 -> 代理客户端 -> 代理服务器 -> Google "你好 Google 我将和你进行加密通话 我支持的加密方式有。。" (这个包也叫 TLS Client Hello) 第四个包 浏览器 <- 代理客户端 <- 代理服务器 <- Google "你好 用户 这是 Google 证书 本次将使用 TLS_AES_128_GCM_SHA256 加密 让我们开始加密通话!" (这个包也叫 TLS Server Hello) 第五个包 浏览器 -> 代理客户端 -> 代理服务器 -> Google "收到 让我们开始加密通话!"
你所知道的代理协议万变不离其宗,只要用户使用了任何 TLS 连接,都需要进行上述的握手过程。前面提到,外层 TLS 加密后可以认为是绝对安全的,但对于审查者而言,除了破解信息以外,还可以利用一些附加信息来识别这5个包。
这就是所谓 TLS in TLS 检测的关键点。
四、生死5包
最明显的特征,是这5个包的长度。其中
第一个包 很短 唯一的变数是目标地址 第二个包 很短 几乎固定 第三个包 短 变化很少 几乎唯一的变数是目标 SNI 第四个包 长 变化较大 第五个包 很短 变化很少
可以直观的感受到,它们的包长特征其实是十分明显的。在 Vision 中,我们的应对方法也十分简单,就是将每一个短包的长度填充至 900 到 1400 这么一个区间。注意,这个方法与传统的随机填充不同,我们不是盲目的在所有包都加上填充,而是基于我们对内部流量的分析,有针对性的,对 TLS 握手过程的标志性的包进行填充。
另一个比较隐蔽的特征叫做时序特征。受限于 TLS 握手的设计,你可以注意到,前面这几个包的顺序是固定的。也就是说,浏览器发送 TLS Client Hello 之后,必须等待 Google 发出 TLS Server Hello 这一信息,而这之后浏览器又必须发送一个”收到 让我们开始加密通话!”,如此后面的对话才可以正常进行。
如果把用户到服务端发一个包叫做 C,反方向一个包叫做 S。审查者是否能够根据 CSCSC 这种数据时序,它们的时间间隔特征来判定这是一个 TLS in TLS 连接?
我们认为现在还不足以下结论,Vision 并没有在这个方面做处理。
有很多开发者都提到 MUX 多路复用对抗 TLS in TLS 检测。它在这方面的确有混淆作用,假如多路复用两个不同的 TLS 连接在一个隧道里,就有机会会形成 CCSSCC 等各种不同的时序特征。
可以预期,翻墙的技术战争将从 shadowsocks (加密)-> 主动探测 -> TLS -> 机器学习 继续升级,是生存或者死亡,将很大程度上取决于这5个包的处理。
五、常见问题
问:Vision 的填充长度是写死的,是不是也有统计学特征?
答:首先网络安全概念上没有绝对的安全,理论上讲任何加密都可以暴力破解,只是计算量(投入资源)大小而已。作为安全协议的设计者,我们只需要把破解和识别的难度提高到审查者无法企及的高度即可,这个高度是多高?恐怕需要在战争拉锯中我们才能知晓。
回到我们已知的信息,TLS 1.2 和 1.3 握手包的长度分布是非常稳定的。几个关键包访问主流网站(比如 Google)可以看作是固定长度。如果把 Vision 现有的大包随机长度,跟不加填充的握手包相比,识别难度应当会增加一个数量级。
另外,在一些泄露出来的讨论中,有人提到机器学习可以识别低于 40% 的随机填充。这可以侧面证明机器学习存在辨识上限。
问:为什么新流控取名 Vision
答:我们认为 Vision 代表了 RPRX 原本的设计理念。XTLS 初版事实上是在探索中开发的,而且受限于当时的开发环境,有一些地方过于复杂,可以说,Vision 代表了 XTLS 的理想形态和未来方向。RPRX 说:
Flow.. 要解决什么问题?它影响的是宏观流量时序特征,而不是微观特征,后者是加密要解决的事情。流量时序特征可以是协议带来的,比如 Socks5 over TLS 时的 Socks5 握手 ,TLS 上不同的这种特征对于监测者来说就是不同的协议,此时无限 Schedulers 就相当于无限协议(重新分配每次发送的数据量大小等)
Direct 其实并不需要魔改 TLS 库就可以实现,它不需要读过滤,甚至传输 TLSv1.3 时连写过滤都不需要,非常简洁、高效
问:新流控这么好,你们推荐所有人都使用它翻墙吗
答:正如其它开发者所言,对于当前的审查者,把所有鸡蛋都放在一个篮子里是十分危险的。所以我们鼓励大家善用每个工具的特性,分散特征。
- @klzgrad NaiveProxy 使用 Chrome 浏览器架构当作代理客户端以及 Caddy 当作代理服务端,可以高度模仿一个普通的 HTTPS 访问,它也包含的 TLS 握手以及其它特征包的填充
- @gfw-report 仅仅花一个下午写出的魔改 shadowsocks 通过注入额外数据的方式,改变传统 shadowsocks 无序流量的特征
- 在纯自用的情形下,使用 MITM 代理,目前这种方式工具较少,可以参考 https://github.com/KiriKira/Kirikira.moe/blob/master/articles-md/V2Ray%E7%9A%84%E8%BF%9B%E9%98%B6%E6%95%99%E7%A8%8B(2):MITM.md
问:对于未来你推荐国密比如 sm4 吗?
答:不推荐,正如一开始提到,我们认为最安全的方法就是隐藏于互联网中最常见的流量之中。除了 HTTPS 以外,我们应该考虑什么样的出国流量是常见的。SSH?Remote Desktop?微信视频?Email(雾)?电波通信(大雾)?
而不是使用一个极其小众的加密和协议。