shadowsocks / shadowsocks-org

www.shadowsocks.org
MIT License
887 stars 544 forks source link

为什么应该用 SSL 翻墙 #48

Closed yvbbrjdr closed 7 years ago

yvbbrjdr commented 7 years ago

为了让更多人看懂,这篇文章使用中文撰写。 原文地址:https://gist.github.com/yvbbrjdr/ea80fc5ef21f1a518346c92bda611993

为什么应该用 SSL 翻墙

由Glype想到的


2013年7月8日,clowwindy写道:

为什么不应该用 SSL 翻墙

SSL 设计目标:

1. 防内容篡改
2. 防冒充服务器身份
3. 加密通信内容

而翻墙的目标:

1. 不被检测出客户端在访问什么网站
2. 不被检测出服务器在提供翻墙服务

SSL 和这个目标还是有一些出入。其中最大的问题是,2. 防冒充服务器身份 这个功能多余了。他会导致墙嗅探出证书信息,继而墙会知道服务器身份。如果墙知道一个服务器身份是用来翻墙的,它要做的仅仅是封掉使用这个证书的所有 IP。

墙看见的 SSL 握手响应头部如下:

(以下省略一个明显带有特征的Twitter HTTPS头)

这一段内容对翻墙的目标总结得非常到位:不被检测出客户端在访问什么网站以及不被检测出服务器在提供翻墙服务。具体来说:

不被检测出客户端在访问什么网站

是指即使翻墙包被截获并分析,也无法探知其中的内容。实现这一点非常容易,用加密算法就能实现。总之要让墙无法通过低成本的方法破解出内容即可。

不被检测出服务器在提供翻墙服务

这个比较复杂。半年来shadowsocks以及shadowsocksR的更新都是在做这件事情。它包含两个方面:

  1. 即使翻墙包被截获并分析,也无法区分其与其他数据包的区别(换言之,无法识别是否是翻墙包)。注意:识别翻墙包不一定需要解密其中的内容。
  2. 对于一个翻墙服务器,无法利用协议漏洞,通过各种攻击方式(重放攻击、篡改攻击、中间人攻击等等)来探测其是否是翻墙服务器。

现有的各种翻墙包结构基本无法实现上面的第2点,因为如果要自定义一个翻墙协议,一定会暴露出某些特征。我认为解决的方法是:不使用自定义的协议,而将翻墙协议建立在已有的、流行的、安全的协议之上,于是我想出一种利用SSL进行翻墙的方法,只是对原来的HTTPS进行一些不大的修改。

在阐述协议之前,我先利用clowwindy对于两个目标的描述说明为什么SSL适合翻墙:

SSL 设计目标:

  1. 防内容篡改 -- 防止篡改攻击
  2. 防冒充服务器身份 -- 防止中间人攻击
  3. 加密通信内容 -- 不被检测出客户端在访问什么网站

且因为每一次SSL协商时对称加密密钥都会不同,也顺便防止了重放攻击;因为HTTPS是一个非常常用的协议,HTTPS请求经过GFW时不会被怀疑,也无法检测是否是翻墙包。

下面用自然语言阐述这个翻墙协议:

众所周知,HTTPS是HTTP套了一层SSL。而由于SSL的加密特点,HTTP请求和响应的明文是不会被中间人截获的。事实上,不管SSL的下层协议是什么,其内容明文都不会被第三方获知。因此,我们可以将shadowsocks协议外套一层SSL来实现翻墙,唯一的改变是,将shadowsocks请求头的末尾加上\r\n(即HTTP行结束符)。如果GFW用HTTPS探测服务器,那么服务器返回一个正常的网站(比如Wordpress,甚至可以是自己真正的博客,可以用Nginx或者Apache实现),如果GFW用shadowsocks over SSL协议探测服务器,那么在收到第一个\r\n的时候服务器立即检查数据合法性,发现既不是HTTP协议又不是正确的(密码无误的)shadowsocks协议,那么立即关连接,或者返回HTTP 400 Bad Request(与HTTP处理不合法包的方法一样)。这样在不知道密码的情况下,GFW只能探测出这是一个HTTPS服务器,而不知道其是否运行shadowsocks over SSL。

