Skip to content

Commit

Permalink
Update the nftables crate dependency
Browse files Browse the repository at this point in the history
  • Loading branch information
mbuesch committed Jan 5, 2025
1 parent 18c6ff7 commit d3c5e66
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 49 deletions.
31 changes: 25 additions & 6 deletions Cargo.lock

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

3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -56,4 +56,7 @@ debug-assertions = false
overflow-checks = true
codegen-units = 1

[patch.crates-io]
nftables = { git = "https://github.com/mbuesch/nftables-rs.git", branch = "helpers-asref-osstr" }

# vim: ts=4 sw=4 expandtab
82 changes: 39 additions & 43 deletions letmeinfwd/src/firewall/nftables.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@ use letmein_conf::Config;
use nftables::{
batch::Batch,
expr::{Expression, NamedExpression, Payload, PayloadField},
helper::{apply_ruleset, get_current_ruleset},
helper::{apply_ruleset_with_args, get_current_ruleset_with_args, DEFAULT_ARGS},
schema::{Chain, FlushObject, NfCmd, NfListObject, NfObject, Rule},
stmt::{Match, Operator, Statement},
types::NfFamily,
};
use std::{fmt::Write as _, net::IpAddr};
use std::{borrow::Cow, fmt::Write as _, net::IpAddr};

struct NftNames<'a> {
family: NfFamily,
Expand Down Expand Up @@ -59,7 +59,7 @@ impl<'a> NftNames<'a> {
}

