Shadowsocks Documentation

repository·main·Indexed 21 days ago

https://github.com/shadowsocks/shadowsocks-org

Official documentation for Shadowsocks, a high-performance, secure socks5 proxy designed to bypass internet censorship. Includes guides on AEAD ciphers, JSON configuration, URI formats, and deployment instructions for various implementations including shadowsocks-libev, go-shadowsocks2, outline-ss-server, libQtShadowsocks, and Net::Shadowsocks.

Tokens
11.1K
Snippets
38
Records
59
Agent score
77%

What's inside Shadowsocks

  1. How AEAD key derivation works

    main

    Shadowsocks derives a per-session subkey from a pre-shared master key (provided by the user or generated from a password) using HKDF_SHA1.

    Key derivation follows the EVP_BytesToKey(3) specification from OpenSSL. The HKDF_SHA1 function requires:

    • key: The secret key.
    • salt: A non-secret salt that must be unique throughout the life of the pre-shared master key.
    • info: The application context string, which must be exactly "ss-subkey" (without quotes).
    HKDF_SHA1(key, salt, info) => subkey
  2. How stream encryption and decryption work

    main

    Stream encryption uses a secret key and an initialization vector (IV) to transform a message into ciphertext of the same length. Decryption reverses this process using the same key and IV.

    Encryption Function: Stream_encrypt(key, IV, message) => ciphertext

    Decryption Function: Stream_decrypt(key, IV, ciphertext) => message

    Key Derivation: Keys can be provided directly or generated from a password. When generated from a password, the derivation follows the EVP_BytesToKey(3) specification from OpenSSL.

    Stream_encrypt(key, IV, message) => ciphertext
    Stream_decrypt(key, IV, ciphertext) => message
  3. TCP Stream Format and Encryption in Shadowsocks 2022

    main

    TCP connections map 1:1 to proxy connections, each consisting of a request stream and a response stream. Data is transferred using a length-chunk-payload-chunk model.

    Encryption

    Each stream derives its own session subkey using a random salt. A 12-byte little-endian integer (u96le) counter is used as the nonce and is incremented after every operation.

    Stream Structure

    • Request Stream: Starts with a random salt, followed by two standalone header chunks. Then, it repeats a pattern of one encrypted length chunk and one encrypted payload chunk.
    • Response Stream: Starts with a random salt, followed by a single fixed-length header chunk (which also serves as the first length chunk). Subsequent data follows the repeating length-payload pattern.

    Chunk Details

    • Length Chunk: A 16-bit big-endian unsigned integer (u16be) describing the length of the following payload chunk.
    • Payload Chunk: Can contain up to 65,535 bytes (0xFFFF) of unencrypted payload.
    u96le counter
    aead := aead_new(key: session_subkey)
    ciphertext := aead.seal(nonce: counter, plaintext)
    plaintext := aead.open(nonce: counter, ciphertext)
  4. Data packet structures for TCP and UDP stream ciphers

    main

    When using stream ciphers, the data packets are structured with a randomly generated initialization vector (IV) prepended to the encrypted payload.

    • TCP: The stream starts with the IV, followed by the encrypted payload data.
    • UDP: Each packet is encrypted/decrypted independently. Every packet contains its own randomly generated IV followed by the encrypted payload.

    Packet Format (both TCP and UDP): [IV][encrypted payload]

    [IV][encrypted payload]
  5. How Shadowsocks works

    main

    Shadowsocks is a secure split proxy based on the SOCKS5 protocol. It operates using two main components:

    1. ss-local: Acts as a local SOCKS5 server for clients. It encrypts data streams/packets and forwards them to the remote component.
    2. ss-remote: Receives encrypted data from ss-local, decrypts it, and forwards it to the final target. It also handles the return path by encrypting replies from the target and sending them back to ss-local.

    The link between ss-local and ss-remote is fully encrypted.

  6. Pass arguments to a SIP003 plugin

    main

    SIP003 plugins receive configuration through environment variables.

    Required Environment Variables

    The following four variables MUST be provided to the plugin:

    • SS_REMOTE_HOST: The hostname of the remote plugin service.
    • SS_REMOTE_PORT: The port of the remote plugin service.
    • SS_LOCAL_HOST: The hostname of the local shadowsocks or plugin service.
    • SS_LOCAL_PORT: The port of the local shadowsocks or plugin service.

    Optional Configuration

    To pass additional arguments (e.g., a path to a config file or specific obfuscation settings), use the SS_PLUGIN_OPTIONS environment variable.

    Formatting Rules:

    • Use a formatted string like key1=value1;key2=value2.
    • Semicolons (;), equal signs (=), and backslashes (\) MUST be escaped with a backslash.
  7. Handling UDP Separate Headers with Identity PSKs

    main

    When using identity PSKs (iPSKs) in UDP, the separate header (session ID, packet ID) MUST be encrypted with the first iPSK.

    Each identity processor in the chain is responsible for:

    1. Decrypting the separate header with its current layer's PSK.
    2. Decrypting the identity header.
    3. Re-encrypting the separate header with the next layer's PSK.
    4. Passing the packet forward.
  8. How SIP003 plugins work

    main

    SIP003 is a simplified plugin design for shadowsocks where every plugin acts as a tunnel (local port forwarding).

    Unlike the SOCKS5 proxy design used in Tor's Pluggable Transport (PT), SIP003 plugins function as a tunnel between a plugin client and a plugin server. The shadowsocks client/server connects to the plugin via local loopback, and the plugin handles the obfuscated or transformed traffic over the public internet.

    Key characteristics:

    • Process Model: The plugin client/server is started as a child process of the shadowsocks client/server.
    • Lifecycle: If a plugin child process exits with an error, the parent shadowsocks process will also stop (via SIGCHLD). If the shadowsocks process is stopped by the user, the plugin child process is terminated.
    • Traffic Support: Currently, only TCP traffic is forwarded. UDP traffic forwarding is not supported.
  9. Shadowsocks UDP data flow

    main

    Shadowsocks handles UDP by performing a form of Network Address Translation (NAT) via ss-remote:

    1. Outbound: ss-local sends an encrypted packet containing the target address + payload to ss-remote.
    2. Forwarding: ss-remote decrypts the packet, extracts the target address, and sends a new packet containing only the payload to the target.
    3. Inbound: When the target replies, ss-remote receives the data, prepends the target address to the payload, and sends an encrypted copy back to ss-local.
  10. How subkey derivation works in Shadowsocks 2022

    main

    Shadowsocks 2022 uses the BLAKE3 key derivation mode to generate session subkeys, replacing the obsolete HKDF_SHA1 used in previous editions.

    A randomly generated salt (with the same length as the PSK) is appended to the PSK to form the key material. This derived subkey is then used for the actual encryption/decryption of traffic during the session.

    session_subkey := blake3::derive_key(context: "shadowsocks 2022 session subkey", key_material: key + salt)
  11. Understand the SIP acceptance process

    main
    A SIP is accepted when most core contributors agree to it. Once accepted, a formal SIP document is published. Developers then review and follow the document to implement the proposed changes across their respective implementations. Note that the review and implementation process typically takes several months.