https://github.com/XTLS/REALITY
reality是安全传输层的实现,其和TLS类似都实现了安全传输,除此之外还进行TLS指纹伪装
简单来说就是:
- 确定一个伪装服务器目标,比如https://example.com
- 当普通客户端来访问reality服务端时,将其代理到example.com
- 当特殊客户端来访问reality服务端时,进行特定处理流程
具体来说就是在客户端与伪装服务器进行TLS握手的同时,也进行了私有握手
首先reality服务端和特殊客户端预先共享一对公私密钥(x25519)
私有握手关键步骤如下:
- 特殊客户端在Client Hello中
- 生成临时公私密钥对(x25519)
- Client Hello中将Extension的key_share修改为临时公钥
- 通过临时私钥与预先共享的公钥,以及hkdf算法生成authkey
- 通过authkey对版本号、时间戳等信息加密,并替换Client Hello中的Session ID字段
- reality服务端收到Client Hello后
- 通过预先共享的私钥和Client Hello中的临时公钥,以及hkdf算法生成authkey
- 通过authkey解密Session ID字段,并验证时间戳、版本号信息
- 验证成功则生成一个临时可信证书(ed25519)
- 验证失败则代理到伪装服务器
- 特殊客户端在收到reality服务端证书后
- 通过hmac算法和authkey计算证书签名,与收到的证书签名对比
- 若签名一致,进行特定处理流程
- 若签名不一致
- 但签名是example.com的真证书,则进入爬虫模式
- 否则发送TLS alert
特点:
- 完美模拟了伪装服务器的TLS指纹
- 特殊客户端巧妙的利用TLS1.3的key_share和Session ID字段进行私有握手
- 这两字段原本都是随机的,即使替换也没有特征
- 不需要域名,也不需要证书
限制:
只能使用TLS1.3,且必须使用x25519
- key_share是TLS1.3新增内容https://www.rfc-editor.org/rfc/rfc8446#section-4.2.8
- reality服务端返回的临时证书本质上是有特征的,但TLS1.3中Certificate包是加密的,也就规避了这一问题
- 如果伪装服务器目标不使用x25519,则私有握手无法成功
- 使用两组预共享公私钥,分别用于密钥交换/验签,验签使用额外一次通信进行
- 模仿站必须是tls1.2,且最好使用aead的套件
- TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305
- TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305
- TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
- TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
- TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
- TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
- TLS_RSA_WITH_AES_128_GCM_SHA256
- TLS_RSA_WITH_AES_256_GCM_SHA384
- 服务端代码实现更简单,不需要修改tls库,用读写过滤的方式来判断是否已经握手完成