2019-10-23 12:59:06 +02:00
|
|
|
# Mullvad VPN app security
|
|
|
|
|
|
|
|
This document describes the security properties of the Mullvad VPN app. It describes it for all
|
2019-11-29 11:03:11 +01:00
|
|
|
platforms and their differences. Individual platforms might have slightly different properties and
|
|
|
|
allow or block network traffic a bit differently, but all such deviations are described here.
|
2019-10-23 12:59:06 +02:00
|
|
|
|
2019-11-29 11:03:11 +01:00
|
|
|
This document does not describe in detail *how* we reach and uphold these properties, just what
|
|
|
|
they are. See the [architecture](architecture.md) document for details on how the firewall
|
|
|
|
integration is implemented.
|
2019-10-23 12:59:06 +02:00
|
|
|
|
2024-10-15 15:02:32 +02:00
|
|
|
For known security and privacy issues, that might cause the app to not uphold the
|
|
|
|
properties described in this document under certain conditions, please see the
|
|
|
|
[known issues] document.
|
|
|
|
|
2019-11-28 16:01:52 +01:00
|
|
|
The main purpose of the app is to allow the user to make all network/internet traffic to and
|
|
|
|
from the device travel via an encrypted VPN tunnel.
|
2019-10-23 12:59:06 +02:00
|
|
|
|
2019-11-29 11:03:11 +01:00
|
|
|
## Desktop vs mobile
|
|
|
|
|
|
|
|
For desktop operating systems, the security is ensured via tight integration with the default
|
|
|
|
system firewall. This means WFP on Windows, PF on macOS and nftables on Linux. All changes to
|
2020-01-07 20:38:37 +01:00
|
|
|
the rules are applied as atomic transactions. This means that there is no time window of
|
|
|
|
inconsistent or invalid rules during changes.
|
2019-11-29 11:03:11 +01:00
|
|
|
|
2019-12-19 11:07:52 +01:00
|
|
|
On mobile, Android and iOS, it is not possible for apps to directly access and manipulate the
|
|
|
|
firewall, routing table or DNS settings. There we employ other techniques to keep the system as
|
|
|
|
secure as possible with the limitations of the OS APIs.
|
2019-11-29 11:03:11 +01:00
|
|
|
|
|
|
|
### Android
|
|
|
|
|
2024-10-16 15:08:53 +02:00
|
|
|
> ⚠️ When we say *all traffic* in this chapter it does not include traffic exempt by the system
|
2024-10-15 15:02:32 +02:00
|
|
|
or traffic affected by [known issues].
|
2024-10-16 15:08:53 +02:00
|
|
|
|
|
|
|
The only way an android app can filter network traffic is via the VPN Service API. This API allows
|
|
|
|
*all traffic* to and from the device to be routed through a third party app. This API is what the
|
|
|
|
Mullvad VPN app uses for the tunnel itself and for leak protection.
|
|
|
|
|
|
|
|
When establishing a VPN connection using the default settings* the app will set the routes `0/0` and
|
|
|
|
`::0/0` in order to force *all traffic* to be routed through the app. This also applies when the app is
|
|
|
|
in a state where it blocks *all traffic*, such as the [connecting], [disconnecting] and [error]
|
|
|
|
states. Additionally the android system has a setting called *Block connections without VPN* that
|
|
|
|
enables the Android OS to block *all traffic* that is not routed through the Mullvad VPN.
|
|
|
|
|
2024-10-15 15:02:32 +02:00
|
|
|
Besides the [known issues], Android has many variants and flavors that may introduce variances to
|
|
|
|
the default [Android Open Source Project](https://source.android.com/) behavior. This means that
|
|
|
|
the Mullvad VPN app, like all other VPN apps, is subject to the limitations of the VPN Service API.
|
|
|
|
|
2024-10-16 15:08:53 +02:00
|
|
|
> **\*:** Local Network Sharing affects the routes and Split Tunneling will allow apps to bypass the
|
|
|
|
tunnel.
|
2022-10-04 12:28:55 +02:00
|
|
|
|
|
|
|
#### Exempt traffic
|
|
|
|
|
2024-10-16 15:08:53 +02:00
|
|
|
Even though not being properly documented by Google, some traffic is exempt by the system from
|
|
|
|
using the VPN, which means that the traffic will leak and therefore potentially impact user
|
|
|
|
privacy. This applies even if Block connections without VPN is enabled. The exempt traffic includes:
|
|
|
|
|
|
|
|
- Connectivity checks (DNS lookups and HTTP(S) connections)
|
|
|
|
- Network provided time (NTP)
|
|
|
|
- Traffic to and from hotspot clients.
|
2022-10-04 12:28:55 +02:00
|
|
|
|
|
|
|
The following issues have been reported by Mullvad in the Android issue tracker in order to improve
|
|
|
|
documentation and user privacy:
|
2024-10-16 15:08:53 +02:00
|
|
|
|
|
|
|
- [Incorrect VPN lockdown documentation](https://issuetracker.google.com/issues/249990229)
|
|
|
|
- [Add option to disable connectivity checks when VPN lockdown is enabled](https://issuetracker.google.com/issues/250529027)
|
|
|
|
|
2019-11-29 11:03:11 +01:00
|
|
|
|
|
|
|
### iOS
|
|
|
|
|
2019-12-19 11:07:52 +01:00
|
|
|
On iOS a designated packet tunnel process handles the network packet flow. iOS implementation
|
|
|
|
delegates the traffic handling to wireguard-go, which works directly with the tun interface.
|
2020-01-07 20:38:37 +01:00
|
|
|
The network configuration set up by the packet tunnel extension specifies the routing rules
|
|
|
|
that all traffic should flow through the tunnel, the same way it works on Android.
|
2019-12-19 11:07:52 +01:00
|
|
|
|
2019-11-29 11:03:11 +01:00
|
|
|
|
2019-10-23 12:59:06 +02:00
|
|
|
## App states
|
|
|
|
|
2019-11-28 16:01:52 +01:00
|
|
|
At the core of the app is a state machine called the "tunnel state machine". The following
|
|
|
|
sub-sections will describe each state and what security properties hold and what network activity
|
2020-01-07 20:38:37 +01:00
|
|
|
will be blocked and allowed in each state.
|
2019-11-28 16:01:52 +01:00
|
|
|
|
2019-11-29 11:03:11 +01:00
|
|
|
Except what is described as allowed in this document, all network packets should be blocked.
|
2019-11-28 16:01:52 +01:00
|
|
|
|
2019-12-10 15:15:42 +01:00
|
|
|
The following network traffic is allowed or blocked independent of state:
|
2019-11-28 16:01:52 +01:00
|
|
|
|
2019-12-10 15:15:42 +01:00
|
|
|
1. All traffic on loopback adapters is always allowed.
|
2019-11-28 16:01:52 +01:00
|
|
|
|
2019-12-10 15:15:42 +01:00
|
|
|
1. DHCPv4 and DHCPv6 requests are always allowed to go out and responses to come in:
|
2019-12-09 16:37:54 +01:00
|
|
|
* Outgoing UDP from `*:68` to `255.255.255.255:67` (client to server)
|
|
|
|
* Incoming UDP `*:67` to `*:68` (server to client)
|
|
|
|
* Outgoing UDP from `[fe80::]/10:546` to `[ff02::1:2]:547` and `[ff05::1:3]:547` (client to
|
|
|
|
server)
|
|
|
|
* Incoming UDP from `[fe80::]/10:547` to `[fe80::]/10:546` (server to client)
|
2019-11-28 16:01:52 +01:00
|
|
|
|
2021-10-06 13:58:40 +02:00
|
|
|
1. A subset of NDP is allowed:
|
2019-12-11 10:52:03 +01:00
|
|
|
* Outgoing to `ff02::2`, but only ICMPv6 with type 133 and code 0 (Router solicitation)
|
2021-10-06 13:58:40 +02:00
|
|
|
* Incoming from `fe80::/10`, but only ICMPv6 type 134 and code 0 (Router advertisement)
|
|
|
|
* Incoming from `fe80::/10`, but only ICMPv6 type 137 and code 0 (Redirect)
|
|
|
|
* Outgoing to `ff02::1:ff00:0/104` and `fe80::/10`, but only ICMPv6 with type 135 and code 0 (Neighbor solicitation).
|
|
|
|
* Incoming from `fe80::/10`, but only ICMPv6 with type 135 and code 0 (Neighbor solicitation).
|
|
|
|
* Outgoing to `fe80::/10`, but only ICMPv6 with type 136 and code 0 (Neighbor advertisement).
|
|
|
|
* Incoming from `*`, but only ICMPv6 with type 136 and code 0 (Neighbor advertisement).
|
2019-11-28 16:01:52 +01:00
|
|
|
|
|
|
|
1. If the "Allow LAN" setting is enabled, the following is also allowed:
|
|
|
|
* Outgoing to, and incoming from, any IP in an unroutable network, that means:
|
|
|
|
* `10.0.0.0/8`
|
|
|
|
* `172.16.0.0/12`
|
|
|
|
* `192.168.0.0/16`
|
2020-01-31 16:09:37 +01:00
|
|
|
* `169.254.0.0/16` (Link-local IPv4 range)
|
|
|
|
* `fe80::/10` (Link-local IPv6 range)
|
2020-04-03 10:00:58 +02:00
|
|
|
* `fc00::/7` (Unique local address (ULA) range)
|
2022-08-23 13:36:55 +02:00
|
|
|
* Outgoing to any IP in globally unroutable multicast networks, meaning these:
|
2020-01-31 16:09:37 +01:00
|
|
|
* `224.0.0.0/24` (Local subnet IPv4 multicast)
|
2022-08-23 13:36:55 +02:00
|
|
|
* `239.0.0.0/8` (Administratively scoped IPv4 multicast. E.g. SSDP and mDNS)
|
2020-01-31 16:09:37 +01:00
|
|
|
* `255.255.255.255/32` (Broadcasts to the local network)
|
|
|
|
* `ff01::/16` (Interface-local multicast. Local to a single interface on a node.)
|
2019-11-28 16:01:52 +01:00
|
|
|
* `ff02::/16` (Link-local IPv6 multicast. IPv6 equivalent of `224.0.0.0/24`)
|
2020-01-31 16:09:37 +01:00
|
|
|
* `ff03::/16` (Realm-local IPv6 multicast)
|
|
|
|
* `ff04::/16` (Admin-local IPv6 multicast)
|
2022-08-23 13:36:55 +02:00
|
|
|
* `ff05::/16` (Site-local IPv6 multicast)
|
2019-11-28 16:01:52 +01:00
|
|
|
* Incoming DHCPv4 requests and outgoing responses (be a DHCPv4 server):
|
2019-12-09 16:37:54 +01:00
|
|
|
* Incoming UDP from `*:68` to `255.255.255.255:67`
|
|
|
|
* Outgoing UDP from `*:67` to `*:68`
|
2019-11-28 16:01:52 +01:00
|
|
|
|
2021-04-14 10:56:38 +02:00
|
|
|
#### Packet forwarding
|
|
|
|
|
|
|
|
On Linux, any situation that permits incoming or outgoing traffic also allows that traffic to be
|
|
|
|
forwarded. All other forward traffic is rejected.
|
|
|
|
|
2021-12-07 11:49:51 +01:00
|
|
|
#### Mullvad API
|
|
|
|
|
2021-12-09 16:29:23 +00:00
|
|
|
The firewall allows traffic to the API regardless of tunnel state, so the daemon is able to update
|
|
|
|
keys, fetch account data, etc. In the [Connected] state, API traffic is only allowed inside the tunnel.
|
|
|
|
For the other states, API traffic will bypass the firewall. On Windows, only the Mullvad service and
|
|
|
|
problem report tool are able to communicate with the API in any of the blocking states. On macOS and
|
2023-03-26 03:49:21 +02:00
|
|
|
Linux all applications running as root are able to reach the API in blocking states.
|
2021-12-07 11:49:51 +01:00
|
|
|
|
2019-10-23 12:59:06 +02:00
|
|
|
### Disconnected
|
|
|
|
|
2019-11-28 16:01:52 +01:00
|
|
|
This is the default state that the `mullvad-daemon` starts in when the device boots, unless
|
2019-11-29 11:03:11 +01:00
|
|
|
"Launch app on start-up" and "Auto-connect" are **both** active. Then the app will proceed to the
|
|
|
|
[connecting] state immediately.
|
2019-11-28 16:01:52 +01:00
|
|
|
|
|
|
|
The disconnected state behaves very differently depending on the value of the
|
2020-10-09 13:39:40 +02:00
|
|
|
"always require VPN" setting. If this setting is enabled, the disconnected state behaves
|
2020-01-28 00:21:58 +01:00
|
|
|
like and has the same security properties as, the [error] state. If the setting is
|
2019-11-29 11:03:11 +01:00
|
|
|
disabled (the default), then it is the only state where the app does not enforce any firewall
|
|
|
|
rules. It then behaves the same as if the `mullvad-daemon` was not even running. It lets
|
2019-11-28 16:01:52 +01:00
|
|
|
network traffic flow in and out of the computer freely.
|
|
|
|
|
|
|
|
The disconnected state is not active while the app changes server or if the VPN tunnel goes down
|
2019-11-29 11:03:11 +01:00
|
|
|
unexpectedly. See the [connecting] state and [kill switch](#kill-switch) documentation for these
|
|
|
|
unexpected network issues. The only time this state is active is initially when the daemon
|
|
|
|
starts and later when the user explicitly clicks the disconnect/cancel button to intentionally
|
|
|
|
disable the VPN.
|
2019-11-28 16:01:52 +01:00
|
|
|
|
2019-10-23 12:59:06 +02:00
|
|
|
### Connecting
|
|
|
|
|
2019-11-28 16:01:52 +01:00
|
|
|
This state is active from when the app decides to create a VPN tunnel, until said tunnel has
|
2019-11-29 11:03:11 +01:00
|
|
|
been established and verified to work. Then it transitions to the [connected] state.
|
2019-11-28 16:01:52 +01:00
|
|
|
|
2019-12-11 11:23:42 +01:00
|
|
|
In this state, network traffic to the IP+port+protocol combination used for the first hop of the
|
|
|
|
VPN tunnel is allowed on all interfaces, together with responses to this outgoing traffic.
|
|
|
|
First hop means the bridge server if one is used, otherwise the VPN server directly.
|
2020-06-23 12:21:43 +02:00
|
|
|
This IP+port+protocol combination should only be allowed for the process establishing the
|
|
|
|
VPN tunnel, or only administrator level processes, depending on what the platform firewall
|
2020-08-31 16:35:05 +01:00
|
|
|
allows restricting. On Windows the rule only allows processes from binaries in certain paths. macOS
|
|
|
|
the rule only allows packets from processes running as `root`. On Linux, the rule only allows
|
|
|
|
packets that have the mark `0x6d6f6c65` set: setting a firewall mark on traffic requires elevated
|
|
|
|
privileges when using tunnels that support marking traffic, otherwise the rule is the same as on
|
|
|
|
macOS: the packet needs to originate from a process running as `root`.
|
2020-06-23 12:21:43 +02:00
|
|
|
This process/user check is important to not allow unprivileged programs
|
|
|
|
to leak packets to this IP outside the tunnel, as those packets can be fingerprinted.
|
|
|
|
|
2019-12-11 11:23:42 +01:00
|
|
|
Examples:
|
|
|
|
1. No bridge is used and the tunnel protocol is OpenVPN trying to connect with UDP to a VPN
|
2020-06-23 12:21:43 +02:00
|
|
|
server at IP `a.b.c.d` port `1301` - Allow traffic to `a.b.c.d:1301/UDP` for `openvpn.exe`
|
|
|
|
or any process running as `root`, and incoming matching traffic.
|
2019-12-11 11:23:42 +01:00
|
|
|
1. Connecting to the same VPN server, but via a bridge. The bridge is at IP `e.f.g.h` and the
|
2020-06-23 12:21:43 +02:00
|
|
|
proxy service listens on TCP port `443` - Allow traffic to `e.f.g.h:443/TCP` for
|
2022-03-31 15:40:04 +02:00
|
|
|
`mullvad-daemon.exe` or any process running as `root`, and incoming matching
|
2019-12-11 11:23:42 +01:00
|
|
|
traffic. Do not allow any direct communication with the VPN server.
|
2020-06-23 12:21:43 +02:00
|
|
|
1. Connecting to `a.b.c.d` port `1234` using WireGuard: Allow `a.b.c.d:1234/UDP` for
|
|
|
|
`mullvad-daemon.exe` or any process running as `root`.
|
2019-11-28 16:01:52 +01:00
|
|
|
|
2021-05-18 14:48:58 +02:00
|
|
|
When using WireGuard, traffic inside the tunnel is permitted immediately after the tunnel device
|
|
|
|
has been created. See the [connected] state for details on this.
|
2019-11-28 16:01:52 +01:00
|
|
|
|
2019-10-23 12:59:06 +02:00
|
|
|
### Connected
|
|
|
|
|
2019-11-29 11:03:11 +01:00
|
|
|
This state becomes active when [connecting] has fully established a VPN tunnel. It
|
2019-11-28 16:01:52 +01:00
|
|
|
stays active until the user requests a disconnect, quit, server change, change of other setting
|
|
|
|
that affects the tunnel or until the tunnel goes down unexpectedly.
|
|
|
|
|
2019-11-29 11:03:11 +01:00
|
|
|
In this state, all traffic in both directions over the tunnel interface is allowed. Minus DNS
|
2020-10-19 16:48:29 +02:00
|
|
|
requests (TCP and UDP destination port 53) not to a gateway IP on the tunnel interface or
|
|
|
|
one of the defined custom DNS servers.
|
|
|
|
We can *only* request DNS inside the tunnel and *only* from the relay server itself,
|
|
|
|
unless one or more custom DNS servers are provided. If custom servers are specified, DNS requests
|
|
|
|
can only be made to them.
|
2019-11-28 16:01:52 +01:00
|
|
|
|
2019-12-11 11:23:42 +01:00
|
|
|
This state allows traffic on all interfaces to and from the IP+port+protocol combination that
|
|
|
|
the tunnel runs over. See the [connecting] state for details on this rule.
|
2019-11-28 16:01:52 +01:00
|
|
|
|
2019-10-23 12:59:06 +02:00
|
|
|
### Disconnecting
|
|
|
|
|
2019-11-28 16:01:52 +01:00
|
|
|
This state becomes active if there is a VPN tunnel active but the app decides to close said
|
|
|
|
tunnel. This state is active until the tunnel has been properly closed.
|
|
|
|
|
|
|
|
This state does not apply its own security policy on the firewall. It just keeps what was already
|
2019-11-29 11:03:11 +01:00
|
|
|
active. All states transitioning into this state, and all states this state later
|
|
|
|
transitions to, have their own security policies. This state is just a short transition between
|
2019-11-28 16:01:52 +01:00
|
|
|
those, while the app waits for a running tunnel to come down and clean up after itself.
|
|
|
|
|
2020-01-28 00:21:58 +01:00
|
|
|
### Error
|
2019-10-23 12:59:06 +02:00
|
|
|
|
2019-11-28 16:01:52 +01:00
|
|
|
This state is only active when there is a problem/error. As described in other sections, the app
|
|
|
|
will never unlock the firewall and allow network traffic outside the tunnel unless a
|
2019-11-29 11:03:11 +01:00
|
|
|
disconnect/quit is explicitly requested by the user. At the same time there might be situations
|
2019-11-28 16:01:52 +01:00
|
|
|
when the app can't establish a tunnel for the device. This includes, but is not limited to:
|
2019-11-29 11:03:11 +01:00
|
|
|
* Account runs out of time
|
|
|
|
* The computer is offline
|
2019-11-28 16:01:52 +01:00
|
|
|
* Some internal error parsing or modifying system routing table, DNS settings etc.
|
|
|
|
|
|
|
|
In the above cases the app gives up trying to create a tunnel, but it can't go to the
|
2019-11-29 11:03:11 +01:00
|
|
|
[disconnected] state, since it should not unlock the firewall. Then it enters this state.
|
2019-11-28 16:01:52 +01:00
|
|
|
This state locks the firewall so no traffic can flow (except the always active exceptions) and
|
|
|
|
informs the user what the problem is. The user must then explicitly click disconnect in order
|
|
|
|
to unlock the firewall and get access to the internet again.
|
|
|
|
|
2020-01-28 00:21:58 +01:00
|
|
|
If the firewall integration fails, so this state fails to block traffic. Then it is not much
|
|
|
|
left the app can do to prevent leaks. It then informs the user of the seriousness of the
|
|
|
|
situation.
|
|
|
|
|
2019-11-28 16:01:52 +01:00
|
|
|
## Kill switch
|
|
|
|
|
2019-12-18 13:44:29 +01:00
|
|
|
The app has an always on "kill switch" that can't be disabled. There is no setting for it.
|
2019-11-28 16:01:52 +01:00
|
|
|
This means that whenever the app changes server or temporarily loses tunnel connectivity it will
|
|
|
|
ensure no network traffic leaks out unencrypted.
|
|
|
|
|
2019-12-18 13:44:29 +01:00
|
|
|
The app avoids the term "kill switch". Because it sounds like a red button
|
2020-01-07 20:38:37 +01:00
|
|
|
that has to be *engaged when a problem arises*. This app is much more proactive and applies
|
2019-12-18 13:44:29 +01:00
|
|
|
[strict firewall rules](#app-states) directly when it leaves the [disconnected]
|
2019-11-29 13:12:05 +01:00
|
|
|
state and keeps those rules active and enforced until the app comes back to the [disconnected]
|
2020-02-26 00:31:24 +05:30
|
|
|
state via an explicit user request again. Said strict firewall rules ensure that packets can only
|
2019-12-11 11:36:35 +01:00
|
|
|
leave or enter the computer in a few predefined ways, most notably to the selected VPN server of
|
|
|
|
course. Changes to the firewall are done in atomic transactions. Meaning there is no time window
|
|
|
|
where no or invalid rules are active on the device.
|
|
|
|
|
|
|
|
If the tunnel were to come down and your operating system tries to route packets out via the
|
|
|
|
normal network rather than through the VPN, these rules would block them from leaving.
|
|
|
|
So rather than failing open, meaning if the tunnel fails your traffic leaves in other ways,
|
|
|
|
we fail closed, meaning if the packets don't leave encrypted in the way the app intends,
|
|
|
|
then they can't leave at all.
|
2019-11-28 16:01:52 +01:00
|
|
|
|
2019-11-29 11:03:11 +01:00
|
|
|
Essentially, one can say that the app's "kill switch" is the fact that the [connecting],
|
2020-01-28 00:21:58 +01:00
|
|
|
[disconnecting] and [error] states prevent leaks via firewall rules.
|
2019-11-29 11:03:11 +01:00
|
|
|
|
2020-10-09 13:39:40 +02:00
|
|
|
### Always require VPN
|
2019-11-28 16:01:52 +01:00
|
|
|
|
2020-10-09 13:39:40 +02:00
|
|
|
The "always require VPN" setting in the app is regularly misunderstood as the kill switch.
|
|
|
|
This is not the case. The "always require VPN" setting only changes whether or not the
|
2019-11-29 11:03:11 +01:00
|
|
|
[disconnected] state should allow traffic to flow freely or to block it. The
|
2019-11-28 16:01:52 +01:00
|
|
|
disconnected state is not active during intermittent network issues or server changes, when
|
|
|
|
a kill switch would normally be operating.
|
|
|
|
|
|
|
|
The intended use case for this setting is when the user want to only switch between no internet
|
|
|
|
connectivity at all and using VPN. With this setting active, the device can never communicate
|
|
|
|
with the internet outside of a VPN tunnel.
|
2019-10-23 12:59:06 +02:00
|
|
|
|
2019-11-29 11:03:11 +01:00
|
|
|
## DNS
|
2019-10-23 12:59:06 +02:00
|
|
|
|
2019-11-29 11:03:11 +01:00
|
|
|
DNS is treated a bit differently from other protocols. Since a user's DNS history can give a
|
2019-12-11 11:39:11 +01:00
|
|
|
detailed view of what they are doing, it is important to not leak it.
|
|
|
|
Since an invalid or missing DNS response prevents the user from going where they want to go,
|
|
|
|
it is important that it works and gives correct replies, from an anti-censorship point of view.
|
|
|
|
Poisoned DNS replies is a very common way of censoring the network in many places.
|
2019-10-23 12:59:06 +02:00
|
|
|
|
2020-10-19 16:48:29 +02:00
|
|
|
By default, the app makes sure that every DNS request from the device goes inside the VPN tunnel
|
|
|
|
and only to the VPN relay server that the device is currently connected to. If custom DNS servers
|
|
|
|
are provided, requests are always made inside the tunnel unless the address belongs to a private
|
|
|
|
address range (such as 192.168.0.0/16) or a loopback address.
|
2019-11-28 16:01:52 +01:00
|
|
|
|
2019-11-29 11:03:11 +01:00
|
|
|
The above holds during the [connected] state. In the [disconnected]
|
|
|
|
state the app does nothing with DNS, meaning the default one is used, probably from the ISP.
|
|
|
|
In the other states DNS is simply blocked.
|
|
|
|
|
2021-07-30 09:58:53 +01:00
|
|
|
|
2019-12-16 09:53:40 +01:00
|
|
|
## Desktop system service
|
|
|
|
|
|
|
|
On all desktop platforms the VPN tunnel and the device security is handled by a system
|
|
|
|
service called `mullvad-daemon`. This service is installed as the administrator/root user
|
|
|
|
during app install and is then always running in the background, even when the user
|
|
|
|
quits the GUI and when no tunnels are running.
|
|
|
|
|
|
|
|
This system service can be controlled via a management interface, exposed locally
|
2024-12-12 09:21:12 +07:00
|
|
|
via Unix domain sockets (UDS) on Linux and macOS and via named pipes on Windows.
|
2019-12-16 09:53:40 +01:00
|
|
|
This management interface can be reached by any process running on the device.
|
|
|
|
Locally running malicious programs are outside of the app's threat model.
|
|
|
|
|
2022-09-26 16:19:25 +02:00
|
|
|
The `mullvad-daemon` transition to the [disconnected] state before exiting. To
|
|
|
|
limit leaks during computer shutdown, it will maintain the blocking firewall
|
|
|
|
rules upon exit in the following scenarios:
|
|
|
|
- _Always require VPN_ is enabled
|
|
|
|
- A user didn't explicitly request for the `mullvad-daemon` to be shut down and
|
|
|
|
either or both of the following are true
|
|
|
|
- The daemon is currently in one of the blocking states ([connected],
|
|
|
|
[connecting], or [error])
|
|
|
|
- _auto-connect_ is enabled
|
|
|
|
|
|
|
|
In other cases, when the daemon process stops normally, firewall rules will be
|
|
|
|
removed.
|
|
|
|
|
2020-10-09 13:40:17 +02:00
|
|
|
|
|
|
|
### Windows
|
|
|
|
On Windows, persistent firewall filters may be added when the service exits, in case the service
|
|
|
|
decides to continue to enforce a blocking policy. These filters block any traffic occurring before
|
|
|
|
the service has started back up again during boot, including before the BFE service has started.
|
|
|
|
|
|
|
|
As with "Always require VPN", enabling "Auto-connect" in the service will cause it to
|
|
|
|
enforce the blocking policy before being stopped.
|
|
|
|
|
2022-09-26 16:19:25 +02:00
|
|
|
### Linux
|
|
|
|
|
|
|
|
Due to the dependence on various other services, the `mullvad-daemon` is not
|
|
|
|
started early enough to prevent leaks. To prevent this, another system unit is
|
|
|
|
started during early boot that applies a blocking policy that persists until the
|
|
|
|
`mullvad-daemon` is started.
|
|
|
|
|
2019-12-16 09:53:40 +01:00
|
|
|
## Desktop Electron GUI
|
|
|
|
|
|
|
|
The graphical frontend for the app on desktop is an Electron app. This app only ever loads
|
2024-12-12 09:21:12 +07:00
|
|
|
local resources in the form of html, CSS and JavaScript directly from the installation
|
2019-12-16 09:53:40 +01:00
|
|
|
directory of the app, and never from remote sources.
|
|
|
|
|
|
|
|
The GUI only communicates with the system service (`mullvad-daemon`), it makes no other
|
2020-01-28 00:14:10 +01:00
|
|
|
network connections. Except when the user sends a problem report, then it spawn the
|
2019-12-16 09:53:40 +01:00
|
|
|
`mullvad-problem-report` tool, which in turn communicate over TLS with our API.
|
|
|
|
|
2019-10-23 12:59:06 +02:00
|
|
|
|
2019-11-29 11:03:11 +01:00
|
|
|
[disconnected]: #disconnected
|
|
|
|
[connecting]: #connecting
|
|
|
|
[connected]: #connected
|
|
|
|
[disconnecting]: #disconnecting
|
2020-01-28 00:21:58 +01:00
|
|
|
[error]: #error
|
2019-12-16 09:53:40 +01:00
|
|
|
[GUI]: #desktop-electron-gui
|
2024-10-15 15:02:32 +02:00
|
|
|
[known issues]: ./known-issues.md
|