Comparison with Other Protocols
A protocol-level comparison of OpenSnell's Snell v4/v5 with Shadowsocks 2022 (SIP022) and mieru TCP — what each defends against, what each leaks on the wire, and which threat model picks which.
This page is an investigation, not advocacy. OpenSnell implements Snell — that's our bias up front. The findings below try to be honest about where Snell loses, with source citations into each codebase so any claim is verifiable.
The three protocols compared:
- Snell v4 / v5 — Surge's proprietary proxy protocol, re-implemented
in OpenSnell from
components/snell/v4.goandcipher.go. v4 and v5 share the same TCP frame format — we use "Snell" to mean either. - Shadowsocks 2022 / SIP022 — the AEAD-2022 protocol family
(specification SIP022),
read from
shadowsocks-rust'scrates/shadowsocks/src/relay/{tcprelay,udprelay}/aead_2022.rs. We do not cover the older SIP004 AEAD scheme. - mieru TCP — the TCP underlay of
enfein/mieru, read fromdocs/protocol.md,pkg/cipher,pkg/protocol, andpkg/replay. mieru also has a UDP transport, but this page compares the no-TLS, TCP-on-the-wire case because that is the closest axis to Snell and bare Shadowsocks.
TL;DR
| Dimension | Winner |
|---|---|
| Cryptographic protocol design | Shadowsocks 2022 |
| Bare TCP against passive entropy classifiers | Snell / mieru — both deliberately avoid pure random-looking streams |
| Bare TCP against replay probes | Shadowsocks 2022 / mieru |
| Surviving the GFW with a modern wrapper | Shadowsocks 2022 + Reality / shadow-TLS |
| Recovering plaintext from a capture (no PSK) | Tie — all three rely on modern AEAD |
| Identifying the protocol from a capture | See § The high-entropy paradox — the question splits in two |
| Multi-user / key rotation | Shadowsocks 2022 (EIH) and mieru (per-user credentials) |
| Implementation maturity / audits | Shadowsocks 2022 |
The verdict is contextual. There is no axis on which one protocol is strictly better than the other two.
How to read this page
"Secure" and "uncensorable" use the same word for different things. Each finding below is tagged with which adversary it applies to:
- Passive censor. Logs traffic, applies offline classifiers. The GFW circa 2010.
- Active censor. Probes flagged endpoints, attempts replay, fingerprints handshakes. The GFW since ~2020.
- Network observer / researcher. Captures pcaps and tries to identify what protocol is in use. No interaction with the server.
- Cryptographic adversary (no PSK). The standard threat model. What can they do with ciphertext alone?
- Adversary with PSK / credential. Has somehow obtained the Snell/Shadowsocks pre-shared key or a mieru user credential. What can they still not do?
The three protocols make very different tradeoffs across these.
First packet on the wire
A side-by-side of what the very first TCP segment looks like for each:
Snell (first frame)
+-------------+----------------------------+----------------------+----------------------+
| salt (16B) | AEAD(header_7B) + tag(16B) | padding(256..511 B) | AEAD(payload) + tag |
+-------------+----------------------------+----------------------+----------------------+
| plaintext | header_7B = [0x04, 0, 0, | bytes at *even* | first payload is the |
| | padLen_be, payloadLen_be]| indices SWAPPED with | CONNECT request: |
| | | even-indexed payload | [ver, cmd, cid_len, |
| | | ciphertext bytes — | cid, hostlen, host, |
| | | padding never | port_be] |
| | | contiguous on wire | |
+-------------+----------------------------+----------------------+----------------------+The padding bytes are picked by
makeV4Padding
to push the overall ones/zeros ratio of salt + padding + payload
toward 1.6 or 0.4 — explicitly away from the 1.0 ratio that
uniform-random AEAD output produces. The first segment is shaped to
not look like high-entropy noise.
Shadowsocks 2022 (first request)
+-------------+--------------------------------+-----------------------------------+
| salt | AEAD(fixed_header) + tag(16B) | AEAD(variable_header) + tag(16B) |
| (16 or 32B) | fixed_header (11B) = | variable_header = |
| | [type=0, ts_be(8), len_be(2)] | [ATYP, addr, port_be, |
| | | padLen_be(2), padding(0..900), |
| | | payload] |
+-------------+--------------------------------+-----------------------------------+
| plaintext | exactly 27 ciphertext bytes | uniform random bytes throughout |
+-------------+--------------------------------+-----------------------------------+The padding is uniform random. There is no statistical shaping.
From byte 0 onward (after the salt prefix), every byte is
indistinguishable from /dev/urandom output.
mieru TCP (first open-session segment)
+-------------+-----------------------------+----------------------+----------------------+
| nonce (24B) | AEAD(metadata_32B) + tag(16)| AEAD(payload) + tag | padding(0..255 B) |
+-------------+-----------------------------+----------------------+----------------------+
| visible | metadata includes protocol | optional first | random bytes shaped |
| | type, minute timestamp, | payload can carry | either toward a |
| | session ID, sequence, | the SOCKS request | printable run or a |
| | payloadLen, suffixLen | and even 0-RTT data | lower-bit target |
+-------------+-----------------------------+----------------------+----------------------+In the TCP underlay, the nonce appears once per direction, on the
first encrypted metadata block; later metadata and payload AEAD calls
increment that implicit 24-byte nonce (docs/protocol.md:37,
api.go:95-105, cipher.go:99-132,323-334). The open-session segment
may carry the SOCKS request as its encrypted payload when it fits
within 1024 bytes (session.go:311-330).
The visible nonce is not necessarily uniform random. The default
traffic-pattern path generates a nonce rule, and without unlockAll
it chooses a printable or common-64 prefix of 6-12 bytes
(trafficpattern/config.go:136-174, cipher.go:275-283). The last
4 bytes of the nonce are also a server-side user lookup hint:
SHA256(username || nonce[0:16])[:4] (docs/protocol.md:23,
api.go:36-39, cipher.go:336-347).
Cryptographic primitives
Key derivation
| Property | Snell | Shadowsocks 2022 | mieru TCP |
|---|---|---|---|
| KDF | Argon2id(t=3, m=8KiB, p=1) | BLAKE3::derive_key | SHA256(password || 0x00 || username) -> PBKDF2-SHA256 |
| Inputs | PSK string + 16 B salt | PSK bytes + per-stream salt | user password hash + 2-minute time salt |
| PSK assumption | Arbitrary string (weak OK) | High-entropy 16 / 32 B (openssl rand -base64 16) | User password, but time sync required |
| Cost per connection | One Argon2 call (~ms, 8 KiB RAM) | One BLAKE3 call (~µs) | Cached PBKDF2, 64 iterations, 32-byte key |
The choice reflects a different threat model assumption:
- Snell assumes the operator might pick a weak PSK like
mypassword123. Argon2id makes that PSK expensive to brute-force from a captured handshake. It costs ~1 ms and 8 KiB of memory per new TCP connection on the server. - Shadowsocks 2022 assumes the PSK is already a uniformly random 16- or 32-byte key. Under that assumption, Argon2 buys nothing — you can't brute-force a 128-bit random key regardless of how slow the KDF is. The spec explicitly forbids the EVP_BytesToKey password expansion that Shadowsocks AEAD-2017 used.
- mieru hashes
password || 0x00 || usernamewith SHA-256, then derives a 32-byte key with PBKDF2-SHA256 using a salt derived from rounded system time. The protocol constants are 64 PBKDF2 iterations and a 2-minute key refresh interval; the server tries the previous, current, and next time salt (docs/protocol.md:13-21,keygen.go:27-38,55-73,cache.go:88-110). This makes old captures expire as the time window moves, but it is not a memory-hard password KDF. If the username/password are human-guessable and the attacker knows the capture time, the offline brute-force story is weaker than Snell's Argon2id story.
Neither approach is wrong. They're optimized for different operator populations.
AEAD
| Property | Snell | Shadowsocks 2022 | mieru TCP |
|---|---|---|---|
| Cipher | AES-128-GCM only | AES-128-GCM, AES-256-GCM, ChaCha20-Poly1305 (+ optional ChaCha8) | XChaCha20-Poly1305 only |
| Nonce | 12 B counter, init 0, per-AEAD-op increment | 12 B counter, init 0, per-AEAD-op increment | 24 B nonce, sent once per direction, incremented per AEAD op |
| Max plaintext / chunk | 0x3FFF (16383) | 0xFFFF (65535) | 32768 B stream fragment; 1024 B open-session payload |
Snell and Shadowsocks 2022 use the standard AES-GCM counter-nonce pattern, which is safe provided the key is fresh (which it is — derived from a per-stream random salt). mieru uses XChaCha20-Poly1305's 24-byte nonce and then increments the nonce in implicit-nonce TCP mode for later AEAD operations.
Algorithm agility is where the gap shows: Shadowsocks 2022 supports
ChaCha20 for ARM / embedded systems without AES-NI hardware
acceleration, and AES-256 for operators with a stronger key
requirement. Snell is hard-coded to AES-128-GCM. mieru is hard-coded to
XChaCha20-Poly1305 (cipher.go:34-82), which is a good primitive and
avoids AES-NI dependency, but still gives operators no cipher choice.
The 4× larger Shadowsocks chunk size (65535 vs Snell's 16383) cuts framing overhead proportionally for bulk transfers. mieru sits between them for stream payloads at 32768 bytes, while open-session payloads are capped at 1024 bytes so the first segment stays bounded.
Protocol-level defenses
This is where Snell is weakest. Shadowsocks 2022 and mieru both add freshness checks; they do it in very different ways.
Replay protection
| Defense | Snell | Shadowsocks 2022 | mieru TCP |
|---|---|---|---|
| Fresh visible value | 16 B salt | Per-stream salt | 24 B nonce |
| Server replay cache | (60 s salt cache) | (~6 min signature cache) | |
| Timestamp window | (30 s, aead_2022.rs:377-379) | (encrypted minute timestamp, ±1 minute check) | |
| Key expiry | at protocol layer | time-derived key, three adjacent salts |
What an attacker can do against Snell, without ever decrypting:
- Capture a complete client-initiated TCP session.
- Replay the exact byte sequence to the same server hours later.
- The server will Argon2-derive a fresh session key from the salt (the salt is in the capture), accept every frame's GCM tag (they verify, since the replayed nonce sequence matches), execute the CONNECT to whatever host was originally requested, and faithfully reproduce the original session — possibly fetching the same URL, re-triggering side effects on the upstream.
This is a real protocol-level weakness in Snell. Shadowsocks 2022 catches the same replay because (a) the salt is in the 60-second cache during the legitimate session and (b) the embedded timestamp will be well outside the ±30 s window on replay.
mieru also rejects this class of replay. For TCP, the server keeps a
global replay cache sized at 4M entries with an expiry of
KeyRefreshInterval * 3 (2 min × 3 = ~6 min), and the stream reader
turns a duplicated first-session signature into a replay error
(underlay_stream.go:40-44,355-386). Its encrypted metadata also
carries a minute timestamp and rejects values outside a ±1 minute
window (metadata.go:140-165,213-240). After the key-refresh window
moves, the server no longer derives the same AEAD key anyway
(keygen.go:27-38,55-73).
Direction binding
| Defense | Snell | Shadowsocks 2022 | mieru TCP |
|---|---|---|---|
| Direction field inside encrypted metadata | (0=client, 1=server) | (distinct protocol types, side-validated by session) |
Shadowsocks 2022 puts a type byte at the start of every AEAD'd
header chunk: 0 for client→server, 1 for server→client. The receiver
checks it (aead_2022.rs:367-373). An attacker can't take a
server-side ciphertext and feed it back to the server as if it were
client traffic.
Snell has no such field. The first byte of the AEAD'd header is a
fixed 0x04 (version constant), which is identical in both directions.
The two streams are still cryptographically separated because each
direction has its own salt → its own key → its own nonce counter, so a
swap would fail tag verification. But the defense is implicit (from the
key separation) rather than explicit (from a domain separator), which
historically has been the source of cross-protocol attacks.
mieru's encrypted metadata has separate protocol values for
openSessionRequest, openSessionResponse, dataClientToServer,
dataServerToClient, and both ACK directions (metadata.go:28-39).
The session layer rejects server-bound packets with server-to-client
protocols and vice versa (session.go:872-880). This is closer to
Shadowsocks 2022 than to Snell, although the encoding is a richer
session protocol rather than a single 0/1 type byte.
Request → response binding
Shadowsocks 2022 server responses embed the client's request salt
inside the encrypted response header (aead_2022.rs:382-387). The
client checks it before trusting the response. This binds every
response to its specific request — preventing an active attacker who
controls the network from splicing one server's response to a
different client's request.
Snell has no equivalent.
mieru has a weaker equivalent: the open-session response carries the
same encrypted session ID and sequence space as the request
(session.go:1008-1045), but it does not echo the client nonce or
salt in the response the way Shadowsocks 2022 does. So the request →
response binding is operationally present through the session state,
not cryptographically explicit in the first response header.
Multi-user / identity
Shadowsocks 2022 ships Extensible Identity Headers (EIH, SIP022-2). A single server can hold N user keys; each request carries an encrypted hash that identifies which user it's from. This lets you:
- Run one shared server for many users without one user's PSK compromise affecting the others.
- Rotate keys without downtime by adding a new user, migrating clients, then removing the old one.
Official Snell and OpenSnell's standalone stable config use a single PSK. One leak means everyone re-keys. OpenSnell's alpha branch adds a library-level multi-user server mode by trial-decrypting the first encrypted frame against a user store, but that is not an official Snell wire feature and carries no on-wire user hint.
mieru supports multiple users on one server (README.md:20,
server-install.md:102-125). Each user has a separate username/password
derived key, and v3.31.0 added a visible 4-byte nonce hint to accelerate
server-side user lookup (server-install.md:329-337,
cipher.go:336-347). That gives operators practical per-user rotation,
but it is not the same design as Shadowsocks 2022 EIH: the identity
hint is a short protocol artifact, not an extensible encrypted identity
header family.
Anti-censorship behavior
This is the axis where Snell and mieru catch up. All three can run over plain TCP without TLS; only Shadowsocks 2022 normally expects a modern external wrapper when censorship resistance is the main goal.
What Snell does
- First-frame padding shaping.
makeV4Paddingcomputes a target number of1bits for the padding such that the combinedsalt + padding + payloadbit distribution lands at roughly 61.5 % ones (or 28.5 % if zeros outnumber ones in the AEAD output). The intent is explicit: avoid the ~50/50 ratio that uniform-random AEAD output produces, because "perfectly uniform random bytes" is itself a DPI heuristic for encrypted-proxy traffic. - Padding interleave. Even-indexed padding bytes are swapped
with even-indexed bytes of the payload ciphertext
(
swapPadding). Padding bytes never appear contiguously on the wire, so a passive observer can't count "runs of suspiciously-random bytes" and isolate the padding region. - Dynamic Record Sizing (v5). The first frame on a stream is small (~1.5 KB), with subsequent frames in the same burst growing until they saturate the 16 KB chunk cap. Idle for 30 s resets back to small. This mimics the size distribution of normal HTTPS application records rather than the "constant max-size frames" pattern of bulk proxies.
- Built-in
http/tlsobfs. Static fake-handshake wrappers for TCP. These are 2014-era templates and don't fool a 2025-era DPI on their own, but they layer over the AEAD frames at zero extra cost.
What Shadowsocks 2022 does
At the protocol level: nothing. The first packet after the salt prefix is uniform-random ciphertext. The optional 0–900 B request padding is random bytes, not statistically shaped.
The Shadowsocks 2022 design intentionally delegates anti-censorship to external transports:
shadow-tls— wraps the Shadowsocks stream inside a real TLS 1.3 handshake against a chosen upstream domain.v2ray-plugin— WebSocket / mKCP / QUIC carriers.- REALITY — TLS handshake stealing from a real upstream, with the proxy data ride-along.
With any of these wrappers, Shadowsocks 2022 is at least as hard to
detect as Snell's static tls obfs — usually meaningfully harder,
because the wrappers do real TLS rather than replaying a 2014
ClientHello template.
What mieru does
- No TLS dependency. mieru explicitly advertises that it does not
use TLS and does not require a domain name or fake website
(
README.md:16-19). That makes it operationally closer to Snell than to the modern Shadowsocks+REALITY deployment pattern. - Random padding with selectable shape. The documented segment
format has optional padding before/around/after encrypted fields, and
the TCP implementation adds up to 255 bytes of padding on stream
segments (
docs/protocol.md:27-39,padding.go:61-73,underlay_stream.go:570-603). For open-session segments, the padding strategy is stable per user and chooses either a printable run or a lower-bit probability target of 0.325 (padding.go:28-30,75-101). - Nonce pattern manipulation. The default generated traffic pattern
avoids a fully random-looking nonce prefix by choosing printable or
common-64 bytes unless
unlockAllexpands the range (trafficpattern/config.go:136-174,cipher.go:275-283). - Replay/probe friction. The replay cache and timestamp window mean
a censor cannot simply replay a captured TCP opener and watch whether
the server performs the same upstream action. After read errors,
the stream underlay can also keep reading a random amount for a random
time to make probes less crisp (
underlay_stream.go:777-785).
The tradeoff is that mieru's shaped nonce and metadata cadence are also a fingerprint. It avoids the "pure random stream" smell, but a classifier trained on "24-byte visible nonce with printable/common prefix, 48-byte encrypted metadata, optional payload, then padding" has something concrete to look for.
Net result
| Scenario | Verdict |
|---|---|
| Bare protocol over plain TCP, passive classifier | Snell / mieru (probably) — both shape visible bytes away from uniform random |
| Bare protocol over plain TCP, replay probe | mieru / Shadowsocks 2022 — Snell lacks replay freshness |
| With a modern wrapper (shadow-TLS, REALITY, etc.) | Shadowsocks 2022 — better wrappers exist in its ecosystem |
With Snell's built-in http / tls obfs only | Marginal improvement over bare Snell — the templates are old enough to fingerprint |
Note the "probably" on the first row. We have no public, current data on whether the GFW actually misses Snell v4/v5 or mieru today. Snell's anti-fingerprinting design is from 2018-era thinking, and mieru's visible nonce/padding strategy is also something a classifier could learn. Shaping helps against naive entropy filters; it does not make a protocol magically unidentifiable.
The high-entropy paradox
All three protocols can be observed in pcap. Without the PSK or user credential, none should be decryptable — the AEAD layer is not the weak link. So the meaningful question becomes "can the observer tell what protocol this is?" — and that question splits into two opposing answers:
Answer 1 (the GFW's perspective). Can a passive classifier flag this as "an encrypted proxy"?
- Shadowsocks 2022 has perfect uniform-random byte distribution after the salt. This is, ironically, easier to flag — it matches the signature of every encrypted proxy in existence. The Wu et al. USENIX Security 2023 paper "How the Great Firewall of China Detects and Blocks Fully Encrypted Traffic" documents the GFW using exactly this heuristic against bare Shadowsocks variants.
- Snell's bit-count shaping deliberately pulls the distribution away from 50/50, into a range that looks more like real TCP/TLS payload. A naive entropy classifier sees it as more "normal" traffic.
- mieru's first segment also avoids pure random-looking bytes: the visible nonce can have a printable/common prefix, and padding can be shaped toward printable runs or a lower-bit target. A naive "is this just random bytes?" classifier has less to grab than it does with bare Shadowsocks 2022.
Answer 2 (the protocol-identification perspective). Can someone who already knows what to look for tell which specific protocol this is?
- Shadowsocks 2022 has no static field anywhere in the visible bytes. Once a session is past the salt, there's nothing structural that says "this is Shadowsocks". You can only confirm by attempting decryption — which requires the PSK.
- Snell's bit-count shaping is itself a fingerprint. Any first-frame
whose
salt + padding + payloadlands at roughly 61.5 % or 28.5 % ones, with apadLenfield consistent with that interval, is identifiable as Snell. Once a researcher publishes that classifier, passive identification becomes feasible. - mieru exposes a 24-byte nonce before encrypted metadata. With the
default traffic pattern, the prefix is intentionally not uniform
random, and the last 4 bytes carry the user hint. The fixed
nonce + 48B encrypted metadata + optional encrypted payload + paddingcadence is useful to the server, but also useful to a protocol-specific classifier.
These two answers point in opposite directions:
| Asked question | Easier-to-flag | Harder-to-flag |
|---|---|---|
| "Is this an encrypted proxy?" | Shadowsocks 2022 | Snell / mieru |
| "Which specific proxy protocol is this?" | Snell / mieru | Shadowsocks 2022 |
The GFW cares about question 1 (block-by-class). A reverse-engineer cares about question 2 (identify-by-protocol). Snell and mieru spend visible bytes to look less like random ciphertext; Shadowsocks 2022 spends no visible bytes and relies on wrappers when that matters.
Findings matrix
| Adversary | Snell | Shadowsocks 2022 | mieru TCP |
|---|---|---|---|
| Cryptographic (no PSK / credential) | Plaintext not recoverable | Plaintext not recoverable | Plaintext not recoverable |
| Cryptographic (with PSK / credential) | Full plaintext + all session data + can replay sessions | Full plaintext, but captured sessions cannot be replayed after freshness checks | Full plaintext for that user's traffic; stale replay blocked by timestamp/cache/key window |
| Passive censor (entropy classifier) | Lower detection probability (shaped padding) | High detection probability (uniform random) | Lower detection probability than pure random, but visible nonce/padding shape remains |
| Active censor (replay probe) | Vulnerable — full session replay works | Resistant — salt cache + timestamp window | Resistant — replay cache + timestamp + time-derived key |
| Active censor (handshake fingerprint) | Built-in http/tls obfs is dated and fingerprintable | No built-in obfs; must combine with shadow-TLS / REALITY | No TLS dependency; shaped nonce/padding and probe-drain behavior, but still protocol-specific |
| Researcher (passive identification) | Bit-count shaping is itself a fingerprint | No static field; identification only via decrypt attempt | Nonce prefix/user hint and fixed metadata cadence are fingerprints |
| Multi-tenant operator | Official/stable: single PSK; OpenSnell alpha library can trial-decrypt N user PSKs | EIH — N keys, hot-rotatable | N users with separate credentials; practical rotation, not EIH |
When to pick which
- Pick Snell if your bias is toward "must just work in the Chinese network today, with minimal extra infrastructure", you're the only user, and you accept the cryptographic protocol's age (no replay protection, no direction binding, no official on-wire user identity).
- Pick Shadowsocks 2022 if you need multi-tenancy, you want a protocol that's been independently implemented and audited, or you plan to layer a modern transport (shadow-TLS, REALITY, etc.) and don't care that the bare protocol is easy to flag.
- Pick mieru if you want a no-TLS/no-fake-site TCP proxy like Snell, but you also want replay freshness and per-user credentials. The tradeoff is a newer, less-audited protocol with time-sync sensitivity and a visible nonce/padding fingerprint.
- Run more than one protocol, on the same host or on different hosts, if you have the budget for it. The threats they fail against barely overlap.
Caveats and limits of this analysis
- No live GFW data. This page asserts that Snell's anti-entropy shaping helps "in 2025" without giving you a measurement. We do not have a current, controlled study of which protocols the GFW actually flags. The relative ranking here is based on what each protocol makes available to a classifier, not on observed block rates.
- No active probing analysis. We did not test what any server does in response to an active probing attempt (replayed handshake, malformed first frame, etc.). These protocols should close the connection quietly, but probing-resistance is its own research area.
- Snell is a black-box protocol. It has no public specification. All Snell-related claims here are derived from reverse-engineering documented at MetaCubeX/mihomo#2816 and from this repository's own implementation. Surge could change the wire format and invalidate any of these findings in a future release.
- Shadowsocks 2022 is a moving target too. The SIP022 spec has
been extended (EIH, UDP) since the original 2022 publication. We
reference the current
masterofshadowsocks-rustand the live spec on the Shadowsocks-NET/shadowsocks-specs repo as of this writing. - mieru TCP only. mieru also supports a UDP transport. This page only analyzes the TCP underlay because it is the closest comparison to Snell and bare Shadowsocks 2022 over TCP. mieru's generated traffic pattern can also change with configuration, seed, and version.
- "Better" is a contextual word. Every "winner" cell in the tables above is conditional on the threat model in its row. There is no overall winner.
References
- Snell v4/v5 wire format —
components/snell/v4.go,cipher.go. See also Protocol reference on this site. - Shadowsocks 2022 spec — SIP022-1: 2022 edition, SIP022-2: Extensible Identity Headers.
- Shadowsocks 2022 reference implementation —
shadowsocks-rust,crates/shadowsocks/src/relay/tcprelay/aead_2022.rsand the parallel UDP file. - mieru protocol and implementation —
docs/protocol.md,pkg/cipher,pkg/protocol,pkg/replay/replay.go, andapis/trafficpattern. - GFW detection of fully-encrypted traffic — Mingshi Wu et al., "How the Great Firewall of China Detects and Blocks Fully Encrypted Traffic", USENIX Security 2023.
- Modern Shadowsocks transports — shadow-tls, REALITY, v2ray-plugin.