diff --git a/src/main.rs b/src/main.rs index 4591c6d..fd5d1a0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -57,7 +57,7 @@ pub struct Args { #[derive(Subcommand, Clone, Debug)] pub enum Command { /// Fetch a reflected IP address and update A and AAAA entries in DNS. - Run, + Run(Run), /// List all A and AAAA entries in each zone in the config. List(List), } @@ -107,6 +107,13 @@ impl Display for Color { } } +#[derive(Parser, Clone, Debug)] +pub struct Run { + /// The directory to store cache files. + #[clap(long)] + cache_dir: Option, +} + fn main() -> ExitCode { let runtime = Runtime::new().unwrap(); let result = runtime.block_on(real_main()); @@ -149,12 +156,12 @@ async fn real_main() -> Result<()> { let config = load_config(args.config_file).context("Failed to find a suitable config file")?; match args.cmd { - Command::Run => handle_run(config).await, + Command::Run(run) => handle_run(config, run).await, Command::List(list) => handle_list(config, list).await, } } -async fn handle_run(conf: Config) -> Result<()> { +async fn handle_run(conf: Config, run: Run) -> Result<()> { let ipv4 = if let Some(addr_to_req) = conf.ip_reflector.ipv4 { let ip = get_ipv4(addr_to_req) .await @@ -176,7 +183,7 @@ async fn handle_run(conf: Config) -> Result<()> { None }; - let ip_cache_path = ip_cache_path().context("while getting the ip cache path")?; + let ip_cache_path = ip_cache_path(run.cache_dir).context("while getting the ip cache path")?; let mut cache_file = load_ip_cache(&ip_cache_path).context("while loading the ip cache")?; let mut rate_limit = time::interval(Duration::from_millis(250)); @@ -293,8 +300,10 @@ fn load_ip_cache + Debug>(path: P) -> Result { }) } -fn ip_cache_path() -> Result { - dirs::cache_dir() +#[instrument(level = "debug", ret)] +fn ip_cache_path(cache_dir: Option) -> Result { + cache_dir + .or(dirs::cache_dir()) .context("Failed to determine cache directory") .map(|path| path.join("cloudflare-ddns.cache")) } diff --git a/systemd/cloudflare-ddns.service b/systemd/cloudflare-ddns.service index 89547f8..b8c45a7 100644 --- a/systemd/cloudflare-ddns.service +++ b/systemd/cloudflare-ddns.service @@ -5,13 +5,16 @@ After=network-online.target [Service] Type=oneshot -ExecStart=/usr/bin/cloudflare-ddns run +ExecStart=/usr/bin/cloudflare-ddns run --config-file "${CREDENTIALS_DIRECTORY}/cloudflare-ddns.toml" --cache-dir "${CACHE_DIRECTORY}" + +# Please modify the path after the : to point to a custom config location if you'd like +LoadCredential=cloudflare-ddns.toml:/etc/cloudflare-ddns.toml + +# Security Hardening +# Run `systemd-analyze security cloudflare-ddns` for recommendations -# Security NoNewPrivileges=true - -# Sandboxing config -ProtectSystem=true +ProtectSystem=strict PrivateTmp=true PrivateDevices=true ProtectHostname=true @@ -25,6 +28,21 @@ LockPersonality=true MemoryDenyWriteExecute=true RestrictRealtime=true RestrictSUIDSGID=true +CapabilityBoundingSet= +SystemCallArchitectures=native +SystemCallFilter=@system-service +SystemCallFilter=~@privileged +SystemCallFilter=~@resources +ProtectProc=invisible +ProcSubset=pid +RestrictAddressFamilies=AF_INET AF_INET6 +UMask=066 +DynamicUser=true +CacheDirectory=cloudflare-ddns +PrivateUsers=true +ProtectHome=true +# Refuse to execute any other binary +ExecPaths=/usr/bin/cloudflare-ddns [Install] WantedBy=multi-user.target \ No newline at end of file