nftlb stands for nftables load balancer, the next generation linux firewall that will replace iptables is adapted to behave as a complete load balancer and traffic distributor.
nftlb is provided with a JSON API, so you can use your preferred health checker to enable/disable backends or virtual services and automate processes with it.
More info: What is nftlb?
In this repository is included:
- src/: main source code files.
- include/: include files.
- tests/: automated testbed suite with example configuration files and the script exec_tests.sh to run all of them.
- tests/api: automated testbed suite for API interactionand the script api_tests.sh to run all of them.
nftlb depends on:
- linux-kernel: Kernel version 4.19 or higher with nftables modules enabled (iptables, ebtables, etc not required).
- nftables: nftables package with libnftables included and its dependencies (libgmp, libmnl and libnftnl).
- libev: Events library for the web service.
- libjansson: JSON parser for the API.
To build nftlb, just execute:
root# autoreconf -fi
root# ./configure
root# make
Finally, install it:
root# make install
Also, deb packages are available.
Check out the command help:
# ./nftlb -h
Here is the list of options:
[ -h | --help ]: Show the command help.
[ -l <LEVEL> | --log <LEVEL> ]: The logs will be shown in the syslog file and with this option you can change the loglevel from 0 to 7 (5 by default).
[ -c <FILE> | --config <FILE> ]: Initial configuration file, this argument is optional.
[ -k <KEY> | --key <KEY> ]: The authentication key for the web service can be set by command line, or automatically generated. If it's automatically generated, it'll be shown by command line.
[ -e | --exit ]: This option executes the configuration file into nftables rules and then exit, so the web server won't be available.
[ -d | --daemon ]: Run nftlb as a daemon in background.
[ -6 | --ipv6 ]: Enable IPv6 support for the web service listening port.
[ -H <HOST> | --host <HOST> ]: Set the host for the web service (all interfaces by default).
[ -P <PORT> | --port <PORT> ]: Set the TCP port for the web service (5555 by default).
[ -S | --serial ]: Serialize nft commands.
Note: In order to use sNAT or dNAT modes, ensure you have activated the ip forwarding option in your system.
The configuration files have the following format:
{
"farms" : [
{ <object farm 1> },
{ <object farm 2> },
{ ... }
],
"policies" : [
{ <object policy 1> },
{ <object policy 2> },
{ ... }
]
}
Where every farm object has the following attributes:
{
"name" : "<string>", *Name of the service (required)*
"family": "<ipv4 | ipv6 | dual>", *Family of the virtual service (ipv4 by default)*
"virtual-addr": "<ip address>", *IP address for the virtual service (required)*
"virtual-ports": "<port list>", *Port list separated by commas or ranges separated by a hyphen*
"source-addr": "<ip address>", *Source IP address instead of masquerading*
"mode": "<snat | dnat | dsr | stlsdnat | local>", *Topology to be implemented (required)*
"protocol": "<tcp | udp | sctp | all>", *Protocol to be used by the virtual service (tcp by default)*
"scheduler": "<weight | rr | hash | symhash>", *Scheduler to be used (round robin by default)*
"sched-param": "<srcip | dstip | srcport | dstport | srcmac | dstmac | none>", *Hash input parameters (none by default)*
"persistence": "<srcip | dstip | srcport | dstport | srcmac | dstmac | none>", *Configured stickiness between client and backend (none by default)*
"persist-ttl": "<number>", *Stickiness timeout in seconds (60 by default)*
"helper": "<none | amanda | ftp | h323 | irc | netbios-ns | pptp | sane | sip | snmp | tftp>", *L7 helper to be used (none by default)*
"log": "<none | input | forward | output>", *Enable logging (none by default)*
"log-prefix": "<string|KNAME|TYPE|FNAME>", *Farm log prefix (default "TYPE-FNAME")*
"mark": "<hexadecimal mark>", *Set mark mask for the farm (none by default)*
"priority": "<number>", *Priority availability for backends > 0 (1 by default)*
"new-rtlimit": "<number>", *Number of new connections per second per service (disabled by default)*
"new-rtlimit-burst": "<number>", *Number of burst packets (disabled by default)*
"new-rtlimit-log-prefix": "<string|KNAME|TYPE|FNAME>", *Farm new rtlimit log prefix (default "KNAME-TYPE-FNAME")*
"rst-rtlimit": "<number>", *Number of tcp resets per second allowed (disabled by default)*
"rst-rtlimit-burst": "<number>", *Number of burst RST packets (disabled by default)*
"rst-rtlimit-log-prefix": "<string|KNAME|TYPE|FNAME>", *Farm reset rtlimit log prefix (default "KNAME-TYPE-FNAME")*
"est-connlimit": "<number>", *Number of established connections allowed (disabled by default)*
"est-connlimit-log-prefix": "<string|KNAME|TYPE|FNAME>", *Farm established connlimit log prefix (default "KNAME-TYPE-FNAME")*
"tcp-strict": "<on | off>", *Option to avoid bogus TCP attacks (disabled by default)*
"tcp-strict-log-prefix": "<string|KNAME|TYPE|FNAME>", *Farm TCP strict log prefix (default "KNAME-TYPE-FNAME")*
"flow-offload": "<on | off>", *Option to enable flow offload (disabled by default)*
"queue": "<number>", *Number of the queue to send the packets to userspace (disabled by default)*
"state": "<up | down | off>", *Set the status of the virtual service (up by default)*
"backends" : [ *List of backends*
{<object backend 1>},
{<object backend 2>},
{...}
],
"sessions" : [ *List of static sessions. It requires persistence enabled.*
{
{<object session 1>},
{<object session 2>},
{...}
],
"policies" : [ *List of policies*
{
"name" : "<policy name>",
},
{...}
]
}
Where every backend object has the following attributes:
{
"name" : "<string>", *Name of the backend (required)*
"ip-addr": "<ip address>", *IP address for the backend (required, except for DSR)*
"port": "<number>", *Backend port to redirect the connections*
"source-addr": "<ip address>", *Source IP address for a certain backend instead of masquerading or virtual service source address*
"weight": "<number>", *Weight of the backend (1 by default)*
"priority": "<number>", *Priority availability for the backend > 0 (1 by default)*
"mark": "<hexadecimal mark>", *Set mark mask for the backend (none by default)*
"est-connlimit": "<number>", *Number of established connections allowed per backend (disabled by default)*
"est-connlimit-log-prefix": "<string|KNAME|TYPE|FNAME|BNAME>", *Backend established connections log prefix (default "KNAME-FNAME-BNAME")*
"state": "<up | down | off>", *Set the status of the backend (up by default)*
}
Where every session object has the following attributes:
{
"client" : "<ip address>", *Client with the same format than persistence configuration*
"backend": "<backend id>", *Backend ID to set a stickyness between client and backend*
"expiration": "<time>" *Dynamic sessions timeout. Static sessions doesn't include this attribute*
}
Where every policy object has the following attributes:
{
"name" : "<string>", *Name of the policy (required)*
"type": "<blacklist | whitelist>", *Policy type*
"family": "<ipv4 | ipv6>", *Family of the policy (ipv4 by default)*
"log-prefix": "<string|KNAME|TYPE|FNAME|PNAME>", *Policy established connections log prefix (default "KNAME-TYPE-PNAME-FNAME")*
"elements" : [ *List of IPs or networks*
{
"data" : "<ip or network>"
},
{...}
]
}
You can find some examples in the tests/ folder.
Once launched nftlb you can manage it through the API.
Virtual service listing.
curl -H "Key: <MYKEY>" http://<NFTLB IP>:5555/farms
Setup a new virtual service.
curl -H "Key: <MYKEY>" -X POST http://<NFTLB IP>:5555/farms -d "@tests/008_snat_ipv4_all_rr.json"
Add a new backend into a virtual service.
curl -H "Key: <MYKEY>" -X POST http://<NFTLB IP>:5555/farms -d '{"farms" : [ { "name" : "myfarm", "backends" : [ { "name" : "mynewbck", "ip-addr" : "192.168.0.150", "state" : "up" } ] } ] }'
Delete a virtual service.
curl -H "Key: <MYKEY>" -X DELETE http://<NFTLB IP>:5555/farms/lb01
Delete a backend of a virtual service.
curl -H "Key: <MYKEY>" -X DELETE http://<NFTLB IP>:5555/farms/lb01/backends/bck1
Get the static and dynamic sessions.
curl -H "Key: <MYKEY>" -X GET http://<NFTLB IP>:5555/farms/lb01/sessions
nftlb uses the nftables infrastructure to build virtual services, from user to kernel side. In that regard, the expressions numgen (with its random and inc modes) and hash (say jhash and symhash) allows to distribute traffic among several backends among other properties. More information:
https://wiki.nftables.org/wiki-nftables/index.php/Load_balancing https://www.netfilter.org/projects/nftables/manpage.html
This software creates the required tables named nftlb which are exclusive to the nftlb service and should not be managed manually. Ex: ip nftlb, ip6 nftlb, netdev nftlb...
The integration of nftlb with custom firewall rules are possible creating separated tables and playing with chain priorities. More information:
https://www.zevenet.com/knowledge-base/nftlb/
Please refer to the netfilter users mailing list