├── 2022-1-shadowsocks-2022-edition.md ├── 2022-2-shadowsocks-2022-extensible-identity-headers.md ├── 2022-3-shadowsocks-url.md ├── 2022-4-shadowsocks-implementations.md ├── 2023-1-shadowsocks-server-management-api-v1.md ├── LICENSE └── README.md /2022-1-shadowsocks-2022-edition.md: -------------------------------------------------------------------------------- 1 | # Shadowsocks 2022 Edition: Secure L4 Tunnel with Symmetric Encryption 2 | 3 | ## Abstract 4 | 5 | This document defines the 2022 Edition of the Shadowsocks protocol. Improving upon Shadowsocks AEAD (2017), Shadowsocks 2022 addresses well-known issues of the previous editions, drops usage of obsolete cryptography, optimizes for security and performance, and leaves room for future extensions. 6 | 7 | ## 1. Overview 8 | 9 | Shadowsocks 2022 is a secure proxy protocol for TCP and UDP traffic. The protocol uses [AEAD](https://en.wikipedia.org/wiki/Authenticated_encryption) with a pre-shared symmetric key to protect payload integrity and confidentiality. The proxy traffic is indistinguishable from a random byte stream, and therefore can circumvent firewalls and Internet censors that rely on [DPI (Deep Packet Inspection)](https://en.wikipedia.org/wiki/Deep_packet_inspection). 10 | 11 | Compared to [previous editions](https://github.com/shadowsocks/shadowsocks-org/blob/master/whitepaper/whitepaper.md) of the protocol family, Shadowsocks 2022 allows and mandates full replay protection. Each message has its unique type and cannot be used for unintended purposes. The session-based UDP proxying significantly reduces protocol overhead and improves reliability and efficiency. Obsolete cryptographic functions have been replaced by their modern counterparts. 12 | 13 | As with previous editions, Shadowsocks 2022 does not provide forward secrecy. It is believed that using a pre-shared key without performing handshakes is best for its use cases. 14 | 15 | A Shadowsocks 2022 implementation consists of a server, a client, and optionally a relay. This document specifies requirements that implementations must follow. 16 | 17 | ### 1.1. Document Structure 18 | 19 | This document describes the Shadowsocks 2022 Edition and is structured as follows: 20 | 21 | - Section 2 describes requirements on the encryption key and how to derive session subkeys. 22 | - Section 3 defines the encoding details of the required AES-GCM methods and the process for handling requests and responses. 23 | - Section 4 defines the encoding details of the optional ChaCha-Poly1305 methods. 24 | 25 | ### 1.2. Terms and Definitions 26 | 27 | The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 [RFC2119](https://www.rfc-editor.org/info/rfc2119) [RFC8174](https://www.rfc-editor.org/info/rfc8174) when, and only when, they appear in all capitals, as shown here. 28 | 29 | Commonly used terms in this document are described below. 30 | 31 | - Shadowsocks AEAD: The original AEAD construction of Shadowsocks, standardized in 2017. 32 | 33 | ## 2. Encryption/Decryption Keys 34 | 35 | A pre-shared key is used to derive session subkeys, which are subsequently used to encrypt/decrypt traffic for the session. The pre-shared key is also used directly in some places. 36 | 37 | ### 2.1. PSK 38 | 39 | Unlike previous editions, Shadowsocks 2022 requires that a cryptographically-secure fixed-length PSK to be directly provided by the user. Implementations MUST NOT use the old `EVP_BytesToKey` function or any other method to generate keys from passwords. 40 | 41 | The PSK is encoded in base64 for convenience. Practically, it can be generated with `openssl rand -base64 `. The key size depends on the chosen method. This change was inspired by WireGuard. 42 | 43 | | Method | Key Bytes | Salt Bytes | 44 | | ----------------------- | --------: | ---------: | 45 | | 2022-blake3-aes-128-gcm | 16 | 16 | 46 | | 2022-blake3-aes-256-gcm | 32 | 32 | 47 | 48 | ### 2.2. Subkey Derivation 49 | 50 | Shadowsocks 2022's subkey derivation uses [BLAKE3](https://raw.githubusercontent.com/BLAKE3-team/BLAKE3-specs/master/blake3.pdf)'s key derivation mode, which replaces the obsolete HKDF_SHA1 function in previous editions. A randomly generated salt is appended to the PSK to be used as key material. The salt has the same length as the pre-shared key. 51 | 52 | ``` 53 | session_subkey := blake3::derive_key(context: "shadowsocks 2022 session subkey", key_material: key + salt) 54 | ``` 55 | 56 | ## 3. Required Methods 57 | 58 | Method `2022-blake3-aes-128-gcm` and `2022-blake3-aes-256-gcm` MUST be implemented by all implementations. `2022` reflects the fast-changing and flexible nature of the protocol. 59 | 60 | ### 3.1. TCP 61 | 62 | TCP connections over a Shadowsocks 2022 tunnel maps 1:1 to proxy connections. Each proxy connection carries 2 proxy streams: request stream and response stream. A client initiates a proxy connection by starting a request stream, and the server sends back response over the response stream. These streams carry chunks of data encrypted by the session subkey. 63 | 64 | For payload transfer, Shadowsocks 2022 inherits the length-chunk-payload-chunk model from Shadowsocks AEAD, with some minor tweaks to improve performance. Standalone header chunks are added to both request and response streams to improve security and protect against replay attacks. 65 | 66 | #### 3.1.1. Encryption and Decryption 67 | 68 | Each proxy stream derives its own session subkey with a random salt for encryption and decryption. A 12-byte little-endian integer is used as nonce, and is incremented after each encryption or decryption operation. 69 | 70 | ``` 71 | u96le counter 72 | aead := aead_new(key: session_subkey) 73 | ciphertext := aead.seal(nonce: counter, plaintext) 74 | plaintext := aead.open(nonce: counter, ciphertext) 75 | ``` 76 | 77 | #### 3.1.2. Format 78 | 79 | A request stream starts with one random salt and two standalone header chunks, followed repeatedly by one length chunk and one payload chunk. Each chunk is independently encrypted/decrypted using the AEAD cipher. 80 | 81 | A response stream also starts with a random salt, but only has one fixed-length header chunk, which also acts as the first length chunk. 82 | 83 | A length chunk is a 16-bit big-endian unsigned integer that describes the payload length in the next payload chunk. Servers and clients rely on length chunks to know how many bytes to read for the next payload chunk. 84 | 85 | A payload chunk can have up to 0xFFFF (65535) bytes of unencrypted payload. The 0x3FFF (16383) length cap in Shadowsocks AEAD does not apply to this edition. 86 | 87 | ``` 88 | +----------------+ 89 | | length chunk | 90 | +----------------+ 91 | | u16 big-endian | 92 | +----------------+ 93 | 94 | +---------------+ 95 | | payload chunk | 96 | +---------------+ 97 | | variable | 98 | +---------------+ 99 | 100 | Request stream: 101 | +--------+------------------------+---------------------------+------------------------+---------------------------+---+ 102 | | salt | encrypted header chunk | encrypted header chunk | encrypted length chunk | encrypted payload chunk |...| 103 | +--------+------------------------+---------------------------+------------------------+---------------------------+---+ 104 | | 16/32B | 11B + 16B tag | variable length + 16B tag | 2B length + 16B tag | variable length + 16B tag |...| 105 | +--------+------------------------+---------------------------+------------------------+---------------------------+---+ 106 | 107 | Response stream: 108 | +--------+------------------------+---------------------------+------------------------+---------------------------+---+ 109 | | salt | encrypted header chunk | encrypted payload chunk | encrypted length chunk | encrypted payload chunk |...| 110 | +--------+------------------------+---------------------------+------------------------+---------------------------+---+ 111 | | 16/32B | 27/43B + 16B tag | variable length + 16B tag | 2B length + 16B tag | variable length + 16B tag |...| 112 | +--------+------------------------+---------------------------+------------------------+---------------------------+---+ 113 | ``` 114 | 115 | #### 3.1.3. Header 116 | 117 | ``` 118 | Request fixed-length header: 119 | +------+------------------+--------+ 120 | | type | timestamp | length | 121 | +------+------------------+--------+ 122 | | 1B | u64be unix epoch | u16be | 123 | +------+------------------+--------+ 124 | 125 | Request variable-length header: 126 | +------+----------+-------+----------------+----------+-----------------+ 127 | | ATYP | address | port | padding length | padding | initial payload | 128 | +------+----------+-------+----------------+----------+-----------------+ 129 | | 1B | variable | u16be | u16be | variable | variable | 130 | +------+----------+-------+----------------+----------+-----------------+ 131 | 132 | Response fixed-length header: 133 | +------+------------------+----------------+--------+ 134 | | type | timestamp | request salt | length | 135 | +------+------------------+----------------+--------+ 136 | | 1B | u64be unix epoch | 16/32B | u16be | 137 | +------+------------------+----------------+--------+ 138 | 139 | HeaderTypeClientStream = 0 140 | HeaderTypeServerStream = 1 141 | MinPaddingLength = 0 142 | MaxPaddingLength = 900 143 | ``` 144 | 145 | - 1-byte type: Differentiates between client and server messages. A request stream has type `0`. A response stream has type `1`. 146 | - 8-byte Unix epoch timestamp: Messages with over 30 seconds of time difference MUST be treated as replay. 147 | - Length: Indicates the next chunk's plaintext length (not including the authentication tag). 148 | - ATYP + address + port: Target address in [SOCKS5 address format](https://datatracker.ietf.org/doc/html/rfc1928#section-5). 149 | - Request salt in response header: This maps a response stream to a request stream. The client MUST check this field in response header against the request salt. 150 | 151 | #### 3.1.3. Detection Prevention 152 | 153 | The random salt and header chunks MUST be buffered and sent in one write call to the underlying socket. Separate writes can result in predictable packet sizes, which could reveal the protocol in use. 154 | 155 | To process the salt and the fixed-length header, servers and clients MUST make exactly one read call. If the amount of data received is not enough for decryption, or decryption fails, or header validation fails, the server MUST act in a way that does not exhibit the amount of bytes consumed by the server. This defends against probes that send one byte at a time to detect how many bytes the server consumes before closing the connection. 156 | 157 | In such circumstances, do not immediately close the socket. Closing the socket with unread data causes RST to be sent. This reveals the exact number of bytes consumed by the server. Implementations MAY choose to employ one of the following strategies: 158 | 159 | 1. To consistently send RST even when the receive buffer is empty, set `SO_LINGER` to true with a zero timeout, then close the socket. 160 | 2. To consistently send FIN even when the receive buffer has unread data, shut down the write half of the connection by calling `shutdown(SHUT_WR)`, then drain the connection for any further received data. 161 | 3. To consistently send FIN even when the receive buffer has unread data, but disallow unlimited writes, shut down the write half of the connection by calling `shutdown(SHUT_WR)`, then `epoll` for `EPOLLRDHUP`. Read until EOF then close the connection. This limits the amount of data the other party can send to the size of your socket receive buffer. 162 | 163 | In a request header, either initial payload or padding MUST be present. When making a request header, if payload is not available, add non-zero random length padding. 164 | 165 | For client implementations, a simple approach is to always send random length padding. To accommodate TCP Fast Open (TFO), clients MAY wait a short amount of time (typically less than one second) for client-first protocols to write the first payload, before carrying on to establish a proxy connection and write the header. 166 | 167 | Servers MUST reject the request if the variable-length header chunk does not contain payload and the padding length is 0. 168 | Servers MUST enforce that the request header (including padding) does not extend beyond the header chunks. 169 | 170 | For response streams, the header is always sent along with payload. No padding is needed. 171 | 172 | #### 3.1.4. Replay Protection 173 | 174 | Servers MUST store all incoming salts for 60 seconds. When a new TCP session is established, the first received message is decrypted and its timestamp MUST be checked against system time. If the time difference is within 30 seconds, then the salt is checked against all stored salts. If no repeated salt is discovered, then the salt is added to the pool and the session is successfully established. 175 | 176 | Some techniques in implementations of previous editions are no longer necessary and SHOULD NOT be implemented for Shadowsocks 2022: 177 | 178 | - Clients do not need to check the salt in response streams, because the response header includes an associated request salt. 179 | - Outgoing salts do not need to be added to the salt pool, because the header has a type field that indicates the direction of the stream. 180 | - For salt storage, implementations MUST NOT use Bloom filters or anything that could return a false positive result, because salts only have to be stored for 60 seconds. 181 | 182 | ### 3.2. UDP 183 | 184 | Shadowsocks 2022 completely overhauled UDP relay. Each UDP relay session has a unique session ID, which is also used as salt to derive the session subkey. A packet ID acts as packet counter for the session. The session ID and packet ID are combined and encrypted in a separate header. 185 | 186 | Clients create UDP relay sessions based on source address and port. When a client receives a packet from a new source address and port, it opens a new relay session, and subsequent packets from that source are sent over the same session. 187 | 188 | Servers manage UDP relay sessions by session ID. Each client session corresponds to one outgoing UDP socket on the server. 189 | 190 | #### 3.2.1. Encryption and Decryption 191 | 192 | The separate header is encrypted/decrypted with the pre-shared key using an AES block cipher. The body is encrypted/decrypted with the session subkey using an AEAD cipher specific to the session. 193 | 194 | ``` 195 | block_cipher := aes_new(psk) 196 | encrypted_separate_header := block_cipher.encrypt(separate_header) 197 | decrypted_separate_header := block_cipher.decrypt(encrypted_separate_header) 198 | 199 | session_subkey := blake3::derive_key(context: "shadowsocks 2022 session subkey", key_material: key + separate_header[0..8]) 200 | session_aead_cipher := aes_gcm_new(session_subkey) 201 | encrypted_body := session_aead_cipher.seal(nonce: separate_header[4..16], body) 202 | decrypted_body := session_aead_cipher.open(nonce: separate_header[4..16], body) 203 | ``` 204 | 205 | #### 3.2.2. Format and Separate Header 206 | 207 | A UDP packet consists of a separate header and an AEAD-encrypted body. The separate header consists of an 8-byte session ID and an 8-byte big-endian unsigned integer as packet ID. The body is made up of the main header and payload. 208 | 209 | ``` 210 | Packet: 211 | +---------------------------+---------------------------+ 212 | | encrypted separate header | encrypted body | 213 | +---------------------------+---------------------------+ 214 | | 16B | variable length + 16B tag | 215 | +---------------------------+---------------------------+ 216 | 217 | Separate header: 218 | +------------+-----------+ 219 | | session ID | packet ID | 220 | +------------+-----------+ 221 | | 8B | u64be | 222 | +------------+-----------+ 223 | ``` 224 | 225 | UDP sessions are initiated by clients. To start a UDP session, the client generates a new random session ID and maintains a counter starting at zero as packet ID. These are used in client-to-server messages and are usually referred to as client session ID and client packet ID. 226 | 227 | Servers use client session IDs to identify UDP sessions. For server-to-client messages, a different set of session ID and packet ID is used, and may be referred to as server session ID and server packet ID. Like the client session ID, the server session ID MUST be randomly generated. 228 | 229 | #### 3.2.3. Main Header 230 | 231 | The main header, or message header, is the header at the start of the body. The client-to-server message header consists of type, timestamp, padding and SOCKS address. The server-to-client message header has an additional client session ID field, which maps the server session to a client session. 232 | 233 | ``` 234 | Client-to-server message header: 235 | +------+------------------+----------------+----------+------+----------+-------+ 236 | | type | timestamp | padding length | padding | ATYP | address | port | 237 | +------+------------------+----------------+----------+------+----------+-------+ 238 | | 1B | u64be unix epoch | u16be | variable | 1B | variable | u16be | 239 | +------+------------------+----------------+----------+------+----------+-------+ 240 | 241 | Server-to-client message header: 242 | +------+------------------+-------------------+----------------+----------+------+----------+-------+ 243 | | type | timestamp | client session ID | padding length | padding | ATYP | address | port | 244 | +------+------------------+-------------------+----------------+----------+------+----------+-------+ 245 | | 1B | u64be unix epoch | 8B | u16be | variable | 1B | variable | u16be | 246 | +------+------------------+-------------------+----------------+----------+------+----------+-------+ 247 | 248 | HeaderTypeClientPacket = 0 249 | HeaderTypeServerPacket = 1 250 | ``` 251 | 252 | - 1-byte type: Differentiates between client and server messages. A client message has type `0`. A server message has type `1`. 253 | - 8-byte Unix epoch timestamp: Messages with over 30 seconds of time difference MUST be treated as replay. 254 | - Padding length: Specifies the length of the optional padding. Implementations MAY allow users to select from a list of predefined padding policies. Care SHOULD be taken to not exceed the network path's MTU when padding packets. 255 | 256 | #### 3.2.4. Session ID based Routing and Sliding Window Replay Protection 257 | 258 | Servers MUST route packets based on client session ID, not packet source address. When a server receives a packet with a new client session ID, a new relay session is created, and subsequent packets from that client session are sent over this relay session. 259 | 260 | A relay session MUST keep track of the last seen client address. When a packet is received from the client and is successfully validated, the last seen client address MUST be updated. Return packets MUST be sent to this address. This allows UDP sessions to survive client network changes. 261 | 262 | Each relay session MUST be remembered for at least 60 seconds. A shorter NAT timeout may allow attackers to successfully replay packets from an already forgotten client session. 263 | 264 | To handle server restarts, clients MUST allow each client session to be associated with more than one server session. Each association MUST be remembered for no less than the NAT timeout, which is at least 60 seconds. Alternatively, clients MAY choose to keep track of one old server session and one current server session, and reject newer server sessions when the last packet received from the old session is less than 1 minute old. 265 | 266 | Clients and servers MUST employ a sliding window filter for each relay session to check incoming packets for duplicate or out-of-window packet IDs. Existing implementations from WireGuard MAY be used. The packet ID MAY be checked as soon as the separate header is decrypted, but the sliding window state MUST NOT be updated before successful header validation, which filters out packets that are semantically invalid or have a bad timestamp. 267 | 268 | ## 4. Optional Methods 269 | 270 | Implementations MAY choose to implement `2022-blake3-chacha20-poly1305`, `2022-blake3-chacha12-poly1305` and `2022-blake3-chacha8-poly1305` when support for CPUs without AES instructions is a priority. The use of reduced-round ChaCha20 variants is justified by [this paper](https://eprint.iacr.org/2019/1492.pdf). 271 | 272 | For TCP, AES-GCM is simply replaced by ChaCha-Poly1305. For UDP, a slightly different construction is used. 273 | 274 | ### 4.1. UDP Construction 275 | 276 | `2022-blake3-chacha20-poly1305` uses XChaCha20-Poly1305 with the pre-shared key directly and a random nonce for each message. 277 | 278 | A UDP packet starts with the random nonce, followed by an encrypted body. The session ID and packet ID are merged into the main header. 279 | 280 | The same sliding window filter is used for replay protection. It is not necessary to check for repeated nonce. 281 | 282 | ``` 283 | Packet: 284 | +-------+---------------------------+ 285 | | nonce | encrypted body | 286 | +-------+---------------------------+ 287 | | 24B | variable length + 16B tag | 288 | +-------+---------------------------+ 289 | 290 | Client-to-server message header: 291 | +-------------------+------------------+------+------------------+----------------+----------+------+----------+-------+ 292 | | client session ID | client packet ID | type | timestamp | padding length | padding | ATYP | address | port | 293 | +-------------------+------------------+------+------------------+----------------+----------+------+----------+-------+ 294 | | 8B | u64be | 1B | u64be unix epoch | u16be | variable | 1B | variable | u16be | 295 | +-------------------+------------------+------+------------------+----------------+----------+------+----------+-------+ 296 | 297 | Server-to-client message header: 298 | +-------------------+------------------+------+------------------+-------------------+----------------+----------+------+----------+-------+ 299 | | server session ID | server packet ID | type | timestamp | client session ID | padding length | padding | ATYP | address | port | 300 | +-------------------+------------------+------+------------------+-------------------+----------------+----------+------+----------+-------+ 301 | | 8B | u64be | 1B | u64be unix epoch | 8B | u16be | variable | 1B | variable | u16be | 302 | +-------------------+------------------+------+------------------+-------------------+----------------+----------+------+----------+-------+ 303 | ``` 304 | 305 | ## Acknowledgement 306 | 307 | I would like to thank @zonyitoo, @xiaokangwang, and @nekohasekai for their input on the design of the protocol. 308 | -------------------------------------------------------------------------------- /2022-2-shadowsocks-2022-extensible-identity-headers.md: -------------------------------------------------------------------------------- 1 | # Shadowsocks 2022 Extensible Identity Headers 2 | 3 | Identity headers are one or more additional layers of headers, each consisting of the next layer's PSK hash. The next layer of an identity header is the next identity header, or the protocol header if it's the last identity header. Identity headers are encrypted with the current layer's identity PSK using an AES block cipher. 4 | 5 | Identity headers are implemented in such a way that's fully backward compatible with current Shadowsocks 2022 implementations. Each identity processor is fully transparent to the next. 6 | 7 | - iPSKn: The nth identity PSK that identifies the current layer. 8 | - uPSKn: The nth user PSK that identifies a user on the server. 9 | 10 | ## TCP 11 | 12 | In TCP requests, identity headers are located between salt and AEAD chunks. 13 | 14 | ``` 15 | identity_subkey := blake3::derive_key(context: "shadowsocks 2022 identity subkey", key_material: iPSKn + salt) 16 | plaintext := blake3::hash(iPSKn+1)[0..16] // Take the first 16 bytes of the next iPSK's hash. 17 | identity_header := aes_encrypt(key: identity_subkey, plaintext: plaintext) 18 | ``` 19 | 20 | ## UDP 21 | 22 | In UDP request packets, identity headers are located between the separate header (session ID, packet ID) and AEAD ciphertext. 23 | 24 | Response packets do not have identity headers. 25 | 26 | ``` 27 | plaintext := blake3::hash(iPSKn+1)[0..16] ^ session_id_packet_id // XOR to make it different for each packet. 28 | identity_header := aes_encrypt(key: iPSKn, plaintext: plaintext) 29 | ``` 30 | 31 | For request packets, when iPSKs are used, the separate header MUST be encrypted with the first iPSK. Each identity processor MUST decrypt and re-encrypt the separate header with the next layer's PSK. 32 | 33 | For response packets, no special handling is needed for the separate header. The server encrypts the separate header with the user's PSK, per the base spec. Identity processors MUST forward response packets directly to clients without parsing or modifying them. 34 | 35 | ## Scenarios 36 | 37 | ``` 38 | client0 >---+ 39 | (iPSK0:iPSK1:uPSK0) \ 40 | \ 41 | client1 >------\ +---> server0 [iPSK1] 42 | (iPSK0:iPSK1:uPSK1) \ / [uPSK0, uPSK1, uPSK2] 43 | >-> relay0 [iPSK0] >-< 44 | client2 / [iPSK1, uPSK3] \ 45 | (iPSK0:iPSK1:uPSK2) >------/ +---> server1 [uPSK3] 46 | / 47 | client3 / 48 | (iPSK0:uPSK3) >---+ 49 | ``` 50 | 51 | A set of PSKs, delimited by `:`, are assigned to each client. To send a request, a client MUST generate one identity header for each iPSK. 52 | 53 | A relay decrypts the first identity header with its identity key, looks up the PSK hash table to find the target server, and relays the remainder of the request. 54 | 55 | A single-port-multi-user-capable server decrypts the identity header with its identity key, looks up the user PSK hash table to find the cipher for the user PSK, and processes the remainder of the request. 56 | 57 | In the above graph, `client0`, `client1`, `client2` are users of `server0`, which is relayed through `relay0`. `server1` is a simple server without identity header support. `client3` connects to `server1` via `relay0`. 58 | 59 | To start a TCP session, `client0` generates a random salt, encrypts iPSK1's hash with iPSK0-derived subkey as the 1st identity header, encrypts uPSK0's hash with iPSK1-derived subkey as the 2nd identity header, and finishes the remainder of the request following the original spec. 60 | 61 | To process the TCP request, `relay0` decrypts the 1st identity header with iPSK0-derived subkey, looks up the PSK hash table, and writes the salt and remainder of the request (without the processed identity header) to `server0`. 62 | 63 | To send a UDP packet, `client0` encrypts the separate header with iPSK0, encrypts (iPSK1's hash XOR session_id_packet_id) with iPSK0 as the 1st identity header, encrypts (uPSK0's hash XOR session_id_packet_id) with iPSK1 as the 2nd identity header, and finishes off following the original spec. 64 | 65 | To process the UDP packet, `relay0` decrypts the separate header in-place with iPSK0, decrypts the 1st identity header with iPSK0, looks up the PSK hash table, re-encrypt the separate header into the place of the first identity header, and sends the packet (starting at the re-encrypted separate header) to `server0`. 66 | -------------------------------------------------------------------------------- /2022-3-shadowsocks-url.md: -------------------------------------------------------------------------------- 1 | # Shadowsocks Server Configuration URL 2 | 3 | This document defines the URL format for Shadowsocks server configuration sharing. 4 | 5 | Most programming languages provide utilities for parsing and assembling URLs in their standard libraries. Feed the following information into a URL builder to produce a URL. 6 | 7 | - Scheme: `ss` 8 | - Userinfo 9 | - Username: method 10 | - Password: password 11 | - Fragment: server name 12 | 13 | Examples: 14 | 15 | ``` 16 | ss://2022-blake3-aes-128-gcm:5mOQSa20Kt6ay2LXruBoHQ%3D%3D@example.com:443/#name 17 | ss://2022-blake3-aes-256-gcm:t7XRzLCvgsH4r4r669cyqPnVNFG2c%2FHC5Tt%2BMjINJB0%3D@[2001:db8:1f74:3c86:aef9:a75:5d2a:425e]:20220/#name 18 | ``` 19 | -------------------------------------------------------------------------------- /2022-4-shadowsocks-implementations.md: -------------------------------------------------------------------------------- 1 | # Shadowsocks 2022 Implementations 2 | 3 | This document tracks and compares implementations of Shadowsocks 2022 by feature and spec compliance, and showcases some benchmark and speedtest results. 4 | 5 | ## 1. Implementations 6 | 7 | ### 1.1. Reference Implementations 8 | 9 | Reference implementations of Shadowsocks 2022 are fully spec-compliant, performance-optimized, and ready for production. 10 | 11 | | | shadowsocks-go | shadowsocks-rust | sing-box | 12 | | --- | -------------: | ---------------: | -------: | 13 | | Description | A versatile and efficient proxy platform for secure communications. | CLIs and libraries written in Rust. | The universal proxy platform. | 14 | | URL | https://github.com/database64128/shadowsocks-go | https://github.com/shadowsocks/shadowsocks-rust | https://github.com/SagerNet/sing-shadowsocks, https://github.com/SagerNet/sing-box | 15 | | License | AGPLv3 | MIT | GPLv3 | 16 | | Server | ✅ | ✅ | ✅ | 17 | | Relay | ❌ | ❌ | ✅ | 18 | | Client | ✅ | ✅ | ✅ | 19 | | [EIH (Extensible Identity Headers)](2022-2-shadowsocks-2022-extensible-identity-headers.md) | ✅ | ✅ | ✅ | 20 | 21 | ### 1.2. Derived Implementations 22 | 23 | Derived implementations are based on one of the reference implementations but developed separately by downstream developers. 24 | 25 | | | v2ray-core (SagerNet Fork) | Xray-core | 26 | | --- | -------------------------: | --------: | 27 | | URL | https://github.com/SagerNet/v2ray-core | https://github.com/XTLS/Xray-core | 28 | | Protocol Implementation | sing-shadowsocks | sing-shadowsocks | 29 | | License | GPLv3 | MPLv2 | 30 | | Server | ✅ | ✅ | 31 | | Relay | ✅ | ✅ | 32 | | Client | ✅ | ✅ | 33 | | [EIH (Extensible Identity Headers)](2022-2-shadowsocks-2022-extensible-identity-headers.md) | ✅ | ✅ | 34 | 35 | ### 1.3. GUI Clients 36 | 37 | ### 1.4. Other Implementations 38 | 39 | ## 2. Benchmarks 40 | 41 | ### 2.1. Header Benchmarks 42 | 43 | https://github.com/database64128/cubic-go-playground/blob/main/shadowsocks/udpheader/udpheader_test.go 44 | 45 | ``` 46 | BenchmarkGenSaltHkdfSha1-8 372712 3283 ns/op 1264 B/op 18 allocs/op 47 | BenchmarkGenSaltBlake3-8 770426 1554 ns/op 0 B/op 0 allocs/op 48 | BenchmarkAesEcbHeaderEncryption-8 99224395 12.84 ns/op 0 B/op 0 allocs/op 49 | BenchmarkAesEcbHeaderDecryption-8 100000000 11.79 ns/op 0 B/op 0 allocs/op 50 | ``` 51 | 52 | ### 2.2. Full UDP Packet Construction Benchmarks 53 | 54 | https://github.com/database64128/cubic-go-playground/blob/main/shadowsocks/udp_test.go 55 | 56 | ``` 57 | BenchmarkShadowsocksAEADAes256GcmEncryption-8 252819 4520 ns/op 2160 B/op 23 allocs/op 58 | BenchmarkShadowsocksAEADAes256GcmWithBlake3Encryption-8 320718 3367 ns/op 896 B/op 5 allocs/op 59 | BenchmarkDraftSeparateHeaderAes256GcmEncryption-8 2059383 590.5 ns/op 0 B/op 0 allocs/op 60 | BenchmarkDraftXChaCha20Poly1305Encryption-8 993336 1266 ns/op 0 B/op 0 allocs/op 61 | ``` 62 | 63 | ### 2.3. Speed Tests 64 | 65 | - CPU: i9-13900K 66 | - Linux: 6.0.8-arch1-1 67 | - shadowsocks-go: commit 88c2d63ccd0b022f76902195ceb1559eaf15a3a7 (2022-11-13) built with Go 1.19.3 68 | - shadowsocks-rust: commit ff3590a830a84b4ee4f4b98623897487eed43196 (2022-11-21) built with Rust 1.65 69 | - TCP: `iperf3 -c ::1 -p 30001 -R` 70 | - UDP 🔽: `iperf3 -c ::1 -p 30001 -Rub 0 -l 1382` 71 | - UDP 🔼: `iperf3 -c ::1 -p 30001 -ub 0 -l 1390` 72 | 73 | | 2022-blake3-aes-128-gcm | TCP | UDP 🔽 | UDP 🔼 | 74 | | ----------------------- | -------: | -------: | -------: | 75 | | shadowsocks-go | 31.0Gbps | 5.20Gbps | 6.03Gbps | 76 | | shadowsocks-rust | 27.7Gbps | 4.32Gbps | 4.38Gbps | 77 | 78 | | shadowsocks-rust | TCP | UDP 🔽 | 79 | | ----------------------------- | -------: | -------: | 80 | | 2022-blake3-aes-128-gcm | 27.7Gbps | 4.32Gbps | 81 | | 2022-blake3-aes-256-gcm | Gbps | Gbps | 82 | | 2022-blake3-chacha20-poly1305 | Gbps | Gbps | 83 | | 2022-blake3-chacha8-poly1305 | Gbps | Gbps | 84 | | aes-128-gcm | Gbps | Gbps | 85 | | aes-256-gcm | Gbps | Gbps | 86 | | chacha20-poly1305 | Gbps | Gbps | 87 | -------------------------------------------------------------------------------- /2023-1-shadowsocks-server-management-api-v1.md: -------------------------------------------------------------------------------- 1 | # Shadowsocks Server Management API v1 2 | 3 | This document defines a RESTful API for managing Shadowsocks servers. 4 | 5 | ## 1. Security 6 | 7 | The API server SHOULD use TLS client certificates to authenticate API users, or host the endpoints behind a secret path. 8 | 9 | ## 2. Standard Error Response 10 | 11 | API errors MUST return a JSON object with at least an error message in the `error` field: 12 | 13 | ```json 14 | { 15 | "error": "server not found" 16 | } 17 | ``` 18 | 19 | ## 3. Server Info 20 | 21 | Get information about the server. 22 | 23 | #### Request 24 | 25 | ``` 26 | GET / 27 | ``` 28 | 29 | #### Response: `200 OK` 30 | 31 | ```json 32 | { 33 | "server": "shadowsocks-go 1.13.0", 34 | "apiVersion": "v1" 35 | } 36 | ``` 37 | 38 | ## 4. Users 39 | 40 | A Shadowsocks server with EIH support can serve multiple users on a single port. 41 | 42 | When a server has EIH configured, this API endpoint can be used to manage users. If EIH is not used, respond with 404 and a friendly error message. 43 | 44 | ### 4.1. List Users 45 | 46 | #### Request 47 | 48 | ``` 49 | GET /users 50 | ``` 51 | 52 | #### Response: `200 OK` 53 | 54 | ```json 55 | { 56 | "users": [ 57 | { 58 | "username": "database64128", 59 | "uPSK": "oE/s2z9Q8EWORAB8B3UCxw==" 60 | } 61 | ] 62 | } 63 | ``` 64 | 65 | ### 4.2. Add User 66 | 67 | #### Request 68 | 69 | ``` 70 | POST /users 71 | ``` 72 | 73 | ```json 74 | { 75 | "username": "database64128", 76 | "uPSK": "oE/s2z9Q8EWORAB8B3UCxw==" 77 | } 78 | ``` 79 | 80 | #### Response: `201 Created` 81 | 82 | Successfully added the new user. 83 | 84 | #### Response: `400 Bad Request` 85 | 86 | - A user with the same username already exists. 87 | - Malformed request. 88 | 89 | ### 4.3. Get User Details 90 | 91 | #### Request 92 | 93 | ``` 94 | GET /users/:username 95 | ``` 96 | 97 | #### Response: `200 OK` 98 | 99 | ```json 100 | { 101 | "username": "database64128", 102 | "uPSK": "oE/s2z9Q8EWORAB8B3UCxw==", 103 | "downlinkPackets": 64, 104 | "downlinkBytes": 4096, 105 | "uplinkPackets": 32, 106 | "uplinkBytes": 2048, 107 | "tcpSessions": 16, 108 | "udpSessions": 8 109 | } 110 | ``` 111 | 112 | #### Response: `404 Not Found` 113 | 114 | User not found. 115 | 116 | ### 4.4. Update User 117 | 118 | #### Request 119 | 120 | ``` 121 | PATCH /users/:username 122 | ``` 123 | 124 | ```json 125 | { 126 | "uPSK": "DL7Vrnv7sOdPPDghtxyxgg==" 127 | } 128 | ``` 129 | 130 | #### Response: `204 No Content` 131 | 132 | Successfully updated the user's uPSK. 133 | 134 | #### Response: `400 Bad Request` 135 | 136 | - The provided uPSK is the same as the existing one. 137 | - Malformed request. 138 | 139 | #### Response: `404 Not Found` 140 | 141 | User not found. 142 | 143 | ### 4.5. Delete User 144 | 145 | #### Request 146 | 147 | ``` 148 | DELETE /users/:username 149 | ``` 150 | 151 | #### Response: `204 No Content` 152 | 153 | Successfully deleted the user. 154 | 155 | #### Response: `404 Not Found` 156 | 157 | User not found. 158 | 159 | ## 5. Stats 160 | 161 | Get data usage stats. 162 | 163 | #### Request 164 | 165 | ``` 166 | GET /stats 167 | ``` 168 | 169 | `?clear=true`: also clear stats 170 | 171 | #### Response: `200 OK` 172 | 173 | ```json 174 | { 175 | "downlinkPackets": 64, 176 | "downlinkBytes": 4096, 177 | "uplinkPackets": 32, 178 | "uplinkBytes": 2048, 179 | "tcpSessions": 16, 180 | "udpSessions": 8, 181 | "users": [ 182 | { 183 | "username": "database64128", 184 | "downlinkPackets": 64, 185 | "downlinkBytes": 4096, 186 | "uplinkPackets": 32, 187 | "uplinkBytes": 2048, 188 | "tcpSessions": 16, 189 | "udpSessions": 8 190 | } 191 | ] 192 | } 193 | ``` 194 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Creative Commons Legal Code 2 | 3 | CC0 1.0 Universal 4 | 5 | CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE 6 | LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN 7 | ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS 8 | INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES 9 | REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS 10 | PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM 11 | THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED 12 | HEREUNDER. 13 | 14 | Statement of Purpose 15 | 16 | The laws of most jurisdictions throughout the world automatically confer 17 | exclusive Copyright and Related Rights (defined below) upon the creator 18 | and subsequent owner(s) (each and all, an "owner") of an original work of 19 | authorship and/or a database (each, a "Work"). 20 | 21 | Certain owners wish to permanently relinquish those rights to a Work for 22 | the purpose of contributing to a commons of creative, cultural and 23 | scientific works ("Commons") that the public can reliably and without fear 24 | of later claims of infringement build upon, modify, incorporate in other 25 | works, reuse and redistribute as freely as possible in any form whatsoever 26 | and for any purposes, including without limitation commercial purposes. 27 | These owners may contribute to the Commons to promote the ideal of a free 28 | culture and the further production of creative, cultural and scientific 29 | works, or to gain reputation or greater distribution for their Work in 30 | part through the use and efforts of others. 31 | 32 | For these and/or other purposes and motivations, and without any 33 | expectation of additional consideration or compensation, the person 34 | associating CC0 with a Work (the "Affirmer"), to the extent that he or she 35 | is an owner of Copyright and Related Rights in the Work, voluntarily 36 | elects to apply CC0 to the Work and publicly distribute the Work under its 37 | terms, with knowledge of his or her Copyright and Related Rights in the 38 | Work and the meaning and intended legal effect of CC0 on those rights. 39 | 40 | 1. Copyright and Related Rights. A Work made available under CC0 may be 41 | protected by copyright and related or neighboring rights ("Copyright and 42 | Related Rights"). Copyright and Related Rights include, but are not 43 | limited to, the following: 44 | 45 | i. the right to reproduce, adapt, distribute, perform, display, 46 | communicate, and translate a Work; 47 | ii. moral rights retained by the original author(s) and/or performer(s); 48 | iii. publicity and privacy rights pertaining to a person's image or 49 | likeness depicted in a Work; 50 | iv. rights protecting against unfair competition in regards to a Work, 51 | subject to the limitations in paragraph 4(a), below; 52 | v. rights protecting the extraction, dissemination, use and reuse of data 53 | in a Work; 54 | vi. database rights (such as those arising under Directive 96/9/EC of the 55 | European Parliament and of the Council of 11 March 1996 on the legal 56 | protection of databases, and under any national implementation 57 | thereof, including any amended or successor version of such 58 | directive); and 59 | vii. other similar, equivalent or corresponding rights throughout the 60 | world based on applicable law or treaty, and any national 61 | implementations thereof. 62 | 63 | 2. Waiver. To the greatest extent permitted by, but not in contravention 64 | of, applicable law, Affirmer hereby overtly, fully, permanently, 65 | irrevocably and unconditionally waives, abandons, and surrenders all of 66 | Affirmer's Copyright and Related Rights and associated claims and causes 67 | of action, whether now known or unknown (including existing as well as 68 | future claims and causes of action), in the Work (i) in all territories 69 | worldwide, (ii) for the maximum duration provided by applicable law or 70 | treaty (including future time extensions), (iii) in any current or future 71 | medium and for any number of copies, and (iv) for any purpose whatsoever, 72 | including without limitation commercial, advertising or promotional 73 | purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each 74 | member of the public at large and to the detriment of Affirmer's heirs and 75 | successors, fully intending that such Waiver shall not be subject to 76 | revocation, rescission, cancellation, termination, or any other legal or 77 | equitable action to disrupt the quiet enjoyment of the Work by the public 78 | as contemplated by Affirmer's express Statement of Purpose. 79 | 80 | 3. Public License Fallback. Should any part of the Waiver for any reason 81 | be judged legally invalid or ineffective under applicable law, then the 82 | Waiver shall be preserved to the maximum extent permitted taking into 83 | account Affirmer's express Statement of Purpose. In addition, to the 84 | extent the Waiver is so judged Affirmer hereby grants to each affected 85 | person a royalty-free, non transferable, non sublicensable, non exclusive, 86 | irrevocable and unconditional license to exercise Affirmer's Copyright and 87 | Related Rights in the Work (i) in all territories worldwide, (ii) for the 88 | maximum duration provided by applicable law or treaty (including future 89 | time extensions), (iii) in any current or future medium and for any number 90 | of copies, and (iv) for any purpose whatsoever, including without 91 | limitation commercial, advertising or promotional purposes (the 92 | "License"). The License shall be deemed effective as of the date CC0 was 93 | applied by Affirmer to the Work. Should any part of the License for any 94 | reason be judged legally invalid or ineffective under applicable law, such 95 | partial invalidity or ineffectiveness shall not invalidate the remainder 96 | of the License, and in such case Affirmer hereby affirms that he or she 97 | will not (i) exercise any of his or her remaining Copyright and Related 98 | Rights in the Work or (ii) assert any associated claims and causes of 99 | action with respect to the Work, in either case contrary to Affirmer's 100 | express Statement of Purpose. 101 | 102 | 4. Limitations and Disclaimers. 103 | 104 | a. No trademark or patent rights held by Affirmer are waived, abandoned, 105 | surrendered, licensed or otherwise affected by this document. 106 | b. Affirmer offers the Work as-is and makes no representations or 107 | warranties of any kind concerning the Work, express, implied, 108 | statutory or otherwise, including without limitation warranties of 109 | title, merchantability, fitness for a particular purpose, non 110 | infringement, or the absence of latent or other defects, accuracy, or 111 | the present or absence of errors, whether or not discoverable, all to 112 | the greatest extent permissible under applicable law. 113 | c. Affirmer disclaims responsibility for clearing rights of other persons 114 | that may apply to the Work or any use thereof, including without 115 | limitation any person's Copyright and Related Rights in the Work. 116 | Further, Affirmer disclaims responsibility for obtaining any necessary 117 | consents, permissions or other rights required for any use of the 118 | Work. 119 | d. Affirmer understands and acknowledges that Creative Commons is not a 120 | party to this document and has no duty or obligation with respect to 121 | this CC0 or use of the Work. 122 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Shadowsocks Specifications 2 | 3 | This repo contains specs of the Shadowsocks protocol family. 4 | 5 | ## Specs 6 | 7 | ### 2022 8 | 9 | 1. [Shadowsocks 2022 Edition: Secure L4 Tunnel with Symmetric Encryption](2022-1-shadowsocks-2022-edition.md) 10 | 2. [Shadowsocks 2022 Extensible Identity Headers](2022-2-shadowsocks-2022-extensible-identity-headers.md) 11 | 3. [Shadowsocks Server Configuration URL](2022-3-shadowsocks-url.md) 12 | 4. [Shadowsocks 2022 Implementations](2022-4-shadowsocks-implementations.md) 13 | 14 | ### 2023 15 | 16 | 1. [Shadowsocks Server Management API v1](2023-1-shadowsocks-server-management-api-v1.md) 17 | 18 | ## How to Propose New Protocols 19 | 20 | Open an issue or a discussion if you have something in mind and would like to discuss with the community. 21 | 22 | Open a PR when you are ready to submit your proposed standard document to the repository. 23 | --------------------------------------------------------------------------------