aboutsummaryrefslogtreecommitdiff
path: root/src/fw_actor.rs
diff options
context:
space:
mode:
authordarkgallium <florian+git@aloneinthedark.xyz>2020-05-24 20:40:49 +0200
committerdarkgallium <florian+git@aloneinthedark.xyz>2020-05-24 20:40:49 +0200
commitd2ae084fc1be2671c2a301e689c8632576922785 (patch)
treefb340afde570ffacf42f9349df135624fcb4178f /src/fw_actor.rs
parenta2d25820985b04f15f3c0f38cabfd7130124d943 (diff)
downloaddiplonat-d2ae084fc1be2671c2a301e689c8632576922785.tar.gz
diplonat-d2ae084fc1be2671c2a301e689c8632576922785.zip
add actor for firewall & massive refactor
Diffstat (limited to 'src/fw_actor.rs')
-rw-r--r--src/fw_actor.rs80
1 files changed, 80 insertions, 0 deletions
diff --git a/src/fw_actor.rs b/src/fw_actor.rs
new file mode 100644
index 0000000..9bc6610
--- /dev/null
+++ b/src/fw_actor.rs
@@ -0,0 +1,80 @@
+use igd::aio::*;
+use igd::PortMappingProtocol;
+use std::net::SocketAddrV4;
+use log::*;
+use anyhow::{Result, Context};
+use tokio::{
+ select,
+ sync::watch,
+ time::{
+ self,
+ Duration
+}};
+
+use iptables;
+use crate::messages;
+use crate::fw;
+use std::collections::HashSet;
+
+pub struct FirewallActor {
+ 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).unwrap(),
+ rx_ports: rxp.clone(),
+ last_ports: messages::PublicExposedPorts::new(),
+ refresh: _refresh,
+ };
+
+ fw::setup(&ctx.ipt).expect("iptables setup failed");
+
+ 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).unwrap();
+
+ 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).unwrap();
+
+ return Ok(());
+ }
+
+}