Skip to content

Commit

Permalink
Merge pull request #883 from mheon/nftables
Browse files Browse the repository at this point in the history
Initial draft of nftables support
  • Loading branch information
openshift-merge-bot[bot] authored Jan 10, 2024
2 parents 86ce937 + db43e53 commit 5366e8f
Show file tree
Hide file tree
Showing 11 changed files with 2,248 additions and 71 deletions.
44 changes: 44 additions & 0 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ sha2 = "0.10.8"
netlink-packet-utils = "0.5.2"
netlink-packet-route = "0.18.1"
netlink-packet-core = "0.7.0"
nftables = "0.2.4"
fs2 = "0.4.3"
netlink-sys = "0.8.5"
tokio = { version = "1.35", features = ["rt", "rt-multi-thread", "signal", "fs"] }
Expand Down
26 changes: 26 additions & 0 deletions src/error/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,11 @@ pub enum NetavarkError {
DHCPProxy(tonic::Status),

List(NetavarkErrorList),

Nftables(nftables::helper::NftablesError),

SubnetParse(ipnet::AddrParseError),
AddrParse(std::net::AddrParseError),
}

/// Internal struct for JSON output
Expand Down Expand Up @@ -160,6 +165,9 @@ impl fmt::Display for NetavarkError {
Ok(())
}
}
NetavarkError::Nftables(e) => write!(f, "nftables error: {e}"),
NetavarkError::SubnetParse(e) => write!(f, "parsing IP subnet error: {e}"),
NetavarkError::AddrParse(e) => write!(f, "parsing IP address error: {e}"),
}
}
}
Expand Down Expand Up @@ -213,3 +221,21 @@ impl From<tonic::Status> for NetavarkError {
NetavarkError::DHCPProxy(err)
}
}

impl From<nftables::helper::NftablesError> for NetavarkError {
fn from(err: nftables::helper::NftablesError) -> Self {
NetavarkError::Nftables(err)
}
}

impl From<ipnet::AddrParseError> for NetavarkError {
fn from(err: ipnet::AddrParseError) -> Self {
NetavarkError::SubnetParse(err)
}
}

impl From<std::net::AddrParseError> for NetavarkError {
fn from(err: std::net::AddrParseError) -> Self {
NetavarkError::AddrParse(err)
}
}
69 changes: 68 additions & 1 deletion src/firewall/firewalld.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use crate::network::internal_types;
use crate::network::internal_types::{PortForwardConfig, TearDownNetwork, TeardownPortForward};
use crate::network::types::PortMapping;
use core::convert::TryFrom;
use log::{debug, info};
use log::{debug, info, warn};
use std::collections::HashMap;
use std::vec::Vec;
use zbus::{
Expand Down Expand Up @@ -679,3 +679,70 @@ fn make_port_tuple(port: &PortMapping, addr: &str) -> (String, String, String, S
to_return
}
}

/// Check if firewalld is running.
/// Not used within the firewalld driver, but by other drivers that may need to
/// interact with firewalld.
pub fn is_firewalld_running(conn: &Connection) -> bool {
conn.call_method(
Some("org.freedesktop.DBus"),
"/org/freedesktop/DBus",
Some("org.freedesktop.DBus"),
"GetNameOwner",
&"org.fedoraproject.FirewallD1",
)
.is_ok()
}

/// If possible, add a firewalld rule to allow traffic.
/// Ignore all errors, beyond possibly logging them.
/// Not used within the firewalld driver, but by other drivers that may need to
/// interact with firewalld.
pub fn add_firewalld_if_possible(net: &ipnet::IpNet) {
let conn = match Connection::system() {
Ok(conn) => conn,
Err(_) => return,
};
if !is_firewalld_running(&conn) {
return;
}
debug!("Adding firewalld rules for network {}", net.to_string());

match add_source_subnets_to_zone(&conn, "trusted", &[*net]) {
Ok(_) => {}
Err(e) => warn!(
"Error adding subnet {} from firewalld trusted zone: {}",
net.to_string(),
e
),
}
}

