mirror of https://github.com/wg-easy/wg-easy
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
9.4 KiB
9.4 KiB
AmneziaWG UI Implementation
Overview
The wg-easy interface now fully supports AmneziaWG obfuscation parameters with conditional UI display based on whether AWG is active.
Implementation Details
Backend Changes
1. wgHelper.ts (src/server/utils/wgHelper.ts)
- Added
isUsingAwg()export function to check if AWG is active - Modified config generation to include AWG parameters when
wgExecutable === 'awg' - Server interface config includes: Jc, Jmin, Jmax, S1-S4, H1-H4, I1-I5, J1-J3, Itime
- Client configs include matching AWG parameters
2. API Endpoint (src/server/api/admin/interface/index.get.ts)
- Returns
isUsingAwg: booleanflag in the response - Frontend uses this to conditionally render AWG fields
3. Database Schema (src/server/database/repositories/interface/schema.ts)
- Added all AWG parameter columns with sensible defaults
- Default I1 set to QUIC packet mimic for traffic obfuscation
4. Validation (src/server/database/repositories/interface/types.ts)
- Comprehensive Zod validation for all AWG parameters
- Enforces amneziawg-go constraints:
- Jc: 1-128
- Jmin: 0-1279, must be < Jmax
- Jmax: 1-1280, must be > Jmin
- S1: 0-1132, S1+56 ≠ S2
- S2: 0-1188
- S3: 0-1132
- S4: 0-1188
- H1-H4: >4, all unique
- I1-I5: max 10000 chars
- J1-J3: max 1000 chars
- Itime: 0-2147483647
5. Auto-Generation (src/server/database/sqlite.ts)
- Generates random AWG parameters on first run
- Only randomizes if using default values
- Ensures each installation has unique obfuscation
Frontend Changes
Interface Admin Page (src/app/pages/admin/interface.vue)
Conditional Display:
- Shows AWG fields only when
data.isUsingAwg === true - Shows helpful message when AWG is not active
When AWG is NOT active:
┌─────────────────────────────────────────────┐
│ AmneziaWG │
├─────────────────────────────────────────────┤
│ AmneziaWG obfuscation is not currently │
│ active. To enable it, set │
│ EXPERIMENTAL_AWG=true and ensure the │
│ amneziawg kernel module is available. │
└─────────────────────────────────────────────┘
When AWG IS active:
┌─────────────────────────────────────────────┐
│ AmneziaWG Obfuscation Parameters │
├─────────────────────────────────────────────┤
│ Junk packet count (Jc) [8 ] │
│ Junk packet min size (Jmin) [8 ] │
│ Junk packet max size (Jmax) [80 ] │
│ Init header junk size (S1) [50 ] │
│ Response header junk size (S2) [85 ] │
│ Init magic header (H1) [123... ] │
│ Response magic header (H2) [456... ] │
│ Cookie magic header (H3) [789... ] │
│ Transport magic header (H4) [101... ] │
│ Cookie header junk size (S3) [0 ] │
│ Transport header junk size (S4) [0 ] │
│ Special junk packet 1 (I1) [<b 0x..] │
│ Special junk packet 2 (I2) [ ] │
│ ... (I3-I5, J1-J3, Itime) │
└─────────────────────────────────────────────┘
AWG Parameter Descriptions
Core Obfuscation (AWG 1.0)
| Parameter | Range | Recommended | Description |
|---|---|---|---|
| Jc | 1-128 | 4-12 | Number of junk packets to send |
| Jmin | 0-1279 | 8 | Minimum junk packet size (bytes) |
| Jmax | 1-1280 | 80 | Maximum junk packet size (bytes) |
| S1 | 0-1132 | 15-150 | Init packet header junk size |
| S2 | 0-1188 | 15-150 | Response packet header junk size |
| H1 | >4 | 5-2147483647 | Init magic header (must be unique) |
| H2 | >4 | 5-2147483647 | Response magic header (must be unique) |
| H3 | >4 | 5-2147483647 | Cookie magic header (must be unique) |
| H4 | >4 | 5-2147483647 | Transport magic header (must be unique) |
Advanced Obfuscation (AWG 1.5)
| Parameter | Range | Description |
|---|---|---|
| S3 | 0-1132 | Cookie packet header junk size |
| S4 | 0-1188 | Transport packet header junk size |
| I1-I5 | 0-10000 chars | Special junk packets (protocol mimics in hex) |
| J1-J3 | 0-1000 chars | Junk packet scheduling parameters |
| Itime | 0-2147483647 | Interval time in seconds (0 on Windows) |
How It Works
1. Detection Flow
┌─────────────────┐
│ Frontend loads │
│ /api/admin/ │
│ interface │
└────────┬────────┘
│
▼
┌─────────────────┐
│ Backend checks │
│ isUsingAwg() │
└────────┬────────┘
│
▼
┌─────────────────┐
│ Returns │
│ isUsingAwg: │
│ true/false │
└────────┬────────┘
│
▼
┌─────────────────┐
│ Vue template │
│ v-if renders │
│ conditionally │
└─────────────────┘
2. Configuration Generation
When generating WireGuard configs:
Server Config (wg0.conf):
[Interface]
PrivateKey = ...
Address = 10.8.0.1/24
ListenPort = 51820
MTU = 1420
PreUp = ...
PostUp = ...
PreDown = ...
PostDown = ...
Jc = 8 # ← Only if AWG active
Jmin = 8 # ← Only if AWG active
Jmax = 80 # ← Only if AWG active
S1 = 50 # ← Only if AWG active
S2 = 85 # ← Only if AWG active
H1 = 1376979037 # ← Only if AWG active
H2 = 1283620850 # ← Only if AWG active
H3 = 917053776 # ← Only if AWG active
H4 = 696394151 # ← Only if AWG active
I1 = <b 0x...> # ← Only if AWG active (QUIC mimic)
# ... etc
Client Config:
[Interface]
PrivateKey = ...
Address = 10.8.0.2/24
MTU = 1420
DNS = 1.1.1.1
Jc = 8 # ← Only if AWG active
Jmin = 8 # ← Only if AWG active
# ... (all AWG params match server)
[Peer]
PublicKey = ...
PresharedKey = ...
AllowedIPs = 0.0.0.0/0
PersistentKeepalive = 25
Endpoint = vpn.example.com:51820
Enabling AmneziaWG
Prerequisites
- Alpine Linux with
linux-ltskernel (6.12.50) - AmneziaWG kernel module built and available
- Environment variable set
Configuration
Docker Compose:
services:
wg-easy:
image: wg-easy
environment:
- EXPERIMENTAL_AWG=true # Enable AWG support
cap_add:
- NET_ADMIN
- SYS_MODULE
privileged: true
Optional Override:
environment:
- EXPERIMENTAL_AWG=true
- OVERRIDE_AUTO_AWG=awg # Force AWG (skip detection)
# or
- OVERRIDE_AUTO_AWG=wg # Force standard WireGuard
User Experience
Admin Workflow
-
Navigate to Interface Settings
- Go to Admin → Interface
-
Check AWG Status
- If AWG section shows parameters → AWG is active
- If AWG section shows message → AWG is not active
-
Customize Parameters (if AWG active)
- Adjust values as needed
- Click "Save"
- Click "Restart Interface" to apply
-
Download Client Configs
- All new client configs will include AWG parameters
- Existing clients keep their configs
Default Behavior
- First Install: Random AWG parameters generated automatically
- Existing Install: Keeps current parameters (or defaults if upgrading)
- Standard WG: AWG fields hidden, no params in configs
Security Considerations
Parameter Randomization
Each installation gets unique obfuscation parameters:
- Magic headers (H1-H4): Random 32-bit integers
- Junk sizes (Jc, Jmin, Jmax, S1-S4): Random within recommended ranges
- No fingerprinting: Each server has unique traffic signature
Validation
All parameters validated on:
- Frontend: Vue form validation
- Backend: Zod schema validation
- Database: SQLite constraints
- Runtime: amneziawg-go validation
Troubleshooting
AWG Fields Not Showing
Check:
EXPERIMENTAL_AWG=trueis set- Kernel module is available:
lsmod | grep amneziawg - No override forcing standard WG
Verify:
docker exec wg-easy sh -c 'echo $EXPERIMENTAL_AWG'
docker exec wg-easy lsmod | grep amneziawg
Parameters Not Applied
Solution:
- Save parameters in UI
- Click "Restart Interface"
- Check
/etc/wireguard/wg0.confincludes AWG params
Client Can't Connect
Verify:
- Client uses AmneziaWG-compatible app
- Client config includes AWG parameters
- Parameters match server exactly
Future Enhancements
Potential improvements:
- Parameter presets (stealth, performance, balanced)
- Randomize button in UI
- Import/export parameter profiles
- Visual validation feedback
- Advanced mode toggle for I/J parameters