From 968961d7f20a2c123ea12a6d7af0beb4578e5337 Mon Sep 17 00:00:00 2001 From: Eric Long Date: Fri, 15 Nov 2024 15:55:26 +0800 Subject: [PATCH] Use own nftables fork --- Cargo.lock | 36 +++++++------------ Cargo.toml | 7 ++-- src/kernel/linux/mod.rs | 2 +- src/kernel/linux/nft.rs | 78 ++++++++++++++++++++++------------------- 4 files changed, 58 insertions(+), 65 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ccfa0db..a2b9500 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -232,7 +232,6 @@ dependencies = [ "libc", "log", "nftables", - "nftables-async", "num", "pin-project", "postcard", @@ -243,7 +242,7 @@ dependencies = [ "smallvec", "strum", "test-case", - "thiserror 2.0.0", + "thiserror 2.0.3", "tokio", "tokio-util", ] @@ -484,25 +483,14 @@ dependencies = [ [[package]] name = "nftables" version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c7288de9ee11086e792d89ee45adf490a5a778ff0fddc7e086ce1521989e657" +source = "git+https://github.com/hack3ric/rust-nftables?branch=for-flow#ef9d1929ca90e7ba5cfbf21eef312475a2f79b2c" dependencies = [ "serde", "serde_json", "serde_path_to_error", "strum", "strum_macros", - "thiserror 1.0.68", -] - -[[package]] -name = "nftables-async" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6041770939ebc822b255f1dd14540b5e88b9aa9f71aedb57ded7ebe8856bfffd" -dependencies = [ - "nftables", - "serde_json", + "thiserror 2.0.3", "tokio", ] @@ -710,18 +698,18 @@ checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "serde" -version = "1.0.214" +version = "1.0.215" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f55c3193aca71c12ad7890f1785d2b73e1b9f63a0bbc353c08ef26fe03fc56b5" +checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.214" +version = "1.0.215" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de523f781f095e28fa605cdce0f8307e451cc0fd14e2eb4cd2e98a355b147766" +checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" dependencies = [ "proc-macro2", "quote", @@ -870,11 +858,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.0" +version = "2.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15291287e9bff1bc6f9ff3409ed9af665bec7a5fc8ac079ea96be07bca0e2668" +checksum = "c006c85c7651b3cf2ada4584faa36773bd07bac24acfb39f3c431b36d7e667aa" dependencies = [ - "thiserror-impl 2.0.0", + "thiserror-impl 2.0.3", ] [[package]] @@ -890,9 +878,9 @@ dependencies = [ [[package]] name = "thiserror-impl" -version = "2.0.0" +version = "2.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22efd00f33f93fa62848a7cab956c3d38c8d43095efda1decfc2b3a5dc0b8972" +checksum = "f077553d607adc1caf65430528a576c757a71ed73944b66ebb58ef2bbd243568" dependencies = [ "proc-macro2", "quote", diff --git a/Cargo.toml b/Cargo.toml index 814027e..ab072bb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,7 +20,7 @@ postcard = { version = "1.0.10", default-features = false, features = [ "use-std", ] } replace_with = "0.1.7" -serde = { version = "1.0.210", features = ["derive"] } +serde = { version = "1.0.215", features = ["derive"] } serde_json = "1.0.132" smallvec = { version = "1.13.2", features = [ "union", @@ -42,8 +42,9 @@ tokio = { version = "1.38.0", features = [ tokio-util = "0.7.11" [target.'cfg(target_os = "linux")'.dependencies] -nftables = "0.5.0" -nftables-async = "0.1.1" +nftables = { git = "https://github.com/hack3ric/rust-nftables", branch = "for-flow", features = [ + "tokio", +] } rtnetlink = { git = "https://github.com/hack3ric/rust-rtnetlink", branch = "for-flow" } [dev-dependencies] diff --git a/src/kernel/linux/mod.rs b/src/kernel/linux/mod.rs index 886383c..d5352b7 100644 --- a/src/kernel/linux/mod.rs +++ b/src/kernel/linux/mod.rs @@ -65,7 +65,7 @@ impl Kernel for Linux { let nftables = NftablesReq { objects: rules .into_iter() - .map(|x| NfObject::CmdObject(NfCmd::Add(self.nft.make_new_rule(x, Some(handle))))) + .map(|x| NfObject::CmdObject(NfCmd::Add(self.nft.make_new_rule(x.into(), Some(handle))))) .collect(), }; diff --git a/src/kernel/linux/nft.rs b/src/kernel/linux/nft.rs index 9a8434f..6b26e7d 100644 --- a/src/kernel/linux/nft.rs +++ b/src/kernel/linux/nft.rs @@ -6,7 +6,7 @@ use crate::net::{Afi, IpPrefix}; use crate::util::{Intersect, TruthTable}; use nftables::batch::Batch; use nftables::expr::Expression::{Number as NUM, String as STRING}; -use nftables_async::{apply_ruleset, get_current_ruleset_raw}; +use nftables::helper::{apply_ruleset_async, get_current_ruleset_raw_async}; use nftables::schema::Nftables as NftablesReq; use nftables::{expr, schema, stmt, types}; use num::Integer; @@ -40,19 +40,19 @@ impl Nftables { let mut batch = Batch::new(); batch.add(schema::NfListObject::Table(schema::Table { family: types::NfFamily::INet, - name: table.to_string(), + name: table.clone(), ..Default::default() })); batch.add(schema::NfListObject::Chain(schema::Chain { family: types::NfFamily::INet, - table: table.to_string(), - name: chain.to_string(), + table: table.clone(), + name: chain.clone(), _type: hooked.then_some(types::NfChainType::Filter), hook: hooked.then_some(types::NfHook::Input), prio: hooked.then_some(priority), ..Default::default() })); - apply_ruleset(&batch.to_nftables(), None, None).await?; + apply_ruleset_async(&batch.to_nftables(), None, None).await?; Ok(Self { table, chain, armed: true }) } @@ -61,31 +61,35 @@ impl Nftables { let mut batch = Batch::new(); batch.delete(schema::NfListObject::Chain(schema::Chain { family: types::NfFamily::INet, - table: self.table.to_string(), - name: self.chain.to_string(), + table: self.table.clone(), + name: self.chain.clone(), ..Default::default() })); - Ok(apply_ruleset(&batch.to_nftables(), None, None).await?) + Ok(apply_ruleset_async(&batch.to_nftables(), None, None).await?) } fn exit_sync(&self) -> Result<()> { let mut batch = Batch::new(); batch.delete(schema::NfListObject::Chain(schema::Chain { family: types::NfFamily::INet, - table: self.table.to_string(), - name: self.chain.to_string(), + table: self.table.clone(), + name: self.chain.clone(), ..Default::default() })); Ok(nftables::helper::apply_ruleset(&batch.to_nftables(), None, None)?) } - pub fn make_new_rule(&self, stmts: Vec, comment: Option) -> schema::NfListObject { + pub fn make_new_rule( + &self, + stmts: Cow<'static, [stmt::Statement]>, + comment: Option, + ) -> schema::NfListObject { schema::NfListObject::Rule(schema::Rule { family: types::NfFamily::INet, - table: self.table.to_string(), - chain: self.chain.to_string(), + table: self.table.clone(), + chain: self.chain.clone(), expr: stmts, - comment: comment.map(|x| x.to_string()), + comment: comment.map(|x| x.to_string().into()), ..Default::default() }) } @@ -93,20 +97,20 @@ impl Nftables { pub fn make_rule_handle(&self, handle: u32) -> schema::NfListObject { schema::NfListObject::Rule(schema::Rule { family: types::NfFamily::INet, - table: self.table.to_string(), - chain: self.chain.to_string(), + table: self.table.clone(), + chain: self.chain.clone(), handle: Some(handle), ..Default::default() }) } pub async fn get_current_ruleset_raw(&self) -> Result { - let args = vec!["-n", "-s", "list", "chain", "inet", &self.table, &self.chain]; - Ok(get_current_ruleset_raw(None, Some(args)).await?) + let args = ["-n", "-s", "list", "chain", "inet", &self.table, &self.chain]; + Ok(get_current_ruleset_raw_async(None, Some(&args)).await?) } pub async fn apply_ruleset(&self, n: &NftablesReq) -> Result<()> { - Ok(apply_ruleset(n, None, None).await?) + Ok(apply_ruleset_async(n, None, None).await?) } } @@ -206,10 +210,10 @@ impl Component { } smallvec_inline![smallvec_inline![make_match( tt.inv.then_some(stmt::Operator::NEQ).unwrap_or(stmt::Operator::EQ), - expr::Expression::BinaryOperation(expr::BinaryOperation::AND( - Box::new(make_payload_field("tcp", "flags")), - Box::new(NUM(tt.mask as u32)), - )), + expr::Expression::BinaryOperation(Box::new(expr::BinaryOperation::AND( + make_payload_field("tcp", "flags"), + NUM(tt.mask as u32), + ))), expr::Expression::Named(expr::NamedExpression::Set( (tt.truth.iter().copied()) .map(|x| expr::SetItem::Element(NUM(x as u32))) @@ -355,7 +359,7 @@ impl TrafficFilterAction { value: NUM(dscp.into()), })], RedirectToIp { ip, copy: true } => smallvec_inline![stmt::Statement::Dup(stmt::Dup { - addr: STRING(ip.to_string()), + addr: STRING(ip.to_string().into()), dev: None, })], RedirectToIp { ip, copy: false } => { @@ -384,11 +388,11 @@ fn make_match(op: stmt::Operator, left: expr::Expression, right: expr::Expressio stmt::Statement::Match(stmt::Match { left, right, op }) } -fn make_limit(over: bool, rate: f32, unit: impl ToString, per: impl ToString) -> stmt::Statement { +fn make_limit(over: bool, rate: f32, unit: &'static str, per: &'static str) -> stmt::Statement { stmt::Statement::Limit(stmt::Limit { rate: rate.round() as u32, - rate_unit: Some(unit.to_string()), - per: Some(per.to_string()), + rate_unit: Some(unit.into()), + per: Some(per.into()), burst: None, burst_unit: None, inv: Some(over), @@ -401,9 +405,9 @@ fn make_payload_raw(base: expr::PayloadBase, offset: u32, len: u32) -> expr::Exp ))) } -fn make_payload_field(protocol: impl ToString, field: impl ToString) -> expr::Expression { +fn make_payload_field(protocol: &'static str, field: &'static str) -> expr::Expression { expr::Expression::Named(expr::NamedExpression::Payload(expr::Payload::PayloadField( - expr::PayloadField { protocol: protocol.to_string(), field: field.to_string() }, + expr::PayloadField { protocol: protocol.into(), field: field.into() }, ))) } @@ -411,21 +415,21 @@ fn make_meta(key: expr::MetaKey) -> expr::Expression { expr::Expression::Named(expr::NamedExpression::Meta(expr::Meta { key })) } -fn make_exthdr(name: impl ToString, field: impl ToString, offset: u32) -> expr::Expression { +fn make_exthdr(name: &'static str, field: &'static str, offset: u32) -> expr::Expression { expr::Expression::Named(expr::NamedExpression::Exthdr(expr::Exthdr { - name: name.to_string(), - field: field.to_string(), + name: name.into(), + field: field.into(), offset, })) } -fn prefix_stmt(field: impl ToString, prefix: IpPrefix) -> Option { +fn prefix_stmt(field: &'static str, prefix: IpPrefix) -> Option { (prefix.len() != 0).then(|| { make_match( stmt::Operator::EQ, make_payload_field(if prefix.afi() == Afi::Ipv4 { "ip" } else { "ip6" }, field), expr::Expression::Named(expr::NamedExpression::Prefix(expr::Prefix { - addr: Box::new(STRING(format!("{}", prefix.prefix()))), + addr: Box::new(STRING(format!("{}", prefix.prefix()).into())), len: prefix.len().into(), })), ) @@ -510,9 +514,9 @@ fn range_stmt(left: expr::Expression, ops: &Ops, max: u64) -> Result