CluvexStudio/Aether: a Rust userspace WARP core built on MASQUE over HTTP/3 and HTTP/2
A Rust userspace WARP core for censored networks, built around MASQUE over HTTP/3 and HTTP/2.
At a glance
- What is it?
- Aether is a Rust censorship-circumvention client that discovers reachable WARP endpoints, validates them with real traffic, and exposes a local SOCKS5 proxy. It targets DPI-heavy networks, and it is AGPL-3.0 with a proxy that has no authentication.
- Who is it for?
- Adopt Aether if you are on a network that fingerprints or throttles conventional VPN protocols and you want a SOCKS5 endpoint you control, especially on OpenWrt or Termux where the static musl builds fit. Do not adopt it if you need a multi-user gateway or an authenticated proxy, since the README states the SOCKS5 listener has no authentication and should never be exposed on the WAN.
- Can I use it commercially?
- Yes, with strict conditions. AGPL-3.0 is a network copyleft licence: if people use a modified version over a network, for example as a hosted service, you must offer them its source code under the same licence.
- Is it still maintained?
- Yes. The repository last received commits 6 days ago.
- What is it written in?
- Mainly Rust, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 18, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
What Aether actually solves, and for whom
Aether is a censorship circumvention client. The README frames the target environment precisely: networks where Deep Packet Inspection, protocol fingerprinting, UDP throttling and endpoint blocking are common. That is a narrower problem than "I want a VPN". A conventional WireGuard or OpenVPN client assumes a stable endpoint and a protocol that survives the path between you and it. On a network that drops UDP wholesale or fingerprints the handshake, that assumption fails before authentication even completes. Aether's answer is to discover endpoints at runtime, wrap the tunnel in MASQUE over HTTP/3 or HTTP/2, and only trust a gateway after it passes real data. The audience is individual users on restrictive networks, plus router owners running OpenWrt and Android users running Termux, both of which get dedicated install paths in the README. It is not aimed at teams provisioning site-to-site links.
Endpoint discovery and the data-plane validation step
The most interesting design decision in Aether is what it counts as a working gateway. The README says discovery comes with "end-to-end data-plane validation so a gateway is only trusted once it actually passes traffic, not just once it answers the handshake". That distinction matters on filtered networks, where a middlebox can complete a TLS or QUIC handshake and then blackhole the payload. A client that treats handshake success as reachability will keep selecting an endpoint that never carries a byte. Aether instead requires the data plane to work before the gateway earns trust. The scan has modes, and the Docker example sets AETHER_SCAN=balanced, which implies at least a speed-versus-thoroughness trade-off in how many candidates get probed. The README does not document the full set of scan modes or their cost, so how long a cold scan takes on a given network is something you have to measure yourself. Once a gateway works, quick-reconnect reuses the last known-good one and skips rescanning.
MASQUE, nested tunnels and the routing rules
The transport layer is MASQUE over HTTP/3 and HTTP/2, with optional TLS ClientHello fragmentation on the HTTP/2 path. Fragmentation is a direct response to SNI-based filtering: splitting the ClientHello across TCP segments makes the server name harder to match with a single packet inspection rule. WireGuard is also supported, so Aether is not purely a MASQUE client. Two composition modes stand out. Nested WireGuard, referred to as gool, chains two WireGuard hops, both discovered by the scan or supplied by hand. Nested MASQUE, exposed as --mim, runs a MASQUE tunnel inside another one to reach a different exit address. Routing rules match by domain, address or port, and the README notes they are matched from the TLS server name so they keep working behind a tun front end. That is a real constraint solved rather than hidden: once traffic enters a tun device, the original destination is often lost, and matching on SNI preserves the intent. Optional Tor exit via --tor carries Tor inside the tunnel, so the exit address is a Tor exit. Upstream proxy support lets Aether dial out through a VPN or proxy already running on the machine.
Installing Aether and running a first tunnel
Prebuilt binaries are on the Releases page, and the archive names encode the target. On macOS, the binaries are not notarized, so the README says to clear the download quarantine once after extracting. The commands below extract the Intel macOS archive, remove the quarantine attribute and start the binary. After ./aether runs, the client performs endpoint discovery and then exposes a local SOCKS5 proxy that your applications point at.
tar -xzf aether-macos-x86_64.tar.gz
xattr -d com.apple.quarantine aether
./aetherOn Android under Termux, the README gives a one-line installer that detects the device architecture, downloads the matching release, verifies its checksum and installs aether into $PREFIX/bin. Running aether afterwards starts the client from the installed location.
curl -fsSL https://raw.githubusercontent.com/CluvexStudio/aether/main/aether.sh -o aether.sh && chmod +x aether.sh && ./aether.sh installThe Docker path is the one to read carefully, because the README is explicit that the SOCKS5 proxy has no authentication. The published port is bound to 127.0.0.1 only, and the volume keeps the generated WARP identity between runs. Without the volume, every start registers a new device and Cloudflare begins rate limiting your address.
docker run -it -p 127.0.0.1:1819:1819 -v aether-data:/data ghcr.io/cluvexstudio/aether:latestYou can skip the prompts with environment variables. The example below selects the MASQUE protocol and the balanced scan mode.
docker run -it -p 127.0.0.1:1819:1819 -v aether-data:/data \
-e AETHER_PROTOCOL=masque \
-e AETHER_SCAN=balanced \
ghcr.io/cluvexstudio/aether:latestOn OpenWrt, Aether is a single static binary of 7 to 10 MB and you pick the archive by uname -m. The README warns to keep --config on persistent storage such as /etc/aether, because /tmp is wiped at every reboot and a lost identity means a new device registration each boot, which Cloudflare rate limits.
Where Aether is the wrong tool
The sharpest limitation is stated in the README itself: the SOCKS5 proxy has no authentication, and anyone who can reach the port can use your tunnel. The Docker documentation goes further and warns that -p 1819:1819 listens on every interface of the host and turns the proxy into an open relay. That rules Aether out as a shared gateway for a team or a LAN segment unless you put an authenticated front end in front of it and firewall the port. The OpenWrt instructions repeat the point: binding to the LAN address is possible, but never expose it on the WAN. A second boundary is architecture. MIPS routers, including MT7621, are not supported, which excludes a large installed base of older consumer routers. A third is that the README does not document rollback, and there is no described mechanism for reverting a configuration change beyond editing the config file. If you need auditable, centrally managed policy across many users, a userspace client with a local SOCKS5 listener is the wrong shape.
How Aether differs from sing-box and Xray
The obvious alternatives are general-purpose proxy platforms such as sing-box and Xray, and the difference is not the protocol list. Both of those are configurable engines: you write a JSON configuration describing inbounds, outbounds and routing, and the software executes it. Aether inverts that. It discovers endpoints, validates them at the data plane, and reconnects on its own, with flags, environment variables or interactive prompts as the interface. The README explicitly offers those three input methods as "your choice", which is a statement about the intended user. If you want to hand-tune a routing graph and pin specific outbound selections, sing-box or Xray gives you that control and Aether does not appear to. If you want a client that decides for itself which gateway is reachable on a hostile network, Aether's scan-and-validate loop is the part those engines do not do by default. The trade-off is transparency: a discovery process you did not specify is harder to reason about than a config file you wrote.
Licence, maintenance and the cost of upgrading
Aether is AGPL-3.0. If you modify it and let users interact with it over a network, the AGPL's source-availability obligation is the part to read with a lawyer, not a summary. The repository also carries a TRADEMARK.md, which is a separate constraint from the code licence and typically governs use of the project name. On maintenance, the last push was on 2026-09-12, and v2.0.0 was released the same day, following v1.9.0 on 2026-09-04 and v1.8.0 on 2026-08-29. That is a rapid release cadence, and it cuts both ways: fixes arrive quickly, but a client that changes this often means your pinned version can fall behind on endpoint discovery behaviour. The build path has its own cost. The README requires Rust 1.98 or newer, a C/C++ compiler and CMake, and states that the quiche repository must be placed alongside aether, with the build run from the aether directory so Cargo finds aether/Cargo.toml. The Dockerfile pins GO_VERSION=1.22.12 and builds with --features tor, so a source build pulls in the Go toolchain as well. Upgrading is cheap if you use the prebuilt archives and their .sha256 files, and expensive if you build from source.
Editorial conclusion
Adopt Aether if you are on a network that fingerprints or throttles conventional VPN protocols and you want a SOCKS5 endpoint you control, especially on OpenWrt or Termux where the static musl builds fit. Do not adopt it if you need a multi-user gateway or an authenticated proxy, since the README states the SOCKS5 listener has no authentication and should never be exposed on the WAN. Before committing, verify the endpoint scan actually passes traffic on your network, confirm you can build or find a binary for your architecture (MIPS routers are not supported), and check that the AGPL-3.0 and TRADEMARK.md terms fit how you intend to redistribute it.
Frequently asked questions
What exactly is Aether?
Aether is a censorship circumvention client written in Rust. It discovers reachable routes, establishes an encrypted tunnel using MASQUE over HTTP/3 and HTTP/2 (with WireGuard also supported), and exposes a local SOCKS5 proxy for your applications.
How do I install Aether on Android?
The README gives a one-line Termux installer that detects your device architecture, downloads the matching release, verifies its checksum and installs aether into $PREFIX/bin. After that you run aether directly, and ./aether.sh update handles later updates.
How do I use Aether once it is running?
Aether exposes a local SOCKS5 proxy, and the Docker image sets AETHER_SOCKS to 0.0.0.0:1819, so applications point at that listener. The proxy has no authentication, so the README says to publish the port to 127.0.0.1 only and never expose it on the WAN.
Does Aether need a persistent config directory?
Yes on OpenWrt, where the README says to keep --config on persistent storage such as /etc/aether. Because /tmp is wiped at every reboot, a lost identity means a new device registration on each boot, which Cloudflare rate limits. The Docker image uses the aether-data volume for the same reason.
Which architectures can run Aether?
The README lists Windows x86_64, macOS on Apple Silicon and Intel, Linux x86_64, arm64 and armv7, musl static builds for older glibc and OpenWrt, and Android via Termux. MIPS routers such as MT7621 are explicitly not supported.
What is the Aether licence?
The repository is licensed AGPL-3.0 and also includes a TRADEMARK.md file. The AGPL's source-availability obligation applies when modified versions are offered to users over a network, and the trademark file is a separate constraint from the code licence.
Community notes