Skip to main content
Mullvad VPN implements multiple obfuscation protocols to bypass deep packet inspection (DPI) and network restrictions that may block or throttle WireGuard traffic. These protocols wrap WireGuard UDP packets to make them appear as other types of traffic.

Overview

Obfuscation protocols are transparent local proxies that:
  1. Intercept WireGuard traffic destined for the VPN server
  2. Transform the packets to hide WireGuard’s signature
  3. Forward transformed packets to the obfuscation server
  4. Receive responses from the server and unwrap them
  5. Deliver unwrapped packets to the WireGuard tunnel

Supported Protocols

*QUIC overhead is handled at the QUIC layer, not counted in WireGuard MTU

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

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):
Endpoint Patching (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 the udp-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

Outgoing (WireGuard → Shadowsocks):
Incoming (Shadowsocks → WireGuard):

Packet Format

Shadowsocks AEAD UDP packets (shadowsocks.rs:281-292):
Overhead Calculation:

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 the mullvad-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):
  1. CONNECT-UDP: HTTP/3 method to establish UDP proxy
  2. Datagram Extension: QUIC datagrams carry UDP packets
  3. 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):
Receiving (Deobfuscate):

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):
This calls Android’s VpnService.protect() to prevent routing loops.

Error Handling

Obfuscation Errors

Failure Handling

Obfuscation failures trigger tunnel reconnection (obfuscation.rs:61-76):
Obfuscation errors are marked as recoverable (talpid-wireguard/src/lib.rs:105).

Performance Characteristics

Latency Impact

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