Skip to main content

Overview

The Mullvad VPN daemon communicates with api.mullvad.net for account management, relay list updates, version checks, and other operations. To ensure API reachability even in censored networks, the client supports multiple access methods including direct connections, Shadowsocks bridges, and custom proxies. Reference: mullvad-daemon/src/api.rs, docs/architecture.md:48-62

API Endpoints

The daemon interacts with Mullvad’s REST API for:
  • Account operations: Create account, login, check expiry, submit vouchers
  • Device management: Register devices, rotate WireGuard keys, list/remove devices
  • Relay list updates: Download current relay and bridge server lists
  • Version checks: Check for app updates and security advisories
  • GeoIP lookups: Determine current location and verify tunnel connectivity
  • Problem reports: Submit diagnostic logs (with user consent)

Access Methods

The client supports multiple methods to reach the API, automatically selected based on availability and user configuration.

1. Direct TLS Connection

Default method: Standard HTTPS connection to api.mullvad.net.
Characteristics:
  • Fastest and most reliable when available
  • Uses standard TLS 1.3
  • No additional overhead
  • May be blocked in censored networks
Reference: mullvad-daemon/src/api.rs:54

2. Mullvad Bridges (Shadowsocks)

Censorship-resistant: Routes API traffic through Shadowsocks proxies hosted on Mullvad bridge servers.
How it works:
  1. Client requests bridge server from relay selector
  2. Relay selector chooses Shadowsocks-enabled bridge
  3. All API traffic proxied through bridge
  4. Bridge forwards to actual API endpoint
Configuration:
Reference: mullvad-daemon/src/api.rs:55-63, management_interface.proto:478-488 Shadowsocks details:
Bridge servers provide Shadowsocks endpoints with:
  • Cipher: Encryption algorithm (e.g., chacha20-ietf-poly1305)
  • Password: Shared secret for authentication
  • Protocol: TCP or UDP transport
Reference: management_interface.proto:766-771

3. Encrypted DNS Proxy

Domain fronting: Uses encrypted DNS protocols to obfuscate API connections.
How it works:
  1. Client fetches encrypted DNS proxy configs from frakta.eu
  2. Connects using DNS-over-HTTPS (DoH) or DNS-over-TLS (DoT)
  3. DNS proxy forwards requests to actual API
  4. Appears as DNS traffic to network observers
Implementation:
Reference: mullvad-daemon/src/api.rs:64-78

4. Custom Proxies

Users can configure custom SOCKS5 or Shadowsocks proxies. SOCKS5 (Local):
Local SOCKS5 proxy running on the same machine. Reference: management_interface.proto:448-453 SOCKS5 (Remote):
Remote SOCKS5 proxy with optional authentication. Reference: management_interface.proto:454-462 Shadowsocks (Custom):
Custom Shadowsocks server configuration. Reference: management_interface.proto:463-468

Access Method Selection

The daemon uses an AccessMethodResolver to dynamically select the appropriate access method.

Resolution Process

Reference: mullvad-daemon/src/api.rs:26-96

Access Method Priority

The client maintains a list of access methods with priorities:
Each method can be enabled/disabled:
Reference: management_interface.proto:503-508, 490-495

Automatic Failover

When an API request fails:
  1. Current access method is marked as potentially unavailable
  2. Next enabled access method is tried
  3. Process repeats until success or all methods exhausted
  4. Failed requests can trigger access method testing

Testing Access Methods

Users can test access methods before using them:
Tests verify:
  • Proxy connectivity
  • API reachability through proxy
  • Authentication success
Reference: management_interface.proto:93-94

API Availability Monitoring

The daemon continuously monitors API availability:
Monitoring includes:
  • Periodic connectivity checks
  • Request success/failure tracking
  • Automatic access method switching
  • Exponential backoff on repeated failures
Reference: mullvad-daemon/src/lib.rs:46

Firewall Integration

API traffic must be allowed even when the tunnel is not connected.

Allowed Endpoints

The firewall receives a list of allowed endpoints for API communication:
Reference: mullvad-daemon/src/api.rs:98-100

Tunnel State Coordination

The API runtime coordinates with the tunnel state machine:
  • In secured states (Connecting, Connected, Error), only API traffic allowed outside tunnel
  • In disconnected state, broader internet access may be permitted (depending on lockdown mode)
  • API endpoint changes communicated to firewall in real-time
Important: No actor should block on API requests if the tunnel state machine relies on that actor to change states - this prevents deadlocks. Reference: docs/architecture.md:55-58

