Server Configuration
Every key in snell-server.conf, what it does, and the defaults you usually want.
snell-server.conf is passed via -c <path>. All keys live under the
[snell-server] section.
Full example
[snell-server]
listen = 0.0.0.0:2333
psk = your-shared-secret
obfs = off
udp = true
quic = true
egress-interface =
ipv6 = true
dns =
tfo = falseRun it:
./snell-server -c snell-server.conf # info level logs
./snell-server -c snell-server.conf -v # debug level logsKeys
listen (required)
Bind address(es). Set to 0.0.0.0:<port> to accept from anywhere, or
127.0.0.1:<port> when fronted by another reverse proxy. Use
[::]:<port> for v6 dual-stack inbound.
When quic = true (default) the server additionally listens for UDP
on the same port for QUIC proxy mode — make sure both TCP/<port>
and UDP/<port> are open in any firewall in front of the host.
psk (required)
Pre-shared key. Treated as a raw UTF-8 string (not base64-decoded) — keep this exactly as configured on the client side.
obfs (optional, default off)
Obfuscation layer wrapping the snell stream.
| Value | Behavior |
|---|---|
off | No obfuscation. Recommended — the v4/v5 frame format already uses per-frame padding for traffic-shape obfuscation. |
http | Fake HTTP/1.1 Upgrade handshake. |
tls | Fake TLS ClientHello/ServerHello handshake. |
udp (optional, default true)
Accept UDP-over-TCP from clients — snell's own datagram-in-stream protocol, distinct from QUIC mode below.
quic (optional, default true)
QUIC proxy mode (v5 only). When enabled, the server additionally listens
on UDP/<port> from listen and accepts snell-encrypted envelopes that
wrap a QUIC Initial packet; once the (src_ip, src_port) → upstream
mapping is established, all subsequent UDP packets are forwarded as
raw QUIC in both directions.
Required for HTTP/3 acceleration with Surge clients that have
block-quic=off. See the QUIC page for the wire-level
details.
egress-interface (optional, default empty)
Outbound interface binding. When set, all upstream sockets — TCP dials,
UDP-over-TCP listeners, and QUIC upstream dials — are pinned to this
interface via SO_BINDTODEVICE on Linux or IP_BOUND_IF on macOS.
Other platforms reject this at dial time.
ipv6 (optional, default true)
Whether outbound dials may use IPv6 destinations. Matches the official
Surge snell-server's ipv6 = true. When false, the dialer is
constrained to tcp4 / udp4 — Go's resolver only considers A records
and AAAA lookups are skipped. Useful on hosts whose IPv6 path is broken
or slow.
This only affects outbound; what addresses the server listens on is
still controlled by listen (write [::]:2333 for v6 dual-stack inbound).
dns (optional, default empty)
Comma-separated list of upstream DNS servers used to resolve
client-requested hostnames. Empty means use the host's system resolver
via /etc/resolv.conf.
Each entry is an IP literal (v4 or v6) with an optional :port suffix;
if no port is given, 53 is assumed. Servers are tried in order on each
lookup. Matches the official Surge snell-server's dns = … directive
added in v4.1.0.
Each configured server is logged at startup as:
level=INFO msg="effective DNS" server=<addr>tfo (optional, default false)
TCP Fast Open (RFC 7413).
When enabled, both the inbound TCP listener and outbound upstream TCP
dials get TFO setsockopt, allowing the snell client's first data write
to ride along in the SYN packet — saving one RTT per fresh TCP
connection.
Linux only (uses TCP_FASTOPEN / TCP_FASTOPEN_CONNECT).
Requires the kernel sysctl net.ipv4.tcp_fastopen to have bit 1 set for
the server side:
sysctl -w net.ipv4.tcp_fastopen=3On other platforms this option is a silent no-op.
Alpha-only keys
These keys exist only on the alpha branch and have no
equivalent in the official Surge snell-server. See
TCP Brutal for the full deep dive.
brutal = false
brutal-mbps = 100 ; required when brutal = true
brutal-cwnd-gain = 15 ; optional; tenths (15 = 1.5x)