summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorEmīls <emils@mullvad.net>2021-12-09 16:29:23 +0000
committerEmīls Piņķis <emils@mullvad.net>2021-12-13 15:42:55 +0000
commit2729ca03f9192a6ab60dd6ba041ff2d7ab3209f3 (patch)
treea7f219bd02feb6464226771f5ad1e0a94e67e013
parent785254150f39e42256cf36fbf2d2901694dc6e7c (diff)
downloadmullvadvpn-2729ca03f9192a6ab60dd6ba041ff2d7ab3209f3.tar.xz
mullvadvpn-2729ca03f9192a6ab60dd6ba041ff2d7ab3209f3.zip
Allow only root to reach the API in blocked state
-rw-r--r--CHANGELOG.md5
-rw-r--r--docs/security.md9
-rw-r--r--talpid-core/src/firewall/linux.rs11
-rw-r--r--talpid-core/src/firewall/macos.rs10
-rw-r--r--talpid-core/src/firewall/mod.rs2
5 files changed, 26 insertions, 11 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9e68fb7cdc..66500519a6 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -67,9 +67,10 @@ Line wrap the file at 100 chars. Th
- Fix issue with the user getting kicked out of certain views in settings when the app is brought to the foreground.
### Security
-#### Windows
- Restrict which applications are allowed to communicate with the API while in a blocking state.
- This prevents malicious scripts on websites from trying to do so.
+ This prevents malicious scripts on websites from trying to do so. On Windows, only
+ `mullvad-problem-report.exe` and `mullvad-daemon.exe` executables are allowed to reach the API,
+ whereas on Linux and macOS only root processes are able to reach the API.
## [2021.6] - 2021-11-17
diff --git a/docs/security.md b/docs/security.md
index 8f1986642c..b7ddfea71e 100644
--- a/docs/security.md
+++ b/docs/security.md
@@ -101,10 +101,11 @@ forwarded. All other forward traffic is rejected.
#### Mullvad API
-The firewall allows traffic for the API regardless of tunnel state, to allow for updating keys,
-fetching account data, etc. In the [Connected] state, this is only allowed inside the tunnel.
-For the other states, it is allowed regardless. On Windows, only the Mullvad service and problem
-report tool are able to communicate with the API in any of the blocking states.
+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
+Linux all applications runnning as root are able to reach the API in blocking states.
### Disconnected
diff --git a/talpid-core/src/firewall/linux.rs b/talpid-core/src/firewall/linux.rs
index c10aba6ba8..480bc3c674 100644
--- a/talpid-core/src/firewall/linux.rs
+++ b/talpid-core/src/firewall/linux.rs
@@ -653,15 +653,26 @@ impl<'a> PolicyBatch<'a> {
self.batch.add(&out_rule, nftnl::MsgType::Add);
}
+ /// Adds firewall rules allow traffic to flow to the API. Allows the app to reach the API in
+ /// blocked states.
fn add_allow_endpoint_rules(&mut self, endpoint: &Endpoint) {
let mut in_rule = Rule::new(&self.in_chain);
check_endpoint(&mut in_rule, End::Src, endpoint);
+ let allowed_states = nftnl::expr::ct::States::ESTABLISHED.bits();
+ in_rule.add_expr(&nft_expr!(ct state));
+ in_rule.add_expr(&nft_expr!(bitwise mask allowed_states, xor 0u32));
+ in_rule.add_expr(&nft_expr!(cmp != 0u32));
+ in_rule.add_expr(&nft_expr!(meta skuid));
+ in_rule.add_expr(&nft_expr!(cmp == super::ROOT_UID));
+
add_verdict(&mut in_rule, &Verdict::Accept);
self.batch.add(&in_rule, nftnl::MsgType::Add);
let mut out_rule = Rule::new(&self.out_chain);
check_endpoint(&mut out_rule, End::Dst, endpoint);
+ out_rule.add_expr(&nft_expr!(meta skuid));
+ out_rule.add_expr(&nft_expr!(cmp == super::ROOT_UID));
add_verdict(&mut out_rule, &Verdict::Accept);
self.batch.add(&out_rule, nftnl::MsgType::Add);
diff --git a/talpid-core/src/firewall/macos.rs b/talpid-core/src/firewall/macos.rs
index a10f82bc69..de78524249 100644
--- a/talpid-core/src/firewall/macos.rs
+++ b/talpid-core/src/firewall/macos.rs
@@ -17,9 +17,6 @@ type Result<T> = std::result::Result<T, Error>;
/// replaced by allowing the anchor name to be configured from the public API of this crate.
const ANCHOR_NAME: &'static str = "mullvad";
-const ROOT_UID: u32 = 0;
-
-/// The macOS firewall and DNS implementation.
pub struct Firewall {
pf: pfctl::PfCtl,
pf_was_enabled: Option<bool>,
@@ -286,11 +283,13 @@ impl Firewall {
.proto(pfctl_proto)
.keep_state(pfctl::StatePolicy::Keep)
.tcp_flags(Self::get_tcp_flags())
- .user(Uid::from(ROOT_UID))
+ .user(Uid::from(super::ROOT_UID))
.quick(true)
.build()?)
}
+ /// Produces a rule that allows traffic to flow to the API. Allows the app to reach the API in
+ /// blocked states.
fn get_allowed_endpoint_rule(
&self,
allowed_endpoint: net::Endpoint,
@@ -303,6 +302,7 @@ impl Firewall {
.to(allowed_endpoint.address)
.proto(pfctl_proto)
.keep_state(pfctl::StatePolicy::Keep)
+ .user(Uid::from(super::ROOT_UID))
.quick(true)
.build()?)
}
@@ -359,7 +359,7 @@ impl Firewall {
.direction(pfctl::Direction::Out)
.to(*ip)
.quick(true)
- .user(Uid::from(ROOT_UID))
+ .user(Uid::from(super::ROOT_UID))
.keep_state(pfctl::StatePolicy::Keep)
.build()?,
);
diff --git a/talpid-core/src/firewall/mod.rs b/talpid-core/src/firewall/mod.rs
index 80714d8338..761691e216 100644
--- a/talpid-core/src/firewall/mod.rs
+++ b/talpid-core/src/firewall/mod.rs
@@ -82,6 +82,8 @@ const DHCPV4_CLIENT_PORT: u16 = 68;
const DHCPV6_SERVER_PORT: u16 = 547;
#[cfg(all(unix, not(target_os = "android")))]
const DHCPV6_CLIENT_PORT: u16 = 546;
+#[cfg(all(unix, not(target_os = "android")))]
+const ROOT_UID: u32 = 0;
#[cfg(all(unix, not(target_os = "android")))]
/// Returns whether an address belongs to a private subnet.