/// If possible, remove a firewalld rule to allow traffic.
/// Ignore all errors, beyond possibly logging them.
/// Not used within the firewalld driver, but by other drivers that may need to
/// interact with firewalld.
pub fn rm_firewalld_if_possible(net: &ipnet::IpNet) {
let conn = match Connection::system() {
Ok(conn) => conn,
Err(_) => return,
};
if !is_firewalld_running(&conn) {
return;
}
debug!("Removing firewalld rules for IPs {}", net.to_string());
match conn.call_method(
Some("org.fedoraproject.FirewallD1"),
"/org/fedoraproject/FirewallD1",
Some("org.fedoraproject.FirewallD1.zone"),
"removeSource",
&("trusted", net.to_string()),
) {
Ok(_) => {}
Err(e) => warn!(
"Error removing subnet {} from firewalld trusted zone: {}",
net.to_string(),
e
),
};
}
67 changes: 2 additions & 65 deletions src/firewall/iptables.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ use crate::network::internal_types::{
};
use iptables;
use iptables::IPTables;
use log::{debug, warn};
use zbus::blocking::Connection;

pub(crate) const MAX_HASH_SIZE: usize = 13;

Expand Down Expand Up @@ -64,7 +62,7 @@ impl firewall::FirewallDriver for IptablesDriver {

create_network_chains(chains)?;

add_firewalld_if_possible(&network);
firewalld::add_firewalld_if_possible(&network);
}
}
Ok(())
Expand Down Expand Up @@ -106,7 +104,7 @@ impl firewall::FirewallDriver for IptablesDriver {
}

if tear.complete_teardown {
rm_firewalld_if_possible(&network)
firewalld::rm_firewalld_if_possible(&network)
}
}
}
Expand Down Expand Up @@ -216,64 +214,3 @@ impl firewall::FirewallDriver for IptablesDriver {
Result::Ok(())
}
}

/// Check if firewalld is running
fn is_firewalld_running(conn: &Connection) -> bool {
conn.call_method(
Some("org.freedesktop.DBus"),
"/org/freedesktop/DBus",
Some("org.freedesktop.DBus"),
"GetNameOwner",
&"org.fedoraproject.FirewallD1",
)
.is_ok()
}

/// If possible, add a firewalld rule to allow traffic.
/// Ignore all errors, beyond possibly logging them.
fn add_firewalld_if_possible(net: &ipnet::IpNet) {
let conn = match Connection::system() {
Ok(conn) => conn,
Err(_) => return,
};
if !is_firewalld_running(&conn) {
return;
}
debug!("Adding firewalld rules for network {}", net.to_string());

match firewalld::add_source_subnets_to_zone(&conn, "trusted", &[*net]) {
Ok(_) => {}
Err(e) => warn!(
"Error adding subnet {} from firewalld trusted zone: {}",
net.to_string(),
e
),
}
}

// If possible, remove a firewalld rule to allow traffic.
// Ignore all errors, beyond possibly logging them.
fn rm_firewalld_if_possible(net: &ipnet::IpNet) {
let conn = match Connection::system() {
Ok(conn) => conn,
Err(_) => return,
};
if !is_firewalld_running(&conn) {
return;
}
debug!("Removing firewalld rules for IPs {}", net.to_string());
match conn.call_method(
Some("org.fedoraproject.FirewallD1"),
"/org/fedoraproject/FirewallD1",
Some("org.fedoraproject.FirewallD1.zone"),
"removeSource",
&("trusted", net.to_string()),
) {
Ok(_) => {}
Err(e) => warn!(
"Error removing subnet {} from firewalld trusted zone: {}",
net.to_string(),
e
),
};
}
5 changes: 2 additions & 3 deletions src/firewall/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use zbus::blocking::Connection;
pub mod firewalld;
pub mod fwnone;
pub mod iptables;
pub mod nft;
pub mod state;
mod varktables;

Expand Down Expand Up @@ -108,9 +109,7 @@ pub fn get_supported_firewall_driver(
}
FirewallImpl::Nftables => {
info!("Using nftables firewall driver");
Err(NetavarkError::msg(
"nftables support presently not available",
))
nft::new()
}
FirewallImpl::Fwnone => {
info!("Not using firewall");
Expand Down
Loading

0 comments on commit 5366e8f

Please sign in to comment.