From 04d6d962d8a2e2f13306d2c17437b2028395d284 Mon Sep 17 00:00:00 2001 From: Andrej Walilko Date: Tue, 30 Jun 2020 12:52:06 -0400 Subject: [PATCH 01/29] Create LICENSE --- LICENSE | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..34d06ac --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2018 Intellex + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. From 355e99dfa309d0042150ba699f022e84cda620b7 Mon Sep 17 00:00:00 2001 From: Andrej Walilko Date: Tue, 30 Jun 2020 13:04:14 -0400 Subject: [PATCH 02/29] separate license, integrate all pending commits --- blcheck | 786 +++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 552 insertions(+), 234 deletions(-) mode change 100755 => 100644 blcheck diff --git a/blcheck b/blcheck old mode 100755 new mode 100644 index 02bdb59..fa9db27 --- a/blcheck +++ b/blcheck @@ -1,165 +1,398 @@ #!/bin/bash -# -# MIT License -# -# Copyright (c) Intellex 2015 -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -# + # ============================================================================= # # title : blcheck -# description : Test any domain against more then 100 black lists. +# description : Test any domain against more than 100 black lists. # author : Intellex -# contributors : Darko Poljak -# date : 2016-03-18 -# version : 0.6.0 +# contributors : Darko Poljak, Oliver Mueller, Andrej Walilko +# date : Jun 30 2020 +# version : 0.7.0 # usage : blcheck [options] +# reference : http://multirbl.valli.org/list/ +# code style : https://google.github.io/styleguide/shell.xml +# url : github.com/ch604/blcheck # # ============================================================================= # Config { - # How many tries and for how long to wait for DNS queries CONF_DNS_TRIES=2 CONF_DNS_DURATION=3 # Blacklists to check + # Example formats: + # - General format + # {ip_or_domain}={filter}#{type} + # - IP based blacklist (default DNSBL, any valid return code will match) + # black.list.com + # - IP based blacklist + # black.list.com#DNSBL + # - IP based whitelist + # white.list.com#DNSWL + # - URI based blacklist + # uri.list.com#URIBL + # - Regexp defined return code, only a match will qualify for list. Here it is 127.0.0.2 and 127.0.0.3 + # black.list.com=127\.0\.0\.[23] + # - Regexp defined return code for a URI based blacklist + # black.list.com=127\.0\.[0-9]+\.0#URIBL CONF_BLACKLISTS=" - 0spam-killlist.fusionzero.com - 0spam.fusionzero.com - access.redhawk.org - all.rbl.jp - all.spam-rbl.fr - all.spamrats.com - aspews.ext.sorbs.net - b.barracudacentral.org - backscatter.spameatingmonkey.net - badnets.spameatingmonkey.net - bb.barracudacentral.org - bl.drmx.org - bl.konstant.no - bl.nszones.com - bl.spamcannibal.org - bl.spameatingmonkey.net - bl.spamstinks.com - black.junkemailfilter.com - blackholes.five-ten-sg.com - blacklist.sci.kun.nl + whitelist.rbl.ispa.at#DNSWL + t3direct.dnsbl.net.au + ucepn.dnsbl.net.au + wpbl.dnsbl.net.au + bl.reynolds.net.au + bl.mav.com.br + openproxy.bls.digibase.ca + proxyabuse.bls.digibase.ca + spambot.bls.digibase.ca + probes.dnsbl.net.auproxy.bl.gweep.ca + rbl2.triumf.ca + wbl.triumf.ca#DNSWL + ipbl.zeustracker.abuse.ch + uribl.zeustracker.abuse.ch + spamrbl.imp.ch + wormrbl.imp.ch + rbl.lugh.ch + dnsrbl.swinog.ch + uribl.swinog.ch blacklist.woody.ch + ipv6.blacklist.woody.ch + uri.blacklist.woody.ch + block.ascams.com + superblock.ascams.com + rbl.blockedservers.com + netscan.rbl.blockedservers.com + spam.rbl.blockedservers.com + list.blogspambl.com + dnsbl1.dnsbl.borderware.com + dnsbl2.dnsbl.borderware.com + dnsbl3.dnsbl.borderware.com + dul.dnsbl.borderware.com + csi.cloudmark.com + dnsbl.cobion.com bogons.cymru.com - bsb.empty.us - bsb.spamlookup.net - cart00ney.surriel.com - cbl.abuseat.org - cbl.anti-spam.org.cn - cblless.anti-spam.org.cn - cblplus.anti-spam.org.cn - cdl.anti-spam.org.cn + v4.fullbogons.cymru.com + v6.fullbogons.cymru.com + rbl.dns-servicios.com + 0outspam.fusionzero.com + 0spam.fusionzero.com + 0spam-n.fusionzero.com + 0spamtrust.fusionzero.com + 0spamurl.fusionzero.com + accredit.habeas.com + hil.habeas.com + hul.habeas.com + sa-accredit.habeas.com + sohul.habeas.com + blacklist.hostkarma.com + iadb.isipp.com + iadb2.isipp.com + iddb.isipp.com + wadb.isipp.com + black.junkemailfilter.com + hostkarma.junkemailfilter.com + nobl.junkemailfilter.com + krn.korumail.com + q.mail-abuse.com + r.mail-abuse.com cidr.bl.mcafee.com - combined.rbl.msrbl.net - db.wpbl.info - dev.null.dk - dialups.visi.com - dnsbl-0.uceprotect.net - dnsbl-1.uceprotect.net - dnsbl-2.uceprotect.net - dnsbl-3.uceprotect.net - dnsbl.anticaptcha.net - dnsbl.aspnet.hu + dnsbl.forefront.microsoft.com + bl.mipspace.com + bl.nordspam.com + dbl.nordspam.com#URIBL + bl.nszones.com + dyn.nszones.com + sbl.nszones.com + ubl.nszones.com + wl.nszones.com#DNSWL + safe.dnsbl.prs.proofpoint.com + rbl.realtimeblacklist.com + mailsl.dnsbl.rjek.com + urlsl.dnsbl.rjek.com + dynip.rothen.com + blackholes.scconsult.com + reputation-domain.rbl.scrolloutf1.com + reputation-ip.rbl.scrolloutf1.com + reputation-ns.rbl.scrolloutf1.com + bl.score.senderscore.com + feb.spamlab.com + rbl.spamlab.com + all.spamrats.com + auth.spamrats.com + dyna.spamrats.com + noptr.spamrats.com + spam.spamrats.com + rbl.suresupport.com + psbl.surriel.com + whitelist.surriel.com#DNSWL + bl.tiopan.com + dbl.tiopan.com#URIBL + ubl.unsubscore.com + black.uribl.com + grey.uribl.com + multi.uribl.com + red.uribl.com + white.uribl.com#DNSWL + spam.dnsbl.anonmails.de + bl.blocklist.de + dnsbl.darklist.de dnsbl.inps.de - dnsbl.justspam.org - dnsbl.kempt.net + dnswl.inps.de#DNSWL + admin.bl.kundenserver.de + relays.bl.kundenserver.de + schizo-bl.kundenserver.de + spamblock.kundenserver.de + worms-bl.kundenserver.de dnsbl.madavi.de - dnsbl.rizon.net + torserver.tor.dnsbl.sectoor.de + dunk.dnsbl.tuxad.de + hartkore.dnsbl.tuxad.de + spamsources.fabel.dk + st.technovision.dk + dnsbl.abyan.es + eswlrev.dnsbl.rediris.es#DNSWL + mtawlrev.dnsbl.rediris.es#DNSWL + dnsbl.isx.fr + all.spam-rbl.fr + pofon.foobar.hu + ispmx.pofon.foobar.hu + uribl.pofon.foobar.hu + singular.ttk.pte.hu + blacklist.netcore.co.in dnsbl.rv-soft.info - dnsbl.rymsho.ru - dnsbl.sorbs.net - dnsbl.zapbl.net - dnsrbl.swinog.ch - dul.pacifier.net - dyn.nszones.com - dyna.spamrats.com + nana.bl.techtheft.info + other.bl.techtheft.info + robot.bl.techtheft.info + scanning.bl.techtheft.info + source.bl.techtheft.info + support.bl.techtheft.info + virus.bl.techtheft.info + watchlist.bl.techtheft.info + db.wpbl.info + rbl.jp + spamlist.or.kr + bl.fmb.la + communicado.fmb.la + nsbl.fmb.la + sa.fmb.la + short.fmb.la + dnsbl.anticaptcha.net + dnsbl6.anticaptcha.net + blacklist.mail.ops.asp.att.net + blacklist.sequoia.ops.asp.att.net + blacklist.mailrelay.att.net + rbl.blakjak.net + dul.blackhole.cantv.net + hog.blackhole.cantv.net + rhsbl.blackhole.cantv.net + rot.blackhole.cantv.net + spam.blackhole.cantv.net + rbl.choon.net + ipv6.rbl.choon.net + rwl.choon.net + ipv6.rwl.choon.net + dnsbl.cyberlogic.net fnrbl.fast.net - fresh.spameatingmonkey.net - hostkarma.junkemailfilter.com - images.rbl.msrbl.net - ips.backscatterer.org + truncate.gbudb.net + rbl.interserver.net + rbl.iprange.net + dnsbl.kempt.net + spamguard.leadmon.net + niprbl.mailcleaner.net + uribl.mailcleaner.net + dnsbl.mailshell.net + bl.mailspike.net + rep.mailspike.net + wl.mailspike.net#DNSWL + z.mailspike.net ix.dnsbl.manitu.net + combined.rbl.msrbl.net + images.rbl.msrbl.net + phishing.rbl.msrbl.net + spam.rbl.msrbl.net + virus.rbl.msrbl.net + web.rbl.msrbl.net + relays.nether.net + trusted.nether.net + unsure.nether.net + dul.pacifier.net + all.s5h.net + bl.scientificspam.net + rhsbl.scientificspam.net korea.services.net + dnsbl.sorbs.net + block.dnsbl.sorbs.net + exitnodes.tor.dnsbl.sectoor.dehttp.dnsbl.sorbs.net + dul.dnsbl.sorbs.net + escalations.dnsbl.sorbs.net + http.dnsbl.sorbs.net + misc.dnsbl.sorbs.net + new.dnsbl.sorbs.net + noservers.dnsbl.sorbs.net + old.dnsbl.sorbs.net + problems.dnsbl.sorbs.net + proxies.dnsbl.sorbs.net + recent.dnsbl.sorbs.net + relays.dnsbl.sorbs.net + safe.dnsbl.sorbs.net + smtp.dnsbl.sorbs.net + socks.dnsbl.sorbs.net + spam.dnsbl.sorbs.net + new.spam.dnsbl.sorbs.net + old.spam.dnsbl.sorbs.net + recent.spam.dnsbl.sorbs.net + web.dnsbl.sorbs.net + zombie.dnsbl.sorbs.net + aspews.ext.sorbs.net + l1.bbfh.ext.sorbs.net l2.bbfh.ext.sorbs.net l3.bbfh.ext.sorbs.net l4.bbfh.ext.sorbs.net - list.bbfh.org - list.blogspambl.com - mail-abuse.blacklist.jippg.org + rhsbl.sorbs.net + badconf.rhsbl.sorbs.net + nomail.rhsbl.sorbs.net + bl.spamcop.net + backscatter.spameatingmonkey.net + bl.spameatingmonkey.net + fresh.spameatingmonkey.net + fresh10.spameatingmonkey.net + fresh15.spameatingmonkey.net + fresh30.spameatingmonkey.net + freshzero.spameatingmonkey.net + bl.ipv6.spameatingmonkey.net netbl.spameatingmonkey.net - netscan.rbl.blockedservers.com - no-more-funn.moensted.dk - noptr.spamrats.com + uribl.spameatingmonkey.net + urired.spameatingmonkey.net + bsb.spamlookup.net + dnsbl.spfbl.net + score.spfbl.net + dnswl.spfbl.net#DNSWL + bl.suomispam.net + dbl.suomispam.net#URIBL + gl.suomispam.net + dob.sibl.support-intelligence.net + srn.surgate.net + srnblack.surgate.net + rbl.tdk.net + dnsbl-0.uceprotect.net + dnsbl-1.uceprotect.net + dnsbl-2.uceprotect.net + dnsbl-3.uceprotect.net + all.rbl.webiron.net + babl.rbl.webiron.net + cabl.rbl.webiron.net + crawler.rbl.webiron.net + stabl.rbl.webiron.net + dnsbl.zapbl.net + rhsbl.zapbl.net + rbl.zenon.net + dnsbl.beetjevreemd.nl + bitonly.dnsbl.bit.nl + virbl.bit.nl + blacklist.sci.kun.nl + whitelist.sci.kun.nl#DNSWL + blackholes.tepucom.nl + bl.konstant.no + bl.0spam.org + nbl.0spam.org + url.0spam.org + cbl.abuseat.org orvedb.aupads.org - pbl.spamhaus.org - phishing.rbl.msrbl.net - pofon.foobar.hu - psbl.surriel.com - rbl.abuse.ro - rbl.blockedservers.com - rbl.dns-servicios.com + rsbl.aupads.org + ips.backscatterer.org + b.barracudacentral.org + bb.barracudacentral.org + list.bbfh.org + plus.bondedsender.org + query.bondedsender.org + dnsblchile.org + dnsrbl.org + dwl.dnswl.org#DNSWL + list.dnswl.org#DNSWL + bl.drmx.org + dnsbl.dronebl.org rbl.efnet.org + tor.efnet.org rbl.efnetrbl.org - rbl.iprange.net + dnsbl.rangers.eu.org + dnsbl.httpbl.org + mail-abuse.blacklist.jippg.org + dnsbl.justspam.org + bl.mailspike.org + bl.nosolicitado.org + bl.worst.nosolicitado.org + dnsbl.openresolvers.org + spam.pedantic.org + access.redhawk.org + abuse.rfc-clueless.org + bogusmx.rfc-clueless.org + dsn.rfc-clueless.org + elitist.rfc-clueless.org + fulldom.rfc-clueless.org + postmaster.rfc-clueless.org + whois.rfc-clueless.org + public.sarbl.org rbl.schulte.org - rbl.talkactive.net - rbl2.triumf.ca - rsbl.aupads.org - sbl-xbl.spamhaus.org - sbl.nszones.com + sbl.spamdown.org + dbl.spamhaus.org#URIBL + vouch.dwl.spamhaus.org#DNSWL + pbl.spamhaus.org sbl.spamhaus.org - short.rbl.jp - spam.dnsbl.anonmails.de - spam.pedantic.org - spam.rbl.blockedservers.com - spam.rbl.msrbl.net - spam.spamrats.com - spamrbl.imp.ch - spamsources.fabel.dk - st.technovision.dk - tor.dan.me.uk - tor.dnsbl.sectoor.de - tor.efnet.org - torexit.dan.me.uk - truncate.gbudb.net - ubl.unsubscore.com - uribl.spameatingmonkey.net - urired.spameatingmonkey.net - virbl.dnsbl.bit.nl - virus.rbl.jp - virus.rbl.msrbl.net + sbl-xbl.spamhaus.org + swl.spamhaus.org#DNSWL + xbl.spamhaus.org + zen.spamhaus.org + abuse.surbl.org + cr.surbl.org + multi.surbl.org + mw.surbl.org + dnsbl.tornevall.org + opm.tornevall.org + free.v4bl.org + ip.v4bl.org + ips.whitelisted.org#DNSWL + dnsbl.calivent.com.pe + forbidden.icm.edu.pl + dyn.rbl.polspam.pl + lblip4.rbl.polspam.pl + lblip6.rbl.polspam.pl + rblip4.rbl.polspam.pl + rblip6.rbl.polspam.pl + rhsbl.rbl.polspam.pl + rbl.abuse.ro + uribl.abuse.ro vote.drbl.caravan.ru - vote.drbl.gremlin.ru - web.rbl.msrbl.net work.drbl.caravan.ru + vote.drbl.gremlin.ru work.drbl.gremlin.ru - wormrbl.imp.ch - xbl.spamhaus.org - zen.spamhaus.org" + dul.dnsbl.sorbs.netdul.ru + bl.shlink.orgdul.ru + ###rbl.rbldns.ru + dnsbl.rymsho.ru + rhsbl.rymsho.ru + netblockbl.spamgrouper.to + dnsbl.mcu.edu.tw + dnsbl.net.ua + rbl.fasthosts.co.uk + torexit.dan.me.uk + bsb.empty.us + 88.blocklist.zap" + + + # reputation/scoring pages + # score.senderscore.com + + CONF_BLACKLISTS_TEST=" + rbl.rbldns.ru + rbl.rbldns.ru=127\.0\.0\.1 + rbl.rbldns.ru#DNSWL + black.list.com=127.0.[0-9]+.0#URIBL + dbl.spamhaus.org#URIBL + t3direct.dnsbl.net.au=127\.0\.0\.1#DNSWL + t3direct.dnsbl.net.au#BLA + t3direct.dnsbl.net.au%127\.0\.0\.1#DNSWL" #~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ } @@ -171,6 +404,7 @@ REGEX_IP='\([0-9]\{1,3\}\)\.\([0-9]\{1,3\}\)\.\([0-9]\{1,3\}\)\.\([0-9]\{1,3\}\)' REGEX_DOMAIN='\([a-zA-Z0-9]\+\(-[a-zA-Z0-9]\+\)*\.\)\+[a-zA-Z]\{2,\}' REGEX_TDL='\([a-zA-Z0-9]\+\(-[a-zA-Z0-9]\+\)*\.\)[a-zA-Z]\{2,\}$' + REGEX_LIST='^[ \\t]*([^=#]+)(=(([^#])+))?(#(DNSBL|DNSWL|URIBL))?[ \\t]*$' # Colors if [[ $- == *i* ]]; then @@ -198,6 +432,7 @@ #SPINNER="◴◷◶◵" #SPINNER="◐◓◑◒" + VERBOSE=0 #~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ } @@ -205,9 +440,8 @@ # Macros { # Verbose printing - VERBOSE=0 info() { - if [ $VERBOSE -ge "$1" ]; then + if [[ ${VERBOSE} -ge "$1" ]]; then echo "$2" fi } @@ -222,36 +456,54 @@ progress() { # Bar - x=$(($1 % ${#SPINNER} + 1)) - BAR=$(echo $SPINNER | awk "{ print substr(\$0, ${x}, 1) }") - if test -z "$PLAIN"; then + local x=$(($1 % ${#SPINNER} + 1)) + local BAR=$(echo ${SPINNER} | awk "{ print substr(\$0, ${x}, 1) }") + if [[ -z "${PLAIN}" ]]; then printf "\r "; fi # BAR as printf arg so that backslash will be litteraly interpreted - printf "[ %s %3s%% ] checking... %4s / $2 " "$BAR" $(($1 * 100 / $2)) "$1"; + printf "[ %s %3s%% ] checking... %4s / $2 " "${BAR}" $(($1 * 100 / $2)) "$1"; } # Resolve the IP resolve() { # IP already? - IP=$(echo "$1" | grep "^$REGEX_IP$") - if [ "$IP" ]; then - echo "$IP" + local IP=$(echo "$1" | grep "^${REGEX_IP}$") + if [[ "${IP}" ]]; then + echo "${IP}" # Resolve domain else # Handle special resolve types case "$2" in - "ns" ) TYPE="ns"; REGEX="$REGEX_DOMAIN\.$";; - * ) TYPE="a"; REGEX="$REGEX_IP$";; + "ns" ) TYPE="ns"; REGEX="${REGEX_DOMAIN}\.$";; + * ) TYPE="a"; REGEX="${REGEX_IP}$";; esac - case "$CMD" in - $CMD_DIG ) "$CMD" $DNSSERVER +short -t "$TYPE" +time=$CONF_DNS_DURATION +tries=$CONF_DNS_TRIES "$1" | grep -om 1 "$REGEX";; - $CMD_HOST ) "$CMD" -t "$TYPE" -W $CONF_DNS_DURATION -R $CONF_DNS_TRIES "$1" $DNSSERVER | tail -n1 | grep -om 1 "$REGEX";; + case "${CMD}" in + ${CMD_DIG} ) "${CMD}" ${DNSSERVER} +short -t "${TYPE}" +time=${CONF_DNS_DURATION} +tries=${CONF_DNS_TRIES} "$1" | grep -om 1 "${REGEX}";; + ${CMD_HOST} ) "${CMD}" -t "${TYPE}" -W ${CONF_DNS_DURATION} -R ${CONF_DNS_TRIES} "$1" ${DNSSERVER} | tail -n1 | grep -om 1 "${REGEX}";; + esac + fi + } + + # Result info for IP + text() { + # IP already? + local IP=$(echo "$1" | grep "^${REGEX_IP}$") + if [[ -n "${IP}" ]]; then + echo "${IP}" + + # Resolve domain + else + + local TYPE="txt" + case "${CMD}" in + ${CMD_DIG} ) "${CMD}" ${DNSSERVER} +short -t "${TYPE}" +time=${CONF_DNS_DURATION} +tries=${CONF_DNS_TRIES} "$1" ;; + ${CMD_HOST} ) "${CMD}" -t "${TYPE}" -W ${CONF_DNS_DURATION} -R ${CONF_DNS_TRIES} "$1" ${DNSSERVER} | tail -n1 ;; esac fi } @@ -260,9 +512,9 @@ loadBlacklists() { # Make sure the file is readable - if [ ! "$1" ]; then + if [[ -z "$1" ]]; then error "Option -l requires an additional parameter"; - elif [ ! -r $1 ]; then + elif [[ ! -r $1 ]]; then error "File $1 cannot be opened for reading, make sure it exists and that you have appropriate privileges" fi @@ -281,7 +533,7 @@ If the IP is supplied, the PTR check cannot be executed and will be skipped. -l file Load blacklists from file, separated by space or new line -c Warn if the top level domain of the blacklist has expired -v Verbose mode, can be used multiple times (up to -vvv) --q Quiet modem with absolutely no output (useful for scripts) +-q Quiet mode with absolutely no output (useful for scripts) -p Plain text output (no coloring, no interactive status) -h The help you are just reading @@ -296,21 +548,21 @@ HELP # Parse the params while getopts :vqphcl:d: arg; do - case "$arg" in - d) DNSSERVER=$OPTARG;; - l) loadBlacklists $OPTARG;; + case "${arg}" in + d) DNSSERVER="${OPTARG}";; + l) loadBlacklists "${OPTARG}";; c) VERIFY_BL=TRUE;; - v) VERBOSE=$(( (VERBOSE + 1) % 4));; + v) VERBOSE=$((VERBOSE + 1));; q) VERBOSE=-1;; p) PLAIN=1 RED="" GREEN="" YELLOW="" CLEAR="" ;; h) showHelp;; - ?) error "Unknown option $OPTARG";; + ?) error "Unknown option ${OPTARG}";; esac done shift $((OPTIND - 1)) # Get the domain -if [ $# -eq 0 ]; then +if [[ $# -eq 0 ]]; then echo "Missing target domain or IP." showHelp fi @@ -322,196 +574,262 @@ shopt -s xpg_echo # Get the command we will use: dig or host CMD_DIG=$(which dig) -CMD_HOST=$(which host) -if [ "$CMD_DIG" ]; then - if [[ $DNSSERVER ]]; then - DNSSERVER="@$DNSSERVER" +if [[ "${CMD_DIG}" ]]; then + if [[ -n "${DNSSERVER}" ]]; then + DNSSERVER="@${DNSSERVER}" + fi + CMD=${CMD_DIG} +else + CMD_HOST=$(which host) + if [[ "${CMD_HOST}" ]]; then + CMD=${CMD_HOST} fi - CMD=$CMD_DIG -elif [ "$CMD_HOST" ]; then - CMD=$CMD_HOST fi -if [ ! "$CMD" ]; then +if [[ -z "${CMD}" ]]; then error "Either dig or host command is required." fi -info 3 "Using $CMD to reslove DNS queries" +info 3 "Using ${CMD} to reslove DNS queries" # Parse IP -IP=$(resolve "$TARGET") -if [ ! "$IP" ]; then - error "No DNS record found for $TARGET" -elif [ "$IP" != "$TARGET" ]; then - DOMAIN=$TARGET - info 2 "Using $TARGET for target, resolved to $IP" +IP=$(resolve "${TARGET}") +if [[ -z "${IP}" ]]; then + error "No DNS record found for ${TARGET}" +elif [[ "${IP}" != "${TARGET}" ]]; then + DOMAIN=${TARGET} + info 2 "Using ${TARGET} for target, resolved to ${IP}" + TARGET_TYPE="domain" else - info 3 "Using $TARGET for target" + info 3 "Using ${TARGET} for target" + TARGET_TYPE="ip" fi # Reverse the IP -REVERSED=$(echo "$IP" | sed -ne "s~^$REGEX_IP$~\4.\3.\2.\1~p") -info 3 "Using $REVERSED for reversed IP" +REVERSED=$(echo "${IP}" | sed -ne "s~^${REGEX_IP}$~\4.\3.\2.\1~p") +info 3 "Using ${REVERSED} for reversed IP" # Get the PTR info 3 "Checking the PTR record" -case "$CMD" in - $CMD_DIG ) PTR=$("$CMD" $DNSSERVER +short -x "$IP" | sed s/\.$//);; - $CMD_HOST ) PTR=$("$CMD" "$IP" $DNSSERVER | tail -n1 | grep -o '[^ ]\+$' | sed s/\.$//) +case "${CMD}" in + ${CMD_DIG} ) PTR=$("${CMD}" ${DNSSERVER} +short -x "${IP}" | sed s/\.$//);; + ${CMD_HOST} ) PTR=$("${CMD}" "${IP}" ${DNSSERVER} | tail -n1 | grep -o '[^ ]\+$' | sed s/\.$//) esac # Validate PTR -if [ ! "$PTR" ]; then +if [[ -z "${PTR}" ]]; then info 0 "${YELLOW}Warning: PTR lookup failed${CLEAR}" else # Match against supplied domain - info 1 "PTR resolves to $PTR" - if [ "$DOMAIN" ]; then - if [ "$DOMAIN" != "$PTR" ]; then - info 0 "${YELLOW}Warning: PTR record does not match supplied domain: $TARGET != $PTR${CLEAR}" + info 1 "PTR resolves to ${PTR}" + if [[ -n "${DOMAIN}" ]]; then + if [[ "${DOMAIN}" != "${PTR}" ]]; then + info 0 "${YELLOW}Warning: PTR record does not match supplied domain: ${TARGET} != ${PTR}${CLEAR}" else - info 1 "${GREEN}PTR record matches supplied domain $PTR${CLEAR}" + info 1 "${GREEN}PTR record matches supplied domain ${PTR}${CLEAR}" fi fi fi # Filter out the blacklists BLACKLISTS="" -for BL in $CONF_BLACKLISTS; do - if [ "$BL" ]; then - - # Make sure the domain is a proper one - DOMAIN=$(echo "$BL" | sed -e 's/^[ \t]*//' | grep ^"$REGEX_DOMAIN"$) - if [ ! "$DOMAIN" ]; then - info 0 "${YELLOW}Warning: blacklist '$BL' is not valid and will be ignored${CLEAR}" +COUNT_DNSBL=0 +COUNT_DNSWL=0 +COUNT_URIBL=0 +COUNT=0 +for BL in ${CONF_BLACKLISTS}; do + if [[ "${BL}" ]]; then + if [[ ${BL} =~ ${REGEX_LIST} ]]; then + DOMAIN="${BASH_REMATCH[1]}" + if [[ -n "${BASH_REMATCH[3]}" ]]; then + FILTER="${BASH_REMATCH[3]}" + else + FILTER='127\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})' + fi + if [[ -n "${BASH_REMATCH[6]}" ]]; then + TYPE="${BASH_REMATCH[6]}" + else + TYPE='DNSBL' + fi - else + # Make sure the domain is a proper one + TMP=$(echo "${DOMAIN}" | sed -e 's/^[ \t]*//' | grep ^"${REGEX_DOMAIN}"$) + if [[ -z "${TMP}" ]]; then + info 0 "${YELLOW}Warning: domain '${DOMAIN}' is not valid and will be ignored${CLEAR}" - # It is a proper blacklist - if [ "$BLACKLISTS" ]; then - BLACKLISTS=$(echo "$BLACKLISTS\n$DOMAIN") else - BLACKLISTS="$BL" + if [[ "${TARGET_TYPE}" == 'ip' && "${TYPE}" == 'URIBL' ]]; then + info 0 "${GREEN}Notice: URIBL entry '${DOMAIN}' will be ignore, because ${TARGET} is an IP address${CLEAR}" + else + case "${TYPE}" in + "DNSBL") COUNT_DNSBL=$((COUNT_DNSBL + 1)) ;; + "DNSWL") COUNT_DNSWL=$((COUNT_DNSWL + 1)) ;; + "URIBL") COUNT_URIBL=$((COUNT_URIBL + 1)) ;; + esac + COUNT=$((COUNT + 1)) + + # It is a proper blacklist + if [[ "${BLACKLISTS}" ]]; then + BLACKLISTS=$(echo "${BLACKLISTS}\n${DOMAIN}=${FILTER}#${TYPE}") + else + BLACKLISTS="${DOMAIN}=${FILTER}#${TYPE}" + fi + fi fi + else + info 0 "${YELLOW}Warning: list entry '${BL}' is not valid and will be ignored${CLEAR}" fi fi done # Make sure we have at least one blacklist -COUNT=$(($(echo "$BLACKLISTS" | wc -l))) -if [ ! "$BLACKLISTS" ] || [ "$COUNT" -eq 0 ]; then +if [[ "${COUNT}" -eq 0 ]]; then error "No blacklists have been specified" fi -info 1 "Matching against $COUNT blacklists" +info 1 "Matching against ${COUNT} entries:" +info 1 " - ${COUNT_DNSBL} DNS blacklists" +info 1 " - ${COUNT_DNSWL} DNS whitelists" +info 1 " - ${COUNT_URIBL} URI blacklists" # Initialize the counters INVALID=0 PASSED=0 FAILED=0 +WHITE=0 -# Interate over all blacklists +# Iterate over all blacklists I=0; -for BL in $BLACKLISTS; do +for BL in ${BLACKLISTS}; do PREFIX= I=$((I + 1)) + # Parse list entry + if [[ ! ${BL} =~ ${REGEX_LIST} ]]; then + error "List entry ${BL} broken" + fi + DOMAIN="${BASH_REMATCH[1]}" + FILTER="${BASH_REMATCH[3]}" + TYPE="${BASH_REMATCH[6]}" + + + # What should we test - TEST="$REVERSED.$BL." + if [[ "${TYPE}" != "URIBL" ]]; then + # IP based test + TEST="${REVERSED}.${DOMAIN}." + else + # Domain name based test (URI) + TEST="${TARGET}.${DOMAIN}." + fi - # Make sure the info is shown if we are cheking the servers - if [ "$VERIFY_BL" ] && [ $VERBOSE -lt 1 ]; then + + # Make sure the info is shown if we are checking the servers + if [[ "${VERIFY_BL}" && "${VERBOSE}" -lt 1 ]]; then VERBOSE=1 fi # For verbose output - if [ $VERBOSE -ge 1 ]; then + if [[ "${VERBOSE}" -ge 1 ]]; then # Show percentage STATUS=$(printf " %3s" $((I * 100 / COUNT))) - STATUS="$STATUS%% " + STATUS="${STATUS}%% " # Show additional info - if [ $VERBOSE -ge 3 ]; then - PREFIX=$(printf "%-60s" "$TEST") + if [[ "${VERBOSE}" -ge 3 ]]; then + PREFIX=$(printf "%-60s" "${TEST}") else - PREFIX=$(printf "%-50s" "$BL") + PREFIX=$(printf "%-50s" "${DOMAIN}") fi - PREFIX="$STATUS $PREFIX" - if test -z "$PLAIN"; then - printf "%s \b" "$PREFIX" + PREFIX="${STATUS} ${PREFIX}" + if [[ -z "${PLAIN}" ]]; then + printf "%s \b" "${PREFIX}" fi - elif [ $VERBOSE -ge 0 ]; then - if test -z "$PLAIN"; then - progress "$I" "$COUNT" + elif [[ "${VERBOSE}" -ge 0 ]]; then + if [[ -z "${PLAIN}" ]]; then + progress "${I}" "${COUNT}" fi fi # Get the status - RESPONSE=$(resolve "$TEST") - START=$(echo "$RESPONSE" | cut -c1-4) + RESPONSE=$(resolve "${TEST}") # Not blacklisted - if [ ! "$RESPONSE" ]; then + if [[ -z "${RESPONSE}" ]]; then # Make sure the server is viable ERROR="" - if [ "$VERIFY_BL" ]; then - TDL=$(echo "$BL" | grep -om 1 '\([a-zA-Z0-9]\+\(-[a-zA-Z0-9]\+\)*\.\)[a-zA-Z]\{2,\}$') - if [ ! "$(resolve "$TDL" ns)" ]; then - if test -z "$PLAIN"; then printf "\r"; fi - printf "%s%sUnreachable server%s\n" "$YELLOW" "$PREFIX" "$CLEAR"; + if [[ "${VERIFY_BL}" ]]; then + TDL=$(echo "${DOMAIN}" | grep -om 1 '\([a-zA-Z0-9]\+\(-[a-zA-Z0-9]\+\)*\.\)[a-zA-Z]\{2,\}$') + if [[ ! "$(resolve "${TDL}" ns)" ]]; then + if [[ -z "${PLAIN}" ]]; then printf "\r"; fi + printf "%s%sUnreachable server%s\n" "${YELLOW}" "${PREFIX}" "${CLEAR}"; INVALID=$((INVALID + 1)) ERROR=TRUE fi fi - if [ ! "$ERROR" ]; then - if [ "$VERIFY_BL" ] || [ $VERBOSE -ge 1 ]; then - if test -z "$PLAIN"; then printf "\r"; fi - printf "%s%s✓%s\n" "$CLEAR" "$PREFIX" "$CLEAR"; + if [[ ! "${ERROR}" ]]; then + if [[ -n "${VERIFY_BL}" || "${VERBOSE}" -ge 1 ]]; then + if [[ -z "${PLAIN}" ]]; then printf "\r"; fi + printf "%s%s✓%s\n" "${CLEAR}" "${PREFIX}" "${CLEAR}"; fi PASSED=$((PASSED + 1)) fi; # Invalid response - elif [ "$START" != "127." ]; then - if [ $VERBOSE -ge 1 ]; then - if test -z "$PLAIN"; then printf "\r"; fi - printf "%s%sinvalid response (%s)%s\n" "$YELLOW" "$PREFIX" "$RESPONSE" "$CLEAR"; + elif [[ ! "${RESPONSE}" =~ ${FILTER} ]]; then + if [[ "${VERBOSE}" -ge 1 ]]; then + if [[ -z "${PLAIN}" ]]; then printf "\r"; fi + printf "%s%sinvalid response (%s)%s\n" "${YELLOW}" "${PREFIX}" "${RESPONSE}" "${CLEAR}"; + printf "%s%${#PREFIX}s%s%s\n" "${YELLOW}" "TXT: " "$(text "${TEST}")" "${CLEAR}"; fi; INVALID=$((INVALID + 1)) - # Blacklisted + # matched else - if [ $VERBOSE -ge 1 ]; then - if test -z "$PLAIN"; then printf "\r"; fi - printf "%s%sblacklisted (%s)%s\n" "$RED" "$PREFIX" "$RESPONSE" "$CLEAR"; - elif [ $VERBOSE -ge 0 ]; then - if test -z "$PLAIN"; then printf "\r "; printf "\r"; fi - printf "%s%s%s : %s\n" "$RED" "$BL" "$CLEAR" "$RESPONSE" + if [[ "${TYPE}" != "DNSWL" ]]; then + if [[ "${VERBOSE}" -ge 1 ]]; then + if [[ -z "${PLAIN}" ]]; then printf "\r"; fi + printf "%s%sblacklisted (%s)%s\n" "${RED}" "${PREFIX}" "${RESPONSE}" "${CLEAR}"; + printf "%s%${#PREFIX}s%s%s\n" "${RED}" "TXT: " "$(text "${TEST}")" "${CLEAR}"; + elif [[ "${VERBOSE}" -ge 0 ]]; then + if [[ -z "${PLAIN}" ]]; then printf "\r "; printf "\r"; fi + printf "%s%s%s : %s\n" "${RED}" "${DOMAIN}" "${CLEAR}" "${RESPONSE}" + fi + FAILED=$((FAILED + 1)) + else + if [[ "${VERBOSE}" -ge 1 ]]; then + if [[ -z "${PLAIN}" ]]; then printf "\r"; fi + printf "%s%swhitelisted (%s)%s\n" "${GREEN}" "${PREFIX}" "${RESPONSE}" "${CLEAR}"; + printf "%s%${#PREFIX}s%s%s\n" "${GREEN}" "TXT: " "$(text "${TEST}")" "${CLEAR}"; + elif [[ "${VERBOSE}" -ge 0 ]]; then + if [[ -z "${PLAIN}" ]]; then printf "\r "; printf "\r"; fi + printf "%s%s%s : %s\n" "${GREEN}" "${DOMAIN}" "${CLEAR}" "${RESPONSE}" + fi + WHITE=$((WHITE + 1)) fi - FAILED=$((FAILED + 1)) fi done # Print results -if [ $VERBOSE -ge 0 ]; then - if test -z "$PLAIN"; then +if [[ "${VERBOSE}" -ge 0 ]]; then + if [[ -z "${PLAIN}" ]]; then printf "\r \n" else printf " \n" fi echo "----------------------------------------------------------" - echo Results for "$TARGET" + echo Results for "${TARGET}" echo printf "%-15s" "Tested:"; echo "${COUNT}" printf "%-15s" "Passed:"; echo "${GREEN}${PASSED}${CLEAR}" + printf "%-15s" "Whitelisted:"; echo "${GREEN}${WHITE}${CLEAR}" printf "%-15s" "Invalid:"; echo "${YELLOW}${INVALID}${CLEAR}" printf "%-15s" "Blacklisted:"; echo "${RED}${FAILED}${CLEAR}" echo "----------------------------------------------------------" fi -exit $FAILED; - +exit "${FAILED}" From 215493ef749106cdd3c6f37948b9e66b6fca6f5d Mon Sep 17 00:00:00 2001 From: Andrej Walilko Date: Tue, 30 Jun 2020 13:06:19 -0400 Subject: [PATCH 03/29] remove nszones --- blcheck | 6 ------ 1 file changed, 6 deletions(-) diff --git a/blcheck b/blcheck index fa9db27..bf3a92d 100644 --- a/blcheck +++ b/blcheck @@ -102,11 +102,6 @@ bl.mipspace.com bl.nordspam.com dbl.nordspam.com#URIBL - bl.nszones.com - dyn.nszones.com - sbl.nszones.com - ubl.nszones.com - wl.nszones.com#DNSWL safe.dnsbl.prs.proofpoint.com rbl.realtimeblacklist.com mailsl.dnsbl.rjek.com @@ -369,7 +364,6 @@ work.drbl.gremlin.ru dul.dnsbl.sorbs.netdul.ru bl.shlink.orgdul.ru - ###rbl.rbldns.ru dnsbl.rymsho.ru rhsbl.rymsho.ru netblockbl.spamgrouper.to From 01f6d85b094174b99bd54a3cc2afc665cb43b1db Mon Sep 17 00:00:00 2001 From: Andrej Walilko Date: Tue, 30 Jun 2020 13:10:36 -0400 Subject: [PATCH 04/29] double percent --- blcheck | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blcheck b/blcheck index bf3a92d..5fbe146 100644 --- a/blcheck +++ b/blcheck @@ -727,7 +727,7 @@ for BL in ${BLACKLISTS}; do # Show percentage STATUS=$(printf " %3s" $((I * 100 / COUNT))) - STATUS="${STATUS}%% " + STATUS="${STATUS}% " # Show additional info if [[ "${VERBOSE}" -ge 3 ]]; then From 6daaec26e3267c80897e68ba6c3e7573688dd3c2 Mon Sep 17 00:00:00 2001 From: Andrej Walilko Date: Tue, 30 Jun 2020 14:48:19 -0400 Subject: [PATCH 05/29] parallel processing --- blcheck | 83 ++++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 53 insertions(+), 30 deletions(-) diff --git a/blcheck b/blcheck index 5fbe146..4f31a4a 100644 --- a/blcheck +++ b/blcheck @@ -562,6 +562,19 @@ if [[ $# -eq 0 ]]; then fi TARGET=$1 +if [ ! $(which parallel 2> /dev/null) ]; then + echo "Parallel missing, trying to install..." + [ ! "$(yum -q provides parallel)" ] && yum -y -q install epel-release + yum -y -q install parallel + if [ "$(which parallel 2> /dev/null)" ]; then + mkdir ~/.parallel + touch ~/.parallel/will-cite + else + echo "Failed to install parallel, exiting." + exit 1 + fi +fi + # Some shells disable parsing backslash in echo statements by default # Set the flag to enable echo to behave consistently across platforms shopt -s xpg_echo @@ -685,48 +698,44 @@ info 1 " - ${COUNT_DNSBL} DNS blacklists" info 1 " - ${COUNT_DNSWL} DNS whitelists" info 1 " - ${COUNT_URIBL} URI blacklists" -# Initialize the counters -INVALID=0 -PASSED=0 -FAILED=0 -WHITE=0 - # Iterate over all blacklists -I=0; -for BL in ${BLACKLISTS}; do - PREFIX= - I=$((I + 1)) + +parallel_check() { + local PREFIX= + local I=$1 + local BL=$2 # Parse list entry if [[ ! ${BL} =~ ${REGEX_LIST} ]]; then error "List entry ${BL} broken" + else + local DOMAIN="${BASH_REMATCH[1]}" + local FILTER="${BASH_REMATCH[3]}" + local TYPE="${BASH_REMATCH[6]}" fi - DOMAIN="${BASH_REMATCH[1]}" - FILTER="${BASH_REMATCH[3]}" - TYPE="${BASH_REMATCH[6]}" # What should we test if [[ "${TYPE}" != "URIBL" ]]; then # IP based test - TEST="${REVERSED}.${DOMAIN}." + local TEST="${REVERSED}.${DOMAIN}." else # Domain name based test (URI) - TEST="${TARGET}.${DOMAIN}." + local TEST="${TARGET}.${DOMAIN}." fi # Make sure the info is shown if we are checking the servers if [[ "${VERIFY_BL}" && "${VERBOSE}" -lt 1 ]]; then - VERBOSE=1 + local VERBOSE=1 fi # For verbose output if [[ "${VERBOSE}" -ge 1 ]]; then # Show percentage - STATUS=$(printf " %3s" $((I * 100 / COUNT))) + local STATUS=$(printf " %3s" $((I * 100 / COUNT))) STATUS="${STATUS}% " # Show additional info @@ -748,19 +757,19 @@ for BL in ${BLACKLISTS}; do fi # Get the status - RESPONSE=$(resolve "${TEST}") + local RESPONSE=$(resolve "${TEST}") # Not blacklisted if [[ -z "${RESPONSE}" ]]; then # Make sure the server is viable - ERROR="" + local ERROR="" if [[ "${VERIFY_BL}" ]]; then - TDL=$(echo "${DOMAIN}" | grep -om 1 '\([a-zA-Z0-9]\+\(-[a-zA-Z0-9]\+\)*\.\)[a-zA-Z]\{2,\}$') + local TDL=$(echo "${DOMAIN}" | grep -om 1 '\([a-zA-Z0-9]\+\(-[a-zA-Z0-9]\+\)*\.\)[a-zA-Z]\{2,\}$') if [[ ! "$(resolve "${TDL}" ns)" ]]; then if [[ -z "${PLAIN}" ]]; then printf "\r"; fi printf "%s%sUnreachable server%s\n" "${YELLOW}" "${PREFIX}" "${CLEAR}"; - INVALID=$((INVALID + 1)) + echo "$BL" >> $invalid_file ERROR=TRUE fi fi @@ -770,7 +779,7 @@ for BL in ${BLACKLISTS}; do if [[ -z "${PLAIN}" ]]; then printf "\r"; fi printf "%s%s✓%s\n" "${CLEAR}" "${PREFIX}" "${CLEAR}"; fi - PASSED=$((PASSED + 1)) + echo "$BL" >> $passed_file fi; # Invalid response @@ -793,7 +802,7 @@ for BL in ${BLACKLISTS}; do if [[ -z "${PLAIN}" ]]; then printf "\r "; printf "\r"; fi printf "%s%s%s : %s\n" "${RED}" "${DOMAIN}" "${CLEAR}" "${RESPONSE}" fi - FAILED=$((FAILED + 1)) + echo "$BL" >> $failed_file else if [[ "${VERBOSE}" -ge 1 ]]; then if [[ -z "${PLAIN}" ]]; then printf "\r"; fi @@ -803,10 +812,18 @@ for BL in ${BLACKLISTS}; do if [[ -z "${PLAIN}" ]]; then printf "\r "; printf "\r"; fi printf "%s%s%s : %s\n" "${GREEN}" "${DOMAIN}" "${CLEAR}" "${RESPONSE}" fi - WHITE=$((WHITE + 1)) + echo "$BL" >> $white_file fi fi -done +} + +white_file=$(mktemp) +failed_file=$(mktemp) +passed_file=$(mktemp) +invalid_file=$(mktemp) +export -f parallel_check resolve text progress +export REGEX_LIST REVERSED TARGET VERIFY_BL VERBOSE PLAIN COUNT YELLOW CLEAR RED GREEN SPINNER REGEX_IP REGEX_DOMAIN CMD_DIG DNSSERVER CONF_DNS_DURATION CONF_DNS_TRIES REGEX CMD_HOST CMD white_file failed_file passed_file invalid_file +parallel -j 75% 'parallel_check {#} {}' ::: ${BLACKLISTS} # Print results if [[ "${VERBOSE}" -ge 0 ]]; then @@ -819,11 +836,17 @@ if [[ "${VERBOSE}" -ge 0 ]]; then echo Results for "${TARGET}" echo printf "%-15s" "Tested:"; echo "${COUNT}" - printf "%-15s" "Passed:"; echo "${GREEN}${PASSED}${CLEAR}" - printf "%-15s" "Whitelisted:"; echo "${GREEN}${WHITE}${CLEAR}" - printf "%-15s" "Invalid:"; echo "${YELLOW}${INVALID}${CLEAR}" - printf "%-15s" "Blacklisted:"; echo "${RED}${FAILED}${CLEAR}" + printf "%-15s" "Passed:"; echo "${GREEN}$(cat $passed_file | wc -l)${CLEAR}" + printf "%-15s" "Whitelisted:"; echo "${GREEN}$(cat $white_file | wc -l)${CLEAR}" + printf "%-15s" "Invalid:"; echo "${YELLOW}$(cat $invalid_file | wc -l)${CLEAR}" + printf "%-15s" "Blacklisted:"; echo "${RED}$(cat $failed_file | wc -l)${CLEAR}" echo "----------------------------------------------------------" fi -exit "${FAILED}" +failed=$(cat $failed_file | wc -l) +rm -f $passed_file $white_file $invalid_file $failed_file + +unset -f parallel_check resolve text progress +unset REGEX_LIST REVERSED TARGET VERIFY_BL VERBOSE PLAIN COUNT YELLOW CLEAR RED GREEN SPINNER REGEX_IP REGEX_DOMAIN CMD_DIG DNSSERVER CONF_DNS_DURATION CONF_DNS_TRIES REGEX CMD_HOST CMD white_file failed_file passed_file invalid_file + +exit "${failed}" From dc47c8ba52a28e1e2b08a59b6f474edf63a893e4 Mon Sep 17 00:00:00 2001 From: Andrej Walilko Date: Wed, 1 Jul 2020 09:43:45 -0400 Subject: [PATCH 06/29] output of blacklist hits --- blcheck | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/blcheck b/blcheck index 4f31a4a..e2d61cd 100644 --- a/blcheck +++ b/blcheck @@ -16,6 +16,10 @@ # ============================================================================= # Config { + # where to log blacklist hits permanently if there are any + # this file will be appended, not clobbered. + # format is ${TARGET}\n$blacklist1\n$blacklist2, etc + output="~/blcheck_blacklists.txt" # How many tries and for how long to wait for DNS queries CONF_DNS_TRIES=2 @@ -844,6 +848,7 @@ if [[ "${VERBOSE}" -ge 0 ]]; then fi failed=$(cat $failed_file | wc -l) +[ $failed -gt 0 ] && echo ${TARGET} >> $output && cat $failed_file >> $output rm -f $passed_file $white_file $invalid_file $failed_file unset -f parallel_check resolve text progress From 8a9d1214cfa31ef36d51466786d1c6a054119e77 Mon Sep 17 00:00:00 2001 From: Andrej Walilko Date: Wed, 1 Jul 2020 09:49:19 -0400 Subject: [PATCH 07/29] remove nonworking uribl and add touch to output file --- blcheck | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/blcheck b/blcheck index e2d61cd..1388291 100644 --- a/blcheck +++ b/blcheck @@ -129,11 +129,6 @@ bl.tiopan.com dbl.tiopan.com#URIBL ubl.unsubscore.com - black.uribl.com - grey.uribl.com - multi.uribl.com - red.uribl.com - white.uribl.com#DNSWL spam.dnsbl.anonmails.de bl.blocklist.de dnsbl.darklist.de @@ -848,7 +843,12 @@ if [[ "${VERBOSE}" -ge 0 ]]; then fi failed=$(cat $failed_file | wc -l) -[ $failed -gt 0 ] && echo ${TARGET} >> $output && cat $failed_file >> $output +if [ $failed -gt 0 ]; then + touch $output + echo ${TARGET} >> $output + cat $failed_file >> $output +fi + rm -f $passed_file $white_file $invalid_file $failed_file unset -f parallel_check resolve text progress From 130bd2d023f7f305f43295de88c83c63352d7ba5 Mon Sep 17 00:00:00 2001 From: Andrej Walilko Date: Wed, 1 Jul 2020 09:54:09 -0400 Subject: [PATCH 08/29] correction to output file, job count to settings --- blcheck | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/blcheck b/blcheck index 1388291..c0ba986 100644 --- a/blcheck +++ b/blcheck @@ -6,8 +6,8 @@ # description : Test any domain against more than 100 black lists. # author : Intellex # contributors : Darko Poljak, Oliver Mueller, Andrej Walilko -# date : Jun 30 2020 -# version : 0.7.0 +# date : Jul 01 2020 +# version : 0.7.5 # usage : blcheck [options] # reference : http://multirbl.valli.org/list/ # code style : https://google.github.io/styleguide/shell.xml @@ -19,7 +19,12 @@ # where to log blacklist hits permanently if there are any # this file will be appended, not clobbered. # format is ${TARGET}\n$blacklist1\n$blacklist2, etc - output="~/blcheck_blacklists.txt" + output=~/blcheck_blacklists.txt + + # how many dig/host processes to run in parallel + # this can be a number of threads (6) + # or a percentage of cpu cores (75%) + j="75%" # How many tries and for how long to wait for DNS queries CONF_DNS_TRIES=2 @@ -822,7 +827,7 @@ passed_file=$(mktemp) invalid_file=$(mktemp) export -f parallel_check resolve text progress export REGEX_LIST REVERSED TARGET VERIFY_BL VERBOSE PLAIN COUNT YELLOW CLEAR RED GREEN SPINNER REGEX_IP REGEX_DOMAIN CMD_DIG DNSSERVER CONF_DNS_DURATION CONF_DNS_TRIES REGEX CMD_HOST CMD white_file failed_file passed_file invalid_file -parallel -j 75% 'parallel_check {#} {}' ::: ${BLACKLISTS} +parallel -j $j 'parallel_check {#} {}' ::: ${BLACKLISTS} # Print results if [[ "${VERBOSE}" -ge 0 ]]; then From 3e21218a1a9a2aab3bbde2b26cb3c8486cbfa4e3 Mon Sep 17 00:00:00 2001 From: Andrej Walilko Date: Wed, 1 Jul 2020 10:07:22 -0400 Subject: [PATCH 09/29] increase default job count to 2 per core --- blcheck | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blcheck b/blcheck index c0ba986..415e3ec 100644 --- a/blcheck +++ b/blcheck @@ -24,7 +24,7 @@ # how many dig/host processes to run in parallel # this can be a number of threads (6) # or a percentage of cpu cores (75%) - j="75%" + j="200%" # How many tries and for how long to wait for DNS queries CONF_DNS_TRIES=2 From bd858477ec359b641b72f594f0abd355e6939f3a Mon Sep 17 00:00:00 2001 From: Andrej Walilko Date: Wed, 1 Jul 2020 10:19:19 -0400 Subject: [PATCH 10/29] clean up output files, handle additional invalid counter inside parallel loop --- blcheck | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/blcheck b/blcheck index 415e3ec..d6e2ff3 100644 --- a/blcheck +++ b/blcheck @@ -773,7 +773,7 @@ parallel_check() { if [[ ! "$(resolve "${TDL}" ns)" ]]; then if [[ -z "${PLAIN}" ]]; then printf "\r"; fi printf "%s%sUnreachable server%s\n" "${YELLOW}" "${PREFIX}" "${CLEAR}"; - echo "$BL" >> $invalid_file + echo "$BL" | cut -d= -f1 >> $invalid_file ERROR=TRUE fi fi @@ -783,7 +783,7 @@ parallel_check() { if [[ -z "${PLAIN}" ]]; then printf "\r"; fi printf "%s%s✓%s\n" "${CLEAR}" "${PREFIX}" "${CLEAR}"; fi - echo "$BL" >> $passed_file + echo "$BL" | cut -d= -f1 >> $passed_file fi; # Invalid response @@ -793,7 +793,7 @@ parallel_check() { printf "%s%sinvalid response (%s)%s\n" "${YELLOW}" "${PREFIX}" "${RESPONSE}" "${CLEAR}"; printf "%s%${#PREFIX}s%s%s\n" "${YELLOW}" "TXT: " "$(text "${TEST}")" "${CLEAR}"; fi; - INVALID=$((INVALID + 1)) + echo "$BL" | cut -d= -f1 >> $invalid_file # matched else @@ -806,7 +806,7 @@ parallel_check() { if [[ -z "${PLAIN}" ]]; then printf "\r "; printf "\r"; fi printf "%s%s%s : %s\n" "${RED}" "${DOMAIN}" "${CLEAR}" "${RESPONSE}" fi - echo "$BL" >> $failed_file + echo "$BL" | cut -d= -f1 >> $failed_file else if [[ "${VERBOSE}" -ge 1 ]]; then if [[ -z "${PLAIN}" ]]; then printf "\r"; fi @@ -816,7 +816,7 @@ parallel_check() { if [[ -z "${PLAIN}" ]]; then printf "\r "; printf "\r"; fi printf "%s%s%s : %s\n" "${GREEN}" "${DOMAIN}" "${CLEAR}" "${RESPONSE}" fi - echo "$BL" >> $white_file + echo "$BL" | cut -d= -f1 >> $white_file fi fi } From f0fda40705dc61d748f84e9aa7550b442855b892 Mon Sep 17 00:00:00 2001 From: Andrej Walilko Date: Wed, 1 Jul 2020 10:29:21 -0400 Subject: [PATCH 11/29] license update --- LICENSE | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index 34d06ac..84b8cb2 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,8 @@ MIT License -Copyright (c) 2018 Intellex +Portions Copyright (c) 2018 Intellex +Portions Copyright (c) 2020 Oliver Mueller +Portions Copyright (c) 2020 Andrej Walilko Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal From 523c0a5336d9848232ce821b3fa0baf644d1bdd4 Mon Sep 17 00:00:00 2001 From: Andrej Walilko Date: Wed, 1 Jul 2020 10:31:53 -0400 Subject: [PATCH 12/29] Update README.md --- README.md | 32 ++++---------------------------- 1 file changed, 4 insertions(+), 28 deletions(-) diff --git a/README.md b/README.md index 0568afb..728dde9 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ Script will use dig if it is found. If dig is not found script will use host. Features -------------------- -* More then __100 black lists__ already included! +* More then __300 black lists__ already included! * Automatic distinction between __domain or IP__ * Performs __PTR validation__ (only if domain is supplied, does not work for IP) * 3 verbose (-v) levels and a quiet (-q) mode @@ -46,34 +46,10 @@ TODO -------------------- 1. Handle domains with multiple DNS entries. -Licence --------------------- -MIT License - -Copyright (c) 2018 Intellex - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - Credits -------------------- Script has been written by the [Intellex](http://intellex.rs/en) team. -Contributors: +Additional contributors: [Darko Poljak](https://github.com/darko-poljak) - - + [Oliver Mueller](https://github.com/ogmueller) + [Andrej Walilko](https://github.com/ch604) From 5488c8a3341f5abbe0a60ace85c8c8fa1c06c9ec Mon Sep 17 00:00:00 2001 From: Andrej Walilko Date: Mon, 6 Jul 2020 09:02:12 -0400 Subject: [PATCH 13/29] blacklist to blocklist --- README.md | 14 +++++------ blcheck | 72 +++++++++++++++++++++++++++---------------------------- 2 files changed, 43 insertions(+), 43 deletions(-) diff --git a/README.md b/README.md index 0568afb..3d22ac8 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,17 @@ # blcheck -A powerful script for testing a domain or an IP against mailing black lists. +A powerful script for testing a domain or an IP against mailing block lists and allow lists. Script will use dig if it is found. If dig is not found script will use host. Features -------------------- -* More then __100 black lists__ already included! +* More then __300 block lists__ already included! * Automatic distinction between __domain or IP__ * Performs __PTR validation__ (only if domain is supplied, does not work for IP) * 3 verbose (-v) levels and a quiet (-q) mode -* The result of script is the number of servers which blacklisted the domain, so it can be used for any kind of __automated scripts or cronjobs__ +* The result of script is the number of servers which blocklisted the domain, so it can be used for any kind of __automated scripts or cronjobs__ * Informative and pleasant output @@ -31,15 +31,15 @@ Supplied domain must be full qualified domain name. If the IP is supplied, the PTR check cannot be executed and will be skipped. -d dnshost Use host as DNS server to make lookups --l file Load blacklists from file, separated by space or new line --c Warn if the top level domain of the blacklist has expired +-l file Load blocklists from file, separated by space or new line +-c Warn if the top level domain of the blocklist has expired -v Verbose mode, can be used multiple times (up to -vvv) -q Quiet modem with absolutely no output (useful for scripts) -p Plain text output (no coloring, no interactive status) -h The help you are just reading -Result of the script is the number of blacklisted entries. So if the supplied -IP is not blacklisted on any of the servers the result is 0. +Result of the script is the number of blocklisted entries. So if the supplied +IP is not blocklisted on any of the servers the result is 0. TODO diff --git a/blcheck b/blcheck index d6e2ff3..a92bc2a 100644 --- a/blcheck +++ b/blcheck @@ -3,7 +3,7 @@ # ============================================================================= # # title : blcheck -# description : Test any domain against more than 100 black lists. +# description : Test any domain against more than 100 blocklists. # author : Intellex # contributors : Darko Poljak, Oliver Mueller, Andrej Walilko # date : Jul 01 2020 @@ -16,10 +16,10 @@ # ============================================================================= # Config { - # where to log blacklist hits permanently if there are any + # where to log blocklist hits permanently if there are any # this file will be appended, not clobbered. - # format is ${TARGET}\n$blacklist1\n$blacklist2, etc - output=~/blcheck_blacklists.txt + # format is ${TARGET}\n$blocklist1\n$blocklist2, etc + output=~/blcheck_blocklists.txt # how many dig/host processes to run in parallel # this can be a number of threads (6) @@ -34,18 +34,18 @@ # Example formats: # - General format # {ip_or_domain}={filter}#{type} - # - IP based blacklist (default DNSBL, any valid return code will match) - # black.list.com - # - IP based blacklist - # black.list.com#DNSBL - # - IP based whitelist - # white.list.com#DNSWL - # - URI based blacklist + # - IP based blocklist (default DNSBL, any valid return code will match) + # block.list.com + # - IP based blocklist + # block.list.com#DNSBL + # - IP based allowlist + # allow.list.com#DNSWL + # - URI based blocklist # uri.list.com#URIBL # - Regexp defined return code, only a match will qualify for list. Here it is 127.0.0.2 and 127.0.0.3 - # black.list.com=127\.0\.0\.[23] - # - Regexp defined return code for a URI based blacklist - # black.list.com=127\.0\.[0-9]+\.0#URIBL + # block.list.com=127\.0\.0\.[23] + # - Regexp defined return code for a URI based blocklist + # block.list.com=127\.0\.[0-9]+\.0#URIBL CONF_BLACKLISTS=" whitelist.rbl.ispa.at#DNSWL t3direct.dnsbl.net.au @@ -506,7 +506,7 @@ fi } - # Load the blacklist from file + # Load the blocklist from file loadBlacklists() { # Make sure the file is readable @@ -528,15 +528,15 @@ Supplied domain must be full qualified domain name. If the IP is supplied, the PTR check cannot be executed and will be skipped. -d dnshost Use host as DNS server to make lookups --l file Load blacklists from file, separated by space or new line --c Warn if the top level domain of the blacklist has expired +-l file Load blocklists from file, separated by space or new line +-c Warn if the top level domain of the blocklist has expired -v Verbose mode, can be used multiple times (up to -vvv) -q Quiet mode with absolutely no output (useful for scripts) -p Plain text output (no coloring, no interactive status) -h The help you are just reading -Result of the script is the number of blacklisted entries. So if the supplied -IP is not blacklisted on any of the servers the result is 0. +Result of the script is the number of blocklisted entries. So if the supplied +IP is not blocklisted on any of the servers the result is 0. HELP exit; @@ -642,7 +642,7 @@ else fi fi -# Filter out the blacklists +# Filter out the blocklists BLACKLISTS="" COUNT_DNSBL=0 COUNT_DNSWL=0 @@ -679,7 +679,7 @@ for BL in ${CONF_BLACKLISTS}; do esac COUNT=$((COUNT + 1)) - # It is a proper blacklist + # It is a proper blocklist if [[ "${BLACKLISTS}" ]]; then BLACKLISTS=$(echo "${BLACKLISTS}\n${DOMAIN}=${FILTER}#${TYPE}") else @@ -693,16 +693,16 @@ for BL in ${CONF_BLACKLISTS}; do fi done -# Make sure we have at least one blacklist +# Make sure we have at least one blocklist if [[ "${COUNT}" -eq 0 ]]; then - error "No blacklists have been specified" + error "No blocklists have been specified" fi info 1 "Matching against ${COUNT} entries:" -info 1 " - ${COUNT_DNSBL} DNS blacklists" -info 1 " - ${COUNT_DNSWL} DNS whitelists" -info 1 " - ${COUNT_URIBL} URI blacklists" +info 1 " - ${COUNT_DNSBL} DNS blocklists" +info 1 " - ${COUNT_DNSWL} DNS allowlists" +info 1 " - ${COUNT_URIBL} URI blocklists" -# Iterate over all blacklists +# Iterate over all blocklists parallel_check() { local PREFIX= @@ -763,7 +763,7 @@ parallel_check() { # Get the status local RESPONSE=$(resolve "${TEST}") - # Not blacklisted + # Not blocklisted if [[ -z "${RESPONSE}" ]]; then # Make sure the server is viable @@ -800,7 +800,7 @@ parallel_check() { if [[ "${TYPE}" != "DNSWL" ]]; then if [[ "${VERBOSE}" -ge 1 ]]; then if [[ -z "${PLAIN}" ]]; then printf "\r"; fi - printf "%s%sblacklisted (%s)%s\n" "${RED}" "${PREFIX}" "${RESPONSE}" "${CLEAR}"; + printf "%s%sblocklisted (%s)%s\n" "${RED}" "${PREFIX}" "${RESPONSE}" "${CLEAR}"; printf "%s%${#PREFIX}s%s%s\n" "${RED}" "TXT: " "$(text "${TEST}")" "${CLEAR}"; elif [[ "${VERBOSE}" -ge 0 ]]; then if [[ -z "${PLAIN}" ]]; then printf "\r "; printf "\r"; fi @@ -810,23 +810,23 @@ parallel_check() { else if [[ "${VERBOSE}" -ge 1 ]]; then if [[ -z "${PLAIN}" ]]; then printf "\r"; fi - printf "%s%swhitelisted (%s)%s\n" "${GREEN}" "${PREFIX}" "${RESPONSE}" "${CLEAR}"; + printf "%s%sallowlisted (%s)%s\n" "${GREEN}" "${PREFIX}" "${RESPONSE}" "${CLEAR}"; printf "%s%${#PREFIX}s%s%s\n" "${GREEN}" "TXT: " "$(text "${TEST}")" "${CLEAR}"; elif [[ "${VERBOSE}" -ge 0 ]]; then if [[ -z "${PLAIN}" ]]; then printf "\r "; printf "\r"; fi printf "%s%s%s : %s\n" "${GREEN}" "${DOMAIN}" "${CLEAR}" "${RESPONSE}" fi - echo "$BL" | cut -d= -f1 >> $white_file + echo "$BL" | cut -d= -f1 >> $allow_file fi fi } -white_file=$(mktemp) +allow_file=$(mktemp) failed_file=$(mktemp) passed_file=$(mktemp) invalid_file=$(mktemp) export -f parallel_check resolve text progress -export REGEX_LIST REVERSED TARGET VERIFY_BL VERBOSE PLAIN COUNT YELLOW CLEAR RED GREEN SPINNER REGEX_IP REGEX_DOMAIN CMD_DIG DNSSERVER CONF_DNS_DURATION CONF_DNS_TRIES REGEX CMD_HOST CMD white_file failed_file passed_file invalid_file +export REGEX_LIST REVERSED TARGET VERIFY_BL VERBOSE PLAIN COUNT YELLOW CLEAR RED GREEN SPINNER REGEX_IP REGEX_DOMAIN CMD_DIG DNSSERVER CONF_DNS_DURATION CONF_DNS_TRIES REGEX CMD_HOST CMD allow_file failed_file passed_file invalid_file parallel -j $j 'parallel_check {#} {}' ::: ${BLACKLISTS} # Print results @@ -841,7 +841,7 @@ if [[ "${VERBOSE}" -ge 0 ]]; then echo printf "%-15s" "Tested:"; echo "${COUNT}" printf "%-15s" "Passed:"; echo "${GREEN}$(cat $passed_file | wc -l)${CLEAR}" - printf "%-15s" "Whitelisted:"; echo "${GREEN}$(cat $white_file | wc -l)${CLEAR}" + printf "%-15s" "Whitelisted:"; echo "${GREEN}$(cat $allow_file | wc -l)${CLEAR}" printf "%-15s" "Invalid:"; echo "${YELLOW}$(cat $invalid_file | wc -l)${CLEAR}" printf "%-15s" "Blacklisted:"; echo "${RED}$(cat $failed_file | wc -l)${CLEAR}" echo "----------------------------------------------------------" @@ -854,9 +854,9 @@ if [ $failed -gt 0 ]; then cat $failed_file >> $output fi -rm -f $passed_file $white_file $invalid_file $failed_file +rm -f $passed_file $allow_file $invalid_file $failed_file unset -f parallel_check resolve text progress -unset REGEX_LIST REVERSED TARGET VERIFY_BL VERBOSE PLAIN COUNT YELLOW CLEAR RED GREEN SPINNER REGEX_IP REGEX_DOMAIN CMD_DIG DNSSERVER CONF_DNS_DURATION CONF_DNS_TRIES REGEX CMD_HOST CMD white_file failed_file passed_file invalid_file +unset REGEX_LIST REVERSED TARGET VERIFY_BL VERBOSE PLAIN COUNT YELLOW CLEAR RED GREEN SPINNER REGEX_IP REGEX_DOMAIN CMD_DIG DNSSERVER CONF_DNS_DURATION CONF_DNS_TRIES REGEX CMD_HOST CMD allow_file failed_file passed_file invalid_file exit "${failed}" From 3a31fef49e9e83e66ac711d1a760f008f864a0e3 Mon Sep 17 00:00:00 2001 From: Andrej Walilko Date: Tue, 15 Sep 2020 09:22:35 -0400 Subject: [PATCH 14/29] rhel/debian install support for parallel. error exit code increased so as not to conflict with rbl error output or ssh error output --- blcheck | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/blcheck b/blcheck index a92bc2a..69fafdf 100644 --- a/blcheck +++ b/blcheck @@ -6,8 +6,8 @@ # description : Test any domain against more than 100 blocklists. # author : Intellex # contributors : Darko Poljak, Oliver Mueller, Andrej Walilko -# date : Jul 01 2020 -# version : 0.7.5 +# date : Sep 15 2020 +# version : 0.7.6 # usage : blcheck [options] # reference : http://multirbl.valli.org/list/ # code style : https://google.github.io/styleguide/shell.xml @@ -447,7 +447,7 @@ # Error handling error() { echo "ERROR: $1" >&2 - exit 2 + exit 254 } # Show progress @@ -568,14 +568,21 @@ TARGET=$1 if [ ! $(which parallel 2> /dev/null) ]; then echo "Parallel missing, trying to install..." - [ ! "$(yum -q provides parallel)" ] && yum -y -q install epel-release - yum -y -q install parallel + if [ $(which yum 2> /dev/null) ]; then + [ ! "$(yum -q provides parallel)" ] && yum -y -q install epel-release + yum -y -q install parallel + elif [ $(which dnf 2> /dev/null) ]; then + [ ! "$(dnf -q provides parallel)" ] && dnf -y -q install epel-release + dnf -y -q install parallel + else #assumed debian-like + apt-get -qq update + apt-get -y -q install parallel + fi if [ "$(which parallel 2> /dev/null)" ]; then mkdir ~/.parallel touch ~/.parallel/will-cite else - echo "Failed to install parallel, exiting." - exit 1 + error "Failed to install parallel, exiting." fi fi From 41f022e9b528a9f4c92a744e5fa566753ea555cd Mon Sep 17 00:00:00 2001 From: Andrej Walilko Date: Tue, 5 Mar 2024 10:35:15 -0500 Subject: [PATCH 15/29] blacklists to blocklists --- blcheck | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/blcheck b/blcheck index 69fafdf..7586cd6 100644 --- a/blcheck +++ b/blcheck @@ -46,7 +46,7 @@ # block.list.com=127\.0\.0\.[23] # - Regexp defined return code for a URI based blocklist # block.list.com=127\.0\.[0-9]+\.0#URIBL - CONF_BLACKLISTS=" + CONF_BLOCKLISTS=" whitelist.rbl.ispa.at#DNSWL t3direct.dnsbl.net.au ucepn.dnsbl.net.au @@ -382,7 +382,7 @@ # reputation/scoring pages # score.senderscore.com - CONF_BLACKLISTS_TEST=" + CONF_BLOCKLISTS_TEST=" rbl.rbldns.ru rbl.rbldns.ru=127\.0\.0\.1 rbl.rbldns.ru#DNSWL @@ -516,7 +516,7 @@ error "File $1 cannot be opened for reading, make sure it exists and that you have appropriate privileges" fi - CONF_BLACKLISTS=$(cat "$1") + CONF_BLOCKLISTS=$(cat "$1") } # Show help @@ -650,12 +650,12 @@ else fi # Filter out the blocklists -BLACKLISTS="" +BLOCKLISTS="" COUNT_DNSBL=0 COUNT_DNSWL=0 COUNT_URIBL=0 COUNT=0 -for BL in ${CONF_BLACKLISTS}; do +for BL in ${CONF_BLOCKLISTS}; do if [[ "${BL}" ]]; then if [[ ${BL} =~ ${REGEX_LIST} ]]; then DOMAIN="${BASH_REMATCH[1]}" @@ -687,10 +687,10 @@ for BL in ${CONF_BLACKLISTS}; do COUNT=$((COUNT + 1)) # It is a proper blocklist - if [[ "${BLACKLISTS}" ]]; then - BLACKLISTS=$(echo "${BLACKLISTS}\n${DOMAIN}=${FILTER}#${TYPE}") + if [[ "${BLOCKLISTS}" ]]; then + BLOCKLISTS=$(echo "${BLOCKLISTS}\n${DOMAIN}=${FILTER}#${TYPE}") else - BLACKLISTS="${DOMAIN}=${FILTER}#${TYPE}" + BLOCKLISTS="${DOMAIN}=${FILTER}#${TYPE}" fi fi fi @@ -834,7 +834,7 @@ passed_file=$(mktemp) invalid_file=$(mktemp) export -f parallel_check resolve text progress export REGEX_LIST REVERSED TARGET VERIFY_BL VERBOSE PLAIN COUNT YELLOW CLEAR RED GREEN SPINNER REGEX_IP REGEX_DOMAIN CMD_DIG DNSSERVER CONF_DNS_DURATION CONF_DNS_TRIES REGEX CMD_HOST CMD allow_file failed_file passed_file invalid_file -parallel -j $j 'parallel_check {#} {}' ::: ${BLACKLISTS} +parallel -j $j 'parallel_check {#} {}' ::: ${BLOCKLISTS} # Print results if [[ "${VERBOSE}" -ge 0 ]]; then From e1f87b193f2832e3f6b55383c4843fb0c527f150 Mon Sep 17 00:00:00 2001 From: Andrej Walilko Date: Tue, 5 Mar 2024 10:35:52 -0500 Subject: [PATCH 16/29] blacklists to blocklists --- blcheck | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/blcheck b/blcheck index 7586cd6..fa3fb53 100644 --- a/blcheck +++ b/blcheck @@ -30,7 +30,7 @@ CONF_DNS_TRIES=2 CONF_DNS_DURATION=3 - # Blacklists to check + # blocklists to check # Example formats: # - General format # {ip_or_domain}={filter}#{type} @@ -507,7 +507,7 @@ } # Load the blocklist from file - loadBlacklists() { + loadBlocklists() { # Make sure the file is readable if [[ -z "$1" ]]; then @@ -548,7 +548,7 @@ HELP while getopts :vqphcl:d: arg; do case "${arg}" in d) DNSSERVER="${OPTARG}";; - l) loadBlacklists "${OPTARG}";; + l) loadBlocklists "${OPTARG}";; c) VERIFY_BL=TRUE;; v) VERBOSE=$((VERBOSE + 1));; q) VERBOSE=-1;; @@ -850,7 +850,7 @@ if [[ "${VERBOSE}" -ge 0 ]]; then printf "%-15s" "Passed:"; echo "${GREEN}$(cat $passed_file | wc -l)${CLEAR}" printf "%-15s" "Whitelisted:"; echo "${GREEN}$(cat $allow_file | wc -l)${CLEAR}" printf "%-15s" "Invalid:"; echo "${YELLOW}$(cat $invalid_file | wc -l)${CLEAR}" - printf "%-15s" "Blacklisted:"; echo "${RED}$(cat $failed_file | wc -l)${CLEAR}" + printf "%-15s" "Blocklisted:"; echo "${RED}$(cat $failed_file | wc -l)${CLEAR}" echo "----------------------------------------------------------" fi From 1353333ed1752b6618034e82fc4d13a3c733b0fa Mon Sep 17 00:00:00 2001 From: Andrej Walilko Date: Tue, 19 Mar 2024 12:29:36 -0400 Subject: [PATCH 17/29] clean up comments --- blcheck | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/blcheck b/blcheck index fa3fb53..5aedc75 100644 --- a/blcheck +++ b/blcheck @@ -419,16 +419,6 @@ # Define spinner SPINNER="-\|/" - #SPINNER=".oO@*" - #SPINNER="▉▊▋▌▍▎▏▎▍▌▋▊▉" - #SPINNER="←↖↑↗→↘↓↙" - #SPINNER="▁▂▃▄▅▆▇█▇▆▅▄▃▁" - #SPINNER="▖▘▝▗" - #SPINNER="┤┘┴└├┌┬┐" - #SPINNER="◢◣◤◥" - #SPINNER="◰◳◲◱" - #SPINNER="◴◷◶◵" - #SPINNER="◐◓◑◒" VERBOSE=0 From ca778d1ef7dfe7d3717fd6e239f2389b24eba6f1 Mon Sep 17 00:00:00 2001 From: Andrej Walilko Date: Thu, 17 Oct 2024 13:02:13 -0400 Subject: [PATCH 18/29] help text update --- README.md | 6 +++--- blcheck | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 1e4fc33..fb19c46 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ Features * Automatic distinction between __domain or IP__ * Performs __PTR validation__ (only if domain is supplied, does not work for IP) * 3 verbose (-v) levels and a quiet (-q) mode -* The result of script is the number of servers which blocklisted the domain, so it can be used for any kind of __automated scripts or cronjobs__ +* The exit code of script is the number of servers which blocklisted the domain, so it can be used for any kind of __automated scripts or cronjobs__ * Informative and pleasant output @@ -38,8 +38,8 @@ If the IP is supplied, the PTR check cannot be executed and will be skipped. -p Plain text output (no coloring, no interactive status) -h The help you are just reading -Result of the script is the number of blocklisted entries. So if the supplied -IP is not blocklisted on any of the servers the result is 0. +Exit code of the script is the number of blocklisted entries. So if the supplied +IP is not blocklisted on any of the servers the exit code is 0. TODO diff --git a/blcheck b/blcheck index 5aedc75..f2c03bb 100644 --- a/blcheck +++ b/blcheck @@ -525,8 +525,8 @@ If the IP is supplied, the PTR check cannot be executed and will be skipped. -p Plain text output (no coloring, no interactive status) -h The help you are just reading -Result of the script is the number of blocklisted entries. So if the supplied -IP is not blocklisted on any of the servers the result is 0. +Exit code of the script is the number of blocklisted entries. So if the supplied +IP is not blocklisted on any of the servers the exit code is 0. HELP exit; From 7e4c82eb99042ba527f7ddf082294438b28c553e Mon Sep 17 00:00:00 2001 From: Andrej Walilko Date: Fri, 18 Oct 2024 08:53:27 -0400 Subject: [PATCH 19/29] help notes --- README.md | 3 ++- blcheck | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index fb19c46..1937329 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,8 @@ If the IP is supplied, the PTR check cannot be executed and will be skipped. -c Warn if the top level domain of the blocklist has expired -v Verbose mode, can be used multiple times (up to -vvv) -q Quiet modem with absolutely no output (useful for scripts) --p Plain text output (no coloring, no interactive status) +-p Plain text output (no coloring, no interactive status, useful + for tee'd output to a text file) -h The help you are just reading Exit code of the script is the number of blocklisted entries. So if the supplied diff --git a/blcheck b/blcheck index f2c03bb..c620bcd 100644 --- a/blcheck +++ b/blcheck @@ -522,7 +522,8 @@ If the IP is supplied, the PTR check cannot be executed and will be skipped. -c Warn if the top level domain of the blocklist has expired -v Verbose mode, can be used multiple times (up to -vvv) -q Quiet mode with absolutely no output (useful for scripts) --p Plain text output (no coloring, no interactive status) +-p Plain text output (no coloring, no interactive status, useful + for tee'd output to a text file) -h The help you are just reading Exit code of the script is the number of blocklisted entries. So if the supplied From 5dee9e185f0b1a38329c27bff6d9ae3e916e51e7 Mon Sep 17 00:00:00 2001 From: Andrej Walilko Date: Fri, 27 Dec 2024 13:58:54 -0500 Subject: [PATCH 20/29] integrate pull requests 30 and 31 from upstream --- blcheck | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/blcheck b/blcheck index c620bcd..c3fb688 100644 --- a/blcheck +++ b/blcheck @@ -6,8 +6,8 @@ # description : Test any domain against more than 100 blocklists. # author : Intellex # contributors : Darko Poljak, Oliver Mueller, Andrej Walilko -# date : Sep 15 2020 -# version : 0.7.6 +# date : Dec 27 2024 +# version : 0.7.7 # usage : blcheck [options] # reference : http://multirbl.valli.org/list/ # code style : https://google.github.io/styleguide/shell.xml @@ -297,7 +297,6 @@ bl.0spam.org nbl.0spam.org url.0spam.org - cbl.abuseat.org orvedb.aupads.org rsbl.aupads.org ips.backscatterer.org @@ -785,7 +784,7 @@ parallel_check() { fi; # Invalid response - elif [[ ! "${RESPONSE}" =~ ${FILTER} ]]; then + elif [[ ! "${RESPONSE}" =~ ${FILTER} ]] || [[ ${RESPONSE:0:8} == "127.255." ]]; then if [[ "${VERBOSE}" -ge 1 ]]; then if [[ -z "${PLAIN}" ]]; then printf "\r"; fi printf "%s%sinvalid response (%s)%s\n" "${YELLOW}" "${PREFIX}" "${RESPONSE}" "${CLEAR}"; From 4969ec1610648c3f6bf8023c6dbffaced58c8d21 Mon Sep 17 00:00:00 2001 From: Tobias Date: Wed, 30 Apr 2025 15:49:00 +0200 Subject: [PATCH 21/29] Remove some no longe active blocklists --- README.md | 2 +- blcheck | 45 --------------------------------------------- 2 files changed, 1 insertion(+), 46 deletions(-) diff --git a/README.md b/README.md index 2ac1c95..3f4ddcd 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ Script will use dig if it is found. If dig is not found script will use host. Features -------------------- -* More then __300 block lists__ already included! +* More then __280 block lists__ already included! * Automatic distinction between __domain or IP__ * Performs __PTR validation__ (only if domain is supplied, does not work for IP) * 3 verbose (-v) levels and a quiet (-q) mode diff --git a/blcheck b/blcheck index c3fb688..6bbcf3c 100644 --- a/blcheck +++ b/blcheck @@ -161,14 +161,6 @@ singular.ttk.pte.hu blacklist.netcore.co.in dnsbl.rv-soft.info - nana.bl.techtheft.info - other.bl.techtheft.info - robot.bl.techtheft.info - scanning.bl.techtheft.info - source.bl.techtheft.info - support.bl.techtheft.info - virus.bl.techtheft.info - watchlist.bl.techtheft.info db.wpbl.info rbl.jp spamlist.or.kr @@ -206,7 +198,6 @@ rep.mailspike.net wl.mailspike.net#DNSWL z.mailspike.net - ix.dnsbl.manitu.net combined.rbl.msrbl.net images.rbl.msrbl.net phishing.rbl.msrbl.net @@ -221,37 +212,6 @@ bl.scientificspam.net rhsbl.scientificspam.net korea.services.net - dnsbl.sorbs.net - block.dnsbl.sorbs.net - exitnodes.tor.dnsbl.sectoor.dehttp.dnsbl.sorbs.net - dul.dnsbl.sorbs.net - escalations.dnsbl.sorbs.net - http.dnsbl.sorbs.net - misc.dnsbl.sorbs.net - new.dnsbl.sorbs.net - noservers.dnsbl.sorbs.net - old.dnsbl.sorbs.net - problems.dnsbl.sorbs.net - proxies.dnsbl.sorbs.net - recent.dnsbl.sorbs.net - relays.dnsbl.sorbs.net - safe.dnsbl.sorbs.net - smtp.dnsbl.sorbs.net - socks.dnsbl.sorbs.net - spam.dnsbl.sorbs.net - new.spam.dnsbl.sorbs.net - old.spam.dnsbl.sorbs.net - recent.spam.dnsbl.sorbs.net - web.dnsbl.sorbs.net - zombie.dnsbl.sorbs.net - aspews.ext.sorbs.net - l1.bbfh.ext.sorbs.net - l2.bbfh.ext.sorbs.net - l3.bbfh.ext.sorbs.net - l4.bbfh.ext.sorbs.net - rhsbl.sorbs.net - badconf.rhsbl.sorbs.net - nomail.rhsbl.sorbs.net bl.spamcop.net backscatter.spameatingmonkey.net bl.spameatingmonkey.net @@ -279,11 +239,6 @@ dnsbl-1.uceprotect.net dnsbl-2.uceprotect.net dnsbl-3.uceprotect.net - all.rbl.webiron.net - babl.rbl.webiron.net - cabl.rbl.webiron.net - crawler.rbl.webiron.net - stabl.rbl.webiron.net dnsbl.zapbl.net rhsbl.zapbl.net rbl.zenon.net From ec90f98b6b5edc75c5eaa27d00a35fd100a66637 Mon Sep 17 00:00:00 2001 From: Andrej Walilko Date: Wed, 28 May 2025 10:58:38 -0400 Subject: [PATCH 22/29] shellchecking, bash and printf efficiencies --- blcheck | 103 +++++++++++++++++++++++++++++++------------------------- 1 file changed, 57 insertions(+), 46 deletions(-) diff --git a/blcheck b/blcheck index c3fb688..02eee45 100644 --- a/blcheck +++ b/blcheck @@ -1,4 +1,5 @@ #!/bin/bash +# shellcheck disable=SC2317 # ============================================================================= # @@ -381,6 +382,7 @@ # reputation/scoring pages # score.senderscore.com + # shellcheck disable=SC2034 CONF_BLOCKLISTS_TEST=" rbl.rbldns.ru rbl.rbldns.ru=127\.0\.0\.1 @@ -443,8 +445,9 @@ progress() { # Bar - local x=$(($1 % ${#SPINNER} + 1)) - local BAR=$(echo ${SPINNER} | awk "{ print substr(\$0, ${x}, 1) }") + local x BAR + x=$(($1 % ${#SPINNER} + 1)) + BAR=$(awk "{ print substr(\$0, ${x}, 1) }" <<< "${SPINNER}") if [[ -z "${PLAIN}" ]]; then printf "\r "; fi @@ -457,7 +460,8 @@ resolve() { # IP already? - local IP=$(echo "$1" | grep "^${REGEX_IP}$") + local IP + IP=$(grep -E "^${REGEX_IP}$" <<< "$1") if [[ "${IP}" ]]; then echo "${IP}" @@ -471,8 +475,8 @@ esac case "${CMD}" in - ${CMD_DIG} ) "${CMD}" ${DNSSERVER} +short -t "${TYPE}" +time=${CONF_DNS_DURATION} +tries=${CONF_DNS_TRIES} "$1" | grep -om 1 "${REGEX}";; - ${CMD_HOST} ) "${CMD}" -t "${TYPE}" -W ${CONF_DNS_DURATION} -R ${CONF_DNS_TRIES} "$1" ${DNSSERVER} | tail -n1 | grep -om 1 "${REGEX}";; + "${CMD_DIG}" ) "${CMD}" "${DNSSERVER}" +short -t "${TYPE}" +time=${CONF_DNS_DURATION} +tries=${CONF_DNS_TRIES} "$1" | grep -Eom 1 "${REGEX}";; + "${CMD_HOST}" ) "${CMD}" -t "${TYPE}" -W ${CONF_DNS_DURATION} -R ${CONF_DNS_TRIES} "$1" "${DNSSERVER}" | tail -n1 | grep -Eom 1 "${REGEX}";; esac fi } @@ -480,7 +484,8 @@ # Result info for IP text() { # IP already? - local IP=$(echo "$1" | grep "^${REGEX_IP}$") + local IP + IP=$(grep -E "^${REGEX_IP}$" <<< "$1") if [[ -n "${IP}" ]]; then echo "${IP}" @@ -489,8 +494,8 @@ local TYPE="txt" case "${CMD}" in - ${CMD_DIG} ) "${CMD}" ${DNSSERVER} +short -t "${TYPE}" +time=${CONF_DNS_DURATION} +tries=${CONF_DNS_TRIES} "$1" ;; - ${CMD_HOST} ) "${CMD}" -t "${TYPE}" -W ${CONF_DNS_DURATION} -R ${CONF_DNS_TRIES} "$1" ${DNSSERVER} | tail -n1 ;; + "${CMD_DIG}" ) "${CMD}" "${DNSSERVER}" +short -t "${TYPE}" +time="${CONF_DNS_DURATION}" +tries="${CONF_DNS_TRIES}" "$1" ;; + "${CMD_HOST}" ) "${CMD}" -t "${TYPE}" -W "${CONF_DNS_DURATION}" -R "${CONF_DNS_TRIES}" "$1" "${DNSSERVER}" | tail -n1 ;; esac fi } @@ -556,19 +561,19 @@ if [[ $# -eq 0 ]]; then fi TARGET=$1 -if [ ! $(which parallel 2> /dev/null) ]; then +if ! which parallel &> /dev/null; then echo "Parallel missing, trying to install..." - if [ $(which yum 2> /dev/null) ]; then - [ ! "$(yum -q provides parallel)" ] && yum -y -q install epel-release - yum -y -q install parallel - elif [ $(which dnf 2> /dev/null) ]; then - [ ! "$(dnf -q provides parallel)" ] && dnf -y -q install epel-release - dnf -y -q install parallel + if which yum &> /dev/null; then + [ ! "$(yum -q provides parallel)" ] && yum -y -q --skip-broken install epel-release + yum -y -q --skip-broken install parallel + elif which dnf &> /dev/null; then + [ ! "$(dnf -q provides parallel)" ] && dnf -y -q --skip-broken install epel-release + dnf -y -q --skip-broken install parallel else #assumed debian-like apt-get -qq update apt-get -y -q install parallel fi - if [ "$(which parallel 2> /dev/null)" ]; then + if which parallel &> /dev/null; then mkdir ~/.parallel touch ~/.parallel/will-cite else @@ -618,8 +623,8 @@ info 3 "Using ${REVERSED} for reversed IP" # Get the PTR info 3 "Checking the PTR record" case "${CMD}" in - ${CMD_DIG} ) PTR=$("${CMD}" ${DNSSERVER} +short -x "${IP}" | sed s/\.$//);; - ${CMD_HOST} ) PTR=$("${CMD}" "${IP}" ${DNSSERVER} | tail -n1 | grep -o '[^ ]\+$' | sed s/\.$//) + "${CMD_DIG}" ) PTR=$("${CMD}" "${DNSSERVER}" +short -x "${IP}" | sed s/\.$//);; + "${CMD_HOST}" ) PTR=$("${CMD}" "${IP}" "${DNSSERVER}" | tail -n1 | grep -o '[^ ]\+$' | sed s/\.$//) esac # Validate PTR @@ -661,7 +666,8 @@ for BL in ${CONF_BLOCKLISTS}; do fi # Make sure the domain is a proper one - TMP=$(echo "${DOMAIN}" | sed -e 's/^[ \t]*//' | grep ^"${REGEX_DOMAIN}"$) + # shellcheck disable=SC2001 + TMP=$(sed -e 's/^[ \t]*//' <<< "${DOMAIN}" | grep -E ^"${REGEX_DOMAIN}"$) if [[ -z "${TMP}" ]]; then info 0 "${YELLOW}Warning: domain '${DOMAIN}' is not valid and will be ignored${CLEAR}" @@ -678,7 +684,7 @@ for BL in ${CONF_BLOCKLISTS}; do # It is a proper blocklist if [[ "${BLOCKLISTS}" ]]; then - BLOCKLISTS=$(echo "${BLOCKLISTS}\n${DOMAIN}=${FILTER}#${TYPE}") + BLOCKLISTS=$(echo -e "${BLOCKLISTS}\n${DOMAIN}=${FILTER}#${TYPE}") else BLOCKLISTS="${DOMAIN}=${FILTER}#${TYPE}" fi @@ -736,8 +742,8 @@ parallel_check() { if [[ "${VERBOSE}" -ge 1 ]]; then # Show percentage - local STATUS=$(printf " %3s" $((I * 100 / COUNT))) - STATUS="${STATUS}% " + local STATUS + STATUS="$(printf " %3s" $((I * 100 / COUNT)))% " # Show additional info if [[ "${VERBOSE}" -ge 3 ]]; then @@ -758,7 +764,8 @@ parallel_check() { fi # Get the status - local RESPONSE=$(resolve "${TEST}") + local RESPONSE + RESPONSE=$(resolve "${TEST}") # Not blocklisted if [[ -z "${RESPONSE}" ]]; then @@ -766,11 +773,12 @@ parallel_check() { # Make sure the server is viable local ERROR="" if [[ "${VERIFY_BL}" ]]; then - local TDL=$(echo "${DOMAIN}" | grep -om 1 '\([a-zA-Z0-9]\+\(-[a-zA-Z0-9]\+\)*\.\)[a-zA-Z]\{2,\}$') + local TDL + TDL=$(grep -Eom 1 "${REGEX_TDL}" <<< "${DOMAIN}") if [[ ! "$(resolve "${TDL}" ns)" ]]; then if [[ -z "${PLAIN}" ]]; then printf "\r"; fi printf "%s%sUnreachable server%s\n" "${YELLOW}" "${PREFIX}" "${CLEAR}"; - echo "$BL" | cut -d= -f1 >> $invalid_file + echo "$BL" | cut -d= -f1 >> "$invalid_file" ERROR=TRUE fi fi @@ -780,40 +788,40 @@ parallel_check() { if [[ -z "${PLAIN}" ]]; then printf "\r"; fi printf "%s%s✓%s\n" "${CLEAR}" "${PREFIX}" "${CLEAR}"; fi - echo "$BL" | cut -d= -f1 >> $passed_file + cut -d= -f1 <<< "$BL" >> "$passed_file" fi; # Invalid response elif [[ ! "${RESPONSE}" =~ ${FILTER} ]] || [[ ${RESPONSE:0:8} == "127.255." ]]; then if [[ "${VERBOSE}" -ge 1 ]]; then - if [[ -z "${PLAIN}" ]]; then printf "\r"; fi + [[ -z "${PLAIN}" ]] && printf "\r" printf "%s%sinvalid response (%s)%s\n" "${YELLOW}" "${PREFIX}" "${RESPONSE}" "${CLEAR}"; printf "%s%${#PREFIX}s%s%s\n" "${YELLOW}" "TXT: " "$(text "${TEST}")" "${CLEAR}"; fi; - echo "$BL" | cut -d= -f1 >> $invalid_file + cut -d= -f1 <<< "$BL" >> "$invalid_file" # matched else if [[ "${TYPE}" != "DNSWL" ]]; then if [[ "${VERBOSE}" -ge 1 ]]; then - if [[ -z "${PLAIN}" ]]; then printf "\r"; fi + [[ -z "${PLAIN}" ]] && printf "\r" printf "%s%sblocklisted (%s)%s\n" "${RED}" "${PREFIX}" "${RESPONSE}" "${CLEAR}"; printf "%s%${#PREFIX}s%s%s\n" "${RED}" "TXT: " "$(text "${TEST}")" "${CLEAR}"; elif [[ "${VERBOSE}" -ge 0 ]]; then - if [[ -z "${PLAIN}" ]]; then printf "\r "; printf "\r"; fi + [[ -z "${PLAIN}" ]] && printf "\r%60s\r" " " printf "%s%s%s : %s\n" "${RED}" "${DOMAIN}" "${CLEAR}" "${RESPONSE}" fi - echo "$BL" | cut -d= -f1 >> $failed_file + cut -d= -f1 <<< "$BL" >> "$failed_file" else if [[ "${VERBOSE}" -ge 1 ]]; then - if [[ -z "${PLAIN}" ]]; then printf "\r"; fi + [[ -z "${PLAIN}" ]] && printf "\r" printf "%s%sallowlisted (%s)%s\n" "${GREEN}" "${PREFIX}" "${RESPONSE}" "${CLEAR}"; printf "%s%${#PREFIX}s%s%s\n" "${GREEN}" "TXT: " "$(text "${TEST}")" "${CLEAR}"; elif [[ "${VERBOSE}" -ge 0 ]]; then - if [[ -z "${PLAIN}" ]]; then printf "\r "; printf "\r"; fi + [[ -z "${PLAIN}" ]] && printf "\r%60s\r" " " printf "%s%s%s : %s\n" "${GREEN}" "${DOMAIN}" "${CLEAR}" "${RESPONSE}" fi - echo "$BL" | cut -d= -f1 >> $allow_file + cut -d= -f1 <<< "$BL" >> "$allow_file" fi fi } @@ -823,10 +831,12 @@ failed_file=$(mktemp) passed_file=$(mktemp) invalid_file=$(mktemp) export -f parallel_check resolve text progress -export REGEX_LIST REVERSED TARGET VERIFY_BL VERBOSE PLAIN COUNT YELLOW CLEAR RED GREEN SPINNER REGEX_IP REGEX_DOMAIN CMD_DIG DNSSERVER CONF_DNS_DURATION CONF_DNS_TRIES REGEX CMD_HOST CMD allow_file failed_file passed_file invalid_file -parallel -j $j 'parallel_check {#} {}' ::: ${BLOCKLISTS} +export REGEX_LIST REGEX_TDL REVERSED TARGET VERIFY_BL VERBOSE PLAIN COUNT YELLOW CLEAR RED GREEN SPINNER REGEX_IP REGEX_DOMAIN CMD_DIG DNSSERVER CONF_DNS_DURATION CONF_DNS_TRIES REGEX CMD_HOST CMD allow_file failed_file passed_file invalid_file +# shellcheck disable=SC2086 +parallel -j "$j" 'parallel_check {#} {}' ::: ${BLOCKLISTS} # Print results +# shellcheck disable=SC2002 if [[ "${VERBOSE}" -ge 0 ]]; then if [[ -z "${PLAIN}" ]]; then printf "\r \n" @@ -837,23 +847,24 @@ if [[ "${VERBOSE}" -ge 0 ]]; then echo Results for "${TARGET}" echo printf "%-15s" "Tested:"; echo "${COUNT}" - printf "%-15s" "Passed:"; echo "${GREEN}$(cat $passed_file | wc -l)${CLEAR}" - printf "%-15s" "Whitelisted:"; echo "${GREEN}$(cat $allow_file | wc -l)${CLEAR}" - printf "%-15s" "Invalid:"; echo "${YELLOW}$(cat $invalid_file | wc -l)${CLEAR}" - printf "%-15s" "Blocklisted:"; echo "${RED}$(cat $failed_file | wc -l)${CLEAR}" + printf "%-15s" "Passed:"; echo "${GREEN}$(cat "$passed_file" | wc -l)${CLEAR}" + printf "%-15s" "Whitelisted:"; echo "${GREEN}$(cat "$allow_file" | wc -l)${CLEAR}" + printf "%-15s" "Invalid:"; echo "${YELLOW}$(cat "$invalid_file" | wc -l)${CLEAR}" + printf "%-15s" "Blocklisted:"; echo "${RED}$(cat "$failed_file" | wc -l)${CLEAR}" echo "----------------------------------------------------------" fi -failed=$(cat $failed_file | wc -l) -if [ $failed -gt 0 ]; then +# shellcheck disable=SC2002 +failed=$(cat "$failed_file" | wc -l) +if [ "$failed" -gt 0 ]; then touch $output - echo ${TARGET} >> $output - cat $failed_file >> $output + echo "${TARGET}" >> $output + cat "$failed_file" >> $output fi -rm -f $passed_file $allow_file $invalid_file $failed_file +rm -f "$passed_file" "$allow_file" "$invalid_file" "$failed_file" unset -f parallel_check resolve text progress -unset REGEX_LIST REVERSED TARGET VERIFY_BL VERBOSE PLAIN COUNT YELLOW CLEAR RED GREEN SPINNER REGEX_IP REGEX_DOMAIN CMD_DIG DNSSERVER CONF_DNS_DURATION CONF_DNS_TRIES REGEX CMD_HOST CMD allow_file failed_file passed_file invalid_file +unset REGEX_LIST REGEX_TDL REVERSED TARGET VERIFY_BL VERBOSE PLAIN COUNT YELLOW CLEAR RED GREEN SPINNER REGEX_IP REGEX_DOMAIN CMD_DIG DNSSERVER CONF_DNS_DURATION CONF_DNS_TRIES REGEX CMD_HOST CMD allow_file failed_file passed_file invalid_file exit "${failed}" From cf47519de3012b39516acc38ecb94302a7eab489 Mon Sep 17 00:00:00 2001 From: Andrej Walilko Date: Wed, 28 May 2025 10:59:11 -0400 Subject: [PATCH 23/29] allow cli adjustment of parallelism --- blcheck | 44 ++++++++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 20 deletions(-) diff --git a/blcheck b/blcheck index 02eee45..42e8a75 100644 --- a/blcheck +++ b/blcheck @@ -515,32 +515,35 @@ # Show help showHelp() { - cat < - -Supplied domain must be full qualified domain name. -If the IP is supplied, the PTR check cannot be executed and will be skipped. - --d dnshost Use host as DNS server to make lookups --l file Load blocklists from file, separated by space or new line --c Warn if the top level domain of the blocklist has expired --v Verbose mode, can be used multiple times (up to -vvv) --q Quiet mode with absolutely no output (useful for scripts) --p Plain text output (no coloring, no interactive status, useful - for tee'd output to a text file) --h The help you are just reading - -Exit code of the script is the number of blocklisted entries. So if the supplied -IP is not blocklisted on any of the servers the exit code is 0. - -HELP + cat <<-HELP + blcheck [options] + + Supplied domain must be full qualified domain name. + If the IP is supplied, the PTR check cannot be executed and will be skipped. + + -d dnshost Use host as DNS server to make lookups + -l file Load blocklists from file, separated by space or new line + -c Warn if the top level domain of the blocklist has expired + -v Verbose mode, can be used multiple times (up to -vvv) + -q Quiet mode with absolutely no output (useful for scripts) + -p Plain text output (no coloring, no interactive status, useful + for tee'd output to a text file) + -j num The number of parallel processes to use (default is 200%, or + 2x system core count. See \`man parallel\` for details.) + -h The help you are just reading + + Exit code of the script is the number of blocklisted entries. So if the supplied + IP is not blocklisted on any of the servers the exit code is 0. If there are five + blocklist hits, then the exit code is 5. + + HELP exit; } #~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ } # Parse the params -while getopts :vqphcl:d: arg; do +while getopts :vqphcj:l:d: arg; do case "${arg}" in d) DNSSERVER="${OPTARG}";; l) loadBlocklists "${OPTARG}";; @@ -549,6 +552,7 @@ while getopts :vqphcl:d: arg; do q) VERBOSE=-1;; p) PLAIN=1 RED="" GREEN="" YELLOW="" CLEAR="" ;; h) showHelp;; + j) j="${OPTARG}";; ?) error "Unknown option ${OPTARG}";; esac done From 0377c6eacbb266bc83f072e6509eca694e7b465a Mon Sep 17 00:00:00 2001 From: Andrej Walilko Date: Wed, 28 May 2025 11:00:04 -0400 Subject: [PATCH 24/29] version increment --- blcheck | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/blcheck b/blcheck index 42e8a75..8fbda51 100644 --- a/blcheck +++ b/blcheck @@ -7,8 +7,8 @@ # description : Test any domain against more than 100 blocklists. # author : Intellex # contributors : Darko Poljak, Oliver Mueller, Andrej Walilko -# date : Dec 27 2024 -# version : 0.7.7 +# date : May 28 2025 +# version : 0.8.0 # usage : blcheck [options] # reference : http://multirbl.valli.org/list/ # code style : https://google.github.io/styleguide/shell.xml From a3583de0fc0f6181ec585a5498d747780da02b39 Mon Sep 17 00:00:00 2001 From: Andrej Walilko Date: Wed, 28 May 2025 11:01:22 -0400 Subject: [PATCH 25/29] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 2ac1c95..0c2956f 100644 --- a/README.md +++ b/README.md @@ -38,6 +38,8 @@ If the IP is supplied, the PTR check cannot be executed and will be skipped. -q Quiet modem with absolutely no output (useful for scripts) -p Plain text output (no coloring, no interactive status, useful for tee'd output to a text file) +-j num The number of parallel processes to use (default is 200%, or + 2x system core count. See `man parallel` for details.) -h The help you are just reading From a29fac9639ec074da21d8ae4af3770058bfbc4ae Mon Sep 17 00:00:00 2001 From: Andrej Walilko Date: Fri, 30 May 2025 09:09:59 -0400 Subject: [PATCH 26/29] too much e --- blcheck | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/blcheck b/blcheck index 8fbda51..b5697e1 100644 --- a/blcheck +++ b/blcheck @@ -461,7 +461,7 @@ # IP already? local IP - IP=$(grep -E "^${REGEX_IP}$" <<< "$1") + IP=$(grep "^${REGEX_IP}$" <<< "$1") if [[ "${IP}" ]]; then echo "${IP}" @@ -475,8 +475,8 @@ esac case "${CMD}" in - "${CMD_DIG}" ) "${CMD}" "${DNSSERVER}" +short -t "${TYPE}" +time=${CONF_DNS_DURATION} +tries=${CONF_DNS_TRIES} "$1" | grep -Eom 1 "${REGEX}";; - "${CMD_HOST}" ) "${CMD}" -t "${TYPE}" -W ${CONF_DNS_DURATION} -R ${CONF_DNS_TRIES} "$1" "${DNSSERVER}" | tail -n1 | grep -Eom 1 "${REGEX}";; + "${CMD_DIG}" ) "${CMD}" "${DNSSERVER}" +short -t "${TYPE}" +time=${CONF_DNS_DURATION} +tries=${CONF_DNS_TRIES} "$1" | grep -om 1 "${REGEX}";; + "${CMD_HOST}" ) "${CMD}" -t "${TYPE}" -W ${CONF_DNS_DURATION} -R ${CONF_DNS_TRIES} "$1" "${DNSSERVER}" | tail -n1 | grep -om 1 "${REGEX}";; esac fi } @@ -485,7 +485,7 @@ text() { # IP already? local IP - IP=$(grep -E "^${REGEX_IP}$" <<< "$1") + IP=$(grep "^${REGEX_IP}$" <<< "$1") if [[ -n "${IP}" ]]; then echo "${IP}" @@ -671,7 +671,7 @@ for BL in ${CONF_BLOCKLISTS}; do # Make sure the domain is a proper one # shellcheck disable=SC2001 - TMP=$(sed -e 's/^[ \t]*//' <<< "${DOMAIN}" | grep -E ^"${REGEX_DOMAIN}"$) + TMP=$(sed -e 's/^[ \t]*//' <<< "${DOMAIN}" | grep ^"${REGEX_DOMAIN}"$) if [[ -z "${TMP}" ]]; then info 0 "${YELLOW}Warning: domain '${DOMAIN}' is not valid and will be ignored${CLEAR}" @@ -778,7 +778,7 @@ parallel_check() { local ERROR="" if [[ "${VERIFY_BL}" ]]; then local TDL - TDL=$(grep -Eom 1 "${REGEX_TDL}" <<< "${DOMAIN}") + TDL=$(grep -om 1 "${REGEX_TDL}" <<< "${DOMAIN}") if [[ ! "$(resolve "${TDL}" ns)" ]]; then if [[ -z "${PLAIN}" ]]; then printf "\r"; fi printf "%s%sUnreachable server%s\n" "${YELLOW}" "${PREFIX}" "${CLEAR}"; From 45426e06dfe68e979020afea68a99d7d8fdb7f8b Mon Sep 17 00:00:00 2001 From: Andrej Walilko Date: Fri, 30 May 2025 09:12:12 -0400 Subject: [PATCH 27/29] unneeded quoting --- blcheck | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/blcheck b/blcheck index b5697e1..ec2247b 100644 --- a/blcheck +++ b/blcheck @@ -475,8 +475,8 @@ esac case "${CMD}" in - "${CMD_DIG}" ) "${CMD}" "${DNSSERVER}" +short -t "${TYPE}" +time=${CONF_DNS_DURATION} +tries=${CONF_DNS_TRIES} "$1" | grep -om 1 "${REGEX}";; - "${CMD_HOST}" ) "${CMD}" -t "${TYPE}" -W ${CONF_DNS_DURATION} -R ${CONF_DNS_TRIES} "$1" "${DNSSERVER}" | tail -n1 | grep -om 1 "${REGEX}";; + "${CMD_DIG}" ) "${CMD}" ${DNSSERVER} +short -t "${TYPE}" +time=${CONF_DNS_DURATION} +tries=${CONF_DNS_TRIES} "$1" | grep -om 1 "${REGEX}";; + "${CMD_HOST}" ) "${CMD}" -t "${TYPE}" -W ${CONF_DNS_DURATION} -R ${CONF_DNS_TRIES} "$1" ${DNSSERVER} | tail -n1 | grep -om 1 "${REGEX}";; esac fi } @@ -627,8 +627,8 @@ info 3 "Using ${REVERSED} for reversed IP" # Get the PTR info 3 "Checking the PTR record" case "${CMD}" in - "${CMD_DIG}" ) PTR=$("${CMD}" "${DNSSERVER}" +short -x "${IP}" | sed s/\.$//);; - "${CMD_HOST}" ) PTR=$("${CMD}" "${IP}" "${DNSSERVER}" | tail -n1 | grep -o '[^ ]\+$' | sed s/\.$//) + "${CMD_DIG}" ) PTR=$("${CMD}" ${DNSSERVER} +short -x "${IP}" | sed s/\.$//);; + "${CMD_HOST}" ) PTR=$("${CMD}" "${IP}" ${DNSSERVER} | tail -n1 | grep -o '[^ ]\+$' | sed s/\.$//) esac # Validate PTR From cd4d5bd62231d5bc0b919adfcd1d7fe72e9eb8d4 Mon Sep 17 00:00:00 2001 From: Andrej Walilko Date: Fri, 30 May 2025 09:13:19 -0400 Subject: [PATCH 28/29] shellcheck ignores --- blcheck | 2 ++ 1 file changed, 2 insertions(+) diff --git a/blcheck b/blcheck index ec2247b..54375c4 100644 --- a/blcheck +++ b/blcheck @@ -474,6 +474,7 @@ * ) TYPE="a"; REGEX="${REGEX_IP}$";; esac + # shellcheck disable=SC2086 case "${CMD}" in "${CMD_DIG}" ) "${CMD}" ${DNSSERVER} +short -t "${TYPE}" +time=${CONF_DNS_DURATION} +tries=${CONF_DNS_TRIES} "$1" | grep -om 1 "${REGEX}";; "${CMD_HOST}" ) "${CMD}" -t "${TYPE}" -W ${CONF_DNS_DURATION} -R ${CONF_DNS_TRIES} "$1" ${DNSSERVER} | tail -n1 | grep -om 1 "${REGEX}";; @@ -626,6 +627,7 @@ info 3 "Using ${REVERSED} for reversed IP" # Get the PTR info 3 "Checking the PTR record" +# shellcheck disable=SC2086 case "${CMD}" in "${CMD_DIG}" ) PTR=$("${CMD}" ${DNSSERVER} +short -x "${IP}" | sed s/\.$//);; "${CMD_HOST}" ) PTR=$("${CMD}" "${IP}" ${DNSSERVER} | tail -n1 | grep -o '[^ ]\+$' | sed s/\.$//) From ee9f24e773e53e7be7a3ac52142e1055bba114e6 Mon Sep 17 00:00:00 2001 From: Andrej Walilko Date: Tue, 23 Dec 2025 10:53:52 -0500 Subject: [PATCH 29/29] shellcheck --- blcheck | 61 ++++++++++++++++++++++++++++++--------------------------- 1 file changed, 32 insertions(+), 29 deletions(-) diff --git a/blcheck b/blcheck index f31ead4..f3210cd 100644 --- a/blcheck +++ b/blcheck @@ -397,10 +397,11 @@ } # Show progress + # shellcheck disable=SC2329 progress() { # Bar - local x BAR + local x BAR x=$(($1 % ${#SPINNER} + 1)) BAR=$(awk "{ print substr(\$0, ${x}, 1) }" <<< "${SPINNER}") if [[ -z "${PLAIN}" ]]; then @@ -416,7 +417,7 @@ # IP already? local IP - IP=$(grep "^${REGEX_IP}$" <<< "$1") + IP=$(grep "^${REGEX_IP}$" <<< "$1") if [[ "${IP}" ]]; then echo "${IP}" @@ -438,10 +439,11 @@ } # Result info for IP + # shellcheck disable=SC2329 text() { # IP already? local IP - IP=$(grep "^${REGEX_IP}$" <<< "$1") + IP=$(grep "^${REGEX_IP}$" <<< "$1") if [[ -n "${IP}" ]]; then echo "${IP}" @@ -483,9 +485,9 @@ -v Verbose mode, can be used multiple times (up to -vvv) -q Quiet mode with absolutely no output (useful for scripts) -p Plain text output (no coloring, no interactive status, useful - for tee'd output to a text file) - -j num The number of parallel processes to use (default is 200%, or - 2x system core count. See \`man parallel\` for details.) + for tee'd output to a text file) + -j num The number of parallel processes to use (default is 200%, or + 2x system core count. See \`man parallel\` for details.) -h The help you are just reading Exit code of the script is the number of blocklisted entries. So if the supplied @@ -508,7 +510,7 @@ while getopts :vqphcj:l:d: arg; do q) VERBOSE=-1;; p) PLAIN=1 RED="" GREEN="" YELLOW="" CLEAR="" ;; h) showHelp;; - j) j="${OPTARG}";; + j) j="${OPTARG}";; ?) error "Unknown option ${OPTARG}";; esac done @@ -522,23 +524,23 @@ fi TARGET=$1 if ! which parallel &> /dev/null; then - echo "Parallel missing, trying to install..." - if which yum &> /dev/null; then - [ ! "$(yum -q provides parallel)" ] && yum -y -q --skip-broken install epel-release - yum -y -q --skip-broken install parallel - elif which dnf &> /dev/null; then - [ ! "$(dnf -q provides parallel)" ] && dnf -y -q --skip-broken install epel-release - dnf -y -q --skip-broken install parallel - else #assumed debian-like - apt-get -qq update - apt-get -y -q install parallel - fi - if which parallel &> /dev/null; then - mkdir ~/.parallel - touch ~/.parallel/will-cite - else - error "Failed to install parallel, exiting." - fi + echo "Parallel missing, trying to install..." + if which yum &> /dev/null; then + [ ! "$(yum -q provides parallel)" ] && yum -y -q --skip-broken install epel-release + yum -y -q --skip-broken install parallel + elif which dnf &> /dev/null; then + [ ! "$(dnf -q provides parallel)" ] && dnf -y -q --skip-broken install epel-release + dnf -y -q --skip-broken install parallel + else #assumed debian-like + apt-get -qq update + apt-get -y -q install parallel + fi + if which parallel &> /dev/null; then + mkdir ~/.parallel + touch ~/.parallel/will-cite + else + error "Failed to install parallel, exiting." + fi fi # Some shells disable parsing backslash in echo statements by default @@ -668,6 +670,7 @@ info 1 " - ${COUNT_URIBL} URI blocklists" # Iterate over all blocklists +# shellcheck disable=SC2329 parallel_check() { local PREFIX= local I=$1 @@ -704,7 +707,7 @@ parallel_check() { # Show percentage local STATUS - STATUS="$(printf " %3s" $((I * 100 / COUNT)))% " + STATUS="$(printf " %3s" $((I * 100 / COUNT)))% " # Show additional info if [[ "${VERBOSE}" -ge 3 ]]; then @@ -735,7 +738,7 @@ parallel_check() { local ERROR="" if [[ "${VERIFY_BL}" ]]; then local TDL - TDL=$(grep -om 1 "${REGEX_TDL}" <<< "${DOMAIN}") + TDL=$(grep -om 1 "${REGEX_TDL}" <<< "${DOMAIN}") if [[ ! "$(resolve "${TDL}" ns)" ]]; then if [[ -z "${PLAIN}" ]]; then printf "\r"; fi printf "%s%sUnreachable server%s\n" "${YELLOW}" "${PREFIX}" "${CLEAR}"; @@ -818,9 +821,9 @@ fi # shellcheck disable=SC2002 failed=$(cat "$failed_file" | wc -l) if [ "$failed" -gt 0 ]; then - touch $output - echo "${TARGET}" >> $output - cat "$failed_file" >> $output + touch $output + echo "${TARGET}" >> $output + cat "$failed_file" >> $output fi rm -f "$passed_file" "$allow_file" "$invalid_file" "$failed_file"