尝试自己造个轮子,主要是为了熟悉 Go 语言,做点东西 当然有更好的项目,他们拥有更好的密码学安全性,拥有更强劲的性能,更好的优化,所以这个并不适合部署在生产环境使用,我自己主力都不用这个(划掉) 但是他让我明白原理,让我有机会实践且应用我自己的想法,我还可以根据自己的需要定制化连接的特点,自己 选择和规划伪装方式
警告: 此项目仅用于技术交流与学习,禁止用于任何违规违法用途!!! 作者不承担任何责任和后果
源代码可以随意使用,不作任何限制
-c
加上这个参数才能运行 LOCAL 模式
-r string
仅适用于 LOCAL 模式的,设置远程服务器地址和端口,可以同时使用多个服务器。每个服务器地址用逗号分隔。服务器访问密码的顺序必须与服务器地址相对应,密码字符串也用逗号分隔(默认 :127.0.0.1:10010")
-s string
仅用于服务器模式,设置服务器本地侦听地址和端口,默认为 (127.0.0.1:10010)
-k string
密钥字符串,服务器密码顺序必须对应于服务器地址顺序,密码之间用逗号分隔,在服务器模式下,仅使用第一个密码(默认为"TESTMEBABY")
-norandom
决定选择服务器的方式,默认情况下,有多个服务器可用的时候每次连接都会随机选择一个服务器使用,但如果开启此开关,靠前的服务器的优先级高于
靠后的服务器的优先级,这将导致,靠后的服务器只有在靠前的服务期无法使用的时候才会拿出来使用,相当于添加的服务器作为备份服务器,我并没有
添加服务器淘汰机制,所以增加了服务器连接失败的提示,需要靠人工筛选掉已经无法使用的服务器
-tcptimeout int
设置 TCP 读超时,不应低于 UDP 超时(默认为 30)
-udptimeout int
设置 UDP 超时,应大于 TCP 超时(默认为 150)
-debug 启用 Debug,显示调试信息 -h
显示帮助
-l string
只能在 Local 模式下使用,用于设置 Socks5 监听地址 [::]:10805 (默认 "[::]:10805")
-lower
使用较低安全性的加密方法(AES-128-GCM)而不是 AES-256-GCM,此选项将影响所有密码的加密。使用多台服务器时,请注意,无法自定义每个服务器使用的密码加密模式
-test
在测试模式下,将在一台计算机上运行服务器和客户端
大致流程
SOCKS5客户端 <-----> LOCAL端 <============>SERVER端 <---------->目标服务器
本质上就是把SOCKS5拆成了两半,使用私有的协议和AES GCM方式加密要传输的数据,让被代理的数据无法被第三方识别,分析
关于socks5的通信过程和协议标准,请参阅RFC1928 这个标准文档,我当初就是啃这个文档了解socks5通信流程及标准的,但是后来看到这个博客有个翻译,写的不错,放在这里: SOCKS5协议「RFC1928翻译」
然后就是LOCAL与SERVER的通信部分
数据处理流程:
- LOCAL监听socks5服务端口 10805
- SOCKS5客户端向SOCKS5握手
- LOCAL接受握手,提取连接信息。LOCAL打包数据成私有格式,并用提供的加密方式加密数据,发送到SERVER
- SERVER收到数据包,尝试分析数据包。 成功的话用数据包的信息作为接下来的加密用信息,直接利用这条建立好的网络连接传输信息
这是第一层,第一层所用的简单的指令包结构
| Session ID | Control Code | Address Type | DST.ADDR | DST.PORT |
|---|---|---|---|---|
| 16 byte | 1 byte | 1 byte | variable | 2 byte |
Session 由客户端生成的唯一随机数,16 字节,由客户端定义,作为会话 ID 使用,同时作为iv使用
Control Code 一定范围内的int8 0-100代表IPV4,101-254代表IPV6,255代表Domain Name 生成时生成指定范围内的随机数
Address Type 与 socks5 相同的地址类型
DST.ADDR 与 socks5 相同的地址
DST.PORT 与 socks5 相同的端口
这个数据包是最顶层(第一层)的传输控制指令的数据包,将其称为Realdata后传送到第二层
第二层用于打包数据和添加混淆,避免统计学攻击
| Random Data length | Random Data | RealData |
|---|---|---|
| 1 byte | variable | variable |
random data length 是一个uint8,用于描述随后紧跟的无用填充数据的长度,我手动将其限制在了范围1-55内
random data 是随机数据,用于填充
realdata 第一层传输过来的有用数据
第三层是最底层的加密层
| Payload Length | Payload |
|---|---|
| 4 byte | variable |
Payload Length是一个uint32,描述Payload的长度
payload 由第二层的数据通过AES GCM方式加密得到
此层由 AES GCM(AEAD) 加密,保障消息的机密性与可靠性,所以在这一层接收到的消息可以认为是无误且可信的
客户端建立连接的首个包,由AES - GCM 加密方式加密,每个包都有其独特的包 ID,也就是包头的 16 byte 随机数 在首次连接时这串随机数会被记录,若后续包的随机数与之重复了,就证明其过了加密层的防御,可以断定是一个完全的包数据重放(认为随机数不可能重复)
防止过期数据包(阻止长期完整包重放),首包IV由key + timestmp经过MD5加密得到,后续包IV由首包定义
自己写了一个 FIFO 的链表,服务器首次收到连接都会校验包 ID 是否在这个链表里,在这个链表里就证明一分钟内曾使用过这个 ID 为了防止数组会越来越大,占用内存不说,每次接受连接时遍历数组会越来越困难,开个 goruntime 检查每个 包 ID 的生存周期,过期的包会被删除
采用 FIFO 链表的原因是,这样检测包生存周期的 func,仅需要检查首个数据的生存周期,如果它没过期,那后续包不可能过期, 如果其过期那就删除后检测下一个包(此时其成为新的“首个数据”),还是过期的话继续删除,重复这一操作, 这样的话就不需要检查生存周期时遍历整个链表了,但是检查这个数据是否已存在于链表中,依然需要遍历整个链表
应对本地 echo 重放攻击: Client 的加密数据包有自己的标识,用 GCM 加密方式的ADD Data 部分标识 0XFF,0XFF Server 的加密数据包有自己的标识,用 GCM 加密方式的ADD Data 部分标识 0XFC,0XFF
应对交换顺序的 TCP 包重放: 只能用增加包 ID 来解决,包 ID 从零开始递增,用 uint32,4byte 表示(未完成)
仍然存在的 bug: 被恶意的交换数据包顺序客户端与服务端也不能分辨出来。 可能被大规模的流量分析发现特征,毕竟这是个未知的加密流量
-
V1.0.0:
完成大体框架,跑得起来的程度
-
V1.1.0:
重大更新,重新精炼了代码,加入了抗重放的功能
-
V1.2.0:
修 bug,增加了服务器负载均衡的功能,支持多服务器,支持选择 AES GCM 加密方式的密码位数(128 位,256 位)
-
V1.2.2:
修复了负载均衡的 bug,改善了抗重放的逻辑,安全性提升
-
V1.2.4:
加入 Gzip 压缩数据,是否真的有用呢?还是单纯在耗费 CPU 性能呢?? 调整默认允许的数据包收发两段时间差值到 10 秒,把 nonceGC 运行间隔设置成 15 秒
-
V1.2.5:
更改使用的官方 gzip 库为第三方的 github.com/klauspost/pgzip 库,因为这个库大幅优化了 gzip 的压缩效率,go 官方 gzip 实现相比之下太慢力!
-
V1.2.6:
删除 gzip 压缩方法,无论使用哪个库,都会使 CPU 占用率大幅提升,而速度大幅降低,在我的平台上,开启 gzip 后 CPU 占用率从 4%上升到 24%,但是速度却从 240Mbps 降到了 30Mbps,匪夷所思。
-
V1.2.7:
更新了更多的抗中间人,抗协议分析的过程,吸收了很多前人的经验,更改了加密数据承载的格式,增加了对逐字节重放的防御,优化了对重放的判断逻辑,话说部署测试时真的收到重放数据包了诶
-
V1.2.9 bate:
犯了和酸酸 OTA 作者同样的错误,想要使用 Encrypt-and-MAC (E&M) ,MAC-then-Encrypt (MtE) <- 即 OTA 的做法,这是很不安全
的,而且引入被精准探测的漏洞,应该全程使用 Encrypt-then-MAC (EtM). 增加了个反击开关,默认关闭,我想见识
一下这个方法会不会引起它的反击呢
-
V1.3.0:
- 小改协议,去除了ATYPE使用范围随机数代替的决定,因为已经有混淆层了。将使用链表存储iv数据改为了用给予哈希表的golang自带map,性能高出很多
-
V1.3.2:
- 删除反击模式,因为测试这个模式导致我的VPS被封了,🐴的,统一应对重放的动作,放弃长时间挂起连接,统一特征为直接断开连接
-
V1.3.3 Bate:
- 把gzip压缩流量加回来了,这时候加大read buf对增加压缩率有好处,但是因为性能要求巨大,开启gzip后可能会导致速度下降至多7倍,推荐强CPU小带宽的机器打开,或者线路不好的时候开开。 增加失效服务器自动临时停用功能,避免多服务器场景因为一个服务器无效导致整体延迟大幅上涨
-
V1.3.4 Stable:
- 一个连接会话重用一个AES-256-GCM的加密器,提升了些许效率,修复了少许bug
-
V1.3.5 Bate:
- 添加了FakeTLS模式,和ShadowTLS的原理一模一样,接下来尝试修复主动探测漏洞