nf_tables 0.1.0

Pure Rust crate to interact with the Linux nf_tables subsystem
Documentation
  • Coverage
  • 24.36%
    38 out of 156 items documented1 out of 36 items with examples
  • Size
  • Source code size: 53.43 kB This is the summed size of all the files inside the crates.io package for this release.
  • Documentation size: 2.07 MB This is the summed size of all files generated by rustdoc for all configured targets
  • Ø build duration
  • this release: 5s Average build duration of successful builds.
  • all releases: 5s Average build duration of successful builds in releases after 2024-10-23.
  • Links
  • Repository
  • crates.io
  • Dependencies
  • Versions
  • Owners
  • MrGunflame

Access to Linux' nf_tables subsystem in pure Rust.

This crate direclty communicates with the kernel using netlink and avoids shelling out to nftables or calling C libraries.

In addtion to the expression based system used by nf_tables, this crate provides RuleBuilder for simpler rule creation, similar to the nftables tool.

Basic Usage

# use core::net::{IpAddr, Ipv4Addr};
#
# use nf_tables::*;
# use nf_tables::commands::*;
# use nf_tables::rule::*;
#
let mut conn = Connection::new().unwrap();

// Prepare a list of commands.
let mut batch = Batch::new();

// Create a new table.
// Equivalent to "nft add table inet MyLittleFirewall"
batch.push(AddTable {
    name: c"MyLittleFirewall".into(),
    proto: ProtoFamily::Inet,
    flags: 0,
});

// Create a new chain in the table capturing packets that are being forwarded.
// Equivalent to "nft add chain inet MyLittleFirewall FORWARD { type filter hook forward priority 0; policy drop; }"
batch.push(AddChain {
    table: c"MyLittleFirewall".into(),
    proto: ProtoFamily::Inet,
    name: c"FORWARD".into(),
    hook: Some(ChainHook {
        hook: Hook::Forward,
        priority: 0,
        policy: Policy::Drop,
    }),
});

// Add a new rule allowing all traffic coming from 10.0.0.0/8.
// Equivalent to "nft add rule inet MyLittleFirewall FORWARD ip saddr 10.0.0.0/8 accept"
batch.push(AddRule {
    table: c"MyLittleFirewall".into(),
    proto: ProtoFamily::Inet,
    chain: c"FORWARD".into(),
    position: None,
    exprs: RuleBuilder::new().with_ip_saddr_prefix(IpAddr::V4(Ipv4Addr::new(10, 0, 0, 0)), 8).with_verdict(Verdict::Accept).build(),
});

let results = conn.execute(&batch).unwrap();

for result in results {
    match result.index {
        1 => println!("New chain has handle {:?}", result.handle),
        2 => println!("New rule has handle {:?}", result.handle),
        _ => {}
    }
}

Note that modifying network configuration typically requires root privileges or the CAP_NET_ADMIN capability. If the current process does not have permission to do so, it is possible that [Connection::new] will connect without errors, but [Connection::execute] will always return with EPERM.

Syscalls

Since processes accessing nftable rules typically need to run with elevated privileges, this crate limits the amount of syscalls it makes, making it possible to use together with seccomp.

This crate makes the following syscalls:

  • socket when calling [Connection::new]
  • sendmsg
  • recvmsg
  • close when dropping [Connection]
  • Syscalls made by the global allocator