机场推荐网

Shadowsocks 2022 和老版本差在哪,从加密方式的名字拆起

加密方式一栏写着 2022-blake3 打头的名字,节点用的就是 Shadowsocks 2022。它只收定长随机密钥,请求带时间戳防重放,照旧不握手,也不装成别的协议。

更新于 10 分钟读完作者 阿量参考了 15 份一手资料

订阅里偶尔会冒出这样一个加密方式,2022-blake3-aes-128-gcm。它比老节点上的 aes-256-gcm 长出一大截,多出来的两段各有所指。2022 是协议的版本,对应一份编号 SIP022 的规范。blake3 是推导会话密钥用的哈希函数。末尾的 aes-128-gcm 才是给数据加密的算法。我把 SIP022 原文和几家内核、客户端的文档对了一遍,这三段各自牵着一件用的时候会碰到的事。

Shadowsocks 从第一代起就不握手

Shadowsocks 官方文档给自己下的定义很短,一个大致参照 SOCKS5 的加密分体代理。分体的意思是程序拆成两半。本地那一半叫 ss-local,在你的设备上,客户端内核干的就是它的活。远端那一半叫 ss-remote,跑在机场的服务器上。ss-local 把目标地址和数据一起加密发出去,ss-remote 解开后替你去连目标网站,回来的数据再加密送回。目标地址的写法也照搬 SOCKS5,1 个字节的类型,后面跟地址和 2 个字节的端口。

两头事先各存一份相同的密钥,连接一建立就直接发密文,中间没有协商环节。Trojan 这类靠 TLS 的协议要先走完一轮 TLS 握手,才轮得到代理数据。Shadowsocks 省掉了这一步,代价 SIP022 自己写在概述里。前向保密这一项,前几版没有,2022 版照旧没有,规范作者的看法是预共享密钥配上免握手最适合它的用途。有前向保密的协议,长期密钥哪天漏了,从前被人录走的流量仍旧打不开。Shadowsocks 给不了这个保证。

2022 这一段,冲着老版本被人探测的三个毛病来

Shadowsocks 的加密换过三代,订阅里三代的名字都还见得到。

代际 订阅里常见的名字 密钥从哪来 能否发现数据被改 防重放
流加密 aes-256-cfbrc4-md5chacha20-ietf 密码经 EVP_BytesToKey 推出 包里只有 IV 和密文,没有校验标签
AEAD aes-128-gcmaes-256-gcmchacha20-ietf-poly1305 密码或密钥,再用 HKDF-SHA1 派生子密钥 每块带校验标签 文档里没有写
2022 2022-blake3- 开头 定长随机密钥,用 BLAKE3 派生子密钥 每块带校验标签 时间戳加盐值记录

流加密那一页文档的顶上现在挂着警告,称这类算法已经彻底不安全,近期就会删掉。AEAD 这一代的提案是 2017 年 1 月 12 日由 Mygod 在 shadowsocks-org 仓库提出的 SIP004,它补上了完整性校验。2022 年 5 月 8 日,database64128 在同一个仓库提出 SIP022,规范的致谢里还写了 zonyitoo、xiaokangwang 和 nekohasekai 三个名字。

SIP022 要补什么,Xray 的文档替它总结过,旧协议有三个问题。拦 TCP 重放的那个过滤器用得越久误判越多,UDP 这边压根不防重放,TCP 上还留着几种能被主动探测利用的行为。重放对服务器来说很难办,一段被人录下来再发一遍的密文,密钥对得上,格式和校验也都过得去,和真用户发来的没有两样。

2022 版的办法写得很具体。请求头里多了一个时间戳字段,占 8 个字节,记的是 Unix 时间,它和服务器时间相差超过 30 秒,这条消息就必须按重放处理。服务器还得把最近 60 秒见过的盐值全部记下来,撞上已有记录的连接一律不接。规范点名禁用布隆过滤器,凡是会把没见过的盐误判成见过的数据结构都不行,正对着上面第一个问题。服务器的响应头要带回请求里的盐,客户端必须核对,这样一条响应只能对上一条请求。

防探测那部分管的是服务器的举止。解密失败时,服务器不得让对方看出自己已经读了多少字节,规范给了三种关连接的做法供实现方选。请求头里还必须带上初始数据或者随机填充,两样都没有的请求要拒掉,填充最长 900 字节。

