git subrepo commit (merge) mailcow/src/mailcow-dockerized
subrepo: subdir: "mailcow/src/mailcow-dockerized"
merged: "02ae5285"
upstream: origin: "https://github.com/mailcow/mailcow-dockerized.git"
branch: "master"
commit: "649a5c01"
git-subrepo: version: "0.4.3"
origin: "???"
commit: "???"
Change-Id: I870ad468fba026cc5abf3c5699ed1e12ff28b32b
diff --git a/mailcow/src/mailcow-dockerized/data/Dockerfiles/netfilter/server.py b/mailcow/src/mailcow-dockerized/data/Dockerfiles/netfilter/server.py
index bf3980a..04f6c47 100644
--- a/mailcow/src/mailcow-dockerized/data/Dockerfiles/netfilter/server.py
+++ b/mailcow/src/mailcow-dockerized/data/Dockerfiles/netfilter/server.py
@@ -2,6 +2,7 @@
import re
import os
+import sys
import time
import atexit
import signal
@@ -39,6 +40,7 @@
bans = {}
quit_now = False
+exit_code = 0
lock = Lock()
def log(priority, message):
@@ -61,6 +63,7 @@
def refreshF2boptions():
global f2boptions
global quit_now
+ global exit_code
if not r.get('F2B_OPTIONS'):
f2boptions = {}
f2boptions['ban_time'] = int
@@ -81,10 +84,12 @@
except ValueError:
print('Error loading F2B options: F2B_OPTIONS is not json')
quit_now = True
+ exit_code = 2
def refreshF2bregex():
global f2bregex
global quit_now
+ global exit_code
if not r.get('F2B_REGEX'):
f2bregex = {}
f2bregex[1] = 'warning: .*\[([0-9a-f\.:]+)\]: SASL .+ authentication failed'
@@ -95,6 +100,7 @@
f2bregex[6] = '([0-9a-f\.:]+) \"GET \/SOGo\/.* HTTP.+\" 403 .+'
f2bregex[7] = 'Rspamd UI: Invalid password by ([0-9a-f\.:]+)'
f2bregex[8] = '-login: Aborted login \(auth failed .+\): user=.+, rip=([0-9a-f\.:]+), lip.+'
+ f2bregex[9] = 'NOQUEUE: reject: RCPT from \[([0-9a-f\.:]+)].+Protocol error.+'
r.set('F2B_REGEX', json.dumps(f2bregex, ensure_ascii=False))
else:
try:
@@ -103,6 +109,7 @@
except ValueError:
print('Error loading F2B options: F2B_REGEX is not json')
quit_now = True
+ exit_code = 2
if r.exists('F2B_LOG'):
r.rename('F2B_LOG', 'NETFILTER_LOG')
@@ -110,6 +117,7 @@
def mailcowChainOrder():
global lock
global quit_now
+ global exit_code
while not quit_now:
time.sleep(10)
with lock:
@@ -126,9 +134,11 @@
if position > 2:
logCrit('Error in %s chain order: MAILCOW on position %d, restarting container' % (chain.name, position))
quit_now = True
+ exit_code = 2
if not target_found:
logCrit('Error in %s chain: MAILCOW target not found, restarting container' % (chain.name))
quit_now = True
+ exit_code = 2
def ban(address):
global lock
@@ -270,22 +280,30 @@
logInfo('Watching Redis channel F2B_CHANNEL')
pubsub.subscribe('F2B_CHANNEL')
+ global quit_now
+ global exit_code
+
while not quit_now:
- for item in pubsub.listen():
- refreshF2bregex()
- for rule_id, rule_regex in f2bregex.items():
- if item['data'] and item['type'] == 'message':
- try:
- result = re.search(rule_regex, item['data'])
- except re.error:
- result = False
- if result:
- addr = result.group(1)
- ip = ipaddress.ip_address(addr)
- if ip.is_private or ip.is_loopback:
- continue
- logWarn('%s matched rule id %s (%s)' % (addr, rule_id, item['data']))
- ban(addr)
+ try:
+ for item in pubsub.listen():
+ refreshF2bregex()
+ for rule_id, rule_regex in f2bregex.items():
+ if item['data'] and item['type'] == 'message':
+ try:
+ result = re.search(rule_regex, item['data'])
+ except re.error:
+ result = False
+ if result:
+ addr = result.group(1)
+ ip = ipaddress.ip_address(addr)
+ if ip.is_private or ip.is_loopback:
+ continue
+ logWarn('%s matched rule id %s (%s)' % (addr, rule_id, item['data']))
+ ban(addr)
+ except Exception as ex:
+ logWarn('Error reading log line from pubsub')
+ quit_now = True
+ exit_code = 2
def snat4(snat_target):
global lock
@@ -468,3 +486,5 @@
while not quit_now:
time.sleep(0.5)
+
+ sys.exit(exit_code)