/// Create an nftables IP source address match statement.
fn statement_match_saddr(family: NfFamily, addr: IpAddr) -> ah::Result<Statement> {
fn statement_match_saddr<'a>(family: NfFamily, addr: IpAddr) -> ah::Result<Statement<'a>> {
let (protocol, addr) = match addr {
IpAddr::V4(addr) => match family {
NfFamily::INet | NfFamily::IP => ("ip", addr.to_string()),
Expand Down Expand Up @@ -88,26 +88,26 @@ fn statement_match_saddr(family: NfFamily, addr: IpAddr) -> ah::Result<Statement
Ok(Statement::Match(Match {
left: Expression::Named(NamedExpression::Payload(Payload::PayloadField(
PayloadField {
protocol: protocol.to_string(),
field: "saddr".to_string(),
protocol: Cow::Borrowed(protocol),
field: Cow::Borrowed("saddr"),
},
))),
right: Expression::String(addr),
right: Expression::String(Cow::Owned(addr)),
op: Operator::EQ,
}))
}

/// Create an nftables port match statement.
fn statement_match_dport(port: SingleLeasePort) -> Statement {
fn statement_match_dport<'a>(port: SingleLeasePort) -> Statement<'a> {
let (protocol, port) = match port {
SingleLeasePort::Tcp(port) => ("tcp".to_string(), port),
SingleLeasePort::Udp(port) => ("udp".to_string(), port),
SingleLeasePort::Tcp(port) => ("tcp", port),
SingleLeasePort::Udp(port) => ("udp", port),
};
Statement::Match(Match {
left: Expression::Named(NamedExpression::Payload(Payload::PayloadField(
PayloadField {
protocol,
field: "dport".to_string(),
protocol: Cow::Borrowed(protocol),
field: Cow::Borrowed("dport"),
},
))),
right: Expression::Number(port.into()),
Expand All @@ -116,7 +116,7 @@ fn statement_match_dport(port: SingleLeasePort) -> Statement {
}

/// Create an nftables `accept` statement.
fn statement_accept() -> Statement {
fn statement_accept<'a>() -> Statement<'a> {
Statement::Accept(None)
}

Expand Down Expand Up @@ -149,18 +149,18 @@ fn gen_add_lease_cmd(
expr.push(statement_accept());
let mut rule = Rule {
family: names.family,
table: names.table.to_string(),
chain: names.chain_input.to_string(),
expr,
table: Cow::Borrowed(names.table),
chain: Cow::Borrowed(names.chain_input),
expr: Cow::Owned(expr),
..Default::default()
};
rule.comment = Some(gen_rule_comment(addr, port)?);
rule.comment = Some(Cow::Owned(gen_rule_comment(addr, port)?));
Ok(NfCmd::Add(NfListObject::Rule(rule)))
}

/// Generate the nftables add-rule commands for this lease.
/// These commands will open the port(s) for the IP address.
fn gen_add_lease_cmds(conf: &Config, lease: &Lease) -> ah::Result<Vec<NfCmd>> {
fn gen_add_lease_cmds<'a>(conf: &'a Config, lease: &Lease) -> ah::Result<Vec<NfCmd<'a>>> {
let mut cmds = Vec::with_capacity(2);
let addr = Some(lease.addr());
match lease.port() {
Expand All @@ -181,20 +181,16 @@ fn gen_add_lease_cmds(conf: &Config, lease: &Lease) -> ah::Result<Vec<NfCmd>> {
Ok(cmds)
}

struct ListedRuleset {
objs: Vec<NfObject>,
struct ListedRuleset<'a> {
objs: Cow<'a, [NfObject<'static>]>,
}

impl ListedRuleset {
impl ListedRuleset<'_> {
/// Get the active ruleset from the kernel.
pub fn from_kernel(conf: &Config) -> ah::Result<Self> {
let exe = conf
.nft_exe()
.to_str()
.context("letmeind.conf nftables exe")?;
let ruleset = get_current_ruleset(
Some(exe), // program
None, // args
let ruleset = get_current_ruleset_with_args(
Some(conf.nft_exe()), // program
DEFAULT_ARGS, // args
)?;
Ok(Self {
objs: ruleset.objects,
Expand All @@ -212,9 +208,9 @@ impl ListedRuleset {
port: SingleLeasePort,
) -> ah::Result<u32> {
let comment = gen_rule_comment(Some(addr), port)?;
for obj in &self.objs {
for obj in &*self.objs {
if let NfObject::ListObject(obj) = obj {
match &**obj {
match obj {
NfListObject::Rule(Rule {
family: rule_family,
table: rule_table,
Expand All @@ -240,17 +236,21 @@ impl ListedRuleset {

/// Generate nftables delete-rules for this lease.
/// These rules will close the ports for the IP address.
pub fn gen_delete_lease_cmds(&self, conf: &Config, lease: &Lease) -> ah::Result<Vec<NfCmd>> {
pub fn gen_delete_lease_cmds<'a>(
&self,
conf: &'a Config,
lease: &Lease,
) -> ah::Result<Vec<NfCmd<'a>>> {
let mut cmds = Vec::with_capacity(2);
let names = NftNames::get(conf).context("Read configuration")?;
let addr = lease.addr();

let new_rule = |port: SingleLeasePort| -> ah::Result<NfCmd> {
let mut rule = Rule {
family: names.family,
table: names.table.to_string(),
chain: names.chain_input.to_string(),
expr: vec![],
table: Cow::Borrowed(names.table),
chain: Cow::Borrowed(names.chain_input),
expr: Cow::Owned(vec![]),
..Default::default()
};
rule.handle =
Expand Down Expand Up @@ -326,15 +326,11 @@ impl NftFirewall {

/// Apply a rules batch to the kernel.
fn nftables_apply_batch(&self, conf: &Config, batch: Batch) -> ah::Result<()> {
let exe = conf
.nft_exe()
.to_str()
.context("letmeind.conf nftables exe")?;
let ruleset = batch.to_nftables();
apply_ruleset(
&ruleset, // rules
Some(exe), // program
None, // args
apply_ruleset_with_args(
&ruleset, // rules
Some(conf.nft_exe()), // program
DEFAULT_ARGS, // args
)
.context("Apply nftables")?;
Ok(())
Expand All @@ -349,8 +345,8 @@ impl NftFirewall {
// Remove all rules from our chain.
batch.add_cmd(NfCmd::Flush(FlushObject::Chain(Chain {
family: names.family,
table: names.table.to_string(),
name: names.chain_input.to_string(),
table: Cow::Borrowed(names.table),
name: Cow::Borrowed(names.chain_input),
..Default::default()
})));
if conf.debug() {
Expand Down

0 comments on commit d3c5e66

Please sign in to comment.