From c59d49da225d415428847d97d86e853b79d7a884 Mon Sep 17 00:00:00 2001 From: sebres Date: Tue, 24 Sep 2019 18:46:41 +0200 Subject: [PATCH] nftables-allports: support multiple protocols in single rule; tests/servertestcase.py: added coverage for nftables actions --- config/action.d/nftables-allports.conf | 2 +- fail2ban/tests/servertestcase.py | 94 +++++++++++++++++++++++++- 2 files changed, 93 insertions(+), 3 deletions(-) diff --git a/config/action.d/nftables-allports.conf b/config/action.d/nftables-allports.conf index eb17287a..fad5273a 100644 --- a/config/action.d/nftables-allports.conf +++ b/config/action.d/nftables-allports.conf @@ -17,6 +17,6 @@ before = nftables-common.conf # Notes.: additional matches for nftables filter rule # Values: nftables matches # -match = meta l4proto +match = meta l4proto \{ \} [Init] diff --git a/fail2ban/tests/servertestcase.py b/fail2ban/tests/servertestcase.py index 4d4362db..6375ea24 100644 --- a/fail2ban/tests/servertestcase.py +++ b/fail2ban/tests/servertestcase.py @@ -1256,6 +1256,96 @@ class ServerConfigReaderTests(LogCaptureTestCase): # 'start', 'stop' - should be found (logged) on action start/stop, # etc. testJailsActions = ( + # nftables-multiport -- + ('j-w-nft-mp', 'nftables-multiport[name=%(__name__)s, port="http,https", protocol="tcp"]', { + 'ip4': ('ip ', 'ipv4_addr', 'addr-'), 'ip6': ('ip6 ', 'ipv6_addr', 'addr6-'), + '*-start': ( + r"`nft add table inet f2b-table`", + r"`nft -- add chain inet f2b-table f2b-chain \{ type filter hook input priority -1 \; \}`", + ), + 'ip4-start': ( + r"`nft add set inet f2b-table addr-set-j-w-nft-mp \{ type ipv4_addr\; \}`", + r"`nft add rule inet f2b-table f2b-chain tcp dport \{ http,https \} ip saddr @addr-set-j-w-nft-mp reject`", + ), + 'ip6-start': ( + r"`nft add set inet f2b-table addr6-set-j-w-nft-mp \{ type ipv6_addr\; \}`", + r"`nft add rule inet f2b-table f2b-chain tcp dport \{ http,https \} ip6 saddr @addr6-set-j-w-nft-mp reject`", + ), + 'flush': ( + # todo + ), + 'stop': ( + "`HANDLE_ID=$(nft -a list chain inet f2b-table f2b-chain | grep -m1 '@addr-set-j-w-nft-mp ' | grep -oe ' handle [0-9]*')`", + "`nft delete rule inet f2b-table f2b-chain $HANDLE_ID`", + "`nft delete set inet f2b-table addr-set-j-w-nft-mp`", + "`HANDLE_ID=$(nft -a list chain inet f2b-table f2b-chain | grep -m1 '@addr6-set-j-w-nft-mp ' | grep -oe ' handle [0-9]*')`", + "`nft delete rule inet f2b-table f2b-chain $HANDLE_ID`", + "`nft delete set inet f2b-table addr6-set-j-w-nft-mp`", + ), + 'ip4-check': ( + r"`nft list chain inet f2b-table f2b-chain | grep -q '@addr-set-j-w-nft-mp[ \t]'`", + ), + 'ip6-check': ( + r"`nft list chain inet f2b-table f2b-chain | grep -q '@addr6-set-j-w-nft-mp[ \t]'`", + ), + 'ip4-ban': ( + r"`nft add element inet f2b-table addr-set-j-w-nft-mp { 192.0.2.1 }`", + ), + 'ip4-unban': ( + r"`nft delete element inet f2b-table addr-set-j-w-nft-mp { 192.0.2.1 }`", + ), + 'ip6-ban': ( + r"`nft add element inet f2b-table addr6-set-j-w-nft-mp { 2001:db8:: }`", + ), + 'ip6-unban': ( + r"`nft delete element inet f2b-table addr6-set-j-w-nft-mp { 2001:db8:: }`", + ), + }), + # nft-allports -- + ('j-w-nft-ap', 'nftables-allports[name=%(__name__)s, protocol="tcp,udp"]', { + 'ip4': ('ip ', 'ipv4_addr', 'addr-'), 'ip6': ('ip6 ', 'ipv6_addr', 'addr6-'), + '*-start': ( + r"`nft add table inet f2b-table`", + r"`nft -- add chain inet f2b-table f2b-chain \{ type filter hook input priority -1 \; \}`", + ), + 'ip4-start': ( + r"`nft add set inet f2b-table addr-set-j-w-nft-ap \{ type ipv4_addr\; \}`", + r"`nft add rule inet f2b-table f2b-chain meta l4proto \{ tcp,udp \} ip saddr @addr-set-j-w-nft-ap reject`", + ), + 'ip6-start': ( + r"`nft add set inet f2b-table addr6-set-j-w-nft-ap \{ type ipv6_addr\; \}`", + r"`nft add rule inet f2b-table f2b-chain meta l4proto \{ tcp,udp \} ip6 saddr @addr6-set-j-w-nft-ap reject`", + ), + 'flush': ( + # todo + ), + 'stop': ( + "`HANDLE_ID=$(nft -a list chain inet f2b-table f2b-chain | grep -m1 '@addr-set-j-w-nft-ap ' | grep -oe ' handle [0-9]*')`", + "`nft delete rule inet f2b-table f2b-chain $HANDLE_ID`", + "`nft delete set inet f2b-table addr-set-j-w-nft-ap`", + "`HANDLE_ID=$(nft -a list chain inet f2b-table f2b-chain | grep -m1 '@addr6-set-j-w-nft-ap ' | grep -oe ' handle [0-9]*')`", + "`nft delete rule inet f2b-table f2b-chain $HANDLE_ID`", + "`nft delete set inet f2b-table addr6-set-j-w-nft-ap`", + ), + 'ip4-check': ( + r"""`nft list chain inet f2b-table f2b-chain | grep -q '@addr-set-j-w-nft-ap[ \t]'`""", + ), + 'ip6-check': ( + r"""`nft list chain inet f2b-table f2b-chain | grep -q '@addr6-set-j-w-nft-ap[ \t]'`""", + ), + 'ip4-ban': ( + r"`nft add element inet f2b-table addr-set-j-w-nft-ap { 192.0.2.1 }`", + ), + 'ip4-unban': ( + r"`nft delete element inet f2b-table addr-set-j-w-nft-ap { 192.0.2.1 }`", + ), + 'ip6-ban': ( + r"`nft add element inet f2b-table addr6-set-j-w-nft-ap { 2001:db8:: }`", + ), + 'ip6-unban': ( + r"`nft delete element inet f2b-table addr6-set-j-w-nft-ap { 2001:db8:: }`", + ), + }), # dummy -- ('j-dummy', 'dummy[name=%(__name__)s, init="==", target="/tmp/fail2ban.dummy"]', { 'ip4': ('family: inet4',), 'ip6': ('family: inet6',), @@ -1847,7 +1937,7 @@ class ServerConfigReaderTests(LogCaptureTestCase): # test ban ip4 : self.pruneLog('# === ban-ipv4 ===') action.ban(ainfo['ip4']) - if tests.get('ip4-start'): self.assertLogged(*tests['ip4-start'], all=True) + if tests.get('ip4-start'): self.assertLogged(*tests.get('*-start', ())+tests['ip4-start'], all=True) if tests.get('ip6-start'): self.assertNotLogged(*tests['ip6-start'], all=True) self.assertLogged(*tests.get('ip4-check',())+tests['ip4-ban'], all=True) self.assertNotLogged(*tests['ip6'], all=True) @@ -1859,7 +1949,7 @@ class ServerConfigReaderTests(LogCaptureTestCase): # test ban ip6 : self.pruneLog('# === ban ipv6 ===') action.ban(ainfo['ip6']) - if tests.get('ip6-start'): self.assertLogged(*tests['ip6-start'], all=True) + if tests.get('ip6-start'): self.assertLogged(*tests.get('*-start', ())+tests['ip6-start'], all=True) if tests.get('ip4-start'): self.assertNotLogged(*tests['ip4-start'], all=True) self.assertLogged(*tests.get('ip6-check',())+tests['ip6-ban'], all=True) self.assertNotLogged(*tests['ip4'], all=True)