nftdnsd is a lightweight Go daemon that keeps a Linux nftables set in sync with hostnames defined in a YAML configuration file.
It’s ideal for managing dynamic ACLs where customers or services are identified by DNS names instead of static IP addresses.
- Reads configuration from YAML and watches the configuration file for live updates
- Periodically re-resolves all hostnames every 5 minutes
- Detects and logs:
- New hostnames added to the config
- Added and removed IP addresses per hostname
- Updates nftables atomically using google/nftables
- Skips nft updates when nothing changed
/etc/nftdnsd.yaml
nft:
table: filter
set: customer_hosts
entries:
- name: VIP customer 42
hostname: client1.example.com
- name: VPN partnersite
hostname: vpn.partner.net- Go 1.24 or newer
- Linux system with nftables (
sudo apt install nftables) - Appropriate privileges to modify nftables (usually
root)
git clone https://github.com/erikbos/nftdnsd.git
cd nftdnsd
go build -o nftdnsdsudo ./nftdnsd --config /etc/nftdnsd.yamlYou can also configure it as a systemd service:
[Unit]
Description=nftdnsd NFTables Updater
After=network-online.target
[Service]
ExecStart=/usr/local/bin/nftdnsd --config /etc/nftdnsd.yaml
Restart=always
[Install]
WantedBy=multi-user.target
nftdnsd logs key events:
2025/10/07 15:00:00 Starting nftdnsd daemon, config=/etc/nftdnsd.yaml
2025/10/07 15:00:00 Resolved 5 IPs for 3 hostnames
2025/10/07 15:00:00 Added IP 203.0.113.10 (vpn.partner.net)
2025/10/07 15:00:00 Removed IP 192.0.2.5 (client1.example.com)
2025/10/07 15:00:00 Updated nft set filter/customer_hosts with 5 IPs
Before running nftdnsd, ensure your target nft set exists:
sudo nft add table filter
sudo nft add set filter customer_hosts { type ipv4_addr; flags dynamic; }Then, reference it in your ruleset:
sudo nft add rule filter input ip saddr @customer_hosts acceptnftdnsdperforms atomic nft updates — the entire set is replaced in one transaction.- When using DNS-based access control, ensure hostnames resolve to stable, trusted endpoints.
- You can extend the YAML config with IPv6 support or per-host options.
95% generated using Copilot, use at your own risk.