#nftables #netfilter #linux

nftnl-rs

A Rust crate for Linux Netlink Nftables client for direct control on the netfilter via netlink socket

5 releases (3 breaking)

0.4.0 Mar 31, 2024
0.3.2 Mar 28, 2024
0.2.0 Mar 20, 2024
0.1.0 Mar 18, 2024

#682 in Network programming

Download history 110/week @ 2024-03-13 346/week @ 2024-03-20 317/week @ 2024-03-27 43/week @ 2024-04-03 2/week @ 2024-04-10

715 downloads per month

MPL-2.0 license

165KB
4K SLoC

nftnl-rs (A Nftables manipulation library)

This is a crate (currently in development) which implements a netlink protocol to communicate with the Linux Nftables firewall.

This crate is in its early development state. It is not planned to extend its functionality! Use at your own risk.

This crate was developed only for the tables/sets manipulations i.e add/del/get!!!

At the moment this crate allows to:

  • perform operations on the sets i.e add IP, remove IP, get IP from the list.

For examples, see /examples/ directory.

Get IP from the table's set. i.e performing the following command:

$ sudo nft list set ip table-test table-set
use nftnl_rs::{netlink::{netlink::{NetlinkCb, NetlinkResponseReader, Nlmsghdr, MnlNlmsgBatch, NlmFFlags, NetlinkResponse, NetlinkRespRes, NetlinkCbArr, Nlmsgerr}, MNL_SOCKET_BUFFER_SIZE, linux::Nfproto, socket::mnl_socket}, boxed::Boxed, error::NtflRes, set::{nftnl_set, NftnlSetFlags}, nf_tables::NfTablesMsgTypes};
use rand::Rng;

fn main()
{

    let seq = Sequence::new();

    let mut nl_set = NftnlSet::new();

    nl_set.nftnl_set_set_val(NftnlSetFlagData::SetTable("table-test"));
	nl_set.nftnl_set_set_val(NftnlSetFlagData::SetName("table-set"));
    nl_set.nftnl_set_set_val(NftnlSetFlagData::SetId(1));


    let mut batch = MnlNlmsgBatch::mnl_nlmsg_batch_start(*MNL_SOCKET_BUFFER_SIZE);

    // root
    let _nlh = 
        Nlmsghdr::nftnl_nlmsg_build_hdr(
            &mut batch, 
            NfTablesMsgTypes::NftMsgGetsetelem, 
            Nfproto::NFPROTO_IPV4,
            NlmFFlags::NLM_F_DUMP | NlmFFlags::NLM_F_REQUEST,
            seq
        )?;


    nl_set.nftnl_set_elems_nlmsg_build_payload(&mut batch)?;

    drop(nl_set);

    let mut nl = MnlSocket::mnl_socket_open(NETLINK_NETFILTER)?;

    nl.mnl_socket_bind(0, MNL_SOCKET_AUTOPID)?;

    let portid = nl.mnl_socket_get_portid();

    let len = batch.mnl_nlmsg_batch_size();
    nl.mnl_socket_sendto(batch.mnl_nlmsg_batch_msg(), len)?;

    let mut ret = nl.mnl_socket_recvfrom(*MNL_SOCKET_BUFFER_SIZE)?;

    let mut sets: Vec<NftnlSet> = Vec::new();

    while ret.len() > 0
    {
        let mut resp = NetlinkResponse::new(&ret);

        let lret =
            resp.mnl_parse_check(0, portid, &mut sets)?;

        if lret == NetlinkRespRes::MnlCbStop
        {
            break;
        }

        ret = nl.mnl_socket_recvfrom(*MNL_SOCKET_BUFFER_SIZE)?;
    }

    for set in sets
    {
        if set.is_ip_present(ip_check)? == true
        {
            return Ok(true);
        }
    }

    return Ok(false);
}

Dependencies

~400–570KB
~10K SLoC