diff options
Diffstat (limited to 'src/fw_actor.rs')
-rw-r--r-- | src/fw_actor.rs | 75 |
1 files changed, 75 insertions, 0 deletions
diff --git a/src/fw_actor.rs b/src/fw_actor.rs new file mode 100644 index 0000000..b5e4c7e --- /dev/null +++ b/src/fw_actor.rs @@ -0,0 +1,75 @@ +use anyhow::Result; +use tokio::{ + select, + sync::watch, + time::{ + self, + Duration +}}; +use log::*; + +use iptables; +use crate::messages; +use crate::fw; +use std::collections::HashSet; + +pub struct FirewallActor { + pub ipt: iptables::IPTables, + rx_ports: watch::Receiver<messages::PublicExposedPorts>, + last_ports: messages::PublicExposedPorts, + refresh: Duration +} + +impl FirewallActor { + pub async fn new(_refresh: Duration, rxp: &watch::Receiver<messages::PublicExposedPorts>) -> Result<Self> { + let ctx = Self { + ipt: iptables::new(false)?, + rx_ports: rxp.clone(), + last_ports: messages::PublicExposedPorts::new(), + refresh: _refresh, + }; + + fw::setup(&ctx.ipt)?; + + return Ok(ctx); + } + + pub async fn listen(&mut self) -> Result<()> { + let mut interval = time::interval(self.refresh); + loop { + // 1. Wait for an event + let new_ports = select! { + Some(ports) = self.rx_ports.recv() => Some(ports), + _ = interval.tick() => None, + else => return Ok(()) // Sender dropped, terminate loop. + }; + + // 2. Update last ports if needed + if let Some(p) = new_ports { self.last_ports = p; } + + // 3. Update firewall rules + match self.do_fw_update().await { + Ok(()) => debug!("Successfully updated firewall rules"), + Err(e) => error!("An error occured while updating firewall rules. {}", e), + } + } + } + + pub async fn do_fw_update(&self) -> Result<()> { + let curr_opened_ports = fw::get_opened_ports(&self.ipt)?; + + let diff_tcp = self.last_ports.tcp_ports.difference(&curr_opened_ports.tcp_ports).copied().collect::<HashSet<u16>>(); + let diff_udp = self.last_ports.udp_ports.difference(&curr_opened_ports.udp_ports).copied().collect::<HashSet<u16>>(); + + let ports_to_open = messages::PublicExposedPorts { + tcp_ports: diff_tcp, + udp_ports: diff_udp + }; + + fw::open_ports(&self.ipt, ports_to_open)?; + + return Ok(()); + } + +} + |