Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM rust:1-slim as builder
FROM rust:1-slim AS builder

RUN apt-get update && apt-get -y install protobuf-compiler libnftnl-dev libmnl-dev
WORKDIR /app
Expand Down
12 changes: 6 additions & 6 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion proto
Submodule proto updated 1 files
+13 −1 core/proxy.proto
12 changes: 8 additions & 4 deletions src/enterprise/firewall/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use std::fs::{File, OpenOptions};
#[cfg(target_os = "linux")]
use nftnl::Batch;

use super::{FirewallError, FirewallRule, Policy};
use super::{FirewallError, FirewallRule, Policy, SnatBinding};

#[cfg(any(target_os = "freebsd", target_os = "macos", target_os = "netbsd"))]
const DEV_PF: &str = "/dev/pf";
Expand Down Expand Up @@ -42,11 +42,15 @@ pub(crate) trait FirewallManagementApi {
/// Clean up the firewall rules.
fn cleanup(&mut self) -> Result<(), FirewallError>;

/// Add fireall `rules`.
/// Add firewall rules.
fn add_rules(&mut self, rules: Vec<FirewallRule>) -> Result<(), FirewallError>;

/// Set masquerade status.
fn set_masquerade_status(&mut self, enabled: bool) -> Result<(), FirewallError>;
/// Setup Network Address Translation using POSTROUTING chain rules
fn setup_nat(
&mut self,
masquerade_enabled: bool,
snat_bindings: &[SnatBinding],
) -> Result<(), FirewallError>;

/// Begin rule transaction.
fn begin(&mut self) -> Result<(), FirewallError>;
Expand Down
34 changes: 0 additions & 34 deletions src/enterprise/firewall/dummy/mod.rs

This file was deleted.

43 changes: 40 additions & 3 deletions src/enterprise/firewall/mod.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
pub mod api;
#[cfg(test)]
mod dummy;
mod iprange;
#[cfg(all(not(test), target_os = "linux"))]
#[cfg(target_os = "linux")]
mod nftables;
#[cfg(any(target_os = "freebsd", target_os = "macos", target_os = "netbsd"))]
mod packetfilter;
Expand Down Expand Up @@ -204,10 +202,19 @@ pub(crate) struct FirewallRule {
pub ipv4: bool, // FIXME: is that really needed?
}

#[derive(Debug, Clone, PartialEq)]
pub(crate) struct SnatBinding {
pub id: i64,
pub source_addrs: Vec<Address>,
pub public_ip: IpAddr,
pub comment: Option<String>,
}

#[derive(Debug, Clone, PartialEq)]
pub(crate) struct FirewallConfig {
pub rules: Vec<FirewallRule>,
pub default_policy: Policy,
pub snat_bindings: Vec<SnatBinding>,
}

impl FirewallConfig {
Expand All @@ -216,6 +223,7 @@ impl FirewallConfig {
) -> Result<Self, FirewallError> {
debug!("Parsing following received firewall proto configuration: {config:?}");
let mut rules = Vec::new();
let mut snat_bindings = Vec::new();
let default_policy =
Policy::from_proto(config.default_policy.try_into().map_err(|err| {
FirewallError::TypeConversionError(format!("Invalid default policy: {err:?}"))
Expand All @@ -224,6 +232,7 @@ impl FirewallConfig {
"Default firewall policy defined: {default_policy:?}. Proceeding to parsing rules..."
);

// parse received firewall rules
for rule in config.rules {
debug!("Parsing the following received Defguard ACL proto rule: {rule:?}");
let mut source_addrs = Vec::new();
Expand Down Expand Up @@ -287,9 +296,37 @@ impl FirewallConfig {
rules.push(firewall_rule);
}

// parse received SNAT bindings
for binding in config.snat_bindings {
debug!("Parsing the following received SNAT binding proto: {binding:?}");

let mut source_addrs = Vec::new();
for addr in binding.source_addrs {
source_addrs.push(Address::from_proto(&addr)?);
}

let public_ip = binding.public_ip.parse().map_err(|err| {
FirewallError::TypeConversionError(format!(
"Invalid public IP address format: {err}"
))
})?;

let snat_binding = SnatBinding {
id: binding.id,
source_addrs,
public_ip,
comment: binding.comment,
};

debug!("Parsed received proto SNAT binding as: {snat_binding:?}");

snat_bindings.push(snat_binding);
}

Ok(Self {
rules,
default_policy,
snat_bindings,
})
}
}
Expand Down
29 changes: 11 additions & 18 deletions src/enterprise/firewall/nftables/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ use std::sync::atomic::{AtomicU32, Ordering};

use netfilter::{
allow_established_traffic, apply_filter_rules, drop_table, ignore_unrelated_traffic,
init_firewall, send_batch, set_masq,
init_firewall, send_batch, set_nat_rules,
};
use nftnl::Batch;

use super::{
api::{FirewallApi, FirewallManagementApi},
Address, FirewallError, FirewallRule, Policy, Port, Protocol,
Address, FirewallError, FirewallRule, Policy, Port, Protocol, SnatBinding,
};

static SET_ID_COUNTER: AtomicU32 = AtomicU32::new(0);
Expand Down Expand Up @@ -194,27 +194,20 @@ impl FirewallManagementApi for FirewallApi {
Ok(())
}

// Allows for changing the default policy of the firewall.
// fn set_firewall_default_policy(&mut self, policy: Policy) -> Result<(), FirewallError> {
// debug!("Setting default firewall policy to: {policy:?}");
// if let Some(batch) = &mut self.batch {
// set_default_policy(policy, batch, &self.ifname)?;
// } else {
// return Err(FirewallError::TransactionNotStarted);
// }
// debug!("Set firewall default policy to {policy:?}");
// Ok(())
// }
fn setup_nat(
&mut self,
masquerade_enabled: bool,
snat_bindings: &[SnatBinding],
) -> Result<(), FirewallError> {
debug!("Setting up POSTROUTING chain rules with masquerade status: {masquerade_enabled} and SNAT bindings: {snat_bindings:?}");

/// Allows for changing the masquerade status of the firewall.
fn set_masquerade_status(&mut self, enabled: bool) -> Result<(), FirewallError> {
debug!("Setting masquerade status to: {enabled:?}");
if let Some(batch) = &mut self.batch {
set_masq(&self.ifname, enabled, batch)?;
set_nat_rules(batch, &self.ifname, masquerade_enabled, snat_bindings)?;
} else {
return Err(FirewallError::TransactionNotStarted);
}
debug!("Set masquerade status to: {enabled:?}");

debug!("Finished POSTROUTING chain rules setup");
Ok(())
}

Expand Down
Loading