blake3 这一段,密码从此不能自己起

老版本的密码可以随手起,123456 也行,真正的密钥是程序拿 OpenSSL 的 EVP_BytesToKey 函数从密码里算出来的。SIP022 把这条路封了,实现方不准再从密码推导密钥,EVP_BytesToKey 不行,换别的函数也不行。用户得直接交出一段定长的随机密钥,规范说这一改动借鉴了 WireGuard。

这段密钥以 Base64 的形式出现在配置里。生成它有 OpenSSL 就够,规范里直接给了命令,shadowsocks-rust 另外带了一个自己的子命令。

# 128 位方法填 16,256 位方法填 32
openssl rand -base64 16

# shadowsocks-rust 自带的生成方式
ssservice genkey -m "2022-blake3-aes-256-gcm"

长度可以用眼睛验。16 字节的密钥编码后是 24 个字符,以两个等号结尾。32 字节的是 44 个字符,以一个等号结尾。shadowsocks-rust 的 README 要求密钥长度和加密方式的密钥长度完全一致,Surge 手册的措辞也是 exactly 16 字节或 32 字节。订阅里的 password 是机场面板生成的,别动它,手抄节点时多一个少一个字符都会连不上。

会话密钥的算法也换了。AEAD 那一代用 HKDF-SHA1,信息串固定为 ss-subkey。2022 版改用 BLAKE3 的 derive_key 模式,上下文字符串是 shadowsocks 2022 session subkey,材料是密钥接上盐,盐和密钥一样长。名字中间那个 blake3 指的就是这一步。

有的 password 里会出现用冒号隔开的两段甚至三段 Base64。这是 SIP023 定义的身份头。规范把排在前面的几段叫 iPSK,代表一层层的身份,排在末尾的叫 uPSK,对应具体某个用户,机场靠它在同一个端口上分清谁是谁。Surge 手册把两段的写法记成 serverKey:userKey。分享链接也跟着变了,SIP002 规定 2022 系列的 ss:// 链接不许再把加密方式和密钥做 Base64URL 编码,只能用百分号转义后直接写出来,所以这种链接里能直接读到加密方式的名字。

末尾那段算法名,各家文档认的个数不一样

SIP022 列了五个方法。2022-blake3-aes-128-gcm2022-blake3-aes-256-gcm 必须实现,另有 chacha20、chacha12、chacha8 三个 poly1305 变体属于可选。

到了内核和客户端手里,这个单子各不相同。Xray、mihomo、sing-box 三家文档列的都是两个 AES 方法加 2022-blake3-chacha20-poly1305,一共三个。shadowsocks-rust 多认一个 chacha8。Surge、StashLoon 的文档只列了两个 AES 方法。用 Clash Verge Rev 这类 mihomo 内核客户端的人不用操心这件事。iPhone 用户如果发现某个 SS2022 节点导进去报不支持,先看它的加密方式是不是 chacha20 那一个。

在 mihomo 的配置里,一个 2022 版节点长这样,sing-box 把 cipher 这个字段叫 method,其余意思相同。

proxies:
  - name: "新加坡 02"
    type: ss
    server: sg02.example.net
    port: 20443
    cipher: 2022-blake3-aes-256-gcm
    password: "这里是 44 个字符的 Base64 密钥"
    udp: true

数据的封装沿用了 AEAD 那一代的分块办法,每块带长度和校验标签。单块载荷的上限从 0x3FFF 提到了 0xFFFF,也就是从 16383 字节放宽到 65535 字节。

时钟偏出 30 秒,同一组节点会一起超时

用 2022 版节点的人,碰到的故障多半出在时间上。30 秒的容差很窄,设备时钟走偏半分钟,服务器就会把你的每个请求都当成重放丢掉,表现出来是 SS2022 节点整组超时。

判断起来不难。同一份订阅里别的协议的节点还能连,唯独 2022 版的全灭,先去看系统时间,把自动对时打开。内核跑在路由器上的,要看路由器自己的时间对不对。时间没问题,再去更新订阅,看机场是不是换过密钥。其他情形的排查顺序写在机场连不上怎么查里。

UDP 从逐包加密改成按会话管理

老版本的 UDP 没有会话这个概念,每个包各自带盐、各自加密,AEAD 文档里写的 nonce 是全零。2022 版给每个 UDP 会话配了一个客户端随机生成的 8 字节会话 ID,包上再带一个 8 字节的递增编号,收包的一方用滑动窗口把重复的包滤掉,UDP 的重放保护就是这么补上的。

