Analysis reveals that Mullvad VPN's deterministic exit IP assignment creates a fingerprinting vector that could potentially correlate user identities across different connections.
Mullvad VPN, known for its privacy-focused approach, assigns exit IP addresses to users in a way that creates an unexpected fingerprinting vector. While Mullvad offers multiple exit IPs for its servers to avoid overcrowding any single IP address, the assignment mechanism follows a predictable pattern that reduces the theoretical number of unique combinations from trillions to just hundreds.
The Exit IP Assignment Mechanism
Mullvad assigns exit IPs deterministically based on a user's WireGuard key, which rotates every 1 to 30 days (unless using a third-party client, in which case it never rotates). This means that when a user connects to the same server multiple times with the same key, they'll consistently receive the same exit IP address.
The author tested this by creating a script that changed their public key repeatedly and fetched exit IPs for 9 different Mullvad servers. After collecting data for 3,650 public keys, they mapped out the exit IP ranges for each server:
| Hostname | Start IP | End IP | # IPs |
|---|---|---|---|
| au-syd-wg-101 | 103.136.147.5 | 103.136.147.64 | 60 |
| cl-scl-wg-001 | 149.88.104.4 | 149.88.104.14 | 11 |
| de-ber-wg-007 | 193.32.248.245 | 193.32.248.252 | 8 |
| dk-cph-wg-002 | 45.129.56.196 | 45.129.56.226 | 31 |
| fi-hel-wg-201 | 185.65.133.10 | 185.65.133.75 | 66 |
| us-lax-wg-001 | 23.234.72.36 | 23.234.72.126 | 91 |
| us-nyc-wg-602 | 146.70.168.132 | 146.70.168.190 | 59 |
| us-sjc-wg-302 | 142.147.89.212 | 142.147.89.224 | 13 |
| za-jnb-wg-002 | 154.47.30.145 | 154.47.30.155 | 11 |
The Discovery: Limited Combinations
Theoretically, these servers offer over 8.2 trillion possible exit IP combinations. With such a large number, one would expect each public key to receive a unique combination. However, the author observed only 284 distinct combinations across all tested keys.
The Pattern: Percentile-Based Assignment
By calculating the numerical position of each assigned IP within its pool (distance from the starting IP), the author discovered that all assigned IPs consistently fall within the same percentile of their respective pools. For example:
| Server | IP Position | Pool size | Ratio |
|---|---|---|---|
| au-syd-wg-101 | 49 | 60 | 0.816 |
| cl-scl-wg-001 | 9 | 11 | 0.818 |
| de-ber-wg-007 | 7 | 8 | 0.875 |
| dk-cph-wg-002 | 25 | 31 | 0.806 |
| fi-hel-wg-201 | 54 | 66 | 0.818 |
| us-lax-wg-001 | 74 | 91 | 0.813 |
| us-nyc-wg-602 | 48 | 59 | 0.813 |
| us-sjc-wg-302 | 11 | 13 | 0.846 |
| za-jnb-wg-002 | 9 | 11 | 0.818 |
This pattern explains the limited number of combinations—Mullvad appears to only assign neighboring exit IPs across all its servers.
The Technical Explanation: Seeded Random Number Generation
The author hypothesizes that Mullvad uses a seeded random number generator (RNG) to pick exit IP indexes, where the upper bound parameter is the pool size. This is evidenced by the fact that servers with identical pool sizes (cl-scl-wg-001 and za-jnb-wg-002, both with 11 IPs) consistently share IP indexes across all observed combinations.
Testing with Rust's rand crate revealed that when using a seeded RNG, the first random number generated is effectively a float that gets scaled to fit within the specified bounds. This explains why changing the bounds (pool sizes) doesn't change the underlying random value, only how it's mapped to the range.
The author notes that this behavior might not be intuitive, even for programmers, suggesting that the Mullvad development team might have shared a common misconception about how random number generation works with different bounds.
Implications for User Privacy
This deterministic assignment creates a fingerprinting vector that could potentially correlate user identities across different connections. The author created a tool that can deduce the minimum and maximum float value for a given combination of IPs: https://tmctmt.github.io/mullvad-seed-estimator/.
For example, a particular set of IPs might resolve to a float value between 0.2909 and 0.2943, meaning approximately 0.34% of Mullvad users share these specific IPs across the tested servers. With an estimated 100,000 active Mullvad users, this would correspond to about 340 users sharing the same combination.
While this doesn't provide perfect uniqueness, it offers a >99% confidence level for correlation purposes. This could be used by forum moderators to identify sockpuppet accounts or by entities with access to IP logs through data breaches or legal channels to deanonymize users behind the VPN.
Recommendations for Users
To mitigate this fingerprinting vector, the author suggests:
- Avoid switching servers more than once per public key
- Force rotate your public key by logging out of the Mullvad app
These practices would make it more difficult for observers to correlate different connections to the same user.
This analysis highlights an important consideration in VPN privacy—even services with good privacy intentions can have unexpected side effects in their implementation that create fingerprinting vectors. Users should be aware of these potential limitations and take appropriate precautions when using VPN services for sensitive activities.
Comments
Please log in or register to join the discussion