nftblockd is a robust Rust-based tool designed for managing IP blocklists in nftables. It provides an efficient and
secure mechanism to fetch, validate, deduplicate, and apply IPv4 and IPv6 subnets to a blocklist table in nftables.
The tool is geared toward optimizing network security with ease and reliability.
- IPv4 and IPv6 Support: Handles both IPv4 and IPv6 blocklists.
- Automatic Blocklist Fetching: Fetches blocklists from user-specified or environment-configured endpoints.
- Validation and Deduplication: Ensures subnets are valid, deduplicated, and free of redundancies using a trie-based algorithm.
- High Performance: Uses optimized data structures and algorithms for subnet deduplication.
- Integration with
nftables: Directly applies blocklist rules tonftables. - Anti-Lockout Mechanism: Protects the specified critical IPs from being locked out of the firewall by mistake.
- Periodic Update Support: Periodically fetches and updates the blocklists according to a user-configured interval.
- Smart Logging: Configurable logging levels via the configuration file.
- Install Dependencies
Ensure you have Rust installed on your system. If not, you can install it via rustup:
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh- Clone the Repository:
git clone https://github.com/maromcik/nftblockd.git
cd nftblockd- Build the Binary, use Cargo to build the project:
Standard build using glibc
cargo build --releaseMore portable build using musl
rustup target add x86_64-unknown-linux-musl
cargo build --release --target=x86_64-unknown-linux-musl- Run the Binary:
Run the compiled binary (glibc):
./target/release/nftblockdRun the compiled binary (musl):
./target/x86_64-unknown-linux-musl/release/nftblockdEither use the nftables Ansible role from ansible-collections or deploy it on your own.
Download the binary and run it:
wget https://gitlab.ics.muni.cz/api/v4/projects/7885/packages/generic/nftblockd/latest/nftblockd
nftblockd -c config.yamlInstead of the keyword latest, you can specify the desired tag
The general usage structure for nftblockd is:
nftblockd [OPTIONS]| Flag or Argument | Description | Default or Mandatory |
|---|---|---|
-c, --config <CONFIG_FILE> |
Specifies a YAML configuration file for the tool. | Optional |
-d, --delete |
Deletes the existing blocklist table and stops the execution. | Flag, Optional |
- Run with the default configuration (built-in defaults):
nftblockd- Use a custom YAML configuration file:
nftblockd --config path/to/config.yaml- Delete the blocklist table manually:
nftblockd --deleteYou can view logs using the journalctl -ekf | grep nftblockd command.
journalctl -ekf | grep nftblockd
Jul 23 18:03:21 proxy-dev kernel: nftblockd;prerouting;dropped: IN=eth0 OUT= MAC=bc:24:11:a3:0e:dc:ec:13:db:94:82:c0:08:00 SRC=91.191.209.13 DST=147.251.6.171 LEN=40 TOS=0x00 PREC=0x00 TTL=247 ID=38244 PROTO=TCP SPT=52783 DPT=3397 WINDOW=1024 RES=0x00 SYN URGP=0
Jul 23 19:12:42 proxy-dev kernel: nftblockd;prerouting;dropped: IN=eth0 OUT= MAC=bc:24:11:a3:0e:dc:ec:13:db:94:82:c0:08:00 SRC=188.166.78.140 DST=147.251.6.171 LEN=44 TOS=0x00 PREC=0x00 TTL=247 ID=54321 PROTO=TCP SPT=34686 DPT=22533 WINDOW=65535 RES=0x00 SYN URGP=0
Jul 23 21:45:02 proxy-dev kernel: nftblockd;prerouting;dropped: IN=eth0 OUT= MAC=bc:24:11:a3:0e:dc:ec:13:db:94:82:c0:08:00 SRC=83.222.190.242 DST=147.251.6.171 LEN=44 TOS=0x00 PREC=0x00 TTL=248 ID=34085 PROTO=TCP SPT=57526 DPT=8137 WINDOW=1025 RES=0x00 SYN URGP=0
Jul 23 21:54:17 proxy-dev kernel: nftblockd;prerouting;dropped: IN=eth0 OUT= MAC=bc:24:11:a3:0e:dc:ec:13:db:94:82:c0:08:00 SRC=83.222.190.242 DST=147.251.6.171 LEN=44 TOS=0x00 PREC=0x00 TTL=248 ID=33107 PROTO=TCP SPT=57526 DPT=8103 WINDOW=1025 RES=0x00 SYN URGP=0
Jul 24 04:03:47 proxy-dev kernel: nftblockd;prerouting;dropped: IN=eth0 OUT= MAC=bc:24:11:a3:0e:dc:ec:13:db:94:82:c0:08:00 SRC=79.124.62.122 DST=147.251.6.171 LEN=40 TOS=0x00 PREC=0x00 TTL=247 ID=33224 PROTO=TCP SPT=0 DPT=5060 WINDOW=1024 RES=0x00 SYN URGP=0
Jul 24 06:04:13 proxy-dev kernel: nftblockd;prerouting;dropped: IN=eth0 OUT= MAC=bc:24:11:a3:0e:dc:ec:13:db:94:82:c0:08:00 SRC=152.32.150.29 DST=147.251.6.171 LEN=44 TOS=0x08 PREC=0x20 TTL=44 ID=0 DF PROTO=TCP SPT=38265 DPT=25105 WINDOW=1024 RES=0x00 SYN URGP=0
Jul 24 09:59:09 proxy-dev kernel: nftblockd;prerouting;dropped: IN=eth0 OUT= MAC=bc:24:11:a3:0e:dc:ec:13:db:94:82:c0:08:00 SRC=83.222.191.42 DST=147.251.6.171 LEN=40 TOS=0x00 PREC=0x00 TTL=247 ID=12192 PROTO=TCP SPT=61000 DPT=25708 WINDOW=1024 RES=0x00 SYN URGP=0
Jul 24 10:01:26 proxy-dev kernel: nftblockd;prerouting;dropped: IN=eth0 OUT= MAC=bc:24:11:a3:0e:dc:ec:13:db:94:82:c0:08:00 SRC=83.222.191.42 DST=147.251.6.171 LEN=40 TOS=0x00 PREC=0x00 TTL=247 ID=48645 PROTO=TCP SPT=61000 DPT=25741 WINDOW=1024 RES=0x00 SYN URGP=0
Jul 24 11:55:34 proxy-dev kernel: nftblockd;prerouting;dropped: IN=eth0 OUT= MAC=bc:24:11:a3:0e:dc:ec:13:db:94:82:c0:08:00 SRC=167.99.117.14 DST=147.251.6.171 LEN=44 TOS=0x00 PREC=0x00 TTL=243 ID=54321 PROTO=TCP SPT=54545 DPT=8000 WINDOW=65535 RES=0x00 SYN URGP=0
Jul 24 11:55:34 proxy-dev kernel: nftblockd;prerouting;dropped: IN=eth0 OUT= MAC=bc:24:11:a3:0e:dc:ec:13:db:94:82:c0:08:00 SRC=167.99.117.14 DST=147.251.6.171 LEN=44 TOS=0x00 PREC=0x00 TTL=243 ID=54321 PROTO=TCP SPT=54546 DPT=8000 WINDOW=65535 RES=0x00 SYN URGP=0nftblockctl is a companion CLI for interacting with a running nftblockd daemon. It communicates
with the daemon over gRPC via the Unix socket at /run/nftblockd.sock, so it can be used to inspect
and control the blocklist without restarting the service.
The general usage structure is:
nftblockctl <COMMAND> [OPTIONS]| Command | Description |
|---|---|
reload |
Reloads configuration and triggers an immediate re-fetch of the blocklists and re-applies the nftables ruleset. |
flush |
Deletes the entire blocklist table from nftables (the daemon keeps running). It does not reload configuration. |
status |
Prints the daemon status summary (status_code, status, message). |
stats |
Prints drop statistics (packets/bytes) for the main and custom blocklists, split by chain and IP family. |
Each subcommand accepts the -j, --json flag to print the response as JSON instead of the
human-readable format.
- Check the daemon status:
nftblockctl status- Show drop statistics as JSON:
nftblockctl stats --json- Reload the blocklist after changing its source:
nftblockctl reloadnftblockd is configured via a YAML file, passed with -c/--config. All options are optional and
fall back to the defaults shown below.
Durations use humantime format (e.g. "500ms", "30s", "5m", "1h").
| YAML Key | Description | Default Value |
|---|---|---|
log_level |
Logging level. Options: debug, info, warn, error. |
info |
download_blocklist.ipv4_url |
The IPv4 blocklist fetching URL. | None |
download_blocklist.ipv6_url |
The IPv6 blocklist fetching URL. | None |
download_blocklist.interval |
Interval for updating blocklists. | 30s |
download_blocklist.timeout |
A global timeout for blocklist requests. | 10s |
download_blocklist.split_string |
The string that is used to split the fetched blocklist. | Any whitespace |
download_blocklist.headers |
A map of HTTP header key/value pairs sent with blocklist requests. | None |
custom_blocklist.set_name |
The name of the custom, local blocklist set within the table. | custom_blocklist_set |
custom_blocklist.ipv4_path |
A path to a file with IPv4 addresses to be blocked in the local blocklist. | None |
custom_blocklist.ipv6_path |
A path to a file with IPv6 addresses to be blocked in the local blocklist. | None |
custom_blocklist.split_string |
The string that is used to split the custom blocklist files. | Any whitespace |
anti_lockout.set_name |
The name of the anti-lockout set within the table. | anti_lockout_set |
anti_lockout.ipv4 |
A list of IPv4 anti-lockout IPs/subnets (e.g., admin IPs). | None |
anti_lockout.ipv6 |
A list of IPv6 anti-lockout IPs/subnets (e.g., admin IPs). | None |
nftables.table_name |
The name of the nftables blocklist table. |
nftblockd |
nftables.prerouting_chain |
The name of the nftables prerouting chain in the blocklist table. |
prerouting |
nftables.postrouting_chain |
The name of the nftables postrouting chain in the blocklist table. |
postrouting |
nftables.blocklist_set_name |
The name of the downloaded blocklist set within the table. | blocklist_set |
retry.count |
Number of retry attempts in case of fatal errors. | 10 |
retry.interval |
Retry interval in case of fatal errors. | 2s |
retry.fail_wait |
Wait time before retrying after a fatal error. | 60s |
A fully documented example is also available in config.example.yaml.
log_level: info
download_blocklist:
ipv4_url: "https://example.com/ipv4-blocklist"
ipv6_url: "https://example.com/ipv6-blocklist"
interval: "60s"
timeout: "10s"
# split_string: ","
# headers:
# Authorization: "Bearer <token>"
custom_blocklist:
set_name: custom_blocklist_set
ipv4_path: ipv4.txt
ipv6_path: ipv6.txt
# split_string: ","
anti_lockout:
set_name: anti_lockout_set
ipv4:
- "192.168.1.1"
- "10.0.0.0/24"
ipv6:
- "2001:db8::1"
nftables:
table_name: nftblockd
prerouting_chain: prerouting
postrouting_chain: postrouting
blocklist_set_name: blocklist_set
retry:
count: 10
interval: "2s"To ensure nftblockd runs persistently on your system, even after reboots or network interruptions, you can configure
it as a systemd service. Below is an example systemd service configuration and a detailed explanation of the file
structure.
Save the following configuration as /etc/systemd/system/nftblockd.service:
[Unit]
Description=Update IP blocklist for nftables with nftblockd
Wants=network-online.target nftables.service
After=network-online.target nftables.service
[Service]
Type=simple
Restart=always
RestartSec=60
ExecStart=/usr/local/sbin/nftblockd -c /opt/nftables/nftblockd/nftblockd.yml
ExecReload=/usr/local/sbin/nftblockctl reload
ExecStopPost=/usr/local/sbin/nftblockd -d -c /opt/nftables/nftblockd/nftblockd.yml
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=sysinit.target
And create the YAML configuration file.
cat /opt/nftables/blocklist/nftblockd.yaml
download_blocklist:
ipv4_url: "https://example.com/ipv4-blocklist"
ipv6_url: "https://example.com/ipv6-blocklist"
interval: "60s"
-
Save the Service File:
- Save the example configuration as
/etc/systemd/system/nftblockd.service.
- Save the example configuration as
-
Reload
systemd:- Ensure
systemdrecognizes the new service:
- Ensure
sudo systemctl daemon-reload- Enable the Service:
- Automatically start the service at boot:
sudo systemctl enable nftblockd- Start the Service:
- Manually start the service:
sudo systemctl start nftblockd- Check Service Status:
- To verify it is running:
sudo systemctl status nftblockd- View Logs:
- Check logs using
journalctl:
- Check logs using
journalctl -u nftblockd.serviceAfter enabling and running the service, you can analyze its logs using:
journalctl -u nftblockd.service -n 100 -fExample output:
May 23 12:16:13 <hostname> nftblockd[498270]: [2025-05-23T10:16:13Z INFO nftblockd::blocklist] blocklist fetched from: http://localhost/ipv4.txt
May 23 12:16:13 <hostname> nftblockd[498270]: [2025-05-23T10:16:13Z WARN nftblockd::subnet] invalid ip: 192.168.0.2/16; not a network
May 23 12:16:13 <hostname> nftblockd[498270]: [2025-05-23T10:16:13Z INFO nftblockd::blocklist] blocklist fetched from: http://localhost/ipv6.txt
May 23 12:16:13 <hostname> nftblockd[498270]: [2025-05-23T10:16:13Z INFO nftblockd] the `blocklist` table successfully loaded
May 23 12:16:13 <hostname> nftblockd[498270]: [2025-05-23T10:16:13Z INFO nftblockd] finished
-
Fetch Blocklist:
- Fetches IPv4 and IPv6 blocklists from user-defined endpoints.
-
Validate Blocklist:
- Parses the blocklists and ensures all subnets are well-formed and valid.
-
Deduplicate Subnets:
- Removes redundant subnets using a trie-based algorithm. Ensures performance via prefix grouping.
-
Transform for
nftables:- Converts validated subnets into
nftables-compatible expressions.
- Converts validated subnets into
-
Apply Rules:
- Applies the blocklist to the configured
nftablestable and set, while respecting the anti-lockout rules.
- Applies the blocklist to the configured
main.rs:- Handles CLI, configuration parsing, and the main tool logic.
subnet.rs:- Contains subnet parsing, blocklist validation, and subnet transformations.
iptrie.rs:- Implements the trie-based deduplication algorithm for IPv4 and IPv6 subnets.
network.rs:- Defines the abstraction for IPv4 and IPv6 blocklist networks.
blocklist.rs:- Performs blocklist updating.
anti_lockout.rs:- Ensures certain administrator-defined IPs cannot be blocked by mistake.
nftables.rs:- APIs responsible for constructing and applying rules to
nftables.
- APIs responsible for constructing and applying rules to
- Run Tests: The project includes unit tests for validation, deduplication, and transformations.
cargo test- Static Analysis:
Use
clippyto catch potential issues during development:
cargo clippy --all-targets -- -D warnings - Formatting: Format all Rust code prior to committing:
cargo fmtWe welcome contributions to nftblockd. Feel free to open issues or submit pull requests. Follow the steps below to
contribute:
- Fork this repository.
- Create a feature branch (
git checkout -b feature-name). - Commit your changes (
git commit -m 'Add a feature'). - Push to your branch (
git push origin feature-name). - Open a pull request.
This project is licensed under the MIT License.
This project uses the following third-party libraries:
clap: For command-line argument parsing.ureq: For HTTP requests.logandenv_logger: For logging support.ipnetwork: For managing IPv4/IPv6 subnets.itertools: For enhanced iterator functionality in Rust.
If you have further questions or want to report a bug, feel free to open an issue or reach out!