规范还写了一条对手机有用的规定。服务器每验证通过一个包,就要把记录里的客户端地址更新成最新的,会话至少记住 60 秒。规范的原话是 UDP 会话可以撑过客户端的网络变化。手机离开 Wi-Fi 改走蜂窝数据时,出口地址变了,会话 ID 没变,服务器照样认得这个会话。

本站 28 家机场的协议一栏里找不到 Shadowsocks

Shadowsocks 不装成任何别的协议。SIP022 的说法是代理流量和随机字节流无法区分,这和 Trojan、REALITY 装成 HTTPS 的路子不同。两种思路放到具体网络里谁更顺,我手里没有测试数据,这里不比。

这个站一共收了 28 家机场,协议一栏有记录的只有 8 家,其中 VLESS 6 家,Trojan 2 家,AnyTLS 2 家,灵动云和星岛梦各记了两种。Shadowsocks 是 0 家。这些记录出自机场自己的说法和我整理的资料,核对时间多数是 2026 年 8 月 8 日和 9 日,星岛梦是 9 月 19 日。剩下 20 家的资料里压根没写协议,所以这个 0 只说明没人把 Shadowsocks 当卖点写出来。自己的订阅里有没有 SS 节点,导入客户端后看节点的类型和加密方式最准。各协议在机场里的分布,协议总览那篇有完整的统计。

常见问题

iPhone 上哪些客户端能连 Shadowsocks 2022 节点

Surge、Stash、Loon 的官方文档都写了支持,列出的方法是 2022-blake3-aes-128-gcm 和 2022-blake3-aes-256-gcm 两个,没有 chacha20 那一个。机场下发的若恰好是 chacha20 版本,这几个客户端能不能连我没有实机验证过。

aes-256-cfb、rc4-md5 这种老 Shadowsocks 节点还能继续用吗

多数内核还认,但不建议再用。Shadowsocks 官方文档的流加密一页挂着警告,称这类算法已经彻底不安全、近期就会删掉,新用户只该选 AEAD 方法。shadowsocks-rust 把它们收在一个标着 UNSAFE 的编译开关后面,sing-box 文档把它们归进旧方法一栏。

Shadowsocks 2022 的 password 中间有个冒号,是订阅出错了吗

没有出错。SIP023 给 2022 版加了身份头,好让一个端口同时服务许多用户。写法是服务器一级的密钥在前,用户自己的密钥在后,中间拿冒号连上。Surge 手册里把这两段叫 serverKey 和 userKey。整串原样保留,别拆开。

Shadowsocks 2022 能伪装成 HTTPS 流量吗

协议本身不伪装。SIP022 的说法是代理流量和随机字节流无法区分,它走的是让人看不出格式这条路。想在外面再套一层 TLS 外观要靠插件,mihomo 文档列了 shadow-tls、restls 等七种插件,sing-box 只内置 obfs-local 和 v2ray-plugin。

手机从 Wi-Fi 切到流量,Shadowsocks 2022 的 UDP 连接会断吗

按规范不必断。2022 版的每个 UDP 会话有一个 8 字节的会话 ID,服务器验证通过一个包以后,要把记录里的客户端地址更新成最新的那个,会话至少记住 60 秒。实际表现还要看机场服务端和客户端内核各自怎么实现。

参考来源

  1. Shadowsocks SIP022,AEAD-2022 规范原文
  2. Shadowsocks SIP023,可扩展身份头
  3. Shadowsocks SIP002,ss 分享链接格式
  4. Shadowsocks 文档,AEAD 加密
  5. Shadowsocks 文档,流加密
  6. Shadowsocks 文档,协议定义与地址格式
  7. shadowsocks-org 议题 196,SIP022 提案(2022-05-08)
  8. shadowsocks-org 议题 30,SIP004 AEAD 提案(2017-01-12)
  9. shadowsocks-rust 仓库 README
  10. Xray 文档,Shadowsocks 出站
  11. mihomo 文档,Shadowsocks 节点
  12. sing-box 文档,Shadowsocks 出站
  13. Surge 手册,Shadowsocks 策略
  14. Stash 文档,支持的代理协议
  15. Loon 文档,节点格式

更新记录

  • 首次发布