A high-performance MASQUE proxy server written in Rust. HTTP/3 carries TCP, UDP, and IP traffic using standard CONNECT, CONNECT-UDP, and CONNECT-IP; HTTP/2 provides a TCP/TLS compatibility transport for all three when a network blocks QUIC.
The project is pre-1.0. Protocol behavior, configuration compatibility, and release packaging are tested, but operators should still validate upgrades in a staging environment.
- Standard CONNECT for TCP streams
- CONNECT-UDP (RFC 9298) using HTTP Datagrams
- CONNECT-IP (RFC 9484) with Linux TUN integration
- HTTP/3 over UDP for performance, plus HTTP/2 Extended CONNECT and the Cloudflare/usque CONNECT-IP dialect over TCP/TLS as compatibility fallbacks
- HTTP Basic authentication with Argon2id password verification, or TLS client certificate authentication against a public-key roster
- Multiple listeners in one process, each with its own Basic or client-certificate authentication mode while sharing proxy policies, client roster, and TUN state
- CIDR allow and deny policies for TCP and UDP targets
- Adaptive QUIC Retry plus process-wide per-source connection and Basic-auth admission limits
- Bounded queues and backpressure across authentication and tunnel I/O
- Linux
recvmmsg/sendmmsg, UDP GRO, optional UDP GSO, and TUN offload - Multi-core sharding with
SO_REUSEPORT - Optional loopback health/readiness endpoints and low-overhead Prometheus metrics, with packaged static alert rules and a Grafana dashboard JSON
- Optional JSON logs plus native systemd readiness and shard-liveness watchdog
- Atomic
SIGHUPreload of the full TLS certificate chain and private key without dropping established connections; active roster updates disconnect only revoked certificate clients - Read-only
doctorchecks for CONNECT-IP TUN, forwarding, route, firewall, and NAT prerequisites without modifying the host - Static Linux x86_64 release archives with a systemd installer
Build the server:
cargo build --release --bin masque-serverEach [[listeners]] entry chooses transport = "http3" (the default and
recommended path) or transport = "http2", and has an explicit
[listeners.auth] table. For a basic listener, generate an Argon2id password
hash:
printf '%s' 'replace-this-password' | \
target/release/masque-server hash-passwordCopy deploy/config/masque.toml, set the server TLS
certificate, private key, username, and password hash, then start the server:
target/release/masque-server --config ./masque.tomlAfter replacing both TLS files, systemctl reload masque makes new HTTP/2 and
HTTP/3 handshakes use them while established connections continue normally.
Invalid or mismatched replacement material is rejected and the previous
identity remains active.
Authentication is fail-closed. In basic mode the server refuses to start until
a valid username and Argon2id hash are configured.
Alternatively, set mode = "client_cert" in [listeners.auth] to authenticate
clients during the TLS handshake. Generate each client's P-256 key and
configuration with:
target/release/masque-server --config ./masque.toml enroll-client \
--name laptop --endpoint 203.0.113.9:443 \
--ipv4 10.89.0.2 --ipv6 fd00:abcd::2 --out laptop.jsonAppend the generated [[clients]] block to the server configuration, then
reload or restart the service. The generated client configuration contains a
private key and must be handled as a secret. Basic and client-certificate
authentication are mutually exclusive on one socket, because the mode decides
what the TLS handshake demands. To serve both kinds of client, give each mode
its own [[listeners]] entry in the same process; see
Authentication and
Listeners.
A second listener can be added to a deployed configuration without editing TOML
by hand. This prompts for the HTTP transport, address, authentication mode, and
any credentials, validates the merged file the way check-config does,
test-binds the new address, and leaves the file untouched if anything is wrong:
masque-server --config /etc/masque/masque.toml add-listenerEvery value, including --transport http2|http3, is also available as a flag
for provisioning scripts. See
Adding a listener. A new socket is
bound at startup, so open UDP for HTTP/3 or TCP for HTTP/2, restart the service,
and confirm it came up.
CONNECT-IP is independent of the authentication mode: it needs Linux host
forwarding because it carries complete IP packets through masque0, while
CONNECT and CONNECT-UDP use ordinary userspace sockets. Inspect the host before
qualifying a CONNECT-IP client:
sudo masque-server --config /etc/masque/masque.toml doctorThe command and the server's startup check are read-only. They never change routing, firewall, sysctl, or NAT state.
On Linux x86_64, download, verify, and install the latest stable release with:
curl -fsSL https://raw.githubusercontent.com/Vincent-bin/masque-server/main/install-latest.sh | sudo shFor a new configuration the installer prompts for basic, client_cert, or
dual authentication and optional TLS file locations. Basic mode generates a
random password when none is supplied. Client-certificate mode enrolls the first
client, adds its [[clients]] entry, writes its secret JSON as mode 0600, and
prints the matching usque and mihomo configuration. Dual mode does both, writing
a two-listener configuration that serves credentials on one port and
certificates on another. At the end a fresh installation prints the installed
version, service state, and effective server configuration with the password
hash redacted. It also offers to run the read-only CONNECT-IP host diagnostic;
the installer never configures forwarding, firewall rules, routes, or NAT.
The same command is also the upgrade command. When
/etc/masque/masque.toml already exists, the candidate binary checks that
configuration without binding a port or creating a TUN, then upgrades the
binary, systemd unit, and versioned monitoring assets. It never rewrites the
TOML or referenced TLS files, and it does not copy the existing configuration
into unattended upgrade logs. An
incompatible configuration aborts before replacement; a failed service restart
restores the prior binary, unit, monitoring assets, and service state. See
Deployment for non-interactive
variables, certificate requirements, and installing a specific release.
Release archives contain the binary, an example configuration, a hardened systemd unit, Prometheus rules, a Grafana dashboard, and an installer:
tar xzf masque-vVERSION-linux-x86_64.tar.gz
cd masque-vVERSION-linux-x86_64
sudo ./install.shThe monitoring files are optional static assets. Installation does not install or start Prometheus or Grafana on the server.
The package installer creates an unprivileged masque system user, lets new
installations choose either authentication mode, and enables the service. Set
MASQUE_START_SERVICE=1 to start it immediately; the one-command installer
does this automatically when TLS material is present.
See Deployment for certificates, systemd hardening, upgrades, and diagnostics.
| Document | Contents |
|---|---|
| Architecture | Runtime components, data flow, sharding, and resource bounds |
| Configuration | TOML sections, authentication, policy, and tuning |
| Deployment | Linux installation, systemd, certificates, and upgrades |
| Protocols | Supported RFCs and CONNECT request behavior |
| Performance | Benchmark methodology and Linux fast paths |
| Observability | Health/readiness, metrics, alerts, dashboard, and structured logs |
| Testing | Unit, E2E, benchmark, and release validation |
| Security | Threat model, safe defaults, and operational guidance |
src/ Server library and CLI
capsule/ Capsule Protocol codecs
net/ Platform UDP adapters and Linux batch I/O
tunnel/ TCP, UDP, and IP tunnel implementations
tools/masque-e2e/ E2E client and load generator
tests/e2e/ Docker E2E environment and fixtures
benches/ In-process microbenchmarks
fuzz/ Scheduled libFuzzer targets for public protocol parsers
deploy/ Example config, installer, systemd unit, and monitoring assets
docs/ Operator and contributor documentation
scripts/ Test, benchmark, certificate, and packaging helpers
.github/workflows/ CI and release automation
The server remains a single primary crate deliberately. The hot packet path crosses QUIC, scheduling, and tunnel code, so release builds use fat LTO and a single codegen unit instead of introducing crate boundaries solely for layout.
cargo fmt --all --check
cargo clippy --workspace --all-targets --locked
cargo test --workspace --locked
cargo bench --bench core
scripts/network-bench.shThe Docker E2E suite requires /dev/net/tun, Docker Compose, and permission to
create a container with NET_ADMIN:
scripts/e2e-test.shSee CONTRIBUTING.md before submitting a change.
Linux is the production target and the only platform supporting CONNECT-IP, multi-shard HTTP/3 listeners, UDP GSO/GRO, and batched target UDP I/O. HTTP/2 protocol handling is portable, including CONNECT-IP capsule setup, but actual IP forwarding still needs Linux TUN and host routing. macOS is useful for the portable HTTP/2 and HTTP/3 paths, but it cannot exercise the Linux syscall, TUN, and offload paths.
Licensed under the MIT License.