[2751] | 1 | #! /usr/bin/env python |
---|
| 2 | # |
---|
| 3 | # This is a multi-threaded RBL lookup check for Icinga / Nagios. |
---|
| 4 | # Copyright (C) 2012 Frode Egeland <egeland[at]gmail.com> |
---|
| 5 | # |
---|
| 6 | # Modified by Kumina bv in 2013. We only added an option to use an |
---|
| 7 | # address instead of a hostname. |
---|
| 8 | # |
---|
| 9 | # Modified by Guillaume Subiron (Sysnove) in 2015 : mainly PEP8 |
---|
| 10 | # |
---|
| 11 | # This program is free software: you can redistribute it and/or modify |
---|
| 12 | # it under the terms of the GNU General Public License as published by |
---|
| 13 | # the Free Software Foundation, either version 3 of the License, or |
---|
| 14 | # (at your option) any later version. |
---|
| 15 | # |
---|
| 16 | # This program is distributed in the hope that it will be useful, |
---|
| 17 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
| 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
| 19 | # GNU General Public License for more details. |
---|
| 20 | # |
---|
| 21 | # You should have received a copy of the GNU General Public License |
---|
| 22 | # along with this program. If not, see <http://www.gnu.org/licenses/> |
---|
| 23 | # |
---|
| 24 | # Downloaded from https://raw.githubusercontent.com/egeland/nagios-rbl-check/master/check_rbl.py |
---|
| 25 | # on 2016-02-20 by adehnert |
---|
| 26 | |
---|
| 27 | import sys |
---|
| 28 | import os |
---|
| 29 | import getopt |
---|
| 30 | import socket |
---|
| 31 | import string |
---|
| 32 | |
---|
| 33 | rv = (2, 6) |
---|
| 34 | if rv >= sys.version_info: |
---|
| 35 | print "ERROR: Requires Python 2.6 or greater" |
---|
| 36 | sys.exit(3) |
---|
| 37 | |
---|
| 38 | import Queue |
---|
| 39 | import threading |
---|
| 40 | |
---|
| 41 | serverlist = [ |
---|
| 42 | "truncate.gbudb.net", |
---|
| 43 | "bad.psky.me", |
---|
| 44 | "0spam.fusionzero.com", |
---|
| 45 | "access.redhawk.org", |
---|
| 46 | "b.barracudacentral.org", |
---|
| 47 | "bhnc.njabl.org", |
---|
| 48 | "bl.deadbeef.com", |
---|
| 49 | "bl.spamcannibal.org", |
---|
| 50 | "bl.spamcop.net", |
---|
| 51 | "bl.technovision.dk", |
---|
| 52 | "blackholes.five-ten-sg.com", |
---|
| 53 | "blackholes.mail-abuse.org", |
---|
| 54 | "blacklist.sci.kun.nl", |
---|
| 55 | "blacklist.woody.ch", |
---|
| 56 | "bogons.cymru.com", |
---|
| 57 | "cbl.abuseat.org", |
---|
| 58 | "cdl.anti-spam.org.cn", |
---|
| 59 | "combined.abuse.ch", |
---|
| 60 | "combined.rbl.msrbl.net", |
---|
| 61 | "db.wpbl.info", |
---|
| 62 | "dnsbl-1.uceprotect.net", |
---|
| 63 | "dnsbl-2.uceprotect.net", |
---|
| 64 | "dnsbl-3.uceprotect.net", |
---|
| 65 | "dnsbl.cyberlogic.net", |
---|
| 66 | "dnsbl.inps.de", |
---|
| 67 | "dnsbl.kempt.net", |
---|
| 68 | "dnsbl.njabl.org", |
---|
| 69 | "dnsbl.solid.net", |
---|
| 70 | "dnsbl.sorbs.net", |
---|
| 71 | "drone.abuse.ch", |
---|
| 72 | "duinv.aupads.org", |
---|
| 73 | "dul.ru", |
---|
| 74 | "dyna.spamrats.com", |
---|
| 75 | "dynip.rothen.com", |
---|
| 76 | "forbidden.icm.edu.pl", |
---|
| 77 | "hil.habeas.com", |
---|
| 78 | "images.rbl.msrbl.net", |
---|
| 79 | "ips.backscatterer.org", |
---|
| 80 | "ix.dnsbl.manitu.net", |
---|
| 81 | "korea.services.net", |
---|
| 82 | "mail-abuse.blacklist.jippg.org", |
---|
| 83 | "no-more-funn.moensted.dk", |
---|
| 84 | "noptr.spamrats.com", |
---|
| 85 | "ohps.dnsbl.net.au", |
---|
| 86 | "omrs.dnsbl.net.au", |
---|
| 87 | "orvedb.aupads.org", |
---|
| 88 | "osps.dnsbl.net.au", |
---|
| 89 | "osrs.dnsbl.net.au", |
---|
| 90 | "owfs.dnsbl.net.au", |
---|
| 91 | "owps.dnsbl.net.au", |
---|
| 92 | "phishing.rbl.msrbl.net", |
---|
| 93 | "probes.dnsbl.net.au", |
---|
| 94 | "proxy.bl.gweep.ca", |
---|
| 95 | "proxy.block.transip.nl", |
---|
| 96 | "psbl.surriel.com", |
---|
| 97 | "rbl.interserver.net", |
---|
| 98 | "rbl.orbitrbl.com", |
---|
| 99 | "rbl.schulte.org", |
---|
| 100 | "rdts.dnsbl.net.au", |
---|
| 101 | "relays.bl.gweep.ca", |
---|
| 102 | "relays.bl.kundenserver.de", |
---|
| 103 | "relays.nether.net", |
---|
| 104 | "residential.block.transip.nl", |
---|
| 105 | "ricn.dnsbl.net.au", |
---|
| 106 | "rmst.dnsbl.net.au", |
---|
| 107 | "short.rbl.jp", |
---|
| 108 | "spam.abuse.ch", |
---|
| 109 | "spam.dnsbl.sorbs.net", |
---|
| 110 | "spam.rbl.msrbl.net", |
---|
| 111 | "spam.spamrats.com", |
---|
| 112 | "spamguard.leadmon.net", |
---|
| 113 | "spamlist.or.kr", |
---|
| 114 | "spamrbl.imp.ch", |
---|
| 115 | "spamsources.fabel.dk", |
---|
| 116 | "spamtrap.drbl.drand.net", |
---|
| 117 | "t3direct.dnsbl.net.au", |
---|
| 118 | "tor.dnsbl.sectoor.de", |
---|
| 119 | "torserver.tor.dnsbl.sectoor.de", |
---|
| 120 | "ubl.lashback.com", |
---|
| 121 | "ubl.unsubscore.com", |
---|
| 122 | "virbl.bit.nl", |
---|
| 123 | "virus.rbl.jp", |
---|
| 124 | "virus.rbl.msrbl.net", |
---|
| 125 | "wormrbl.imp.ch", |
---|
| 126 | "zen.spamhaus.org", |
---|
| 127 | ] |
---|
| 128 | |
---|
| 129 | #### |
---|
| 130 | |
---|
| 131 | queue = Queue.Queue() |
---|
| 132 | global on_blacklist |
---|
| 133 | on_blacklist = [] |
---|
| 134 | |
---|
| 135 | |
---|
| 136 | class ThreadRBL(threading.Thread): |
---|
| 137 | def __init__(self, queue): |
---|
| 138 | threading.Thread.__init__(self) |
---|
| 139 | self.queue = queue |
---|
| 140 | |
---|
| 141 | def run(self): |
---|
| 142 | while True: |
---|
| 143 | # grabs host from queue |
---|
| 144 | hostname, root_name = self.queue.get() |
---|
| 145 | |
---|
| 146 | check_host = "%s.%s" % (hostname, root_name) |
---|
| 147 | try: |
---|
| 148 | check_addr = socket.gethostbyname(check_host) |
---|
| 149 | except socket.error: |
---|
| 150 | check_addr = None |
---|
| 151 | if check_addr is not None and "127.0.0." in check_addr: |
---|
| 152 | on_blacklist.append(root_name) |
---|
| 153 | |
---|
| 154 | # signals to queue job is done |
---|
| 155 | self.queue.task_done() |
---|
| 156 | |
---|
| 157 | |
---|
| 158 | def usage(argv0): |
---|
| 159 | print "%s -w <WARN level> -c <CRIT level> -h <hostname>" % argv0 |
---|
| 160 | print " or" |
---|
| 161 | print "%s -w <WARN level> -c <CRIT level> -a <ipv4 address>" % argv0 |
---|
| 162 | |
---|
| 163 | |
---|
| 164 | def main(argv, environ): |
---|
| 165 | options, remainder = getopt.getopt(argv[1:], |
---|
| 166 | "w:c:h:a:", |
---|
| 167 | ["warn=", "crit=", "host=", "address="]) |
---|
| 168 | status = {'OK': 0, 'WARNING': 1, 'CRITICAL': 2, 'UNKNOWN': 3} |
---|
| 169 | host = None |
---|
| 170 | addr = None |
---|
| 171 | |
---|
| 172 | if 3 != len(options): |
---|
| 173 | usage(argv[0]) |
---|
| 174 | sys.exit(status['UNKNOWN']) |
---|
| 175 | |
---|
| 176 | for field, val in options: |
---|
| 177 | if field in ('-w', '--warn'): |
---|
| 178 | warn_limit = int(val) |
---|
| 179 | elif field in ('-c', '--crit'): |
---|
| 180 | crit_limit = int(val) |
---|
| 181 | elif field in ('-h', '--host'): |
---|
| 182 | host = val |
---|
| 183 | elif field in ('-a', '--address'): |
---|
| 184 | addr = val |
---|
| 185 | else: |
---|
| 186 | usage(argv[0]) |
---|
| 187 | sys.exit(status['UNKNOWN']) |
---|
| 188 | |
---|
| 189 | if host and addr: |
---|
| 190 | print "ERROR: Cannot use both host and address, choose one." |
---|
| 191 | sys.exit(status['UNKNOWN']) |
---|
| 192 | |
---|
| 193 | if host: |
---|
| 194 | try: |
---|
| 195 | addr = socket.gethostbyname(host) |
---|
| 196 | except: |
---|
| 197 | print "ERROR: Host '%s' not found - maybe try a FQDN?" % host |
---|
| 198 | sys.exit(status['UNKNOWN']) |
---|
| 199 | addr_parts = string.split(addr, '.') |
---|
| 200 | addr_parts.reverse() |
---|
| 201 | check_name = string.join(addr_parts, '.') |
---|
| 202 | # We set this to make sure the output is nice. It's not used except for the output after this point. |
---|
| 203 | host = addr |
---|
| 204 | |
---|
| 205 | # ##### Thread stuff: |
---|
| 206 | |
---|
| 207 | # spawn a pool of threads, and pass them queue instance |
---|
| 208 | for i in range(10): |
---|
| 209 | t = ThreadRBL(queue) |
---|
| 210 | t.setDaemon(True) |
---|
| 211 | t.start() |
---|
| 212 | |
---|
| 213 | # populate queue with data |
---|
| 214 | for blhost in serverlist: |
---|
| 215 | queue.put((check_name, blhost)) |
---|
| 216 | |
---|
| 217 | # wait on the queue until everything has been processed |
---|
| 218 | queue.join() |
---|
| 219 | |
---|
| 220 | # ##### End Thread stuff |
---|
| 221 | |
---|
| 222 | if on_blacklist: |
---|
| 223 | output = '%s on %s spam blacklists : %s' % (host, |
---|
| 224 | len(on_blacklist), |
---|
| 225 | ', '.join(on_blacklist)) |
---|
| 226 | if len(on_blacklist) >= crit_limit: |
---|
| 227 | print 'CRITICAL: %s' % output |
---|
| 228 | sys.exit(status['CRITICAL']) |
---|
| 229 | if len(on_blacklist) >= warn_limit: |
---|
| 230 | print 'WARNING: %s' % output |
---|
| 231 | sys.exit(status['WARNING']) |
---|
| 232 | else: |
---|
| 233 | print 'OK: %s' % output |
---|
| 234 | sys.exit(status['OK']) |
---|
| 235 | else: |
---|
| 236 | print 'OK: %s not on known spam blacklists' % host |
---|
| 237 | sys.exit(status['OK']) |
---|
| 238 | |
---|
| 239 | |
---|
| 240 | if __name__ == "__main__": |
---|
| 241 | main(sys.argv, os.environ) |
---|