A 0-RTT QUIC Proxy with SNI camouflage
- UDP Friendly with minimum header
- Full Cone
- QUIC based 0-RTT
- User Management
- DNS services
- SNI camouflage with any domain (powered by JLS)
- Anti-hijack
- Resisting active detection
- Free of certificates
Build the native package with nix build. On Linux, build a static musl binary
for the host architecture with:
nix build .#musl
./result/bin/shadowquic --help$ shadowquic -c client.yamlExample config: client.yaml
# config.yaml
{
name: "node_name",
type: shadowquic,
server: "1.1.1.1",
port: 1443,
username: "my_name",
password: "my_password",
server-name: "cloudflare.com"
}$ curl -L https://raw.githubusercontent.com/spongebob888/shadowquic/main/scripts/linux_install.sh | bashThis script will:
- Install
shadowquicto/usr/local/bin/ - Generate random credentials and config at
/etc/shadowquic/server.yaml - Setup and start
shadowquicsystemd service
$ systemctl start shadowquic.service
$ systemctl stop shadowquic.service$ shadowquic -c server.yamlExample config server.yaml
Configuration detail can be found in Documentation
Use inbounds and outbounds lists. Every endpoint requires a nonempty tag,
unique within its list. All inbounds run concurrently and route through the
outbound named by router.default-outbound; if omitted, the first outbound in the list
is used. For example:
inbounds:
- type: socks
tag: local-socks
bind-addr: "127.0.0.1:1080"
- type: socks
tag: second-socks
bind-addr: "127.0.0.1:1081"
outbounds:
- type: direct
tag: direct
- type: socks
tag: upstream
addr: "127.0.0.1:1082"
router:
default-outbound: directBoth listeners above use direct. Additional outbounds are available by tag;
API commands select one with api --outbound TAG. Existing singular
inbound/outbound configs continue to work unchanged. Each object becomes a
single-entry list; omitted tags default to inbound and outbound, respectively.
Explicit tags are preserved. List entries still require tags, and specifying both
the singular and plural key for the same direction is an error.
With the plugin feature, configure request routing with either inline Lua source
or a script file:
router:
src: |
return function(ctx) return "direct" endrouter:
path: router.luaSet only one of src and path. Without a script, requests use
router.default-outbound, or the first outbound if it is omitted. Selecting a
default outbound does not require the plugin feature. File paths resolve from
the process working directory.
Changes reload automatically for subsequent requests.
Read or script-loading errors are logged and the last working
router stays active. A successful reload resets Lua script state; existing
connections are unaffected. Inline src scripts are not watched.
The script returns a function that receives the request context and returns a
configured outbound tag, or nil, error_message to reject the request. See the
router configuration reference
for context fields and destination rewriting.
- docker: example compose file
- QuicProxy: GUI and core
- mihomo