Overview
Obfuscation protocols are transparent local proxies that:- Intercept WireGuard traffic destined for the VPN server
- Transform the packets to hide WireGuard’s signature
- Forward transformed packets to the obfuscation server
- Receive responses from the server and unwrap them
- Deliver unwrapped packets to the WireGuard tunnel
Supported Protocols
| Protocol | Transport | Use Case | Overhead |
|---|---|---|---|
| UDP-over-TCP | TCP | Networks blocking UDP | ~54 bytes |
| Shadowsocks | UDP | Censorship circumvention | ~59 bytes |
| QUIC | QUIC/UDP | Modern HTTP/3 mimicry | ~0 bytes* |
| LWO | UDP | Lightweight header obfuscation | 0 bytes |
Code References
- Integration layer:
talpid-wireguard/src/obfuscation.rs - Protocol implementations:
tunnel-obfuscation/src/- UDP2TCP:
tunnel-obfuscation/src/udp2tcp.rs - Shadowsocks:
tunnel-obfuscation/src/shadowsocks.rs - QUIC:
tunnel-obfuscation/src/quic.rs - LWO:
tunnel-obfuscation/src/lwo.rs - Multiplexer:
tunnel-obfuscation/src/multiplexer.rs
- UDP2TCP:
Architecture
Obfuscator Trait
All obfuscation protocols implement a common interface (tunnel-obfuscation/src/lib.rs:54-70):
Settings Enum
Obfuscation configuration is represented as (lib.rs:72-79):
Integration with WireGuard
Obfuscation is applied before tunnel creation (obfuscation.rs:30-81):
obfuscation.rs:84-87):
The WireGuard peer endpoint is changed from the remote server to the local obfuscator:
Traffic Flow
UDP-over-TCP (UDP2TCP)
Purpose
Encapsulates WireGuard UDP packets inside TCP to traverse networks that block or deprioritize UDP traffic.Implementation
Uses theudp-over-tcp library (udp2tcp.rs:1-101):
Protocol Format
Each UDP packet is prefixed with a 2-byte length field and sent over TCP:TCP Options
- nodelay = true: Disables Nagle’s algorithm for lower latency
- fwmark (Linux): Marks packets for policy routing
Use Cases
- Corporate networks blocking UDP
- ISPs with aggressive UDP throttling
- Networks with broken UDP connectivity
Shadowsocks
Purpose
Originally designed to circumvent the Great Firewall of China, Shadowsocks encrypts and authenticates UDP packets using AEAD ciphers.Implementation
Initialization Sequence
Forwarding Logic
Packet Format
Shadowsocks AEAD UDP packets (shadowsocks.rs:281-292):
Cipher Configuration
- Algorithm: AES-256-GCM (AEAD)
- Password: “mullvad” (shared secret)
- Salt: Random 32 bytes per packet
- Tag: 16-byte authentication tag
Use Cases
- Censorship circumvention in restrictive countries
- Networks with DPI that blocks WireGuard signatures
- Additional encryption layer (defense in depth)
QUIC Obfuscation
Purpose
Masquerades WireGuard as QUIC/HTTP3 traffic, which is becoming increasingly common and is less likely to be blocked.Implementation
Uses themullvad-masque-proxy library for HTTP/3 CONNECT-UDP proxying (quic.rs:1-221):
Configuration Builder
Client Initialization
Forwarding Task
Authentication Token
MASQUE Protocol
Implements IETF MASQUE (Multiplexed Application Substrate over QUIC Encryption):- CONNECT-UDP: HTTP/3 method to establish UDP proxy
- Datagram Extension: QUIC datagrams carry UDP packets
- Authentication: Bearer token in HTTP headers
Use Cases
- Networks that allow HTTP/3 but block VPNs
- Mimicking legitimate web traffic
- Low-latency obfuscation (QUIC’s 0-RTT)
Lightweight WireGuard Obfuscation (LWO)
Purpose
Minimal-overhead obfuscation that XORs WireGuard packet headers with public keys, breaking DPI signatures without significant performance penalty.Implementation
Initialization
Connection Establishment
Obfuscation Algorithm
Sending (Obfuscate):Header Extraction
WireGuard Message Types
Forwarding Loop
Security Properties
- No encryption: Only obfuscates headers, payload remains WireGuard-encrypted
- Zero overhead: No additional bytes added to packets
- DPI evasion: Breaks WireGuard packet signatures
- Key-based: Uses WireGuard public keys for XOR (no shared secret needed)
Use Cases
- Networks with basic DPI that only checks packet signatures
- When minimal overhead is critical
- Environments where performance is more important than deep obfuscation
Multiplexer
The multiplexer allows trying multiple obfuscation protocols simultaneously, using the first one that succeeds.Configuration
Use Cases
- Fallback to direct connection if obfuscation fails
- Trying multiple obfuscation servers
- Adaptive protocol selection based on network conditions
MTU Considerations
Overhead Adjustment
When obfuscation is enabled, the tunnel MTU is reduced (talpid-wireguard/src/lib.rs:189-196):
Obfuscation MTU
The obfuscation layer uses the physical link MTU:Protocol-Specific MTU
- UDP2TCP: Requires ~54 bytes overhead for TCP header
- Shadowsocks: ~55-67 bytes for salt + address + tag
- QUIC: MTU handled internally by QUIC protocol
- LWO: 0 bytes overhead
Android-Specific Handling
VPN Bypass
On Android, obfuscation sockets must be excluded from the VPN (obfuscation.rs:184-197):
VpnService.protect() to prevent routing loops.
Error Handling
Obfuscation Errors
Failure Handling
Obfuscation failures trigger tunnel reconnection (obfuscation.rs:61-76):
talpid-wireguard/src/lib.rs:105).
Performance Characteristics
Latency Impact
| Protocol | Added Latency | Notes |
|---|---|---|
| UDP2TCP | ~5-20ms | TCP handshake + retransmissions |
| Shadowsocks | <1ms | Single encryption/decryption |
| QUIC | ~10-30ms | QUIC handshake (0-RTT after first connection) |
| LWO | <0.5ms | Simple XOR operation |
Throughput Impact
- UDP2TCP: May be limited by TCP congestion control
- Shadowsocks: Minimal (~95% of baseline)
- QUIC: ~90-95% due to QUIC overhead
- LWO: ~99% (negligible)
CPU Usage
- UDP2TCP: Low (kernel TCP stack)
- Shadowsocks: Medium (AES-256-GCM encryption)
- QUIC: Medium-High (TLS 1.3 + QUIC state machine)
- LWO: Very Low (XOR only)
Configuration Examples
Settings Construction
Single Obfuscation Config
Related Documentation
- WireGuard Implementation - Core tunnel that obfuscation wraps
- Quantum-Resistant Tunnels - Post-quantum cryptography layer
- Security Documentation:
docs/security.mdin source repository