3x-ui3x-ui

AmneziaWG

Set up an AmneziaWG inbound in 3x-ui — obfuscation parameters, native IPv6, per-client port-forwarding, and routing client traffic through Xray.

AmneziaWG is a WireGuard fork that adds traffic obfuscation (junk packets, randomized padding, and rewritten protocol magic values) so the tunnel doesn't look like WireGuard to deep-packet inspection. It's a popular choice where plain WireGuard is blocked but a WireGuard-shaped tunnel with a different fingerprint gets through.

AmneziaWG runs embedded in the panel processamneziawg-go over a userspace (gVisor) network stack, not a kernel module. There is no DKMS build, no Secure Boot conflict, and no host network/kernel access requirement, so it works the same way inside a container as on bare metal. Each peer's decapsulated traffic relays into its own loopback Xray SOCKS5 inbound, so a peer's routing, sniffing, and per-client stats all come from Xray's own machinery — the same as any other protocol's inbound, not a separate code path.

Key settings

Server / interface

FieldWhat it is
SubnetThe tunnel's IPv4 subnet (e.g. 10.8.1.0/24); each client gets an address from it.
MTUInterface MTU. Leave at the default unless you have a reason to change it.
DNS (primary/secondary)Seeded into downloadable client configs; the server's own interface doesn't need one.
External interfaceThe host NIC a peer's IPv6 address gets aliased onto when IPv6 is enabled (see below). Leave blank to auto-detect.

Obfuscation (AmneziaWG 3.1)

The same values must match on both ends of the tunnel, so the server stores them once and every client config inherits them. The panel generates a randomized set for you (with a regenerate button) — a static, reused value defeats the point, since DPI can fingerprint it over time.

FieldWhat it is
JcNumber of junk packets sent before the handshake.
Jmin/JmaxSize range (bytes) for those junk packets. Jmin must not exceed Jmax.
S1/S2Padding added to the handshake init/response packets. S1 + 56 must not equal S2 — amneziawg-go rejects a value that would make both packets the same size.
S3Cookie-reply padding, 0-64.
S4Transport (data) packet padding, 0-32.
H1-H4Magic header values that replace WireGuard's standard message-type bytes. Each is a single integer or a low-high range; 1-4 are reserved (real WireGuard message types) and must not be used.
I1-I5Optional signature packets — random bytes prepended before the handshake, e.g. <r 148>. Generated sets fill I1 only, matching Amnezia's own generator.
HeaderProtectionKeyA base64 32-byte key for the 3.0 header-protection mechanism. Must match on every client config; blank disables it.
ContentPaddingAdditionA single integer or low-high byte range of extra padding on content packets. Kept <= 64 by the generator so a 1420-MTU tunnel doesn't fragment.
RekeyAfterTime / RekeyTimeout / RejectAfterTime / KeepaliveTimeout / MaxHandshakeAttemptsHandshake-timing randomization: each is a low-high range (seconds; attempts for the last one) the peer samples from, so session timing stops being a WireGuard fingerprint. Every RekeyAfterTime value must stay below every RejectAfterTime value. Blank keeps the WireGuard default.
RandomTrailersAppends a random number of bytes to the end of every packet.
DisableCookiesNever send cookie replies — removes a DPI-visible WireGuard message type, at the cost of WireGuard's handshake-flood mitigation.

If you enter obfuscation values by hand instead of using the generated defaults, keep H1-H4 non-overlapping and above 4, and double-check S1 + 56 != S2 — a bad value here keeps the embedded interface from coming up at all.

The 3.1 parameters need a 3.1-capable client. Clients must run a 3.1-capable Amnezia app; blanking the 3.1 fields renders a config older clients still understand. There is no host-side version requirement — the panel ships its own pinned amneziawg-go, not whatever happens to be installed on the system.

Set it up in the panel

Add an inbound

Add a new inbound, choose protocol AmneziaWG, and set the port and tunnel subnet.

Leave obfuscation on defaults (or regenerate)

The panel fills in a randomized, kernel-valid obfuscation set automatically. Use Regenerate if you want a fresh one; there's no need to hand-edit these unless you have a specific reason to.

Add a client

Each client gets its own keypair and tunnel address. Download the client's .conf or copy its share link (vpn://…, importable by the official AmneziaWG/AmneziaVPN apps) from the client list.

Optional: enable IPv6

Turning on IPv6 allocates an IPv6 address alongside each client's IPv4 one from the configured IPv6 subnet. The panel aliases that address onto the external interface's host NIC so outbound connections carry the peer's own distinct public IPv6 identity — no NAT66 needed.

Optional: forward ports to a client

Set a client's forwarded ports (e.g. 80, 443, 8000-8100) to open a real listener on the host that relays that traffic straight to the client's tunnel address — useful for a client that needs to expose a service through the server.

Every AmneziaWG inbound's traffic already goes through Xray — each peer relays into its own loopback SOCKS5 inbound, tagged with the AmneziaWG inbound's own tag, so it shows up as a normal source on the Routing page like any other protocol's inbound. There is no separate toggle for this: unlike a kernel tunnel, there's no other way for a peer's traffic to reach the internet once it's decapsulated.

What the configuration looks like

A client's downloadable .conf (also what the vpn:// share link encodes, base64url'd) looks like this:

client .conf
[Interface]
PrivateKey = <client private key>
Address = 10.8.1.2/32
DNS = 8.8.8.8, 8.8.4.4
Jc = 4
Jmin = 65
Jmax = 220
S1 = 87
S2 = 44
S3 = 21
S4 = 9
H1 = 462980921-463150218
H2 = 1177681572-1177787900
H3 = 1907413509-1907903969
H4 = 2029908558-2030313135
I1 = <r 148>
HeaderProtectionKey = 8Iu83eHDA3fMKKSGaEsVW9Ycd2lYYzc0MYlk1jJTvE4=
ContentPaddingAddition = 17-49
RekeyAfterTime = 111-139
RekeyTimeout = 4-7
RejectAfterTime = 187-251
KeepaliveTimeout = 9-14
MaxHandshakeAttempts = 19-36
RandomTrailers = on
DisableCookies = on

# my-client
[Peer]
PublicKey = <server public key>
AllowedIPs = 0.0.0.0/0, ::/0
Endpoint = your-server:443
PersistentKeepalive = 25

Not yet covered

  • Multi-node (sub-nodes) and Telegram bot — AmneziaWG inbounds haven't been exercised through those paths yet. They likely work (the reconciler runs the same way regardless of how the panel itself is deployed), but that's not the same as a confirmed, tested claim — treat it as unverified rather than assume it either way until someone reports back.

On this page