Reverse Engineering of Snell

Snell Server

本文是对 snell 协议版本 1.1 的初步逆向,项目地址在 GitHub.

Overview

Encryption Schema

Schema 同 shadowsocks aead 模式,分组密码选用了 chacha20-poly1305-ietf,详见 Aead Schema
会话密钥生成方式为

1
crypto_pwhash(__out key, 32, psk, psk_len, salt, 3ULL, 0x2000ULL, crypto_pwhash_ALG_ARGON2ID13);

参数意义详见 libsodium documentation

The Snell Protocol

C to S

1
[1-byte version][1-byte command][1-byte client_id length][variable-length client_id][1-byte host length][variable-length host][2-byte port][application data...]

其中

FIELDOPTIONAL VALUECOMMENT
version0x01
command0x00PING
0x01CONNECT
client_id lengthzero currentlyreserved for multi-user
  • 本 repo 给出的 demo 没有实现 obfs 功能
  • host 总是字符串格式的,即使是 ip 地址
  • port 为网络字节序

S to C

1
[1-byte command][content...]

其中

FIELDOPTIONAL VALUECOMMENT
command0x00TUNNEL
0x02ERROR

当 command=0x00 时,content 即是应用层数据,正常建立隧道将远端数据原封不动传递
当 command=0x02 时,content 具有如下模式

1
[1-byte error code][1-byte error msg length][variable-length error message]

Obfuscating Algorithm

HTTP

目前的 http 就是 simple-obfs 的 http mode,不想实现 demo 了,但可作如下验证

1
2
./snell-server -c ./snell-server.conf &
obfs-server -s 0.0.0.0 -p 8787 -r 127.0.0.1:9898 --obfs=http

假定 snell-server.conf 内容如下:

1
2
3
4
$ cat ./snell-server.conf
[snell-server]
listen = 0.0.0.0:9898
psk = zzz

现在 surge 中添加代理test_snell = snell, [SERVER ADDRESS], 8787, psk=zzz, obfs=http可成功访问网络

TLS

TLS 也就是 simple-obfs 的 tls mode,验证方式同上

Build Demo

macOS

1
2
3
4
brew update && brew install boost libsodium glog gflags cmake
# clone and cd into the repo
mkdir build && cd build
cmake .. && make

debian

1
2
3
4
apt update && apt install build-essential libboost-dev libsodium-dev libgoogle-glog-dev libgflags-dev cmake
# clone and cd into the repo
mkdir build && cd build
cmake .. && make