剩下的问题是HTTPS证书。那么随便弄一个自签名证书,或者申请一个免费的就行了,再让客户端信任一下。

hellofwy commented 7 years ago

代码更有说明力。

yvbbrjdr commented 7 years ago

总是先有idea才有代码,不是么。 而且如果这个idea被否定,那么代码写出来也没用。

hellofwy commented 7 years ago

自有自己可以否定自己

yvbbrjdr commented 7 years ago

请你拿出论据和论证。。。不要说空话

breakwa11 commented 7 years ago

早期很多工具都是用的https代理,最后都一一倒下了

yvbbrjdr commented 7 years ago

伪装成网站,如何探测?我不相信早期工具对SSL下层协议伪装,特别是伪装成一个functioning的website

yvbbrjdr commented 7 years ago

也许有人不是很明白,在这里我写一下服务器的伪代码。

函数 新连接() {
    TLS握手
    数据解密后读到第一个\r\n
    如果已经读到的数据是HTTP {
        路由到Apache
    }
    如果已经读到的数据是shadowsocks头 {
        检测合法性
        如果不合法 {
            返回HTTP 400错误
        } 否则 {
            路由到shadowsocks
        }
}
qinyuhang commented 7 years ago

这样的话,焦点就都转移到了证书上了吗?如果GFW伪装成一个用户,购买某家的服务,获取到了该供应商的证书,直接封掉所有使用该证书的链接呢?GFW接下来就寻找类似状态的证书,进行封锁,是否会造成其他风险呢?

Mygod commented 7 years ago

This has been discussed long ago. Gfw can simply block your certificate.

yvbbrjdr commented 7 years ago

这样的话,焦点就都转移到了证书上了吗?如果GFW伪装成一个用户,购买某家的服务,获取到了该供应商的证书,直接封掉所有使用该证书的链接呢?GFW接下来就寻找类似状态的证书,进行封锁,是否会造成其他风险呢?

每一台服务器签一个证书,一个证书不会包含其他服务器的信息。

你说的类似状态是指什么状态?

PS:不管是什么协议,gfw直接购买服务探测都是无解的啊。

yvbbrjdr commented 7 years ago

This has been discussed long ago. Gfw can simply block your certificate.

Wanna see the discussion.

hellofwy commented 7 years ago

我不认为:“半年来shadowsocks以及shadowsocksR的更新都是在做这件事情”即“不被检测出服务器在提供翻墙服务”

ss-libev 引入混淆是最初为了 QoS,插件化是为了方便扩展。引入 AEAD 是为了防篡改数据包。增加随机数长度是为了防止破解密钥。

TLS 相关讨论请搜索 shadowsocks 组织下个各项目的 issues。或者使用搜索引擎。

arloor commented 6 years ago

楼主的意思是说,在本地客户端和远程服务端之间加上ssl加密吗?

ipid commented 6 years ago

恭喜楼主重新发明 v2ray

MaoJianwei commented 5 years ago

我也一直好奇,为什么shadowsocks还不支持SSL。。。顶楼主,早日开发成功并merge

LBYPatrick commented 5 years ago

@yvbbrjdr 不要跟他计较了,你看看@hellofwy的Github项目就知道了:joy:无需多言

MaoJianwei commented 5 years ago

是谁去发起reset的呢?那正常的SSH连接和HTTPS连接不就也受干扰了吗?

在 2018-12-14 16:16:26,"sklinux" notifications@github.com 写道:

ssl早就开始随机reset 链接

— You are receiving this because you commented. Reply to this email directly, view it on GitHub, or mute the thread.

abc123lzf commented 5 years ago

然而经我实验发现利用SSL加密翻墙效果还不错,性能和ShadowsocksR相当。可以参考我的项目flyingsocks