Request Management

Asynchronous Operations

All API requests are asynchronous:

Request Cancellation

API requests can be dropped in flight:
  • When tunnel connects, API connection resets
  • Allows switching between access methods
  • Ensures API uses current endpoint configuration
Reference: docs/architecture.md:59-61

Offline State Handling

When the device is offline:
  • API requests are blocked/queued
  • Prevents wasted connection attempts
  • Resumes when connectivity restored
See Offline Detection for details. Reference: docs/architecture.md:61-62

Address Caching

The API client caches the resolved IP address of api.mullvad.net:
Purpose:
  • Reduces DNS lookup failures
  • Enables API access when DNS is blocked/unreliable
  • Periodically refreshed when DNS is available
Reference: mullvad-daemon/src/api.rs:9,29,36

Connection Modes

Direct Mode

Direct TLS connection to cached or resolved API address.

Proxied Mode

Proxied through configured proxy server. Reference: mullvad-api/src/proxy.rs

API Client Implementation

The API client is implemented in the mullvad-api crate:

Request Flow

  1. Daemon initiates request: api_handle.get_relay_list().await
  2. Access method resolution: Select appropriate access method
  3. Endpoint resolution: Determine IP address and port
  4. Firewall configuration: Ensure endpoint is allowed
  5. HTTP request: Execute via direct or proxied connection
  6. Response processing: Parse and return data
  7. Error handling: Retry or failover on errors

Censorship Resistance Strategies

Traffic Obfuscation

Different access methods provide varying levels of obfuscation:
  • Direct: Standard TLS - easily identifiable
  • Shadowsocks: Encrypted proxy protocol - hard to detect
  • Encrypted DNS Proxy: Masquerades as DNS traffic - very hard to block without breaking DNS
  • Custom SOCKS5: Depends on proxy configuration

Domain Fronting

Encrypted DNS Proxy uses domain fronting:
  • TLS SNI shows innocent domain (frakta.eu)
  • Actual API requests hidden in encrypted payload
  • Difficult to block without blocking entire domain

Port Variability

Multiple ports supported for each method:
  • Shadowsocks: Range of ports from relay list
  • UDP2TCP: Ports 80, 443, 5001
  • QUIC: Port 443
  • Harder to block all ports without false positives

Security Considerations

TLS Certificate Validation

All API connections validate TLS certificates:
  • Pinned certificate or standard CA validation
  • Prevents man-in-the-middle attacks
  • Even when using proxies, end-to-end TLS maintained

Proxy Trust Model

Mullvad bridges:
  • Operated by Mullvad
  • Same trust as Mullvad relays
  • API requests encrypted end-to-end
Custom proxies:
  • User-provided
  • TLS still protects API requests
  • Proxy sees encrypted traffic only

Authentication

API requests authenticated via:
  • Account tokens (for account operations)
  • Device tokens (for device-specific operations)
  • OAuth tokens (for web authentication)
Tokens transmitted over TLS only.

Management Interface Integration

Configuration

Access methods managed via gRPC:
Reference: management_interface.proto:86-92

Events

Access method changes broadcast to frontends:
Reference: management_interface.proto:729-740

Bridge Server List

Separate from relay list, bridge servers are dedicated to API access:
Reference: management_interface.proto:748-761

Bridge Endpoint Data

All bridges provide Shadowsocks endpoints with standardized configuration. Reference: management_interface.proto:764

Debugging and Testing

Access Method Testing

Test individual access methods before relying on them:
Verifies:
  • Proxy connectivity
  • API reachability
  • Authentication

Current Access Method

Check which method is currently active:

Forced Access Method

Override automatic selection:

Error Recovery

Request Retry Logic

Failed API requests trigger:
  1. Immediate retry with same access method
  2. Switch to next access method on repeated failure
  3. Exponential backoff between attempts
  4. Circuit breaker after extended failures

Access Method Rotation

Periodic rotation ensures:
  • Dead access methods are discovered
  • New methods are tested
  • Best-performing method is used

Performance Optimization

Connection Reuse

HTTP connections are reused when possible:
  • Connection pooling for repeated requests
  • Reduced TLS handshake overhead
  • Lower latency for consecutive requests

Caching

  • Relay lists cached locally (refreshed periodically)
  • Account data cached (refreshed on access)
  • Address cache reduces DNS lookups

Parallel Requests

Multiple independent API requests can run concurrently:
  • Relay list updates don’t block account checks
  • Version checks run in background
  • No artificial serialization