A Sudoku-based proxy protocol, ushering in the era of plaintext / low-entropy proxies
Sudoku (ASCII)
Sudoku protocol is now supported by Mihomo kernel!
SUDOKU is a traffic obfuscation protocol based on the creation and solving of 4x4 Sudoku puzzles. It maps arbitrary data streams (data bytes have at most 256 possibilities, while non-isomorphic 4x4 Sudokus have 288 variants) into uniquely solvable Sudoku puzzles based on 4 Clues. Since each Puzzle has more than one setting scheme, the random selection process results in multiple combinations for the same encoded data, generating obfuscation.
The core philosophy of this project is to utilize the mathematical properties of Sudoku grids to implement byte stream encoding/decoding, while providing arbitrary padding and resistance to active probing.
Android Client & Server Install Script:
Core Features
Sudoku Steganography Algorithm
Unlike traditional random noise obfuscation, this protocol uses various masking schemes to map data streams into complete ASCII printable characters. To packet capture tools, it appears as completely plaintext data. Alternatively, other masking schemes can be used to ensure the data stream has sufficiently low entropy.
- Dynamic Padding: Inserts non-data bytes of arbitrary length at arbitrary positions at any time, hiding protocol characteristics.
- Data Hiding: The distribution characteristics of padding bytes match those of plaintext bytes (65%~100%* ASCII ratio), preventing identification of plaintext through data distribution analysis.
- Low Information Entropy: The overall byte Hamming weight is approximately 3.0* (in low entropy mode), which is lower than the 3.4~4.6 range mentioned in the GFW Report that typically triggers blocking.
- User-defined Fingerprints: You can freely choose your preferred byte style via ASCII/entropy preference and
custom_table/custom_tableslayouts. We don’t recommend a single “best” layout — diversity across users helps censorship resistance.
*Note: A 100% ASCII ratio requires the
ASCII-preferredmode; inENTROPY-preferredmode, it is 65%. A Hamming weight of 3.0 requiresENTROPY-preferredmode; inASCII-preferredmode, it is 4.0. Currently, there is no evidence indicating that either preference strategy possesses a distinct fingerprint.
Downlink Modes
- Pure Sudoku Downlink: Default. Uses classic Sudoku puzzles in both directions.
- Bandwidth-Optimized Downlink: Set
"enable_pure_downlink": falseto pack AEAD ciphertext into 6-bit groups (01xxxxxx / 0xx0xxxx) with padding reuse. This reduces downlink overhead while keeping uplink untouched. AEAD must be enabled for this mode. Padding pools and ASCII/entropy preferences still influence the emitted byte distribution (downlink is not “random noise”). In practice, downlink efficiency is typically around 80%.
Security & Encryption
Beneath the obfuscation layer, the protocol optionally employs AEAD to protect data integrity and confidentiality.
- Algorithm Support: AES-128-GCM or ChaCha20-Poly1305.
- Anti-Replay: The handshake phase includes timestamp validation, effectively preventing replay attacks.
Defensive Fallback
When the server detects illegal handshake requests, timed-out connections, or malformed data packets, it does not disconnect immediately. Instead, it seamlessly forwards the connection to a specified decoy address (such as an Nginx or Apache server). Probers will only see a standard web server response.
Drawbacks (TODO)
- Packet Format: TCP native; UDP is relayed via UoT (UDP-over-TCP) without exposing a raw UDP listener.
- Bandwidth Utilization: Obfuscation introduces overhead. Use the packed downlink mode to claw back bandwidth when downloads dominate.
- Client Proxy: Only supports SOCKS5/HTTP.
- Protocol Popularity: Currently only official and mihomo support, no compatibility with other cores.
Quick Start
Build
go build -o sudoku cmd/sudoku-tunnel/main.go
Server Configuration (config.json)
{
"mode": "server",
"local_port": 1080,
"server_address": "",
"fallback_address": "127.0.0.1:80",
"key": "See the running steps below",
"aead": "chacha20-poly1305",
"suspicious_action": "fallback",
"ascii": "prefer_entropy",
"padding_min": 2,
"padding_max": 7,
"custom_table": "xpxvvpvv",
"custom_tables": [
"xpxvvpvv",
"vxpvxvvp"
],
"enable_pure_downlink": true,
"httpmask": {
"disable": false,
"mode": "legacy",
"tls": false,
"host": "",
"path_root": "",
"multiplex": "off"
}
}Add "custom_table": "xpxvvpvv" (two x, two p, four v, 420 permutations allowed) to enforce a custom byte layout; "ascii": "prefer_ascii" still overrides it.
For table rotation, use "custom_tables": ["xpxvvpvv", "vxpvxvvp"]. When custom_tables is non-empty it overrides custom_table; the client picks one table per connection and the server probes the handshake to detect it (no extra plaintext negotiation field).
Note: sudoku:// short links support custom_tables (field ts, with t as a single-table fallback) and CDN-related HTTP mask options (hm/ht/hh/hx). Older links remain compatible.
Client Configuration
Change mode to client, set server_address to the Server IP, set local_port to the proxy listening port, add rule_urls using the template in configs/config.json. Toggle enable_pure_downlink to false if you want the packed downlink mode.
To run behind a CDN/proxy (e.g., Cloudflare orange-cloud), set:
"httpmask": { "disable": false, "mode": "auto" }(or"stream"/"poll")"httpmask": { "multiplex": "auto" }(reuse underlying HTTP connections across multiple tunnel dials; HTTP/2 can multiplex multiple tunnels on one connection)"httpmask": { "multiplex": "on" }(single tunnel, multi-target mux inside one HTTPMask tunnel; reduces per-connection RTT further)- client-side
server_addresscan be a domain (e.g.,"example.com:443"); set"httpmask": { "tls": true }to use HTTPS (no port-based inference).
Compatibility note: legacy top-level keys disable_http_mask / http_mask_* / path_root are still accepted, but the new httpmask object is recommended.
Chain Proxy (Multi-hop)
Client can connect via multiple Sudoku servers (nested tunnels):
{
"server_address": "entry.example.com:443",
"chain": { "hops": ["mid.example.com:443", "exit.example.com:443"] }
}Reverse Proxy (Expose client HTTP services)
Expose a client-side HTTP service (behind NAT) via a server-side HTTP entry and path prefix.
Server:
{ "reverse": { "listen": ":8081" } }Client:
{
"reverse": {
"client_id": "r4s",
"routes": [{ "path": "/gitea", "target": "127.0.0.1:3000" }]
}
}Then access: http://<server>:8081/gitea (default strip_prefix=true).
Docker (Server)
Build locally:
docker build -t sudoku:local .Run (mount your config):
docker run --rm -p 8080:8080 -p 8081:8081 -v "$PWD/config.json:/etc/sudoku/config.json:ro" sudoku:localNote: The Key must be generated specifically by Sudoku.
Run
You must generate a KeyPair first
$ ./sudoku -keygen Available Private Key: b1ec294d5dba60a800e1ef8c3423d5a176093f0d8c432e01bc24895d6828140aac81776fc0b44c3c08e418eb702b5e0a4c0a2dd458f8284d67f0d8d2d4bfdd0e Master Private Key: 709aab5f030c9b8c322811d5c6545497c2136ce1e43b574e231562303de8f108 Master Public Key: 6e5c05c3f7f5d45fcd2f6a5a7f4700f94ff51db376c128c581849feb71ccc58b
You need to enter the Master Public Key into the server configuration's key field, then copy the Available Private Key into the client configuration's key field.
If you want to generate more private keys that fits the public key, you can use the -more option and pass the argument with an existing private key("Master Private Key" also works):
$ ./sudoku -keygen -more 709aab5f030c9b8c322811d5c6545497c2136ce1e43b574e231562303de8f108 Split Private Key: 89acb9663cfd3bd04adf0001cc7000a8eb312903088b33a847d7e5cf102f1d0ad4c1e755e1717114bee50777d9dd3204d7e142dedcb023a6db3d7c602cb9d40e
Run the program specifying the config.json path as an argument:
Protocol Flow
- Initialization: Client and Server generate the same Sudoku mapping table based on the pre-shared Key.
- Handshake: Client sends encrypted timestamp and nonce.
- Transmission: Data -> AEAD Encryption -> Slicing -> Mapping to Sudoku Clues -> Adding Padding -> Sending.
- Reception: Receive Data -> Filter Padding -> Restore Sudoku Clues -> Lookup Table Decoding -> AEAD Decryption.
Disclaimer
Note
This software is for educational and research purposes only. Users are responsible for complying with local network regulations.