diff --git a/docs/.vitepress/theme/custom.css b/docs/.vitepress/theme/custom.css
new file mode 100644
index 00000000..8818dd12
--- /dev/null
+++ b/docs/.vitepress/theme/custom.css
@@ -0,0 +1,3 @@
+:root {
+ --vp-home-hero-name-color: #10b981;
+}
diff --git a/docs/.vitepress/theme/index.ts b/docs/.vitepress/theme/index.ts
index 5facf0c2..7e2de46c 100644
--- a/docs/.vitepress/theme/index.ts
+++ b/docs/.vitepress/theme/index.ts
@@ -1,5 +1,6 @@
import DefaultTheme from 'vitepress/theme'
import SIP002Generator from './components/SIP002Generator.vue'
+import './custom.css'
export default {
...DefaultTheme,
diff --git a/docs/doc/aead.md b/docs/doc/aead.md
index 42f758e5..37656e79 100644
--- a/docs/doc/aead.md
+++ b/docs/doc/aead.md
@@ -51,9 +51,20 @@ AE_decrypt(key, nonce, ciphertext, tag) => message
An AEAD encrypted TCP stream starts with a randomly generated salt to derive the per-session subkey, followed by any number of encrypted chunks. Each chunk has the following structure:
-```
-[encrypted payload length][length tag][encrypted payload][payload tag]
-```
+
Payload length is a 2-byte big-endian unsigned integer capped at 0x3FFF. The higher two bits are reserved and must be set to zero. Payload is therefore limited to 16*1024 - 1 bytes.
@@ -64,9 +75,18 @@ The first AEAD encrypt/decrypt operation uses a counting nonce starting from 0.
An AEAD encrypted UDP packet has the following structure
-```
-[salt][encrypted payload][tag]
-```
+
The salt is used to derive the per-session subkey and must be generated randomly to ensure uniqueness. Each UDP packet is encrypted/decrypted independently, using the derived subkey and a nonce with all zero bytes.
diff --git a/docs/doc/sip003.md b/docs/doc/sip003.md
index 360d377c..dd00b6e8 100644
--- a/docs/doc/sip003.md
+++ b/docs/doc/sip003.md
@@ -4,17 +4,33 @@
The plugin of shadowsocks is very similar to the [Pluggable Transport](https://gitweb.torproject.org/torspec.git/tree/pt-spec.txt) plugins from Tor project. Unlike the SOCKS5 proxy design in PT, every SIP003 plugin works as a tunnel (or called local port forwarding). This design aims to avoid per-connection arguments in PT, leading to much easier implementation.
-```
-+------------+ +---------------------------+
-| SS Client +-- Local Loopback --+ Plugin Client (Tunnel) +--+
-+------------+ +---------------------------+ |
- |
- Public Internet (Obfuscated/Transformed traffic) ==> |
- |
-+------------+ +---------------------------+ |
-| SS Server +-- Local Loopback --+ Plugin Server (Tunnel) +--+
-+------------+ +---------------------------+
-```
+
## Life cycle of a plugin
diff --git a/docs/doc/sip022.md b/docs/doc/sip022.md
index 172eb583..f6b203fa 100644
--- a/docs/doc/sip022.md
+++ b/docs/doc/sip022.md
@@ -84,58 +84,149 @@ A length chunk is a 16-bit big-endian unsigned integer that describes the payloa
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.
-```
-+----------------+
-| length chunk |
-+----------------+
-| u16 big-endian |
-+----------------+
-
-+---------------+
-| payload chunk |
-+---------------+
-| variable |
-+---------------+
-
-Request stream:
-+--------+------------------------+---------------------------+------------------------+---------------------------+---+
-| salt | encrypted header chunk | encrypted header chunk | encrypted length chunk | encrypted payload chunk |...|
-+--------+------------------------+---------------------------+------------------------+---------------------------+---+
-| 16/32B | 11B + 16B tag | variable length + 16B tag | 2B length + 16B tag | variable length + 16B tag |...|
-+--------+------------------------+---------------------------+------------------------+---------------------------+---+
-
-Response stream:
-+--------+------------------------+---------------------------+------------------------+---------------------------+---+
-| salt | encrypted header chunk | encrypted payload chunk | encrypted length chunk | encrypted payload chunk |...|
-+--------+------------------------+---------------------------+------------------------+---------------------------+---+
-| 16/32B | 27/43B + 16B tag | variable length + 16B tag | 2B length + 16B tag | variable length + 16B tag |...|
-+--------+------------------------+---------------------------+------------------------+---------------------------+---+
-```
+
+
+**Request stream:**
+
+
+
+**Response stream:**
+
+
#### 3.1.3. Header
-```
-Request fixed-length header:
-+------+------------------+--------+
-| type | timestamp | length |
-+------+------------------+--------+
-| 1B | u64be unix epoch | u16be |
-+------+------------------+--------+
-
-Request variable-length header:
-+------+----------+-------+----------------+----------+-----------------+
-| ATYP | address | port | padding length | padding | initial payload |
-+------+----------+-------+----------------+----------+-----------------+
-| 1B | variable | u16be | u16be | variable | variable |
-+------+----------+-------+----------------+----------+-----------------+
-
-Response fixed-length header:
-+------+------------------+----------------+--------+
-| type | timestamp | request salt | length |
-+------+------------------+----------------+--------+
-| 1B | u64be unix epoch | 16/32B | u16be |
-+------+------------------+----------------+--------+
+Request fixed-length header:
+
+
+
+Request variable-length header:
+
+
+
+Response fixed-length header:
+
+
+```
HeaderTypeClientStream = 0
HeaderTypeServerStream = 1
MinPaddingLength = 0
@@ -206,21 +297,37 @@ decrypted_body := session_aead_cipher.open(nonce: separate_header[4..16], body)
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.
-```
-Packet:
-+---------------------------+---------------------------+
-| encrypted separate header | encrypted body |
-+---------------------------+---------------------------+
-| 16B | variable length + 16B tag |
-+---------------------------+---------------------------+
-
-Separate header:
-+------------+-----------+
-| session ID | packet ID |
-+------------+-----------+
-| 8B | u64be |
-+------------+-----------+
-```
+Packet:
+
+
+
+Separate header:
+
+
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.
@@ -230,21 +337,72 @@ Servers use client session IDs to identify UDP sessions. For server-to-client me
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.
-```
-Client-to-server message header:
-+------+------------------+----------------+----------+------+----------+-------+
-| type | timestamp | padding length | padding | ATYP | address | port |
-+------+------------------+----------------+----------+------+----------+-------+
-| 1B | u64be unix epoch | u16be | variable | 1B | variable | u16be |
-+------+------------------+----------------+----------+------+----------+-------+
-
-Server-to-client message header:
-+------+------------------+-------------------+----------------+----------+------+----------+-------+
-| type | timestamp | client session ID | padding length | padding | ATYP | address | port |
-+------+------------------+-------------------+----------------+----------+------+----------+-------+
-| 1B | u64be unix epoch | 8B | u16be | variable | 1B | variable | u16be |
-+------+------------------+-------------------+----------------+----------+------+----------+-------+
+Client-to-server message header:
+
+
+
+Server-to-client message header:
+
+
+```
HeaderTypeClientPacket = 0
HeaderTypeServerPacket = 1
```
@@ -279,28 +437,98 @@ A UDP packet starts with the random nonce, followed by an encrypted body. The se
The same sliding window filter is used for replay protection. It is not necessary to check for repeated nonce.
-```
-Packet:
-+-------+---------------------------+
-| nonce | encrypted body |
-+-------+---------------------------+
-| 24B | variable length + 16B tag |
-+-------+---------------------------+
-
-Client-to-server message header:
-+-------------------+------------------+------+------------------+----------------+----------+------+----------+-------+
-| client session ID | client packet ID | type | timestamp | padding length | padding | ATYP | address | port |
-+-------------------+------------------+------+------------------+----------------+----------+------+----------+-------+
-| 8B | u64be | 1B | u64be unix epoch | u16be | variable | 1B | variable | u16be |
-+-------------------+------------------+------+------------------+----------------+----------+------+----------+-------+
-
-Server-to-client message header:
-+-------------------+------------------+------+------------------+-------------------+----------------+----------+------+----------+-------+
-| server session ID | server packet ID | type | timestamp | client session ID | padding length | padding | ATYP | address | port |
-+-------------------+------------------+------+------------------+-------------------+----------------+----------+------+----------+-------+
-| 8B | u64be | 1B | u64be unix epoch | 8B | u16be | variable | 1B | variable | u16be |
-+-------------------+------------------+------+------------------+-------------------+----------------+----------+------+----------+-------+
-```
+Packet:
+
+
+
+Client-to-server message header:
+
+
+
+Server-to-client message header:
+
+
## Acknowledgement
diff --git a/docs/doc/sip023.md b/docs/doc/sip023.md
index b278404b..98ba512b 100644
--- a/docs/doc/sip023.md
+++ b/docs/doc/sip023.md
@@ -30,19 +30,46 @@ When iPSKs are used, the separate header MUST be encrypted with the first iPSK.
## Scenarios
-```
- client0 >---+
-(iPSK0:iPSK1:uPSK0) \
- \
- client1 >------\ +---> server0 [iPSK1]
-(iPSK0:iPSK1:uPSK1) \ / [uPSK0, uPSK1, uPSK2]
- >-> relay0 [iPSK0] >-<
- client2 / [iPSK1, uPSK3] \
-(iPSK0:iPSK1:uPSK2) >------/ +---> server1 [uPSK3]
- /
- client3 /
- (iPSK0:uPSK3) >---+
-```
+
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.
diff --git a/docs/doc/what-is-shadowsocks.md b/docs/doc/what-is-shadowsocks.md
index 14382286..489256be 100644
--- a/docs/doc/what-is-shadowsocks.md
+++ b/docs/doc/what-is-shadowsocks.md
@@ -2,9 +2,29 @@
Shadowsocks is a secure split proxy loosely based on [SOCKS5](https://tools.ietf.org/html/rfc1928).
-```
-client <---> ss-local <--[encrypted]--> ss-remote <---> target
-```
+
The Shadowsocks local component (ss-local) acts like a traditional SOCKS5 server and provides proxy service to clients. It encrypts and forwards data streams and packets from the client to the Shadowsocks remote component (ss-remote), which decrypts and forwards to the target. Replies from target are similarly encrypted and relayed by ss-remote back to ss-local, which decrypts and eventually returns to the original client.
@@ -13,9 +33,21 @@ The Shadowsocks local component (ss-local) acts like a traditional SOCKS5 server
Addresses used in Shadowsocks follow the [SOCKS5 address format](https://tools.ietf.org/html/rfc1928#section-5):
-```
-[1-byte type][variable-length host][2-byte port]
-```
+
The following address types are defined:
@@ -30,9 +62,16 @@ The port number is a 2-byte big-endian unsigned integer.
ss-local initiates a TCP connection to ss-remote by sending an encrypted data stream starting with the target address followed by payload data. The exact encryption scheme differs depending on the cipher used.
-```
-[target address][payload]
-```
+
ss-remote receives the encrypted data stream, decrypts and parses the leading target address. It then establishes a new TCP connection to the target and forwards payload data to it. ss-remote receives reply from the target, encrypts and forwards it back to the ss-local, until ss-local disconnects.
@@ -42,14 +81,28 @@ For better obfuscation purposes, both local and remote SHOULD send the handshake
ss-local sends an encrypted data packet containing the target address and payload to ss-remote.
-```
-[target address][payload]
-```
+
Upon receiving the encrypted packet, ss-remote decrypts and parses the target address. It then sends a new data packet containing only the payload to the target. ss-remote receives data packets back from target and prepends the target address to the payload in each packet, then sends encrypted copies back to ss-local.
-```
-[target address][payload]
-```
+
Essentially, ss-remote is performing Network Address Translation for ss-local.
\ No newline at end of file