diff --git a/bundles/postfix/files/check_spam_blocklist b/bundles/postfix/files/check_spam_blocklist index a2fe993..e8a462c 100644 --- a/bundles/postfix/files/check_spam_blocklist +++ b/bundles/postfix/files/check_spam_blocklist @@ -1,5 +1,6 @@ #!/usr/bin/env python3 +from concurrent.futures import ThreadPoolExecutor, as_completed from ipaddress import ip_address, IPv6Address from sys import argv, exit @@ -9,7 +10,7 @@ from dns.resolver import Resolver, NoAnswer, NXDOMAIN, NoNameservers BLOCKLISTS = [ '0spam.fusionzero.com', - 'bl.mailspike.Dorg', + 'bl.mailspike.org', 'bl.spamcop.net', 'blackholes.brainerd.net', 'dnsbl-1.uceprotect.net', @@ -28,53 +29,68 @@ BLOCKLISTS = [ 'ubl.unsubscore.com', 'unconfirmed.dsbl.org', 'virbl.dnsbl.bit.nl', - 'virbl.dnsbl.bit.nl', 'zen.spamhaus.org', ] +def check_list(ip_list, blocklist): + resolver = Resolver() + resolver.timeout = 5 + resolver.lifetime = 5 + + dns_name = '{}.{}'.format( + '.'.join(ip_list), + blocklist, + ) + + returncode = 0 + msgs = [] + + try: + result = resolver.query(dns_name) + for item in result: + msgs.append('{} listed in {} as {}'.format( + ip, + blocklist, + item, + )) + returncode = 2 + except (NoAnswer, NXDOMAIN, NoNameservers, Timeout): + # Probably fine + pass + except Exception as e: + return [repr(e)], 3 + + return msgs, returncode + try: ip = ip_address(argv[1]) except Exception: print('usage: {} '.format(argv[0])) exit(3) -found = False - -resolver = Resolver() -resolver.timeout = 5 -resolver.lifetime = 5 - if isinstance(ip, IPv6Address): ip_list = list(ip.exploded.replace(':', '')) else: ip_list = ip.exploded.split('.') ip_list.reverse() +exitcode = 0 -for blocklist in BLOCKLISTS: - dns_name = '{}.{}'.format( - '.'.join(ip_list), - blocklist, - ) +with ThreadPoolExecutor(max_workers=len(BLOCKLISTS)) as executor: + futures = set() - try: - result = resolver.query(dns_name) - for item in result: - print('{} listed in {} as {}'.format( - ip, - blocklist, - item, - )) - found = True - except (NoAnswer, NXDOMAIN, NoNameservers, Timeout): - # Probably fine - pass - except Exception as e: - print(repr(e)) - exit(3) + for blocklist in BLOCKLISTS: + futures.add(executor.submit(check_list, ip_list, blocklist)) -if found: - exit(2) -else: + for future in as_completed(futures): + msgs, this_exitcode = future.result() + + for msg in msgs: + print(msg) + + exitcode = max(exitcode, this_exitcode) + +if exitcode == 0: print('OK') - exit(0) + +exit(exitcode) diff --git a/bundles/postfix/metadata.py b/bundles/postfix/metadata.py index 59baf6b..86e35ab 100644 --- a/bundles/postfix/metadata.py +++ b/bundles/postfix/metadata.py @@ -105,7 +105,7 @@ def icinga2(metadata): if not ip.is_private: services[f'SPAM BLOCKLIST {ip}'] = { 'command_on_monitored_host': f'/usr/local/share/icinga/plugins/check_spam_blocklist {ip}', - 'vars.sshmon_timeout': 60, + 'vars.sshmon_timeout': 15, 'check_interval': '15m', 'retry_interval': '5m', }