summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorEmīls Piņķis <emils@mullvad.net>2022-09-01 22:56:21 +0200
committerEmīls Piņķis <emils@mullvad.net>2022-09-12 17:29:29 +0200
commit9598d2efd327fb95d810ce64519f2474b5a7cb46 (patch)
tree09ffb76eff87084eebe9eda65c1d57bcbd09f8bd
parentc5d2534ba7724c2d254f98c295b17a2d91a08f55 (diff)
downloadmullvadvpn-9598d2efd327fb95d810ce64519f2474b5a7cb46.tar.xz
mullvadvpn-9598d2efd327fb95d810ce64519f2474b5a7cb46.zip
Add argument to initialize firewall to a blocking state
-rw-r--r--mullvad-daemon/src/cli.rs15
-rw-r--r--mullvad-daemon/src/early_boot_firewall.rs43
-rw-r--r--mullvad-daemon/src/main.rs29
3 files changed, 85 insertions, 2 deletions
diff --git a/mullvad-daemon/src/cli.rs b/mullvad-daemon/src/cli.rs
index 578bf74dff..e7e332c942 100644
--- a/mullvad-daemon/src/cli.rs
+++ b/mullvad-daemon/src/cli.rs
@@ -10,6 +10,8 @@ pub struct Config {
pub run_as_service: bool,
pub register_service: bool,
pub restart_service: bool,
+ #[cfg(target_os = "linux")]
+ pub initialize_firewall_and_exit: bool,
}
pub fn get_config() -> &'static Config {
@@ -31,11 +33,16 @@ pub fn create_config() -> Config {
let log_to_file = !matches.is_present("disable_log_to_file");
let log_stdout_timestamps = !matches.is_present("disable_stdout_timestamps");
+ #[cfg(target_os = "linux")]
+ let initialize_firewall_and_exit =
+ cfg!(target_os = "linux") && matches.is_present("initialize-early-boot-firewall");
let run_as_service = cfg!(windows) && matches.is_present("run_as_service");
let register_service = cfg!(windows) && matches.is_present("register_service");
let restart_service = cfg!(windows) && matches.is_present("restart_service");
Config {
+ #[cfg(target_os = "linux")]
+ initialize_firewall_and_exit,
log_level,
log_to_file,
log_stdout_timestamps,
@@ -106,5 +113,13 @@ fn create_app() -> App<'static> {
.help("Restarts the existing system service"),
)
}
+
+ if cfg!(target_os = "linux") {
+ app = app.arg(
+ Arg::new("initialize-early-boot-firewall")
+ .long("initialize-early-boot-firewall")
+ .help("Initialize firewall to be used during early boot and exit"),
+ )
+ }
app
}
diff --git a/mullvad-daemon/src/early_boot_firewall.rs b/mullvad-daemon/src/early_boot_firewall.rs
new file mode 100644
index 0000000000..5a852abda7
--- /dev/null
+++ b/mullvad-daemon/src/early_boot_firewall.rs
@@ -0,0 +1,43 @@
+use mullvad_daemon::settings::{self, SettingsPersister};
+use talpid_core::firewall::{self, Firewall, FirewallPolicy};
+
+#[derive(err_derive::Error, Debug)]
+pub enum Error {
+ #[error(display = "Failed to initialize firewall")]
+ Firewall(#[error(source)] firewall::Error),
+
+ #[error(display = "Failed to get settings path")]
+ Path(#[error(source)] mullvad_paths::Error),
+
+ #[error(display = "Failed to get settings")]
+ Settings(#[error(source)] settings::Error),
+}
+
+pub async fn initialize_firewall() -> Result<(), Error> {
+ let mut firewall = Firewall::new()?;
+ let allow_lan = get_allow_lan().await.unwrap_or_else(|err| {
+ log::info!(
+ "Not allowing LAN traffic due to failing to read settings: {}",
+ err
+ );
+ false
+ });
+ let policy = FirewallPolicy::Blocked {
+ allow_lan,
+ allowed_endpoint: talpid_types::net::AllowedEndpoint {
+ endpoint: talpid_types::net::Endpoint {
+ address: (std::net::Ipv4Addr::LOCALHOST, 0).into(),
+ protocol: talpid_types::net::TransportProtocol::Tcp,
+ },
+ },
+ };
+ log::info!("Applying firewall policy {policy}");
+ firewall.apply_policy(policy)?;
+ Ok(())
+}
+
+async fn get_allow_lan() -> Result<bool, Error> {
+ let path = mullvad_paths::settings_dir()?;
+ let settings = SettingsPersister::load(&path).await;
+ Ok(settings.allow_lan)
+}
diff --git a/mullvad-daemon/src/main.rs b/mullvad-daemon/src/main.rs
index f11bb30d98..8991ed8daf 100644
--- a/mullvad-daemon/src/main.rs
+++ b/mullvad-daemon/src/main.rs
@@ -11,12 +11,16 @@ use std::{path::PathBuf, thread, time::Duration};
use talpid_types::ErrorExt;
mod cli;
+#[cfg(target_os = "linux")]
+mod early_boot_firewall;
mod exception_logging;
mod shutdown;
#[cfg(windows)]
mod system_service;
const DAEMON_LOG_FILENAME: &str = "daemon.log";
+#[cfg(target_os = "linux")]
+const EARLY_BOOT_LOG_FILENAME: &str = "early-boot-fw.log";
fn main() {
let config = cli::get_config();
@@ -45,7 +49,18 @@ fn main() {
fn init_logging(config: &cli::Config) -> Result<Option<PathBuf>, String> {
let log_dir = get_log_dir(config)?;
- let log_file = log_dir.as_ref().map(|dir| dir.join(DAEMON_LOG_FILENAME));
+
+ let log_file_name = if cfg!(target_os = "linux") {
+ if config.initialize_firewall_and_exit {
+ EARLY_BOOT_LOG_FILENAME
+ } else {
+ DAEMON_LOG_FILENAME
+ }
+ } else {
+ DAEMON_LOG_FILENAME
+ };
+
+ let log_file = log_dir.as_ref().map(|dir| dir.join(log_file_name));
logging::init_logger(
config.log_level,
@@ -95,7 +110,17 @@ async fn run_platform(config: &cli::Config, log_dir: Option<PathBuf>) -> Result<
}
}
-#[cfg(not(windows))]
+#[cfg(target_os = "linux")]
+async fn run_platform(config: &cli::Config, log_dir: Option<PathBuf>) -> Result<(), String> {
+ if config.initialize_firewall_and_exit {
+ return crate::early_boot_firewall::initialize_firewall()
+ .await
+ .map_err(|err| format!("{}", err));
+ }
+ run_standalone(log_dir).await
+}
+
+#[cfg(not(any(windows, target_os = "linux")))]
async fn run_platform(_config: &cli::Config, log_dir: Option<PathBuf>) -> Result<(), String> {
run_standalone(log_dir).await
}