diff options
Diffstat (limited to 'tests/shell/testcases/nft-f')
63 files changed, 3632 insertions, 7 deletions
diff --git a/tests/shell/testcases/nft-f/0011manydefines_0 b/tests/shell/testcases/nft-f/0011manydefines_0 index 84664f46..aac06706 100755 --- a/tests/shell/testcases/nft-f/0011manydefines_0 +++ b/tests/shell/testcases/nft-f/0011manydefines_0 @@ -4,6 +4,15 @@ HOWMANY=20000 +if [ "$NFT_TEST_HAS_SOCKET_LIMITS" = y ] ; then + # The socket limit /proc/sys/net/core/wmem_max may be unsuitable for + # the test. + # + # Run only a subset of the test and mark as skipped at the end. + HOWMANY=2000 +fi + + tmpfile=$(mktemp) if [ ! -w $tmpfile ] ; then echo "Failed to create tmp file" >&2 @@ -35,3 +44,10 @@ table t { set -e $NFT -f $tmpfile + +if [ "$HOWMANY" != 20000 ] ; then + echo "NFT_TEST_HAS_SOCKET_LIMITS indicates that the socket limit for" + echo "/proc/sys/net/core/wmem_max is too small for this test. Mark as SKIPPED" + echo "You may bump the limit and rerun with \`NFT_TEST_HAS_SOCKET_LIMITS=n\`." + exit 77 +fi diff --git a/tests/shell/testcases/nft-f/0017ct_timeout_obj_0 b/tests/shell/testcases/nft-f/0017ct_timeout_obj_0 index 4f407793..cfb78950 100755 --- a/tests/shell/testcases/nft-f/0017ct_timeout_obj_0 +++ b/tests/shell/testcases/nft-f/0017ct_timeout_obj_0 @@ -1,5 +1,7 @@ #!/bin/bash +# NFT_TEST_REQUIRES(NFT_TEST_HAVE_cttimeout) + EXPECTED='table ip filter { ct timeout cttime{ protocol tcp diff --git a/tests/shell/testcases/nft-f/0018ct_expectation_obj_0 b/tests/shell/testcases/nft-f/0018ct_expectation_obj_0 index 4f9872f6..b288457c 100755 --- a/tests/shell/testcases/nft-f/0018ct_expectation_obj_0 +++ b/tests/shell/testcases/nft-f/0018ct_expectation_obj_0 @@ -1,5 +1,7 @@ #!/bin/bash +# NFT_TEST_REQUIRES(NFT_TEST_HAVE_ctexpect) + EXPECTED='table ip filter { ct expectation ctexpect{ protocol tcp diff --git a/tests/shell/testcases/nft-f/0025empty_dynset_0 b/tests/shell/testcases/nft-f/0025empty_dynset_0 index b66c802f..fbdb5793 100755 --- a/tests/shell/testcases/nft-f/0025empty_dynset_0 +++ b/tests/shell/testcases/nft-f/0025empty_dynset_0 @@ -1,5 +1,7 @@ #!/bin/bash +set -e + RULESET="table ip foo { set inflows { type ipv4_addr . inet_service . ifname . ipv4_addr . inet_service @@ -20,3 +22,9 @@ RULESET="table ip foo { }" $NFT -f - <<< "$RULESET" + +# inflows_ratelimit will be dumped without 'limit rate .. counter' on old kernels. +if [ "$NFT_TEST_HAVE_set_with_two_expressions" = n ]; then + echo "Partial test due to NFT_TEST_HAVE_set_with_two_expressions=n." + exit 77 +fi diff --git a/tests/shell/testcases/nft-f/0032pknock_0 b/tests/shell/testcases/nft-f/0032pknock_0 new file mode 100755 index 00000000..94fc8407 --- /dev/null +++ b/tests/shell/testcases/nft-f/0032pknock_0 @@ -0,0 +1,34 @@ +#!/bin/bash + +set -e + +RULESET="define guarded_ports = {ssh} + +table inet portknock { + set clients_ipv4 { + type ipv4_addr + flags timeout + } + + set candidates_ipv4 { + type ipv4_addr . inet_service + flags timeout + } + + chain input { + type filter hook input priority -10; policy accept; + + tcp dport 10001 add @candidates_ipv4 {ip saddr . 10002 timeout 1s} + tcp dport 10002 ip saddr . tcp dport @candidates_ipv4 add @candidates_ipv4 {ip saddr . 10003 timeout 1s} + tcp dport 10003 ip saddr . tcp dport @candidates_ipv4 add @candidates_ipv4 {ip saddr . 10004 timeout 1s} + tcp dport 10004 ip saddr . tcp dport @candidates_ipv4 add @candidates_ipv4 {ip saddr . 10005 timeout 1s} + tcp dport 10005 ip saddr . tcp dport @candidates_ipv4 add @clients_ipv4 {ip saddr timeout 600s} log prefix \"Successful portknock: \" + + tcp dport \$guarded_ports ip saddr @clients_ipv4 counter accept + tcp dport \$guarded_ports ct state established,related counter accept + + tcp dport \$guarded_ports reject with tcp reset + } +}" + +$NFT -f - <<< "$RULESET" diff --git a/tests/shell/testcases/nft-f/dumps/0001define_slash_0.json-nft b/tests/shell/testcases/nft-f/dumps/0001define_slash_0.json-nft new file mode 100644 index 00000000..546cc597 --- /dev/null +++ b/tests/shell/testcases/nft-f/dumps/0001define_slash_0.json-nft @@ -0,0 +1,11 @@ +{ + "nftables": [ + { + "metainfo": { + "version": "VERSION", + "release_name": "RELEASE_NAME", + "json_schema_version": 1 + } + } + ] +} diff --git a/tests/shell/testcases/nft-f/dumps/0001define_slash_0.nft b/tests/shell/testcases/nft-f/dumps/0001define_slash_0.nft new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/tests/shell/testcases/nft-f/dumps/0001define_slash_0.nft diff --git a/tests/shell/testcases/nft-f/dumps/0002rollback_rule_0.json-nft b/tests/shell/testcases/nft-f/dumps/0002rollback_rule_0.json-nft new file mode 100644 index 00000000..99b0b28d --- /dev/null +++ b/tests/shell/testcases/nft-f/dumps/0002rollback_rule_0.json-nft @@ -0,0 +1,134 @@ +{ + "nftables": [ + { + "metainfo": { + "version": "VERSION", + "release_name": "RELEASE_NAME", + "json_schema_version": 1 + } + }, + { + "table": { + "family": "ip", + "name": "t", + "handle": 0 + } + }, + { + "chain": { + "family": "ip", + "table": "t", + "name": "c", + "handle": 0 + } + }, + { + "chain": { + "family": "ip", + "table": "t", + "name": "other", + "handle": 0 + } + }, + { + "set": { + "family": "ip", + "name": "t", + "table": "t", + "type": "ipv4_addr", + "handle": 0, + "elem": [ + "1.1.1.1" + ] + } + }, + { + "rule": { + "family": "ip", + "table": "t", + "chain": "c", + "handle": 0, + "expr": [ + { + "match": { + "op": "in", + "left": { + "ct": { + "key": "state" + } + }, + "right": "new" + } + } + ] + } + }, + { + "rule": { + "family": "ip", + "table": "t", + "chain": "c", + "handle": 0, + "expr": [ + { + "match": { + "op": "==", + "left": { + "payload": { + "protocol": "tcp", + "field": "dport" + } + }, + "right": { + "set": [ + 22222, + 33333 + ] + } + } + } + ] + } + }, + { + "rule": { + "family": "ip", + "table": "t", + "chain": "c", + "handle": 0, + "expr": [ + { + "match": { + "op": "==", + "left": { + "payload": { + "protocol": "ip", + "field": "saddr" + } + }, + "right": "@t" + } + }, + { + "drop": null + } + ] + } + }, + { + "rule": { + "family": "ip", + "table": "t", + "chain": "c", + "handle": 0, + "expr": [ + { + "jump": { + "target": "other" + } + } + ] + } + } + ] +} diff --git a/tests/shell/testcases/nft-f/dumps/0003rollback_jump_0.json-nft b/tests/shell/testcases/nft-f/dumps/0003rollback_jump_0.json-nft new file mode 100644 index 00000000..99b0b28d --- /dev/null +++ b/tests/shell/testcases/nft-f/dumps/0003rollback_jump_0.json-nft @@ -0,0 +1,134 @@ +{ + "nftables": [ + { + "metainfo": { + "version": "VERSION", + "release_name": "RELEASE_NAME", + "json_schema_version": 1 + } + }, + { + "table": { + "family": "ip", + "name": "t", + "handle": 0 + } + }, + { + "chain": { + "family": "ip", + "table": "t", + "name": "c", + "handle": 0 + } + }, + { + "chain": { + "family": "ip", + "table": "t", + "name": "other", + "handle": 0 + } + }, + { + "set": { + "family": "ip", + "name": "t", + "table": "t", + "type": "ipv4_addr", + "handle": 0, + "elem": [ + "1.1.1.1" + ] + } + }, + { + "rule": { + "family": "ip", + "table": "t", + "chain": "c", + "handle": 0, + "expr": [ + { + "match": { + "op": "in", + "left": { + "ct": { + "key": "state" + } + }, + "right": "new" + } + } + ] + } + }, + { + "rule": { + "family": "ip", + "table": "t", + "chain": "c", + "handle": 0, + "expr": [ + { + "match": { + "op": "==", + "left": { + "payload": { + "protocol": "tcp", + "field": "dport" + } + }, + "right": { + "set": [ + 22222, + 33333 + ] + } + } + } + ] + } + }, + { + "rule": { + "family": "ip", + "table": "t", + "chain": "c", + "handle": 0, + "expr": [ + { + "match": { + "op": "==", + "left": { + "payload": { + "protocol": "ip", + "field": "saddr" + } + }, + "right": "@t" + } + }, + { + "drop": null + } + ] + } + }, + { + "rule": { + "family": "ip", + "table": "t", + "chain": "c", + "handle": 0, + "expr": [ + { + "jump": { + "target": "other" + } + } + ] + } + } + ] +} diff --git a/tests/shell/testcases/nft-f/dumps/0004rollback_set_0.json-nft b/tests/shell/testcases/nft-f/dumps/0004rollback_set_0.json-nft new file mode 100644 index 00000000..99b0b28d --- /dev/null +++ b/tests/shell/testcases/nft-f/dumps/0004rollback_set_0.json-nft @@ -0,0 +1,134 @@ +{ + "nftables": [ + { + "metainfo": { + "version": "VERSION", + "release_name": "RELEASE_NAME", + "json_schema_version": 1 + } + }, + { + "table": { + "family": "ip", + "name": "t", + "handle": 0 + } + }, + { + "chain": { + "family": "ip", + "table": "t", + "name": "c", + "handle": 0 + } + }, + { + "chain": { + "family": "ip", + "table": "t", + "name": "other", + "handle": 0 + } + }, + { + "set": { + "family": "ip", + "name": "t", + "table": "t", + "type": "ipv4_addr", + "handle": 0, + "elem": [ + "1.1.1.1" + ] + } + }, + { + "rule": { + "family": "ip", + "table": "t", + "chain": "c", + "handle": 0, + "expr": [ + { + "match": { + "op": "in", + "left": { + "ct": { + "key": "state" + } + }, + "right": "new" + } + } + ] + } + }, + { + "rule": { + "family": "ip", + "table": "t", + "chain": "c", + "handle": 0, + "expr": [ + { + "match": { + "op": "==", + "left": { + "payload": { + "protocol": "tcp", + "field": "dport" + } + }, + "right": { + "set": [ + 22222, + 33333 + ] + } + } + } + ] + } + }, + { + "rule": { + "family": "ip", + "table": "t", + "chain": "c", + "handle": 0, + "expr": [ + { + "match": { + "op": "==", + "left": { + "payload": { + "protocol": "ip", + "field": "saddr" + } + }, + "right": "@t" + } + }, + { + "drop": null + } + ] + } + }, + { + "rule": { + "family": "ip", + "table": "t", + "chain": "c", + "handle": 0, + "expr": [ + { + "jump": { + "target": "other" + } + } + ] + } + } + ] +} diff --git a/tests/shell/testcases/nft-f/dumps/0005rollback_map_0.json-nft b/tests/shell/testcases/nft-f/dumps/0005rollback_map_0.json-nft new file mode 100644 index 00000000..99b0b28d --- /dev/null +++ b/tests/shell/testcases/nft-f/dumps/0005rollback_map_0.json-nft @@ -0,0 +1,134 @@ +{ + "nftables": [ + { + "metainfo": { + "version": "VERSION", + "release_name": "RELEASE_NAME", + "json_schema_version": 1 + } + }, + { + "table": { + "family": "ip", + "name": "t", + "handle": 0 + } + }, + { + "chain": { + "family": "ip", + "table": "t", + "name": "c", + "handle": 0 + } + }, + { + "chain": { + "family": "ip", + "table": "t", + "name": "other", + "handle": 0 + } + }, + { + "set": { + "family": "ip", + "name": "t", + "table": "t", + "type": "ipv4_addr", + "handle": 0, + "elem": [ + "1.1.1.1" + ] + } + }, + { + "rule": { + "family": "ip", + "table": "t", + "chain": "c", + "handle": 0, + "expr": [ + { + "match": { + "op": "in", + "left": { + "ct": { + "key": "state" + } + }, + "right": "new" + } + } + ] + } + }, + { + "rule": { + "family": "ip", + "table": "t", + "chain": "c", + "handle": 0, + "expr": [ + { + "match": { + "op": "==", + "left": { + "payload": { + "protocol": "tcp", + "field": "dport" + } + }, + "right": { + "set": [ + 22222, + 33333 + ] + } + } + } + ] + } + }, + { + "rule": { + "family": "ip", + "table": "t", + "chain": "c", + "handle": 0, + "expr": [ + { + "match": { + "op": "==", + "left": { + "payload": { + "protocol": "ip", + "field": "saddr" + } + }, + "right": "@t" + } + }, + { + "drop": null + } + ] + } + }, + { + "rule": { + "family": "ip", + "table": "t", + "chain": "c", + "handle": 0, + "expr": [ + { + "jump": { + "target": "other" + } + } + ] + } + } + ] +} diff --git a/tests/shell/testcases/nft-f/dumps/0006action_object_0.json-nft b/tests/shell/testcases/nft-f/dumps/0006action_object_0.json-nft new file mode 100644 index 00000000..546cc597 --- /dev/null +++ b/tests/shell/testcases/nft-f/dumps/0006action_object_0.json-nft @@ -0,0 +1,11 @@ +{ + "nftables": [ + { + "metainfo": { + "version": "VERSION", + "release_name": "RELEASE_NAME", + "json_schema_version": 1 + } + } + ] +} diff --git a/tests/shell/testcases/nft-f/dumps/0006action_object_0.nft b/tests/shell/testcases/nft-f/dumps/0006action_object_0.nft new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/tests/shell/testcases/nft-f/dumps/0006action_object_0.nft diff --git a/tests/shell/testcases/nft-f/dumps/0007action_object_set_segfault_1.json-nft b/tests/shell/testcases/nft-f/dumps/0007action_object_set_segfault_1.json-nft new file mode 100644 index 00000000..546cc597 --- /dev/null +++ b/tests/shell/testcases/nft-f/dumps/0007action_object_set_segfault_1.json-nft @@ -0,0 +1,11 @@ +{ + "nftables": [ + { + "metainfo": { + "version": "VERSION", + "release_name": "RELEASE_NAME", + "json_schema_version": 1 + } + } + ] +} diff --git a/tests/shell/testcases/nft-f/dumps/0007action_object_set_segfault_1.nft b/tests/shell/testcases/nft-f/dumps/0007action_object_set_segfault_1.nft new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/tests/shell/testcases/nft-f/dumps/0007action_object_set_segfault_1.nft diff --git a/tests/shell/testcases/nft-f/dumps/0008split_tables_0.json-nft b/tests/shell/testcases/nft-f/dumps/0008split_tables_0.json-nft new file mode 100644 index 00000000..05ebed5a --- /dev/null +++ b/tests/shell/testcases/nft-f/dumps/0008split_tables_0.json-nft @@ -0,0 +1,67 @@ +{ + "nftables": [ + { + "metainfo": { + "version": "VERSION", + "release_name": "RELEASE_NAME", + "json_schema_version": 1 + } + }, + { + "table": { + "family": "inet", + "name": "filter", + "handle": 0 + } + }, + { + "chain": { + "family": "inet", + "table": "filter", + "name": "ssh", + "handle": 0, + "type": "filter", + "hook": "input", + "prio": 0, + "policy": "accept" + } + }, + { + "chain": { + "family": "inet", + "table": "filter", + "name": "input", + "handle": 0, + "type": "filter", + "hook": "input", + "prio": 1, + "policy": "accept" + } + }, + { + "rule": { + "family": "inet", + "table": "filter", + "chain": "ssh", + "handle": 0, + "expr": [ + { + "match": { + "op": "==", + "left": { + "payload": { + "protocol": "tcp", + "field": "dport" + } + }, + "right": 22 + } + }, + { + "accept": null + } + ] + } + } + ] +} diff --git a/tests/shell/testcases/nft-f/dumps/0009variable_0.json-nft b/tests/shell/testcases/nft-f/dumps/0009variable_0.json-nft new file mode 100644 index 00000000..41236dbe --- /dev/null +++ b/tests/shell/testcases/nft-f/dumps/0009variable_0.json-nft @@ -0,0 +1,44 @@ +{ + "nftables": [ + { + "metainfo": { + "version": "VERSION", + "release_name": "RELEASE_NAME", + "json_schema_version": 1 + } + }, + { + "table": { + "family": "inet", + "name": "forward", + "handle": 0 + } + }, + { + "set": { + "family": "inet", + "name": "concat-set-variable", + "table": "forward", + "type": [ + "ipv4_addr", + "inet_service" + ], + "handle": 0, + "elem": [ + { + "concat": [ + "10.10.10.10", + 25 + ] + }, + { + "concat": [ + "10.10.10.10", + 143 + ] + } + ] + } + } + ] +} diff --git a/tests/shell/testcases/nft-f/dumps/0010variable_0.json-nft b/tests/shell/testcases/nft-f/dumps/0010variable_0.json-nft new file mode 100644 index 00000000..4b4ec4fb --- /dev/null +++ b/tests/shell/testcases/nft-f/dumps/0010variable_0.json-nft @@ -0,0 +1,30 @@ +{ + "nftables": [ + { + "metainfo": { + "version": "VERSION", + "release_name": "RELEASE_NAME", + "json_schema_version": 1 + } + }, + { + "table": { + "family": "inet", + "name": "filter", + "handle": 0 + } + }, + { + "set": { + "family": "inet", + "name": "whitelist_v4", + "table": "filter", + "type": "ipv4_addr", + "handle": 0, + "elem": [ + "1.1.1.1" + ] + } + } + ] +} diff --git a/tests/shell/testcases/nft-f/dumps/0011manydefines_0.nodump b/tests/shell/testcases/nft-f/dumps/0011manydefines_0.nodump new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/tests/shell/testcases/nft-f/dumps/0011manydefines_0.nodump diff --git a/tests/shell/testcases/nft-f/dumps/0012different_defines_0.json-nft b/tests/shell/testcases/nft-f/dumps/0012different_defines_0.json-nft new file mode 100644 index 00000000..1b2e3420 --- /dev/null +++ b/tests/shell/testcases/nft-f/dumps/0012different_defines_0.json-nft @@ -0,0 +1,778 @@ +{ + "nftables": [ + { + "metainfo": { + "version": "VERSION", + "release_name": "RELEASE_NAME", + "json_schema_version": 1 + } + }, + { + "table": { + "family": "inet", + "name": "t", + "handle": 0 + } + }, + { + "chain": { + "family": "inet", + "table": "t", + "name": "c", + "handle": 0 + } + }, + { + "rule": { + "family": "inet", + "table": "t", + "chain": "c", + "handle": 0, + "expr": [ + { + "match": { + "op": "==", + "left": { + "meta": { + "key": "iifname" + } + }, + "right": "whatever" + } + }, + { + "match": { + "op": "==", + "left": { + "meta": { + "key": "oifname" + } + }, + "right": "whatever" + } + }, + { + "match": { + "op": "==", + "left": { + "meta": { + "key": "iif" + } + }, + "right": "lo" + } + }, + { + "match": { + "op": "==", + "left": { + "meta": { + "key": "oif" + } + }, + "right": "lo" + } + } + ] + } + }, + { + "rule": { + "family": "inet", + "table": "t", + "chain": "c", + "handle": 0, + "expr": [ + { + "match": { + "op": "==", + "left": { + "meta": { + "key": "iifname" + } + }, + "right": { + "set": [ + "whatever" + ] + } + } + }, + { + "match": { + "op": "==", + "left": { + "meta": { + "key": "iif" + } + }, + "right": { + "set": [ + "lo" + ] + } + } + }, + { + "match": { + "op": "==", + "left": { + "meta": { + "key": "mark" + } + }, + "right": 123 + } + } + ] + } + }, + { + "rule": { + "family": "inet", + "table": "t", + "chain": "c", + "handle": 0, + "expr": [ + { + "match": { + "op": "in", + "left": { + "ct": { + "key": "state" + } + }, + "right": [ + "established", + "related", + "new" + ] + } + } + ] + } + }, + { + "rule": { + "family": "inet", + "table": "t", + "chain": "c", + "handle": 0, + "expr": [ + { + "match": { + "op": "!=", + "left": { + "ct": { + "key": "state" + } + }, + "right": { + "|": [ + "established", + "related", + "new" + ] + } + } + } + ] + } + }, + { + "rule": { + "family": "inet", + "table": "t", + "chain": "c", + "handle": 0, + "expr": [ + { + "match": { + "op": "==", + "left": { + "payload": { + "protocol": "ip", + "field": "saddr" + } + }, + "right": "10.0.0.0" + } + }, + { + "match": { + "op": "==", + "left": { + "payload": { + "protocol": "ip", + "field": "daddr" + } + }, + "right": "10.0.0.2" + } + }, + { + "match": { + "op": "==", + "left": { + "payload": { + "protocol": "ip", + "field": "saddr" + } + }, + "right": "10.0.0.0" + } + } + ] + } + }, + { + "rule": { + "family": "inet", + "table": "t", + "chain": "c", + "handle": 0, + "expr": [ + { + "match": { + "op": "==", + "left": { + "payload": { + "protocol": "ip6", + "field": "daddr" + } + }, + "right": "fe0::1" + } + }, + { + "match": { + "op": "==", + "left": { + "payload": { + "protocol": "ip6", + "field": "saddr" + } + }, + "right": "fe0::2" + } + } + ] + } + }, + { + "rule": { + "family": "inet", + "table": "t", + "chain": "c", + "handle": 0, + "expr": [ + { + "vmap": { + "key": { + "payload": { + "protocol": "ip", + "field": "saddr" + } + }, + "data": { + "set": [ + [ + "10.0.0.0", + { + "drop": null + } + ], + [ + "10.0.0.2", + { + "accept": null + } + ] + ] + } + } + } + ] + } + }, + { + "rule": { + "family": "inet", + "table": "t", + "chain": "c", + "handle": 0, + "expr": [ + { + "vmap": { + "key": { + "payload": { + "protocol": "ip6", + "field": "daddr" + } + }, + "data": { + "set": [ + [ + "fe0::1", + { + "drop": null + } + ], + [ + "fe0::2", + { + "accept": null + } + ] + ] + } + } + } + ] + } + }, + { + "rule": { + "family": "inet", + "table": "t", + "chain": "c", + "handle": 0, + "expr": [ + { + "match": { + "op": "==", + "left": { + "concat": [ + { + "payload": { + "protocol": "ip6", + "field": "saddr" + } + }, + { + "payload": { + "protocol": "ip6", + "field": "nexthdr" + } + } + ] + }, + "right": { + "set": [ + { + "concat": [ + "fe0::2", + "tcp" + ] + }, + { + "concat": [ + "fe0::1", + "udp" + ] + } + ] + } + } + } + ] + } + }, + { + "rule": { + "family": "inet", + "table": "t", + "chain": "c", + "handle": 0, + "expr": [ + { + "vmap": { + "key": { + "concat": [ + { + "payload": { + "protocol": "ip", + "field": "daddr" + } + }, + { + "meta": { + "key": "iif" + } + } + ] + }, + "data": { + "set": [ + [ + { + "concat": [ + "10.0.0.0", + "lo" + ] + }, + { + "accept": null + } + ] + ] + } + } + } + ] + } + }, + { + "rule": { + "family": "inet", + "table": "t", + "chain": "c", + "handle": 0, + "expr": [ + { + "match": { + "op": "==", + "left": { + "payload": { + "protocol": "tcp", + "field": "dport" + } + }, + "right": { + "range": [ + 100, + 222 + ] + } + } + } + ] + } + }, + { + "rule": { + "family": "inet", + "table": "t", + "chain": "c", + "handle": 0, + "expr": [ + { + "vmap": { + "key": { + "payload": { + "protocol": "udp", + "field": "dport" + } + }, + "data": { + "set": [ + [ + { + "range": [ + 100, + 222 + ] + }, + { + "accept": null + } + ] + ] + } + } + } + ] + } + }, + { + "rule": { + "family": "inet", + "table": "t", + "chain": "c", + "handle": 0, + "expr": [ + { + "match": { + "op": "==", + "left": { + "payload": { + "protocol": "tcp", + "field": "sport" + } + }, + "right": 1 + } + }, + { + "match": { + "op": "==", + "left": { + "payload": { + "protocol": "tcp", + "field": "dport" + } + }, + "right": 1 + } + }, + { + "match": { + "op": "==", + "left": { + "meta": { + "key": "oifname" + } + }, + "right": "foobar" + } + }, + { + "queue": { + "num": 0, + "flags": "bypass" + } + } + ] + } + }, + { + "rule": { + "family": "inet", + "table": "t", + "chain": "c", + "handle": 0, + "expr": [ + { + "match": { + "op": "==", + "left": { + "payload": { + "protocol": "tcp", + "field": "sport" + } + }, + "right": 1 + } + }, + { + "match": { + "op": "==", + "left": { + "payload": { + "protocol": "tcp", + "field": "dport" + } + }, + "right": 1 + } + }, + { + "match": { + "op": "==", + "left": { + "meta": { + "key": "oifname" + } + }, + "right": "foobar" + } + }, + { + "queue": { + "num": { + "range": [ + 1, + 42 + ] + } + } + } + ] + } + }, + { + "rule": { + "family": "inet", + "table": "t", + "chain": "c", + "handle": 0, + "expr": [ + { + "match": { + "op": "==", + "left": { + "payload": { + "protocol": "tcp", + "field": "sport" + } + }, + "right": 1 + } + }, + { + "match": { + "op": "==", + "left": { + "payload": { + "protocol": "tcp", + "field": "dport" + } + }, + "right": 1 + } + }, + { + "match": { + "op": "==", + "left": { + "meta": { + "key": "oifname" + } + }, + "right": "foobar" + } + }, + { + "queue": { + "num": { + "range": [ + 1, + 42 + ] + }, + "flags": [ + "bypass", + "fanout" + ] + } + } + ] + } + }, + { + "rule": { + "family": "inet", + "table": "t", + "chain": "c", + "handle": 0, + "expr": [ + { + "match": { + "op": "==", + "left": { + "payload": { + "protocol": "tcp", + "field": "sport" + } + }, + "right": 1 + } + }, + { + "match": { + "op": "==", + "left": { + "payload": { + "protocol": "tcp", + "field": "dport" + } + }, + "right": 1 + } + }, + { + "match": { + "op": "==", + "left": { + "meta": { + "key": "oifname" + } + }, + "right": "foobar" + } + }, + { + "queue": { + "num": { + "symhash": { + "mod": 2 + } + } + } + } + ] + } + }, + { + "rule": { + "family": "inet", + "table": "t", + "chain": "c", + "handle": 0, + "expr": [ + { + "match": { + "op": "==", + "left": { + "payload": { + "protocol": "tcp", + "field": "sport" + } + }, + "right": 1 + } + }, + { + "match": { + "op": "==", + "left": { + "payload": { + "protocol": "tcp", + "field": "dport" + } + }, + "right": 1 + } + }, + { + "match": { + "op": "==", + "left": { + "meta": { + "key": "oifname" + } + }, + "right": "foobar" + } + }, + { + "queue": { + "num": { + "jhash": { + "mod": 4, + "expr": { + "concat": [ + { + "payload": { + "protocol": "tcp", + "field": "dport" + } + }, + { + "payload": { + "protocol": "tcp", + "field": "sport" + } + } + ] + } + } + }, + "flags": "bypass" + } + } + ] + } + } + ] +} diff --git a/tests/shell/testcases/nft-f/dumps/0013defines_1.json-nft b/tests/shell/testcases/nft-f/dumps/0013defines_1.json-nft new file mode 100644 index 00000000..546cc597 --- /dev/null +++ b/tests/shell/testcases/nft-f/dumps/0013defines_1.json-nft @@ -0,0 +1,11 @@ +{ + "nftables": [ + { + "metainfo": { + "version": "VERSION", + "release_name": "RELEASE_NAME", + "json_schema_version": 1 + } + } + ] +} diff --git a/tests/shell/testcases/nft-f/dumps/0013defines_1.nft b/tests/shell/testcases/nft-f/dumps/0013defines_1.nft new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/tests/shell/testcases/nft-f/dumps/0013defines_1.nft diff --git a/tests/shell/testcases/nft-f/dumps/0014defines_1.json-nft b/tests/shell/testcases/nft-f/dumps/0014defines_1.json-nft new file mode 100644 index 00000000..546cc597 --- /dev/null +++ b/tests/shell/testcases/nft-f/dumps/0014defines_1.json-nft @@ -0,0 +1,11 @@ +{ + "nftables": [ + { + "metainfo": { + "version": "VERSION", + "release_name": "RELEASE_NAME", + "json_schema_version": 1 + } + } + ] +} diff --git a/tests/shell/testcases/nft-f/dumps/0014defines_1.nft b/tests/shell/testcases/nft-f/dumps/0014defines_1.nft new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/tests/shell/testcases/nft-f/dumps/0014defines_1.nft diff --git a/tests/shell/testcases/nft-f/dumps/0015defines_1.json-nft b/tests/shell/testcases/nft-f/dumps/0015defines_1.json-nft new file mode 100644 index 00000000..546cc597 --- /dev/null +++ b/tests/shell/testcases/nft-f/dumps/0015defines_1.json-nft @@ -0,0 +1,11 @@ +{ + "nftables": [ + { + "metainfo": { + "version": "VERSION", + "release_name": "RELEASE_NAME", + "json_schema_version": 1 + } + } + ] +} diff --git a/tests/shell/testcases/nft-f/dumps/0015defines_1.nft b/tests/shell/testcases/nft-f/dumps/0015defines_1.nft new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/tests/shell/testcases/nft-f/dumps/0015defines_1.nft diff --git a/tests/shell/testcases/nft-f/dumps/0016redefines_1.json-nft b/tests/shell/testcases/nft-f/dumps/0016redefines_1.json-nft new file mode 100644 index 00000000..40cdb000 --- /dev/null +++ b/tests/shell/testcases/nft-f/dumps/0016redefines_1.json-nft @@ -0,0 +1,80 @@ +{ + "nftables": [ + { + "metainfo": { + "version": "VERSION", + "release_name": "RELEASE_NAME", + "json_schema_version": 1 + } + }, + { + "table": { + "family": "ip", + "name": "x", + "handle": 0 + } + }, + { + "chain": { + "family": "ip", + "table": "x", + "name": "y", + "handle": 0 + } + }, + { + "rule": { + "family": "ip", + "table": "x", + "chain": "y", + "handle": 0, + "expr": [ + { + "match": { + "op": "==", + "left": { + "payload": { + "protocol": "ip", + "field": "saddr" + } + }, + "right": { + "set": [ + "1.1.1.1", + "2.2.2.2" + ] + } + } + } + ] + } + }, + { + "rule": { + "family": "ip", + "table": "x", + "chain": "y", + "handle": 0, + "expr": [ + { + "match": { + "op": "==", + "left": { + "payload": { + "protocol": "ip", + "field": "saddr" + } + }, + "right": { + "set": [ + "3.3.3.3", + "4.4.4.4" + ] + } + } + } + ] + } + } + ] +} diff --git a/tests/shell/testcases/nft-f/dumps/0016redefines_1.nft b/tests/shell/testcases/nft-f/dumps/0016redefines_1.nft new file mode 100644 index 00000000..65b7f491 --- /dev/null +++ b/tests/shell/testcases/nft-f/dumps/0016redefines_1.nft @@ -0,0 +1,6 @@ +table ip x { + chain y { + ip saddr { 1.1.1.1, 2.2.2.2 } + ip saddr { 3.3.3.3, 4.4.4.4 } + } +} diff --git a/tests/shell/testcases/nft-f/dumps/0017ct_timeout_obj_0.json-nft b/tests/shell/testcases/nft-f/dumps/0017ct_timeout_obj_0.json-nft new file mode 100644 index 00000000..b56240ea --- /dev/null +++ b/tests/shell/testcases/nft-f/dumps/0017ct_timeout_obj_0.json-nft @@ -0,0 +1,53 @@ +{ + "nftables": [ + { + "metainfo": { + "version": "VERSION", + "release_name": "RELEASE_NAME", + "json_schema_version": 1 + } + }, + { + "table": { + "family": "ip", + "name": "filter", + "handle": 0 + } + }, + { + "chain": { + "family": "ip", + "table": "filter", + "name": "c", + "handle": 0 + } + }, + { + "ct timeout": { + "family": "ip", + "name": "cttime", + "table": "filter", + "handle": 0, + "protocol": "tcp", + "l3proto": "ip", + "policy": { + "established": 123, + "close": 12 + } + } + }, + { + "rule": { + "family": "ip", + "table": "filter", + "chain": "c", + "handle": 0, + "expr": [ + { + "ct timeout": "cttime" + } + ] + } + } + ] +} diff --git a/tests/shell/testcases/nft-f/dumps/0017ct_timeout_obj_0.nft b/tests/shell/testcases/nft-f/dumps/0017ct_timeout_obj_0.nft index 7cff1ed5..c5d9649e 100644 --- a/tests/shell/testcases/nft-f/dumps/0017ct_timeout_obj_0.nft +++ b/tests/shell/testcases/nft-f/dumps/0017ct_timeout_obj_0.nft @@ -2,7 +2,7 @@ table ip filter { ct timeout cttime { protocol tcp l3proto ip - policy = { established : 123, close : 12 } + policy = { established : 2m3s, close : 12s } } chain c { diff --git a/tests/shell/testcases/nft-f/dumps/0018ct_expectation_obj_0.json-nft b/tests/shell/testcases/nft-f/dumps/0018ct_expectation_obj_0.json-nft new file mode 100644 index 00000000..21c97970 --- /dev/null +++ b/tests/shell/testcases/nft-f/dumps/0018ct_expectation_obj_0.json-nft @@ -0,0 +1,52 @@ +{ + "nftables": [ + { + "metainfo": { + "version": "VERSION", + "release_name": "RELEASE_NAME", + "json_schema_version": 1 + } + }, + { + "table": { + "family": "ip", + "name": "filter", + "handle": 0 + } + }, + { + "chain": { + "family": "ip", + "table": "filter", + "name": "c", + "handle": 0 + } + }, + { + "ct expectation": { + "family": "ip", + "name": "ctexpect", + "table": "filter", + "handle": 0, + "protocol": "tcp", + "dport": 9876, + "timeout": 60000, + "size": 12, + "l3proto": "ip" + } + }, + { + "rule": { + "family": "ip", + "table": "filter", + "chain": "c", + "handle": 0, + "expr": [ + { + "ct expectation": "ctexpect" + } + ] + } + } + ] +} diff --git a/tests/shell/testcases/nft-f/dumps/0018ct_expectation_obj_0.nft b/tests/shell/testcases/nft-f/dumps/0018ct_expectation_obj_0.nft new file mode 100644 index 00000000..396185eb --- /dev/null +++ b/tests/shell/testcases/nft-f/dumps/0018ct_expectation_obj_0.nft @@ -0,0 +1,13 @@ +table ip filter { + ct expectation ctexpect { + protocol tcp + dport 9876 + timeout 1m + size 12 + l3proto ip + } + + chain c { + ct expectation set "ctexpect" + } +} diff --git a/tests/shell/testcases/nft-f/dumps/0018jump_variable_0.json-nft b/tests/shell/testcases/nft-f/dumps/0018jump_variable_0.json-nft new file mode 100644 index 00000000..f62b48a3 --- /dev/null +++ b/tests/shell/testcases/nft-f/dumps/0018jump_variable_0.json-nft @@ -0,0 +1,49 @@ +{ + "nftables": [ + { + "metainfo": { + "version": "VERSION", + "release_name": "RELEASE_NAME", + "json_schema_version": 1 + } + }, + { + "table": { + "family": "ip", + "name": "foo", + "handle": 0 + } + }, + { + "chain": { + "family": "ip", + "table": "foo", + "name": "bar", + "handle": 0 + } + }, + { + "chain": { + "family": "ip", + "table": "foo", + "name": "ber", + "handle": 0 + } + }, + { + "rule": { + "family": "ip", + "table": "foo", + "chain": "bar", + "handle": 0, + "expr": [ + { + "jump": { + "target": "ber" + } + } + ] + } + } + ] +} diff --git a/tests/shell/testcases/nft-f/dumps/0019jump_variable_1.json-nft b/tests/shell/testcases/nft-f/dumps/0019jump_variable_1.json-nft new file mode 100644 index 00000000..546cc597 --- /dev/null +++ b/tests/shell/testcases/nft-f/dumps/0019jump_variable_1.json-nft @@ -0,0 +1,11 @@ +{ + "nftables": [ + { + "metainfo": { + "version": "VERSION", + "release_name": "RELEASE_NAME", + "json_schema_version": 1 + } + } + ] +} diff --git a/tests/shell/testcases/nft-f/dumps/0019jump_variable_1.nft b/tests/shell/testcases/nft-f/dumps/0019jump_variable_1.nft new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/tests/shell/testcases/nft-f/dumps/0019jump_variable_1.nft diff --git a/tests/shell/testcases/nft-f/dumps/0020jump_variable_1.json-nft b/tests/shell/testcases/nft-f/dumps/0020jump_variable_1.json-nft new file mode 100644 index 00000000..546cc597 --- /dev/null +++ b/tests/shell/testcases/nft-f/dumps/0020jump_variable_1.json-nft @@ -0,0 +1,11 @@ +{ + "nftables": [ + { + "metainfo": { + "version": "VERSION", + "release_name": "RELEASE_NAME", + "json_schema_version": 1 + } + } + ] +} diff --git a/tests/shell/testcases/nft-f/dumps/0020jump_variable_1.nft b/tests/shell/testcases/nft-f/dumps/0020jump_variable_1.nft new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/tests/shell/testcases/nft-f/dumps/0020jump_variable_1.nft diff --git a/tests/shell/testcases/nft-f/dumps/0021list_ruleset_0.json-nft b/tests/shell/testcases/nft-f/dumps/0021list_ruleset_0.json-nft new file mode 100644 index 00000000..f41b1b04 --- /dev/null +++ b/tests/shell/testcases/nft-f/dumps/0021list_ruleset_0.json-nft @@ -0,0 +1,30 @@ +{ + "nftables": [ + { + "metainfo": { + "version": "VERSION", + "release_name": "RELEASE_NAME", + "json_schema_version": 1 + } + }, + { + "table": { + "family": "ip", + "name": "filter", + "handle": 0 + } + }, + { + "chain": { + "family": "ip", + "table": "filter", + "name": "prerouting", + "handle": 0, + "type": "filter", + "hook": "prerouting", + "prio": -50, + "policy": "accept" + } + } + ] +} diff --git a/tests/shell/testcases/nft-f/dumps/0022variables_0.json-nft b/tests/shell/testcases/nft-f/dumps/0022variables_0.json-nft new file mode 100644 index 00000000..09a4c1e3 --- /dev/null +++ b/tests/shell/testcases/nft-f/dumps/0022variables_0.json-nft @@ -0,0 +1,115 @@ +{ + "nftables": [ + { + "metainfo": { + "version": "VERSION", + "release_name": "RELEASE_NAME", + "json_schema_version": 1 + } + }, + { + "table": { + "family": "ip", + "name": "x", + "handle": 0 + } + }, + { + "chain": { + "family": "ip", + "table": "x", + "name": "z", + "handle": 0, + "type": "filter", + "hook": "input", + "prio": 0, + "policy": "accept" + } + }, + { + "set": { + "family": "ip", + "name": "y", + "table": "x", + "type": "ipv4_addr", + "handle": 0, + "size": 65535, + "flags": [ + "timeout", + "dynamic" + ] + } + }, + { + "rule": { + "family": "ip", + "table": "x", + "chain": "z", + "handle": 0, + "expr": [ + { + "set": { + "op": "add", + "elem": { + "payload": { + "protocol": "ip", + "field": "saddr" + } + }, + "set": "@y" + } + } + ] + } + }, + { + "rule": { + "family": "ip", + "table": "x", + "chain": "z", + "handle": 0, + "expr": [ + { + "set": { + "op": "update", + "elem": { + "elem": { + "val": { + "payload": { + "protocol": "ip", + "field": "saddr" + } + }, + "timeout": 30 + } + }, + "set": "@y" + } + } + ] + } + }, + { + "rule": { + "family": "ip", + "table": "x", + "chain": "z", + "handle": 0, + "expr": [ + { + "match": { + "op": "==", + "left": { + "payload": { + "protocol": "ip", + "field": "saddr" + } + }, + "right": "@y" + } + } + ] + } + } + ] +} diff --git a/tests/shell/testcases/nft-f/dumps/0023check_1.json-nft b/tests/shell/testcases/nft-f/dumps/0023check_1.json-nft new file mode 100644 index 00000000..ddb2a057 --- /dev/null +++ b/tests/shell/testcases/nft-f/dumps/0023check_1.json-nft @@ -0,0 +1,30 @@ +{ + "nftables": [ + { + "metainfo": { + "version": "VERSION", + "release_name": "RELEASE_NAME", + "json_schema_version": 1 + } + }, + { + "table": { + "family": "ip", + "name": "foo", + "handle": 0 + } + }, + { + "chain": { + "family": "ip", + "table": "foo", + "name": "bar", + "handle": 0, + "type": "filter", + "hook": "prerouting", + "prio": 0, + "policy": "accept" + } + } + ] +} diff --git a/tests/shell/testcases/nft-f/dumps/0023check_1.nft b/tests/shell/testcases/nft-f/dumps/0023check_1.nft new file mode 100644 index 00000000..04b9e70f --- /dev/null +++ b/tests/shell/testcases/nft-f/dumps/0023check_1.nft @@ -0,0 +1,5 @@ +table ip foo { + chain bar { + type filter hook prerouting priority filter; policy accept; + } +} diff --git a/tests/shell/testcases/nft-f/dumps/0024priority_0.json-nft b/tests/shell/testcases/nft-f/dumps/0024priority_0.json-nft new file mode 100644 index 00000000..cdc4b9d9 --- /dev/null +++ b/tests/shell/testcases/nft-f/dumps/0024priority_0.json-nft @@ -0,0 +1,95 @@ +{ + "nftables": [ + { + "metainfo": { + "version": "VERSION", + "release_name": "RELEASE_NAME", + "json_schema_version": 1 + } + }, + { + "table": { + "family": "inet", + "name": "statelessnat", + "handle": 0 + } + }, + { + "chain": { + "family": "inet", + "table": "statelessnat", + "name": "prerouting", + "handle": 0, + "type": "filter", + "hook": "prerouting", + "prio": -100, + "policy": "accept" + } + }, + { + "chain": { + "family": "inet", + "table": "statelessnat", + "name": "postrouting", + "handle": 0, + "type": "filter", + "hook": "postrouting", + "prio": 100, + "policy": "accept" + } + }, + { + "rule": { + "family": "inet", + "table": "statelessnat", + "chain": "prerouting", + "handle": 0, + "expr": [ + { + "mangle": { + "key": { + "payload": { + "protocol": "ip", + "field": "daddr" + } + }, + "value": { + "map": { + "key": { + "numgen": { + "mode": "inc", + "mod": 16, + "offset": 0 + } + }, + "data": { + "set": [ + [ + { + "range": [ + 0, + 7 + ] + }, + "10.0.1.1" + ], + [ + { + "range": [ + 8, + 15 + ] + }, + "10.0.1.2" + ] + ] + } + } + } + } + } + ] + } + } + ] +} diff --git a/tests/shell/testcases/nft-f/dumps/0025empty_dynset_0.json-nft b/tests/shell/testcases/nft-f/dumps/0025empty_dynset_0.json-nft new file mode 100644 index 00000000..63d67641 --- /dev/null +++ b/tests/shell/testcases/nft-f/dumps/0025empty_dynset_0.json-nft @@ -0,0 +1,105 @@ +{ + "nftables": [ + { + "metainfo": { + "version": "VERSION", + "release_name": "RELEASE_NAME", + "json_schema_version": 1 + } + }, + { + "table": { + "family": "ip", + "name": "foo", + "handle": 0 + } + }, + { + "set": { + "family": "ip", + "name": "inflows", + "table": "foo", + "type": [ + "ipv4_addr", + "inet_service", + "ifname", + "ipv4_addr", + "inet_service" + ], + "handle": 0, + "flags": "dynamic", + "elem": [ + { + "elem": { + "val": { + "concat": [ + "10.1.0.3", + 39466, + "veth1", + "10.3.0.99", + 5201 + ] + }, + "counter": { + "packets": 0, + "bytes": 0 + } + } + } + ] + } + }, + { + "set": { + "family": "ip", + "name": "inflows6", + "table": "foo", + "type": [ + "ipv6_addr", + "inet_service", + "ifname", + "ipv6_addr", + "inet_service" + ], + "handle": 0, + "flags": "dynamic" + } + }, + { + "set": { + "family": "ip", + "name": "inflows_ratelimit", + "table": "foo", + "type": [ + "ipv4_addr", + "inet_service", + "ifname", + "ipv4_addr", + "inet_service" + ], + "handle": 0, + "flags": "dynamic", + "elem": [ + { + "elem": { + "val": { + "concat": [ + "10.1.0.3", + 39466, + "veth1", + "10.3.0.99", + 5201 + ] + }, + "limit": { + "rate": 1, + "burst": 5, + "per": "second" + } + } + } + ] + } + } + ] +} diff --git a/tests/shell/testcases/nft-f/dumps/0025empty_dynset_0.nft b/tests/shell/testcases/nft-f/dumps/0025empty_dynset_0.nft index 2bb35592..33b9e4ff 100644 --- a/tests/shell/testcases/nft-f/dumps/0025empty_dynset_0.nft +++ b/tests/shell/testcases/nft-f/dumps/0025empty_dynset_0.nft @@ -13,6 +13,6 @@ table ip foo { set inflows_ratelimit { type ipv4_addr . inet_service . ifname . ipv4_addr . inet_service flags dynamic - elements = { 10.1.0.3 . 39466 . "veth1" . 10.3.0.99 . 5201 limit rate 1/second counter packets 0 bytes 0 } + elements = { 10.1.0.3 . 39466 . "veth1" . 10.3.0.99 . 5201 limit rate 1/second burst 5 packets counter packets 0 bytes 0 } } } diff --git a/tests/shell/testcases/nft-f/dumps/0026listing_0.json-nft b/tests/shell/testcases/nft-f/dumps/0026listing_0.json-nft new file mode 100644 index 00000000..8acdcdf4 --- /dev/null +++ b/tests/shell/testcases/nft-f/dumps/0026listing_0.json-nft @@ -0,0 +1,56 @@ +{ + "nftables": [ + { + "metainfo": { + "version": "VERSION", + "release_name": "RELEASE_NAME", + "json_schema_version": 1 + } + }, + { + "table": { + "family": "ip", + "name": "A", + "handle": 0 + } + }, + { + "chain": { + "family": "ip", + "table": "A", + "name": "B", + "handle": 0 + } + }, + { + "rule": { + "family": "ip", + "table": "A", + "chain": "B", + "handle": 0, + "expr": [ + { + "match": { + "op": "==", + "left": { + "payload": { + "protocol": "tcp", + "field": "dport" + } + }, + "right": { + "set": [ + 1, + 2 + ] + } + } + }, + { + "accept": null + } + ] + } + } + ] +} diff --git a/tests/shell/testcases/nft-f/dumps/0026listing_0.nft b/tests/shell/testcases/nft-f/dumps/0026listing_0.nft new file mode 100644 index 00000000..fd0bb686 --- /dev/null +++ b/tests/shell/testcases/nft-f/dumps/0026listing_0.nft @@ -0,0 +1,5 @@ +table ip A { + chain B { + tcp dport { 1, 2 } accept + } +} diff --git a/tests/shell/testcases/nft-f/dumps/0026policy_variable_0.nft b/tests/shell/testcases/nft-f/dumps/0026policy_variable_0.nft deleted file mode 100644 index d729e1ea..00000000 --- a/tests/shell/testcases/nft-f/dumps/0026policy_variable_0.nft +++ /dev/null @@ -1,5 +0,0 @@ -table inet global { - chain prerouting { - type filter hook prerouting priority filter; policy drop; - } -} diff --git a/tests/shell/testcases/nft-f/dumps/0027split_chains_0.json-nft b/tests/shell/testcases/nft-f/dumps/0027split_chains_0.json-nft new file mode 100644 index 00000000..bda8bfc9 --- /dev/null +++ b/tests/shell/testcases/nft-f/dumps/0027split_chains_0.json-nft @@ -0,0 +1,53 @@ +{ + "nftables": [ + { + "metainfo": { + "version": "VERSION", + "release_name": "RELEASE_NAME", + "json_schema_version": 1 + } + }, + { + "table": { + "family": "inet", + "name": "filter", + "handle": 0 + } + }, + { + "chain": { + "family": "inet", + "table": "filter", + "name": "x", + "handle": 0 + } + }, + { + "chain": { + "family": "inet", + "table": "filter", + "name": "input", + "handle": 0, + "type": "filter", + "hook": "input", + "prio": 0, + "policy": "accept" + } + }, + { + "rule": { + "family": "inet", + "table": "filter", + "chain": "input", + "handle": 0, + "expr": [ + { + "jump": { + "target": "x" + } + } + ] + } + } + ] +} diff --git a/tests/shell/testcases/nft-f/dumps/0028variable_cmdline_0.json-nft b/tests/shell/testcases/nft-f/dumps/0028variable_cmdline_0.json-nft new file mode 100644 index 00000000..69d826df --- /dev/null +++ b/tests/shell/testcases/nft-f/dumps/0028variable_cmdline_0.json-nft @@ -0,0 +1,34 @@ +{ + "nftables": [ + { + "metainfo": { + "version": "VERSION", + "release_name": "RELEASE_NAME", + "json_schema_version": 1 + } + }, + { + "table": { + "family": "inet", + "name": "filter", + "handle": 0 + } + }, + { + "set": { + "family": "inet", + "name": "whitelist_v4", + "table": "filter", + "type": "ipv4_addr", + "handle": 0, + "elem": [ + "1.1.1.1", + "2.2.2.2", + "3.3.3.3", + "4.4.4.4", + "5.5.5.5" + ] + } + } + ] +} diff --git a/tests/shell/testcases/nft-f/dumps/0029split_file_0.json-nft b/tests/shell/testcases/nft-f/dumps/0029split_file_0.json-nft new file mode 100644 index 00000000..ab680af8 --- /dev/null +++ b/tests/shell/testcases/nft-f/dumps/0029split_file_0.json-nft @@ -0,0 +1,61 @@ +{ + "nftables": [ + { + "metainfo": { + "version": "VERSION", + "release_name": "RELEASE_NAME", + "json_schema_version": 1 + } + }, + { + "table": { + "family": "inet", + "name": "filter", + "handle": 0 + } + }, + { + "chain": { + "family": "inet", + "table": "filter", + "name": "prerouting", + "handle": 0, + "type": "filter", + "hook": "prerouting", + "prio": 0, + "policy": "accept" + } + }, + { + "set": { + "family": "inet", + "name": "whitelist_v4", + "table": "filter", + "type": "ipv4_addr", + "handle": 0 + } + }, + { + "rule": { + "family": "inet", + "table": "filter", + "chain": "prerouting", + "handle": 0, + "expr": [ + { + "match": { + "op": "==", + "left": { + "payload": { + "protocol": "ip", + "field": "daddr" + } + }, + "right": "@whitelist_v4" + } + } + ] + } + } + ] +} diff --git a/tests/shell/testcases/nft-f/dumps/0029split_file_0.nft b/tests/shell/testcases/nft-f/dumps/0029split_file_0.nft new file mode 100644 index 00000000..32d5c0e9 --- /dev/null +++ b/tests/shell/testcases/nft-f/dumps/0029split_file_0.nft @@ -0,0 +1,10 @@ +table inet filter { + set whitelist_v4 { + type ipv4_addr + } + + chain prerouting { + type filter hook prerouting priority filter; policy accept; + ip daddr @whitelist_v4 + } +} diff --git a/tests/shell/testcases/nft-f/dumps/0030variable_reuse_0.json-nft b/tests/shell/testcases/nft-f/dumps/0030variable_reuse_0.json-nft new file mode 100644 index 00000000..e0704b7d --- /dev/null +++ b/tests/shell/testcases/nft-f/dumps/0030variable_reuse_0.json-nft @@ -0,0 +1,44 @@ +{ + "nftables": [ + { + "metainfo": { + "version": "VERSION", + "release_name": "RELEASE_NAME", + "json_schema_version": 1 + } + }, + { + "table": { + "family": "ip", + "name": "x", + "handle": 0 + } + }, + { + "set": { + "family": "ip", + "name": "y", + "table": "x", + "type": "ipv4_addr", + "handle": 0, + "elem": [ + "1.1.1.1", + "2.2.2.2" + ] + } + }, + { + "set": { + "family": "ip", + "name": "z", + "table": "x", + "type": "ipv4_addr", + "handle": 0, + "elem": [ + "1.1.1.1", + "3.3.3.3" + ] + } + } + ] +} diff --git a/tests/shell/testcases/nft-f/dumps/0031vmap_string_0.json-nft b/tests/shell/testcases/nft-f/dumps/0031vmap_string_0.json-nft new file mode 100644 index 00000000..546cc597 --- /dev/null +++ b/tests/shell/testcases/nft-f/dumps/0031vmap_string_0.json-nft @@ -0,0 +1,11 @@ +{ + "nftables": [ + { + "metainfo": { + "version": "VERSION", + "release_name": "RELEASE_NAME", + "json_schema_version": 1 + } + } + ] +} diff --git a/tests/shell/testcases/nft-f/dumps/0031vmap_string_0.nft b/tests/shell/testcases/nft-f/dumps/0031vmap_string_0.nft new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/tests/shell/testcases/nft-f/dumps/0031vmap_string_0.nft diff --git a/tests/shell/testcases/nft-f/dumps/0032pknock_0.json-nft b/tests/shell/testcases/nft-f/dumps/0032pknock_0.json-nft new file mode 100644 index 00000000..4c7d2bbe --- /dev/null +++ b/tests/shell/testcases/nft-f/dumps/0032pknock_0.json-nft @@ -0,0 +1,484 @@ +{ + "nftables": [ + { + "metainfo": { + "version": "VERSION", + "release_name": "RELEASE_NAME", + "json_schema_version": 1 + } + }, + { + "table": { + "family": "inet", + "name": "portknock", + "handle": 0 + } + }, + { + "chain": { + "family": "inet", + "table": "portknock", + "name": "input", + "handle": 0, + "type": "filter", + "hook": "input", + "prio": -10, + "policy": "accept" + } + }, + { + "set": { + "family": "inet", + "name": "clients_ipv4", + "table": "portknock", + "type": "ipv4_addr", + "handle": 0, + "size": 65535, + "flags": [ + "timeout", + "dynamic" + ] + } + }, + { + "set": { + "family": "inet", + "name": "candidates_ipv4", + "table": "portknock", + "type": [ + "ipv4_addr", + "inet_service" + ], + "handle": 0, + "size": 65535, + "flags": [ + "timeout", + "dynamic" + ] + } + }, + { + "rule": { + "family": "inet", + "table": "portknock", + "chain": "input", + "handle": 0, + "expr": [ + { + "match": { + "op": "==", + "left": { + "payload": { + "protocol": "tcp", + "field": "dport" + } + }, + "right": 10001 + } + }, + { + "set": { + "op": "add", + "elem": { + "elem": { + "val": { + "concat": [ + { + "payload": { + "protocol": "ip", + "field": "saddr" + } + }, + 10002 + ] + }, + "timeout": 1 + } + }, + "set": "@candidates_ipv4" + } + } + ] + } + }, + { + "rule": { + "family": "inet", + "table": "portknock", + "chain": "input", + "handle": 0, + "expr": [ + { + "match": { + "op": "==", + "left": { + "payload": { + "protocol": "tcp", + "field": "dport" + } + }, + "right": 10002 + } + }, + { + "match": { + "op": "==", + "left": { + "concat": [ + { + "payload": { + "protocol": "ip", + "field": "saddr" + } + }, + { + "payload": { + "protocol": "tcp", + "field": "dport" + } + } + ] + }, + "right": "@candidates_ipv4" + } + }, + { + "set": { + "op": "add", + "elem": { + "elem": { + "val": { + "concat": [ + { + "payload": { + "protocol": "ip", + "field": "saddr" + } + }, + 10003 + ] + }, + "timeout": 1 + } + }, + "set": "@candidates_ipv4" + } + } + ] + } + }, + { + "rule": { + "family": "inet", + "table": "portknock", + "chain": "input", + "handle": 0, + "expr": [ + { + "match": { + "op": "==", + "left": { + "payload": { + "protocol": "tcp", + "field": "dport" + } + }, + "right": 10003 + } + }, + { + "match": { + "op": "==", + "left": { + "concat": [ + { + "payload": { + "protocol": "ip", + "field": "saddr" + } + }, + { + "payload": { + "protocol": "tcp", + "field": "dport" + } + } + ] + }, + "right": "@candidates_ipv4" + } + }, + { + "set": { + "op": "add", + "elem": { + "elem": { + "val": { + "concat": [ + { + "payload": { + "protocol": "ip", + "field": "saddr" + } + }, + 10004 + ] + }, + "timeout": 1 + } + }, + "set": "@candidates_ipv4" + } + } + ] + } + }, + { + "rule": { + "family": "inet", + "table": "portknock", + "chain": "input", + "handle": 0, + "expr": [ + { + "match": { + "op": "==", + "left": { + "payload": { + "protocol": "tcp", + "field": "dport" + } + }, + "right": 10004 + } + }, + { + "match": { + "op": "==", + "left": { + "concat": [ + { + "payload": { + "protocol": "ip", + "field": "saddr" + } + }, + { + "payload": { + "protocol": "tcp", + "field": "dport" + } + } + ] + }, + "right": "@candidates_ipv4" + } + }, + { + "set": { + "op": "add", + "elem": { + "elem": { + "val": { + "concat": [ + { + "payload": { + "protocol": "ip", + "field": "saddr" + } + }, + 10005 + ] + }, + "timeout": 1 + } + }, + "set": "@candidates_ipv4" + } + } + ] + } + }, + { + "rule": { + "family": "inet", + "table": "portknock", + "chain": "input", + "handle": 0, + "expr": [ + { + "match": { + "op": "==", + "left": { + "payload": { + "protocol": "tcp", + "field": "dport" + } + }, + "right": 10005 + } + }, + { + "match": { + "op": "==", + "left": { + "concat": [ + { + "payload": { + "protocol": "ip", + "field": "saddr" + } + }, + { + "payload": { + "protocol": "tcp", + "field": "dport" + } + } + ] + }, + "right": "@candidates_ipv4" + } + }, + { + "set": { + "op": "add", + "elem": { + "elem": { + "val": { + "payload": { + "protocol": "ip", + "field": "saddr" + } + }, + "timeout": 600 + } + }, + "set": "@clients_ipv4" + } + }, + { + "log": { + "prefix": "Successful portknock: " + } + } + ] + } + }, + { + "rule": { + "family": "inet", + "table": "portknock", + "chain": "input", + "handle": 0, + "expr": [ + { + "match": { + "op": "==", + "left": { + "payload": { + "protocol": "tcp", + "field": "dport" + } + }, + "right": 22 + } + }, + { + "match": { + "op": "==", + "left": { + "payload": { + "protocol": "ip", + "field": "saddr" + } + }, + "right": "@clients_ipv4" + } + }, + { + "counter": { + "packets": 0, + "bytes": 0 + } + }, + { + "accept": null + } + ] + } + }, + { + "rule": { + "family": "inet", + "table": "portknock", + "chain": "input", + "handle": 0, + "expr": [ + { + "match": { + "op": "==", + "left": { + "payload": { + "protocol": "tcp", + "field": "dport" + } + }, + "right": 22 + } + }, + { + "match": { + "op": "in", + "left": { + "ct": { + "key": "state" + } + }, + "right": [ + "established", + "related" + ] + } + }, + { + "counter": { + "packets": 0, + "bytes": 0 + } + }, + { + "accept": null + } + ] + } + }, + { + "rule": { + "family": "inet", + "table": "portknock", + "chain": "input", + "handle": 0, + "expr": [ + { + "match": { + "op": "==", + "left": { + "payload": { + "protocol": "tcp", + "field": "dport" + } + }, + "right": 22 + } + }, + { + "reject": { + "type": "tcp reset" + } + } + ] + } + } + ] +} diff --git a/tests/shell/testcases/nft-f/dumps/0032pknock_0.nft b/tests/shell/testcases/nft-f/dumps/0032pknock_0.nft new file mode 100644 index 00000000..f29dfb28 --- /dev/null +++ b/tests/shell/testcases/nft-f/dumps/0032pknock_0.nft @@ -0,0 +1,25 @@ +table inet portknock { + set clients_ipv4 { + type ipv4_addr + size 65535 + flags dynamic,timeout + } + + set candidates_ipv4 { + type ipv4_addr . inet_service + size 65535 + flags dynamic,timeout + } + + chain input { + type filter hook input priority filter - 10; policy accept; + tcp dport 10001 add @candidates_ipv4 { ip saddr . 10002 timeout 1s } + tcp dport 10002 ip saddr . tcp dport @candidates_ipv4 add @candidates_ipv4 { ip saddr . 10003 timeout 1s } + tcp dport 10003 ip saddr . tcp dport @candidates_ipv4 add @candidates_ipv4 { ip saddr . 10004 timeout 1s } + tcp dport 10004 ip saddr . tcp dport @candidates_ipv4 add @candidates_ipv4 { ip saddr . 10005 timeout 1s } + tcp dport 10005 ip saddr . tcp dport @candidates_ipv4 add @clients_ipv4 { ip saddr timeout 10m } log prefix "Successful portknock: " + tcp dport 22 ip saddr @clients_ipv4 counter packets 0 bytes 0 accept + tcp dport 22 ct state established,related counter packets 0 bytes 0 accept + tcp dport 22 reject with tcp reset + } +} diff --git a/tests/shell/testcases/nft-f/dumps/named_set_as_protocol_dep.json-nft b/tests/shell/testcases/nft-f/dumps/named_set_as_protocol_dep.json-nft new file mode 100644 index 00000000..4bc24aa3 --- /dev/null +++ b/tests/shell/testcases/nft-f/dumps/named_set_as_protocol_dep.json-nft @@ -0,0 +1,75 @@ +{ + "nftables": [ + { + "metainfo": { + "version": "VERSION", + "release_name": "RELEASE_NAME", + "json_schema_version": 1 + } + }, + { + "table": { + "family": "inet", + "name": "test", + "handle": 0 + } + }, + { + "chain": { + "family": "inet", + "table": "test", + "name": "prerouting", + "handle": 0, + "type": "filter", + "hook": "prerouting", + "prio": -150, + "policy": "accept" + } + }, + { + "set": { + "family": "inet", + "name": "protos", + "table": "test", + "type": { + "typeof": { + "meta": { + "key": "l4proto" + } + } + }, + "handle": 0, + "elem": [ + "tcp", + "udp" + ] + } + }, + { + "rule": { + "family": "inet", + "table": "test", + "chain": "prerouting", + "handle": 0, + "expr": [ + { + "match": { + "op": "==", + "left": { + "meta": { + "key": "l4proto" + } + }, + "right": "@protos" + } + }, + { + "tproxy": { + "port": 1088 + } + } + ] + } + } + ] +} diff --git a/tests/shell/testcases/nft-f/dumps/named_set_as_protocol_dep.nft b/tests/shell/testcases/nft-f/dumps/named_set_as_protocol_dep.nft new file mode 100644 index 00000000..2bc0c2ad --- /dev/null +++ b/tests/shell/testcases/nft-f/dumps/named_set_as_protocol_dep.nft @@ -0,0 +1,11 @@ +table inet test { + set protos { + typeof meta l4proto + elements = { tcp, udp } + } + + chain prerouting { + type filter hook prerouting priority mangle; policy accept; + meta l4proto @protos tproxy to :1088 + } +} diff --git a/tests/shell/testcases/nft-f/dumps/nfqueue.nft b/tests/shell/testcases/nft-f/dumps/nfqueue.nft new file mode 100644 index 00000000..7fe3ca66 --- /dev/null +++ b/tests/shell/testcases/nft-f/dumps/nfqueue.nft @@ -0,0 +1,11 @@ +table inet t { + map get_queue_id { + typeof ip saddr . ip daddr . tcp dport : queue + elements = { 127.0.0.1 . 127.0.0.1 . 22 : 1, + 127.0.0.1 . 127.0.0.2 . 22 : 2 } + } + + chain test { + queue flags bypass to ip saddr . ip daddr . tcp dport map @get_queue_id + } +} diff --git a/tests/shell/testcases/nft-f/dumps/sample-ruleset.nft b/tests/shell/testcases/nft-f/dumps/sample-ruleset.nft new file mode 100644 index 00000000..1a9f4e7a --- /dev/null +++ b/tests/shell/testcases/nft-f/dumps/sample-ruleset.nft @@ -0,0 +1,239 @@ +table inet filter { + map if_input { + type ifname : verdict + elements = { "eth0" : jump public_input, + "eth1" : jump home_input, + "eth2.10" : jump home_input, + "eth2.20" : jump home_input } + } + + map if_forward { + type ifname : verdict + elements = { "eth0" : jump public_forward, + "eth1" : jump trusted_forward, + "eth2.10" : jump voip_forward, + "eth2.20" : jump guest_forward } + } + + map if_output { + type ifname : verdict + elements = { "eth0" : jump public_output, + "eth1" : jump home_output, + "eth2.10" : jump home_output, + "eth2.20" : jump home_output } + } + + set ipv4_blacklist { + type ipv4_addr + flags interval + auto-merge + } + + set ipv6_blacklist { + type ipv6_addr + flags interval + auto-merge + } + + set limit_src_ip { + type ipv4_addr + size 1024 + flags dynamic,timeout + } + + set limit_src_ip6 { + type ipv6_addr + size 1024 + flags dynamic,timeout + } + + chain PREROUTING_RAW { + type filter hook prerouting priority raw; policy accept; + meta l4proto != { icmp, tcp, udp, ipv6-icmp } counter packets 0 bytes 0 drop + tcp flags syn jump { + tcp option maxseg size 1-500 counter packets 0 bytes 0 drop + tcp sport 0 counter packets 0 bytes 0 drop + } + rt type 0 counter packets 0 bytes 0 drop + } + + chain PREROUTING_MANGLE { + type filter hook prerouting priority mangle; policy accept; + ct state vmap { invalid : jump ct_invalid_pre, related : jump rpfilter, new : jump ct_new_pre, untracked : jump ct_untracked_pre } + } + + chain ct_invalid_pre { + counter packets 0 bytes 0 drop + } + + chain ct_untracked_pre { + icmpv6 type { mld-listener-query, nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert, mld2-listener-report } return + counter packets 0 bytes 0 drop + } + + chain ct_new_pre { + jump rpfilter + tcp flags & (fin | syn | rst | ack) != syn counter packets 0 bytes 0 drop + iifname "eth0" meta nfproto vmap { ipv4 : jump blacklist_input_ipv4, ipv6 : jump blacklist_input_ipv6 } + } + + chain rpfilter { + ip saddr 0.0.0.0 ip daddr 255.255.255.255 udp sport 68 udp dport 67 return + ip6 saddr :: ip6 daddr . icmpv6 type { ff02::1:ff00:0/104 . nd-neighbor-solicit, ff02::16 . mld2-listener-report } return + fib saddr . iif oif 0 counter packets 0 bytes 0 drop + } + + chain blacklist_input_ipv4 { + ip saddr { 0.0.0.0/8, 10.0.0.0/8, 100.64.0.0/10, 127.0.0.0/8, 169.254.0.0/16, 172.16.0.0/12, 192.0.0.0/24, 192.0.2.0/24, 192.168.0.0/16, 198.18.0.0/15, 198.51.100.0/24, 203.0.113.0/24, 224.0.0.0/3 } counter packets 0 bytes 0 drop + ip saddr @ipv4_blacklist counter packets 0 bytes 0 drop + } + + chain blacklist_input_ipv6 { + icmpv6 type { nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert } ip6 saddr fe80::/64 return + udp sport 547 ip6 saddr fe80::/64 return + ip6 saddr { ::/3, 2001::/32, 2001:2::/48, 2001:3::/32, 2001:10::-2001:2f:ffff:ffff:ffff:ffff:ffff:ffff, 2001:db8::/32, 2002::/16, 3000::-ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff } counter packets 0 bytes 0 drop + ip6 saddr @ipv6_blacklist counter packets 0 bytes 0 drop + } + + chain INPUT { + type filter hook input priority filter; policy drop; + iif "lo" accept + ct state established,related accept + iifname vmap @if_input + log prefix "NFT REJECT IN " flags ip options flags ether limit rate 5/second burst 10 packets reject + } + + chain public_input { + icmpv6 type { nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert } ip6 saddr fe80::/64 ip6 hoplimit 255 accept + udp sport 547 udp dport 546 ip6 saddr fe80::/64 accept + fib daddr type { broadcast, anycast, multicast } counter packets 0 bytes 0 drop + counter packets 0 bytes 0 drop + } + + chain home_input { + icmpv6 type { nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert } ip6 hoplimit 255 accept + icmpv6 type { mld-listener-query, mld2-listener-report } ip6 hoplimit 1 accept + udp sport 68 udp dport 67 accept + udp sport 546 udp dport 547 iifname { "eth1", "eth2.10", "eth2.20" } accept + fib daddr type { broadcast, anycast, multicast } counter packets 0 bytes 0 drop + icmp type echo-request accept + icmpv6 type echo-request accept + tcp dport 22 iifname "eth1" accept + meta l4proto { tcp, udp } th dport 53 jump { + ip6 saddr != { fd00::/8, fe80::/64 } counter packets 0 bytes 0 reject with icmpv6 port-unreachable + accept + } + udp dport 123 accept + tcp dport 8443 accept + } + + chain FORWARD_MANGLE { + type filter hook forward priority mangle; policy accept; + oifname "eth0" jump { + ct state new meta nfproto vmap { ipv4 : jump blacklist_output_ipv4, ipv6 : jump blacklist_output_ipv6 } + tcp flags & (syn | rst) == syn tcp option maxseg size set rt mtu + } + } + + chain blacklist_output_ipv4 { + ip daddr { 0.0.0.0/8, 10.0.0.0/8, 100.64.0.0/10, 127.0.0.0/8, 169.254.0.0/16, 172.16.0.0/12, 192.0.0.0/24, 192.0.2.0/24, 192.168.0.0/16, 198.18.0.0/15, 198.51.100.0/24, 203.0.113.0/24, 224.0.0.0/3 } goto log_blacklist + ip daddr @ipv4_blacklist goto log_blacklist + } + + chain blacklist_output_ipv6 { + icmpv6 type . ip6 daddr { nd-router-solicit . ff02::2, nd-neighbor-solicit . ff02::1:ff00:0/104, nd-neighbor-advert . fe80::/64, nd-neighbor-advert . ff02::1, nd-neighbor-advert . ff02::1:ff00:0/104, mld2-listener-report . ff02::16 } return + udp dport 547 ip6 daddr ff02::1:2 return + ip6 daddr { ::/3, 2001::/32, 2001:2::/48, 2001:3::/32, 2001:10::-2001:2f:ffff:ffff:ffff:ffff:ffff:ffff, 2001:db8::/32, 2002::/16, 3000::-ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff } goto log_blacklist + ip6 daddr @ipv6_blacklist goto log_blacklist + } + + chain log_blacklist { + log prefix "NFT BLACKLIST " flags ip options flags ether limit rate 5/minute burst 10 packets drop + counter packets 0 bytes 0 drop + } + + chain FORWARD { + type filter hook forward priority filter; policy drop; + ct state established,related accept + fib daddr type { broadcast, anycast, multicast } counter packets 0 bytes 0 drop + iifname vmap @if_forward + log prefix "NFT REJECT FWD " flags ip options flags ether limit rate 5/second burst 10 packets reject + } + + chain public_forward { + udp dport { 5060, 7078-7097 } oifname "eth2.10" jump { + ip6 saddr { 2001:db8::1-2001:db8::2 } accept + meta nfproto ipv6 log prefix "NFT DROP SIP " flags ip options flags ether limit rate 5/second burst 10 packets drop + } + counter packets 0 bytes 0 drop + } + + chain trusted_forward { + oifname "eth0" accept + icmp type echo-request accept + icmpv6 type echo-request accept + ip daddr { 192.168.3.30, 192.168.4.40 } tcp dport vmap { 22 : accept, 80 : drop, 443 : accept } + ip daddr 192.168.2.20 jump { + tcp dport { 80, 443, 515, 631, 9100 } accept + udp dport 161 accept + } + } + + chain voip_forward { + icmpv6 type { destination-unreachable, packet-too-big, time-exceeded, parameter-problem, echo-request } oifname "eth0" accept + ip6 daddr { 2001:db8::1-2001:db8::2 } jump { + udp dport { 3478, 5060 } accept + udp sport 7078-7097 accept + tcp dport 5061 accept + } + tcp dport 587 ip daddr 10.0.0.1 accept + tcp dport 80 oifname "eth0" counter packets 0 bytes 0 reject + } + + chain guest_forward { + oifname "eth0" accept + } + + chain OUTPUT { + type filter hook output priority filter; policy drop; + oif "lo" accept + ct state vmap { invalid : jump ct_invalid_out, established : accept, related : accept, untracked : jump ct_untracked_out } + oifname vmap @if_output + log prefix "NFT REJECT OUT " flags ip options flags ether limit rate 5/second burst 10 packets reject + } + + chain ct_invalid_out { + counter packets 0 bytes 0 drop + } + + chain ct_untracked_out { + icmpv6 type { mld-listener-query, nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert, mld2-listener-report } return + counter packets 0 bytes 0 drop + } + + chain public_output { + ct state new meta nfproto vmap { ipv4 : jump blacklist_output_ipv4, ipv6 : jump blacklist_output_ipv6 } + icmp type { destination-unreachable, echo-request, time-exceeded, parameter-problem } accept + icmpv6 type { destination-unreachable, packet-too-big, time-exceeded, parameter-problem, echo-request } accept + icmpv6 type { nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert } ip6 hoplimit 255 accept + icmpv6 type { mld-listener-query, mld2-listener-report } ip6 hoplimit 1 accept + udp dport 547 ip6 saddr fe80::/64 ip6 daddr ff02::1:2 accept + udp dport { 53, 123 } accept + tcp dport { 443, 587, 853 } accept + } + + chain home_output { + icmp type { destination-unreachable, echo-request, time-exceeded, parameter-problem } accept + icmpv6 type { destination-unreachable, packet-too-big, time-exceeded, parameter-problem, echo-request } accept + icmpv6 type { nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert } ip6 hoplimit 255 accept + icmpv6 type { mld-listener-query, mld2-listener-report } ip6 hoplimit 1 accept + udp sport 547 udp dport 546 ip6 saddr fe80::/64 oifname { "eth1", "eth2.10", "eth2.20" } accept + udp sport 67 udp dport 68 ip saddr { 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16 } accept + tcp dport 22 ip daddr 192.168.1.10 accept + } + + chain POSTROUTING_SRCNAT { + type nat hook postrouting priority srcnat; policy accept; + ip saddr { 192.168.1.0-192.168.4.255 } oifname "eth0" masquerade + } +} diff --git a/tests/shell/testcases/nft-f/named_set_as_protocol_dep b/tests/shell/testcases/nft-f/named_set_as_protocol_dep new file mode 100755 index 00000000..5c516e42 --- /dev/null +++ b/tests/shell/testcases/nft-f/named_set_as_protocol_dep @@ -0,0 +1,5 @@ +#!/bin/bash + +dumpfile=$(dirname $0)/dumps/$(basename $0).nft + +$NFT -f "$dumpfile" || exit 1 diff --git a/tests/shell/testcases/nft-f/nfqueue b/tests/shell/testcases/nft-f/nfqueue new file mode 100755 index 00000000..07820b7c --- /dev/null +++ b/tests/shell/testcases/nft-f/nfqueue @@ -0,0 +1,6 @@ +#!/bin/bash + +set -e +dumpfile=$(dirname $0)/dumps/$(basename $0).nft + +$NFT -f "$dumpfile" diff --git a/tests/shell/testcases/nft-f/sample-ruleset b/tests/shell/testcases/nft-f/sample-ruleset new file mode 100755 index 00000000..763e41a1 --- /dev/null +++ b/tests/shell/testcases/nft-f/sample-ruleset @@ -0,0 +1,262 @@ +#!/bin/bash + +# NFT_TEST_REQUIRES(NFT_TEST_HAVE_chain_binding) + +$NFT -f /dev/stdin <<"EOF" +define public_if = eth0 +define trusted_if = eth1 +define voip_if = eth2.10 +define guest_if = eth2.20 +define home_if = { $trusted_if, $voip_if, $guest_if } +define home_ipv6_if = { $trusted_if, $voip_if, $guest_if } + +define masq_ip = { 192.168.1.0/24, 192.168.2.0/24, 192.168.3.0/24, 192.168.4.0/24 } +define masq_if = $public_if + +define host1_ip = 192.168.1.10 +define host2_ip = 192.168.2.20 +define host3_ip = 192.168.3.30 +define host4_ip = 192.168.4.40 + +define proxy_port = 8443 + +define private_ip = { 192.168.0.0/16, 172.16.0.0/12, 10.0.0.0/8 } +define private_ip6 = { fe80::/64, fd00::/8 } +define bogons_ip = { 0.0.0.0/8, 10.0.0.0/8, 100.64.0.0/10, 127.0.0.0/8, 169.254.0.0/16, 172.16.0.0/12, 192.0.0.0/24, 192.0.2.0/24, 192.168.0.0/16, 198.18.0.0/15, 198.51.100.0/24, 203.0.113.0/24, 224.0.0.0/3 } +define bogons_ip6 = { ::/3, 2001:0002::/48, 2001:0003::/32, 2001:10::/28, 2001:20::/28, 2001::/32, 2001:db8::/32, 2002::/16, 3000::/4, 4000::/2, 8000::/1 } + +define sip_whitelist_ip6 = { 2001:db8::1/128, 2001:db8::2/128 } +define smtps_whitelist_ip = 10.0.0.1 +define protocol_whitelist = { tcp, udp, icmp, ipv6-icmp } + +table inet filter { + map if_input { + type ifname : verdict; + elements = { $public_if : jump public_input, $trusted_if : jump home_input, $voip_if : jump home_input, $guest_if : jump home_input } + } + map if_forward { + type ifname : verdict; + elements = { $public_if : jump public_forward, $trusted_if : jump trusted_forward, $voip_if : jump voip_forward, $guest_if : jump guest_forward } + } + map if_output { + type ifname : verdict; + elements = { $public_if : jump public_output, $trusted_if : jump home_output, $voip_if : jump home_output, $guest_if : jump home_output } + } + + set ipv4_blacklist { type ipv4_addr; flags interval; auto-merge; } + set ipv6_blacklist { type ipv6_addr; flags interval; auto-merge; } + set limit_src_ip { type ipv4_addr; flags dynamic, timeout; size 1024; } + set limit_src_ip6 { type ipv6_addr; flags dynamic, timeout; size 1024; } + + chain PREROUTING_RAW { + type filter hook prerouting priority raw; + + meta l4proto != $protocol_whitelist counter drop + tcp flags syn jump { + tcp option maxseg size 1-500 counter drop + tcp sport 0 counter drop + } + rt type 0 counter drop + } + + chain PREROUTING_MANGLE { + type filter hook prerouting priority mangle; + + ct state vmap { invalid : jump ct_invalid_pre, untracked : jump ct_untracked_pre, new : jump ct_new_pre, related : jump rpfilter } + } + chain ct_invalid_pre { + counter drop + } + chain ct_untracked_pre { + icmpv6 type { nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert, mld-listener-query, mld2-listener-report } return + counter drop + } + chain ct_new_pre { + jump rpfilter + + tcp flags & (fin|syn|rst|ack) != syn counter drop + + iifname $public_if meta nfproto vmap { ipv4 : jump blacklist_input_ipv4, ipv6 : jump blacklist_input_ipv6 } + } + chain rpfilter { + ip saddr 0.0.0.0 ip daddr 255.255.255.255 udp sport bootpc udp dport bootps return + ip6 saddr ::/128 ip6 daddr . icmpv6 type { ff02::1:ff00:0/104 . nd-neighbor-solicit, ff02::16 . mld2-listener-report } return + + fib saddr . iif oif eq 0 counter drop + } + chain blacklist_input_ipv4{ + ip saddr $bogons_ip counter drop + ip saddr @ipv4_blacklist counter drop + } + chain blacklist_input_ipv6{ + icmpv6 type { nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert } ip6 saddr fe80::/64 return + udp sport dhcpv6-server ip6 saddr fe80::/64 return + + ip6 saddr $bogons_ip6 counter drop + ip6 saddr @ipv6_blacklist counter drop + } + + chain INPUT { + type filter hook input priority filter; policy drop; + + iif lo accept + + ct state established,related accept + + iifname vmap @if_input + + log prefix "NFT REJECT IN " flags ether flags ip options limit rate 5/second burst 10 packets reject + } + chain public_input { + icmpv6 type { nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert } ip6 saddr fe80::/64 ip6 hoplimit 255 accept + + udp sport dhcpv6-server udp dport dhcpv6-client ip6 saddr fe80::/64 accept + fib daddr type { broadcast, multicast, anycast } counter drop + + counter drop + } + chain home_input { + icmpv6 type { nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert } ip6 hoplimit 255 accept + icmpv6 type { mld-listener-query, mld2-listener-report } ip6 hoplimit 1 accept + + udp sport bootpc udp dport bootps accept + udp sport dhcpv6-client udp dport dhcpv6-server iifname $home_ipv6_if accept + + fib daddr type { broadcast, multicast, anycast } counter drop + + icmp type echo-request accept + icmpv6 type echo-request accept + + tcp dport ssh iifname $trusted_if accept + + meta l4proto { tcp, udp } th dport domain jump { + ip6 saddr != $private_ip6 counter reject + accept + } + + udp dport ntp accept + + tcp dport $proxy_port accept + } + + chain FORWARD_MANGLE { + type filter hook forward priority mangle; + + oifname $public_if jump { + ct state new meta nfproto vmap { ipv4 : jump blacklist_output_ipv4, ipv6 : jump blacklist_output_ipv6 } + tcp flags & (syn|rst) == syn tcp option maxseg size set rt mtu + } + } + chain blacklist_output_ipv4 { + ip daddr $bogons_ip goto log_blacklist + ip daddr @ipv4_blacklist goto log_blacklist + } + chain blacklist_output_ipv6 { + icmpv6 type . ip6 daddr { nd-router-solicit . ff02::2/128, nd-neighbor-solicit . ff02::1:ff00:0/104, nd-neighbor-advert . fe80::/64, nd-neighbor-advert . ff02::1/128, nd-neighbor-advert . ff02::1:ff00:0/104, mld2-listener-report . ff02::16/128 } return + udp dport dhcpv6-server ip6 daddr ff02::1:2 return + + ip6 daddr $bogons_ip6 goto log_blacklist + ip6 daddr @ipv6_blacklist goto log_blacklist + } + chain log_blacklist { + log prefix "NFT BLACKLIST " flags ether flags ip options limit rate 5/minute burst 10 packets drop + counter drop + } + + chain FORWARD { + type filter hook forward priority filter; policy drop; + + ct state established,related accept + + fib daddr type { broadcast, multicast, anycast } counter drop + + iifname vmap @if_forward + + log prefix "NFT REJECT FWD " flags ether flags ip options limit rate 5/second burst 10 packets reject + } + chain public_forward { + udp dport { 5060, 7078-7097 } oifname $voip_if jump { + ip6 saddr $sip_whitelist_ip6 accept + meta nfproto ipv6 log prefix "NFT DROP SIP " flags ether flags ip options limit rate 5/second burst 10 packets drop + } + + counter drop + } + chain trusted_forward { + oifname $public_if accept + + icmp type echo-request accept + icmpv6 type echo-request accept + + ip daddr { $host3_ip, $host4_ip } tcp dport vmap { ssh : accept, https : accept, http : drop } + + ip daddr $host2_ip jump { + tcp dport { http, https, printer, ipp, 9100 } accept + udp dport snmp accept + } + } + chain voip_forward { + icmpv6 type { destination-unreachable, packet-too-big, time-exceeded, parameter-problem, echo-request } oifname $public_if accept + + ip6 daddr $sip_whitelist_ip6 jump { + udp dport { 3478, 5060 } accept + udp sport { 7078-7097 } accept + tcp dport 5061 accept + } + + tcp dport 587 ip daddr $smtps_whitelist_ip accept + tcp dport http oifname $public_if counter reject + } + chain guest_forward { + oifname $public_if accept + } + + chain OUTPUT { + type filter hook output priority filter; policy drop; + + oif lo accept + + ct state vmap { established : accept, related : accept, invalid : jump ct_invalid_out, untracked : jump ct_untracked_out } + + oifname vmap @if_output + + log prefix "NFT REJECT OUT " flags ether flags ip options limit rate 5/second burst 10 packets reject + } + chain ct_invalid_out { + counter drop + } + chain ct_untracked_out { + icmpv6 type { nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert, mld-listener-query, mld2-listener-report } return + counter drop + } + chain public_output { + ct state new meta nfproto vmap { ipv4 : jump blacklist_output_ipv4, ipv6 : jump blacklist_output_ipv6 } + + icmp type { destination-unreachable, time-exceeded, parameter-problem, echo-request } accept + icmpv6 type { destination-unreachable, packet-too-big, time-exceeded, parameter-problem, echo-request } accept + icmpv6 type { nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert } ip6 hoplimit 255 accept + icmpv6 type { mld-listener-query, mld2-listener-report } ip6 hoplimit 1 accept + + udp dport dhcpv6-server ip6 saddr fe80::/64 ip6 daddr ff02::1:2 accept + + udp dport { domain, ntp } accept + tcp dport { https, 587, domain-s } accept + } + chain home_output { + icmp type { destination-unreachable, time-exceeded, parameter-problem, echo-request } accept + icmpv6 type { destination-unreachable, packet-too-big, time-exceeded, parameter-problem, echo-request } accept + icmpv6 type { nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert } ip6 hoplimit 255 accept + icmpv6 type { mld-listener-query, mld2-listener-report } ip6 hoplimit 1 accept + + udp sport dhcpv6-server udp dport dhcpv6-client ip6 saddr fe80::/64 oifname $home_ipv6_if accept + udp sport bootps udp dport bootpc ip saddr $private_ip accept + tcp dport ssh ip daddr $host1_ip accept + } + + chain POSTROUTING_SRCNAT { + type nat hook postrouting priority srcnat; + + meta nfproto ipv4 ip saddr $masq_ip oifname $masq_if masquerade + } +} +EOF |