network: firewall integration with NFT sets

New directives `NFTSet=`, `IPv4NFTSet=` and `IPv6NFTSet=` provide a method for
integrating configuration of dynamic networks into firewall rules with NFT
sets.

/etc/systemd/network/eth.network
```
[DHCPv4]
...
NFTSet=netdev:filter:eth_ipv4_address
```

```
table netdev filter {
        set eth_ipv4_address {
                type ipv4_addr
                flags interval
        }
        chain eth_ingress {
                type filter hook ingress device "eth0" priority filter; policy drop;
                ip saddr != @eth_ipv4_address drop
                accept
        }
}
```
```
sudo nft list set netdev filter eth_ipv4_address
table netdev filter {
        set eth_ipv4_address {
                type ipv4_addr
                flags interval
                elements = { 10.0.0.0/24 }
        }
}
```
This commit is contained in:
Topi Miettinen
2022-06-08 16:12:25 +00:00
committed by Topi Miettinen
parent e8f1b50f27
commit ab51fd9dbd
13 changed files with 792 additions and 7 deletions
+3
View File
@@ -672,6 +672,9 @@ tests += [
[files('test-hmac.c')],
[files('test-sha256.c')],
[files('test-nft-set.c'),
[], [], [], '', 'manual'],
]
############################################################
+69
View File
@@ -0,0 +1,69 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include <assert.h>
#include <unistd.h>
#include "firewall-util.h"
#include "in-addr-util.h"
#include "log.h"
#include "parse-util.h"
#include "string-util.h"
#include "tests.h"
int main(int argc, char **argv) {
int r;
assert_se(argc == 7);
test_setup_logging(LOG_DEBUG);
if (getuid() != 0)
return log_tests_skipped("not root");
int nfproto;
nfproto = nfproto_from_string(argv[2]);
assert_se(nfproto > 0);
const NFTSetContext nft_set_context = {
.nfproto = nfproto,
.table = argv[3],
.set = argv[4],
};
if (streq(argv[5], "uint32")) {
uint32_t element;
r = safe_atou32(argv[6], &element);
assert_se(r == 0);
if (streq(argv[1], "add"))
r = nft_set_element_add_uint32(&nft_set_context, element);
else
r = nft_set_element_del_uint32(&nft_set_context, element);
assert_se(r == 0);
} else if (streq(argv[5], "uint64")) {
uint64_t element;
r = safe_atou64(argv[6], &element);
assert_se(r == 0);
if (streq(argv[1], "add"))
r = nft_set_element_add_uint64(&nft_set_context, element);
else
r = nft_set_element_del_uint64(&nft_set_context, element);
assert_se(r == 0);
} else {
union in_addr_union addr;
int af;
unsigned char prefixlen;
r = in_addr_prefix_from_string_auto(argv[6], &af, &addr, &prefixlen);
assert_se(r == 0);
if (streq(argv[1], "add"))
r = nft_set_element_add_in_addr(&nft_set_context, af, &addr, prefixlen);
else
r = nft_set_element_del_in_addr(&nft_set_context, af, &addr, prefixlen);
assert_se(r == 0);
}
return 0;
}