This failover addon enables you to have one NFTables variable that will always point to a server that is online.
Why would you want that?
It's an alternative to using a load-balancer/reverse-proxy to perform a failover between nodes.
Many times a central endpoint is a better solution - but if it is a high-traffic or low-latency application it might be smarter to send the traffic directly to the target node.
Currently only TCP port-checks are supported.
NFTables documentation: docs.o-x-l.com
-
Create directories:
mkdir -p /var/local/lib/nftables_addons /etc/nftables.d/addons/
-
Add the script-files:
-
Add the config file:
/etc/nftables.d/addons/failover.json
-
Optional: Create a service user
- Add sudoers privileges
- Allow to read lib-dir
- Allow to write to addons-config-dir
-
Add cron or systemd-timer to execute the script on a schedule:
python3 /var/local/lib/nftables_addons/failover.py
-
Test it and verify it's working as expected
cat /etc/nftables.d/addons/failover.nft
> # Auto-Generated config - DO NOT EDIT MANUALLY!
>
> define endpoint_filer_v4 = 192.168.87.100
> define endpoint_filer_v6 = 2001:DB8:2:2
> define endpoint_print_v4 = 192.168.93.52 # if first one is offline
> define endpoint_print_v6 = ::
> define mark_proxy_v4 = 200
> define mark_proxy_v6 = :: # unused
-
A configuration file needs to be created:
/etc/nftables.d/addons/failover.json
{ "failover": { "endpoint_filer": { "ip4": ["192.168.87.100", "192.168.87.101"], "ip6": ["2001:DB8:2:2", "2001:DB8:2:3"], "port": 443 }, "endpoint_print": { "ip4": ["192.168.93.51", "192.168.93.52"], "port": 631 }, "mark_proxy": { // set fwmark for policy routing "ip4": ["192.168.132.2", "192.168.132.3"], "port": 3129, "values": [200, 201] } } }
Config options:
-
port
: requiredTCP Port to check for online-status
-
values
: optional; default = using IPs1-to-1 mapping to ip-lists. Lists must be of the same length
-
-
The script is executed
python3 /var/local/lib/nftables_addons/failover.py
-
It will load the configuration
-
Run port-checks for all configured variables - use first host that is online
-
Map hosts to values if supplied
-
If no host is online - will use first host/value
-
The new addon-config is written to
/tmp/nftables_failover.nft
-
Its md5-hash is compared to the existing config to check if it changed
-
If it has changed:
-
Config validation is done:
-
An include-file is written to
/tmp/nftables_main.nft
:include /tmp/nftables_failover.nft # including all other adoon configs include /etc/nftables.d/addons/other_addon1.nft include /etc/nftables.d/addons/other_addon2.nft # include other main configs include /etc/nftables.d/*.nft
-
This include-file is validated:
sudo nft -cf /tmp/nftables_main.nft
-
-
The new config is written to
/etc/nftables.d/addons/failover.nft
-
The actual config is validated:
sudo nft -cf /etc/nftables.conf
-
NFTables is reloaded:
sudo systemctl reload nftables.service
-
-
You will have to include the addon-config in your main-config file
/etc/nftables.conf
:... include /etc/nftables.d/addons/*.nft ...
If the script should be run as non-root user - you will need to add a sudoers.d file to add the needed privileges:
Cmnd_Alias NFTABLES_ADDON = \
/usr/bin/systemctl reload nftables.service,
/usr/sbin/nft -cf *
service_user ALL=(ALL) NOPASSWD: NFTABLES_ADDON
You may not change the owner of the addon-files as the script will not be able to overwrite them.
As explained above - there is a config-validation process to ensure the addon will not supply a bad config and lead to a failed nftables reload/restart.
If you want to be even safer - you can add a config-validation inside the nftables.service
:
# /etc/systemd/system/nftables.service.d/override.conf
[Service]
# catch errors at start
ExecStartPre=/usr/sbin/nft -cf /etc/nftables.conf
# catch errors at reload
ExecReload=
ExecReload=/usr/sbin/nft -cf /etc/nftables.conf
ExecReload=/usr/sbin/nft -f /etc/nftables.conf
# catch errors at restart
ExecStop=
ExecStop=/usr/sbin/nft -cf /etc/nftables.conf
ExecStop=/usr/sbin/nft flush ruleset
Restart=on-failure
RestartSec=5s
This will catch and log config-errors before doing a reload/restart.
You can either:
- Add a Systemd Timer: example
- Add a cron job
Here you can find an Ansible Role to manage NFTables Addons:
MIT