summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorMarkus Pettersson <markus.pettersson@mullvad.net>2025-07-01 09:22:07 +0200
committerMarkus Pettersson <markus.pettersson@mullvad.net>2025-07-04 15:31:41 +0200
commit846dfb364fcbb4fdc76d6cbad1f09768d6c904c1 (patch)
tree222713288e5c0dcabab568115852182b95a5c800
parent1bdd1be3a3c07a5c4fc49489597de0f582085fed (diff)
downloadmullvadvpn-846dfb364fcbb4fdc76d6cbad1f09768d6c904c1.tar.xz
mullvadvpn-846dfb364fcbb4fdc76d6cbad1f09768d6c904c1.zip
Add new ephemeral WinFW policy for blocking until next reboot
Define a new WinFW policy WINFW_CLEANUP_POLICY_BLOCK_UNTIL_REBOOT that behaves just like WINFW_CLEANUP_POLICY_CONTINUE_BLOCKING, but only until next reboot.
-rw-r--r--talpid-core/src/firewall/windows/mod.rs19
-rw-r--r--windows/winfw/src/winfw/winfw.cpp56
-rw-r--r--windows/winfw/src/winfw/winfw.h4
3 files changed, 74 insertions, 5 deletions
diff --git a/talpid-core/src/firewall/windows/mod.rs b/talpid-core/src/firewall/windows/mod.rs
index 3ef49938dd..4515ba72b7 100644
--- a/talpid-core/src/firewall/windows/mod.rs
+++ b/talpid-core/src/firewall/windows/mod.rs
@@ -80,7 +80,18 @@ const WINFW_TIMEOUT_SECONDS: u32 = 5;
const LOGGING_CONTEXT: &[u8] = b"WinFw\0";
/// The Windows implementation for the firewall.
-pub struct Firewall(());
+pub struct Firewall {
+ /// If firewall rules should even if firewall module is shut down or dies.
+ ///
+ /// This should only very cautiously be turned off.
+ persist: bool,
+}
+
+impl Default for Firewall {
+ fn default() -> Self {
+ Self { persist: true }
+ }
+}
impl Firewall {
pub fn from_args(args: FirewallArguments) -> Result<Self, Error> {
@@ -102,7 +113,7 @@ impl Firewall {
};
log::trace!("Successfully initialized windows firewall module");
- Ok(Firewall(()))
+ Ok(Firewall::default())
}
fn initialize_blocked(
@@ -128,7 +139,7 @@ impl Firewall {
consume_and_log_hyperv_err("Add block-all Hyper-V filter", result);
});
- Ok(Firewall(()))
+ Ok(Firewall::default())
}
pub fn apply_policy(&mut self, policy: FirewallPolicy) -> Result<(), Error> {
@@ -408,6 +419,7 @@ impl Firewall {
impl Drop for Firewall {
fn drop(&mut self) {
+ // TODO: If
if unsafe {
WinFw_Deinitialize(WinFwCleanupPolicy::ContinueBlocking)
.into_result()
@@ -689,6 +701,7 @@ mod winfw {
pub enum WinFwCleanupPolicy {
ContinueBlocking = 0,
ResetFirewall = 1,
+ BlockingUntilReboot = 2,
}
ffi_error!(InitializationResult, Error::Initialization);
diff --git a/windows/winfw/src/winfw/winfw.cpp b/windows/winfw/src/winfw/winfw.cpp
index c862de4b5a..cd90befead 100644
--- a/windows/winfw/src/winfw/winfw.cpp
+++ b/windows/winfw/src/winfw/winfw.cpp
@@ -4,6 +4,7 @@
#include "objectpurger.h"
#include "mullvadobjects.h"
#include "rules/persistent/blockall.h"
+#include "rules/baseline/blockall.h"
#include "libwfp/ipnetwork.h"
#include <windows.h>
#include <libcommon/error.h>
@@ -167,11 +168,14 @@ WinFw_Deinitialize(WINFW_CLEANUP_POLICY cleanupPolicy)
delete g_fwContext;
g_fwContext = nullptr;
+ std::stringstream ss;
+ ss << "Deinitializing WinFw";
+ g_logSink(MULLVAD_LOG_LEVEL_WARNING, ss.str().c_str(), g_logSinkContext);
+
//
- // Continue blocking if this is what the caller requested
+ // Continue blocking with persistent rules if this is what the caller requested
// and if the current policy is "(net) blocked".
//
-
if (WINFW_CLEANUP_POLICY_CONTINUE_BLOCKING == cleanupPolicy
&& FwContext::Policy::Blocked == activePolicy)
{
@@ -182,6 +186,10 @@ WinFw_Deinitialize(WINFW_CLEANUP_POLICY cleanupPolicy)
rules::persistent::BlockAll blockAll;
+ std::stringstream ss;
+ ss << "Adding persistent block rules";
+ g_logSink(MULLVAD_LOG_LEVEL_WARNING, ss.str().c_str(), g_logSinkContext);
+
return sessionController->executeTransaction([&](SessionController &controller, wfp::FilterEngine &engine)
{
ObjectPurger::GetRemoveNonPersistentFunctor()(engine);
@@ -205,6 +213,50 @@ WinFw_Deinitialize(WINFW_CLEANUP_POLICY cleanupPolicy)
}
}
+ //
+ // Continue blocking with non-persistent rules if this is what the caller requested
+ // and if the current policy is "(net) blocked".
+ //
+ if (WINFW_CLEANUP_POLICY_BLOCK_UNTIL_REBOOT == cleanupPolicy
+ && FwContext::Policy::Blocked == activePolicy)
+ {
+ try
+ {
+ auto engine = wfp::FilterEngine::StandardSession(DEINITIALIZE_TIMEOUT);
+ auto sessionController = std::make_unique<SessionController>(std::move(engine));
+
+ rules::baseline::BlockAll blockAll;
+
+ std::stringstream ss;
+ ss << "Adding ephemeral block rules";
+ g_logSink(MULLVAD_LOG_LEVEL_WARNING, ss.str().c_str(), g_logSinkContext);
+
+ return sessionController->executeTransaction([&](SessionController &controller, wfp::FilterEngine &engine)
+ {
+ // Keep non-persistent filters intact, the intent is just to *not*
+ // persist any filters across a BFE restart, not muck around with
+ // any other filters. We will apply blocking filters anyway.
+ ObjectPurger::GetRemovePersistentFunctor()(engine);
+
+ return controller.addProvider(*MullvadObjects::Provider())
+ && controller.addSublayer(*MullvadObjects::SublayerBaseline())
+ && blockAll.apply(controller);
+ });
+ }
+ catch (std::exception & err)
+ {
+ if (nullptr != g_logSink)
+ {
+ g_logSink(MULLVAD_LOG_LEVEL_ERROR, err.what(), g_logSinkContext);
+ }
+ return false;
+ }
+ catch (...)
+ {
+ return false;
+ }
+ }
+
return WINFW_POLICY_STATUS_SUCCESS == WinFw_Reset();
}
diff --git a/windows/winfw/src/winfw/winfw.h b/windows/winfw/src/winfw/winfw.h
index ab2a136ceb..f40d835a95 100644
--- a/windows/winfw/src/winfw/winfw.h
+++ b/windows/winfw/src/winfw/winfw.h
@@ -127,6 +127,10 @@ enum WINFW_CLEANUP_POLICY : uint32_t
// Remove all objects that have been registered with WFP.
WINFW_CLEANUP_POLICY_RESET_FIREWALL = 1,
+
+ // Continue blocking if this is the active policy.
+ // Adds ephemeral blocking filters that are active until WinFw is shut down (??)
+ WINFW_CLEANUP_POLICY_BLOCK_UNTIL_REBOOT = 2,
};
//