diff --git a/data/Dockerfiles/netfilter/server.py b/data/Dockerfiles/netfilter/server.py index 9f3cacb3..428ddb96 100644 --- a/data/Dockerfiles/netfilter/server.py +++ b/data/Dockerfiles/netfilter/server.py @@ -96,6 +96,7 @@ def verifyF2boptions(f2boptions): verifyF2boption(f2boptions,'netban_ipv4', 32) verifyF2boption(f2boptions,'netban_ipv6', 128) verifyF2boption(f2boptions,'banlist_id', str(uuid.uuid4())) + verifyF2boption(f2boptions,'manage_external', 0) def verifyF2boption(f2boptions, f2boption, f2bdefault): f2boptions[f2boption] = f2boptions[f2boption] if f2boption in f2boptions and f2boptions[f2boption] is not None else f2bdefault @@ -158,6 +159,7 @@ def mailcowChainOrder(): exit_code = 2 def ban(address): + global f2boptions global lock refreshF2boptions() BAN_TIME = int(f2boptions['ban_time']) @@ -199,7 +201,7 @@ def ban(address): cur_time = int(round(time.time())) NET_BAN_TIME = BAN_TIME if not BAN_TIME_INCREMENT else BAN_TIME * 2 ** bans[net]['ban_counter'] logCrit('Banning %s for %d minutes' % (net, NET_BAN_TIME / 60 )) - if type(ip) is ipaddress.IPv4Address: + if type(ip) is ipaddress.IPv4Address and int(f2boptions['manage_external']) != 1: with lock: chain = iptc.Chain(iptc.Table(iptc.Table.FILTER), 'MAILCOW') rule = iptc.Rule() @@ -208,7 +210,7 @@ def ban(address): rule.target = target if rule not in chain.rules: chain.insert_rule(rule) - else: + elif int(f2boptions['manage_external']) != 1: with lock: chain = iptc.Chain(iptc.Table6(iptc.Table6.FILTER), 'MAILCOW') rule = iptc.Rule6() @@ -253,37 +255,52 @@ def unban(net): bans[net]['ban_counter'] += 1 def permBan(net, unban=False): + global f2boptions global lock if type(ipaddress.ip_network(net, strict=False)) is ipaddress.IPv4Network: - with lock: - chain = iptc.Chain(iptc.Table(iptc.Table.FILTER), 'MAILCOW') - rule = iptc.Rule() - rule.src = net - target = iptc.Target(rule, "REJECT") - rule.target = target - if rule not in chain.rules and not unban: - logCrit('Add host/network %s to blacklist' % net) - chain.insert_rule(rule) - r.hset('F2B_PERM_BANS', '%s' % net, int(round(time.time()))) - elif rule in chain.rules and unban: - logCrit('Remove host/network %s from blacklist' % net) - chain.delete_rule(rule) - r.hdel('F2B_PERM_BANS', '%s' % net) + if int(f2boptions['manage_external']) != 1: + with lock: + chain = iptc.Chain(iptc.Table(iptc.Table.FILTER), 'MAILCOW') + rule = iptc.Rule() + rule.src = net + target = iptc.Target(rule, "REJECT") + rule.target = target + if rule not in chain.rules and not unban: + logCrit('Add host/network %s to blacklist' % net) + chain.insert_rule(rule) + r.hset('F2B_PERM_BANS', '%s' % net, int(round(time.time()))) + elif rule in chain.rules and unban: + logCrit('Remove host/network %s from blacklist' % net) + chain.delete_rule(rule) + r.hdel('F2B_PERM_BANS', '%s' % net) + elif not unban: + logCrit('Add host/network %s to blacklist' % net) + r.hset('F2B_PERM_BANS', '%s' % net, int(round(time.time()))) + elif unban: + logCrit('Remove host/network %s from blacklist' % net) + r.hdel('F2B_PERM_BANS', '%s' % net) else: - with lock: - chain = iptc.Chain(iptc.Table6(iptc.Table6.FILTER), 'MAILCOW') - rule = iptc.Rule6() - rule.src = net - target = iptc.Target(rule, "REJECT") - rule.target = target - if rule not in chain.rules and not unban: - logCrit('Add host/network %s to blacklist' % net) - chain.insert_rule(rule) - r.hset('F2B_PERM_BANS', '%s' % net, int(round(time.time()))) - elif rule in chain.rules and unban: - logCrit('Remove host/network %s from blacklist' % net) - chain.delete_rule(rule) - r.hdel('F2B_PERM_BANS', '%s' % net) + if int(f2boptions['manage_external']) != 1: + with lock: + chain = iptc.Chain(iptc.Table6(iptc.Table6.FILTER), 'MAILCOW') + rule = iptc.Rule6() + rule.src = net + target = iptc.Target(rule, "REJECT") + rule.target = target + if rule not in chain.rules and not unban: + logCrit('Add host/network %s to blacklist' % net) + chain.insert_rule(rule) + r.hset('F2B_PERM_BANS', '%s' % net, int(round(time.time()))) + elif rule in chain.rules and unban: + logCrit('Remove host/network %s from blacklist' % net) + chain.delete_rule(rule) + r.hdel('F2B_PERM_BANS', '%s' % net) + elif not unban: + logCrit('Add host/network %s to blacklist' % net) + r.hset('F2B_PERM_BANS', '%s' % net, int(round(time.time()))) + elif unban: + logCrit('Remove host/network %s from blacklist' % net) + r.hdel('F2B_PERM_BANS', '%s' % net) def quit(signum, frame): global quit_now @@ -555,7 +572,7 @@ def initChain(): chain.insert_rule(rule) if __name__ == '__main__': - + refreshF2boptions() # In case a previous session was killed without cleanup clear() # Reinit MAILCOW chain diff --git a/data/web/inc/functions.fail2ban.inc.php b/data/web/inc/functions.fail2ban.inc.php index 3e0c75c4..abc12cc3 100644 --- a/data/web/inc/functions.fail2ban.inc.php +++ b/data/web/inc/functions.fail2ban.inc.php @@ -247,6 +247,7 @@ function fail2ban($_action, $_data = null, $_extra = null) { $netban_ipv6 = intval((isset($_data['netban_ipv6'])) ? $_data['netban_ipv6'] : $is_now['netban_ipv6']); $wl = (isset($_data['whitelist'])) ? $_data['whitelist'] : $is_now['whitelist']; $bl = (isset($_data['blacklist'])) ? $_data['blacklist'] : $is_now['blacklist']; + $manage_external = (isset($_data['manage_external'])) ? intval($_data['manage_external']) : 0; } else { $_SESSION['return'][] = array( @@ -266,6 +267,8 @@ function fail2ban($_action, $_data = null, $_extra = null) { $f2b_options['netban_ipv6'] = ($netban_ipv6 > 128) ? 128 : $netban_ipv6; $f2b_options['max_attempts'] = ($max_attempts < 1) ? 1 : $max_attempts; $f2b_options['retry_window'] = ($retry_window < 1) ? 1 : $retry_window; + $f2b_options['banlist_id'] = $is_now['banlist_id']; + $f2b_options['manage_external'] = ($manage_external > 0) ? 1 : 0; try { $redis->Set('F2B_OPTIONS', json_encode($f2b_options)); $redis->Del('F2B_WHITELIST'); @@ -351,8 +354,8 @@ function fail2ban($_action, $_data = null, $_extra = null) { switch ($_data) { case 'get': try { - $bl = $redis->hGetAll('F2B_BLACKLIST'); - $active_bans = $redis->hGetAll('F2B_ACTIVE_BANS'); + $bl = $redis->hKeys('F2B_BLACKLIST'); + $active_bans = $redis->hKeys('F2B_ACTIVE_BANS'); } catch (RedisException $e) { $_SESSION['return'][] = array( @@ -362,7 +365,7 @@ function fail2ban($_action, $_data = null, $_extra = null) { ); return false; } - $banlist = implode("\n", array_merge(array_keys($bl), array_keys($active_bans))); + $banlist = implode("\n", array_merge($bl, $active_bans)); return $banlist; break; case 'refresh': diff --git a/data/web/lang/lang.de-de.json b/data/web/lang/lang.de-de.json index 2091e670..7c2171aa 100644 --- a/data/web/lang/lang.de-de.json +++ b/data/web/lang/lang.de-de.json @@ -181,6 +181,8 @@ "f2b_blacklist": "Blacklist für Netzwerke und Hosts", "f2b_filter": "Regex-Filter", "f2b_list_info": "Ein Host oder Netzwerk auf der Blacklist wird immer eine Whitelist-Einheit überwiegen. Die Aktualisierung der Liste dauert einige Sekunden.", + "f2b_manage_external": "Fail2Ban extern verwalten", + "f2b_manage_external_info": "Fail2ban wird die Banlist weiterhin pflegen, jedoch werden keine aktiven Regeln zum blockieren gesetzt. Die unten generierte Banlist, kann verwendet werden, um den Datenverkehr extern zu blockieren.", "f2b_max_attempts": "Max. Versuche", "f2b_max_ban_time": "Maximale Bannzeit in Sekunden", "f2b_netban_ipv4": "Netzbereich für IPv4-Banns (8-32)", diff --git a/data/web/lang/lang.en-gb.json b/data/web/lang/lang.en-gb.json index b176bc28..e7c82cda 100644 --- a/data/web/lang/lang.en-gb.json +++ b/data/web/lang/lang.en-gb.json @@ -185,6 +185,8 @@ "f2b_blacklist": "Blacklisted networks/hosts", "f2b_filter": "Regex filters", "f2b_list_info": "A blacklisted host or network will always outweigh a whitelist entity. List updates will take a few seconds to be applied.", + "f2b_manage_external": "Manage Fail2Ban externally", + "f2b_manage_external_info": "Fail2ban will still maintain the banlist, but it will not actively set rules to block traffic. Use the generated banlist below to externally block the traffic.", "f2b_max_attempts": "Max. attempts", "f2b_max_ban_time": "Max. ban time (s)", "f2b_netban_ipv4": "IPv4 subnet size to apply ban on (8-32)", diff --git a/data/web/templates/admin/tab-config-f2b.twig b/data/web/templates/admin/tab-config-f2b.twig index 68aa57a4..dac69516 100644 --- a/data/web/templates/admin/tab-config-f2b.twig +++ b/data/web/templates/admin/tab-config-f2b.twig @@ -42,6 +42,13 @@ +
+
+ + +
+

{{ lang.admin.f2b_manage_external_info }}

+

{{ lang.admin.f2b_list_info|raw }}