简介
- grss(Golang Reverse SOCKS5 Server) 服务端,需要有公网IP的机器上
- grsc(Golang Reverse SOCKS5 Client) 客户端,需要运行于想要穿透的内网中机器上
- grsu(Golang Reverse SOCKS5 User) 用户端,需要运行于用户机器上,提供socks5服务
grs是一个反向socks5代理,其中grss和grsc和grsu是通过REALITY协议通信
相对于frp,nps等内网穿透工具有以下特点
- 完美消除网络特征
- 防止服务端被主动探测
- 客户端和用户端内嵌配置,不需要命令行或额外配置文件
仓库地址: https://github.com/howmp/reality
使用步骤
生成配置、客户端、用户端
grss gen www.qq.com:443 127.0.0.1:443
www.qq.com:443
是被模拟的目标127.0.0.1:443
是服务器监听地址,这里要填写公网IP,端口最好和模拟目标一致
若SNIAddr或ServerAddr不指定,则尝试加载已有配置文件
1 | Usage: |
启动服务端
grss serv
1 | Usage: |
启动客户端
grsc
启动用户端
grsu
1 | Usage of grsu: |
常见问题
服务端被探测时使用的“真证书”吗?
是,准确的说被探测时,服务端相当于一个端口转发,证书与被模拟的目标完全一致
这样一点可以通过修改本地Hosts文件后,通过浏览器访问来验证
或通过curl验证: curl -v -I --resolve "www.qq.com:443:127.0.0.1" https://www.qq.com
为什么客户端/用户端提示verify failed
?
- 服务端时间和客户端时间相差超过
expire second
- 为了防重放,默认不能相差30秒,可在生成时修改最大超时时间
grss gen -e 60 www.qq.com:443 127.0.0.1:443
- 也可以NTP同步客户端、用户端、服务端时间
- 为了防重放,默认不能相差30秒,可在生成时修改最大超时时间
- 服务端配置重新生成后,也需要使用最新的
grsc
和grsu
,否则预共享密钥不匹配 - 客户端的网络可能被劫持
关于REALITY协议
https://github.com/XTLS/REALITY
reality是安全传输层的实现,其和TLS类似都实现了安全传输,除此之外还进行TLS指纹伪装
简单来说就是:
- 确定一个伪装服务器目标,比如https://example.com
- 当普通客户端来访问reality服务端时,将其代理到example.com
- 当特殊客户端来访问reality服务端时,进行特定处理流程
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
https://github.com/XTLS/Xray-core/issues/1697#issuecomment-1441215569
reality的特点和限制
特点:
- 完美模拟了伪装服务器的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,则私有握手无法成功
与原版的reality的区别
- 使用两组预共享公私钥,分别用于密钥交换/验签,验签使用额外一次通信进行
- 模仿站必须是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库,用读写过滤的方式来判断是否已经握手完成