diff options
| author | Emīls Piņķis <emils@mullvad.net> | 2022-09-01 22:56:21 +0200 |
|---|---|---|
| committer | Emīls Piņķis <emils@mullvad.net> | 2022-09-12 17:29:29 +0200 |
| commit | 9598d2efd327fb95d810ce64519f2474b5a7cb46 (patch) | |
| tree | 09ffb76eff87084eebe9eda65c1d57bcbd09f8bd | |
| parent | c5d2534ba7724c2d254f98c295b17a2d91a08f55 (diff) | |
| download | mullvadvpn-9598d2efd327fb95d810ce64519f2474b5a7cb46.tar.xz mullvadvpn-9598d2efd327fb95d810ce64519f2474b5a7cb46.zip | |
Add argument to initialize firewall to a blocking state
| -rw-r--r-- | mullvad-daemon/src/cli.rs | 15 | ||||
| -rw-r--r-- | mullvad-daemon/src/early_boot_firewall.rs | 43 | ||||
| -rw-r--r-- | mullvad-daemon/src/main.rs | 29 |
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 } |
