nftables-rs

 Automate modern Linux firewalls with nftables through its declarative and imperative JSON API in Rust. 

## Features 🌟

- 🛡️ **Safe and Easy-to-Use Abstraction**: Provides a high-level, safe abstraction over the [nftables JSON API](https://manpages.debian.org/testing/libnftables1/libnftables-json.5.en.html), making it easier and safer to work with nftables in Rust.

- 🛠️ **Comprehensive Functions**: Includes a wide range of functions to create, read, and apply nftables rulesets directly from Rust, streamlining the management of firewall rules.

- 📄 **JSON Parsing and Generation**: Offers detailed parsing and generation capabilities for nftables rulesets in JSON format, enabling seamless integration and manipulation of rulesets.

- 💾 **JSON Schema generation for nftables**: Allows to create and export a JSON Schema for further usage derived from the explicit Rust types.

- 💡 **Inspired by nftnl-rs**: While taking inspiration from [nftnl-rs](https://github.com/mullvad/nftnl-rs), `nftables-rs` focuses on utilizing the JSON API for broader accessibility and catering to diverse use cases.

## Motivation

`nftables-rs` is a Rust library designed to provide a safe and easy-to-use abstraction over the nftables JSON API, known as libnftables-json.

This library is engineered for developers who need to interact with nftables, the Linux kernel's next-generation firewalling tool, directly from Rust applications.
By abstracting the underlying JSON API, nftables-rs facilitates the creation, manipulation, and application of firewall rulesets without requiring deep knowledge of nftables' internal workings.

## Installation

```toml
[dependencies]
nftables = "0.5"
```

Linux nftables v0.9.3 or newer is required at runtime: `nft --version`

## Example

Here are some examples that show use cases of this library.
Check out the `tests/` directory for more usage examples.

### Apply ruleset to nftables

This example applies a ruleset that creates and deletes a table to nftables.

```rust
use nftables::{batch::Batch, helper, schema, types};

/// Applies a ruleset to nftables.
fn test_apply_ruleset() {
    let ruleset = example_ruleset();
    helper::apply_ruleset(&ruleset).unwrap();
}

fn example_ruleset() -> schema::Nftables<'static> {
    let mut batch = Batch::new();
    batch.add(schema::NfListObject::Table(schema::Table {
        family: types::NfFamily::IP,
        name: "test-table-01".into(),
        ..Default::default()
    }));
    batch.delete(schema::NfListObject::Table(schema::Table {
        family: types::NfFamily::IP,
        name: "test-table-01".into(),
        ..Default::default()
    }));
    batch.to_nftables()
}
```

### Parse/Generate nftables ruleset in JSON format

This example compares nftables' native JSON out to the JSON payload generated by this library.

```rust
fn test_chain_table_rule_inet() {
    // nft add table inet some_inet_table
    // nft add chain inet some_inet_table some_inet_chain '{ type filter hook forward priority 0; policy accept; }'
    let expected: Nftables = Nftables {
        objects: Cow::Borrowed(&[
            NfObject::CmdObject(NfCmd::Add(NfListObject::Table(Table {
                family: NfFamily::INet,
                name: Cow::Borrowed("some_inet_table"),
                handle: None,
            }))),
            NfObject::CmdObject(NfCmd::Add(NfListObject::Chain(Chain {
                family: NfFamily::INet,
                table: Cow::Borrowed("some_inet_table"),
                name: Cow::Borrowed("some_inet_chain"),
                newname: None,
                handle: None,
                _type: Some(NfChainType::Filter),
                hook: Some(NfHook::Forward),
                prio: None,
                dev: None,
                policy: Some(NfChainPolicy::Accept),
            }))),
        ]),
    };
    let json = json!({"nftables":[{"add":{"table":{"family":"inet","name":"some_inet_table"}}},{"add":{"chain":{"family":"inet","table":"some_inet_table","name":"some_inet_chain","type":"filter","hook":"forward","policy":"accept"}}}]});
    println!("{}", &json);
    let parsed: Nftables = serde_json::from_value(json).unwrap();
    assert_eq!(expected, parsed);
}
```

### Export JSON Schema

Export a JSON Schema to a file (if no path is set it defaults to `./nftables.schema.json`).

```bash
./nftables-rs schema <export-path | './nftables.schema.json'>
```

## MSRV (Minimum Supported Rust Version)

The MSRV of this crate is currently: **Rust 1.76**

The MSRV will only be increased by a minor or major release of this crate.

## License

Licensed under either of

* Apache License, Version 2.0
  ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
* MIT license
  ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)

at your option.

## Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in the work by you, as defined in the Apache-2.0 license, shall be
dual licensed as above, without any additional terms or conditions.

## Maintainers

This project is currently maintained by the following developers:

|       Name       |      Email Address       |                GitHub Username               |
|:----------------:|:------------------------:|:--------------------------------------------:|
| Jasper Wiegratz  | wiegratz@uni-bremen.de   |       [@jwhb](https://github.com/jwhb)       |
| Jan Romann       | jan.romann@uni-bremen.de |      [@JKRhb](https://github.com/JKRhb)      |

Write access to the main branch and to crates.io is exclusively granted to the maintainers listed above.
