A DNSBL or DNS blacklist is a DNS server that responds to a query of a reverse IP with an answer or not.
If it responds it means the IP is in the blacklist or the reverse.
An IP 10.20.30.40 would be queried like this "40.30.20.10.blacklist.org"
Not each IP needs to be individually listed in that DNS-server.
If all addresses in the "10.20.30.0/24" should be blacklisted, the DNS-server only needs to have 1 DNS-entry and that's "*.30.20.10.blacklist.org"
I have created a bash-script that will fill my DNS-server with all these DNS-entries by taking a file containing all the IP-addresses.
The script works, but it is not able to handle CIDR's that are NOT /8, /16, /24 or /32.
This because the wildcard-DNS system is based on a decimal system and not binary.
If I could convert the list before processing so that it would only contain /8, /16, /24 and /32 blocks it would work for all addresses.
10.20.30.0/23 would become 10.20.30.0/24 and 10.20.31.0/24
So it's somehow the reverse of the utility I often use: "aggregate"
I created this script after reading this question:
https://talk.plesk.com/threads/email-blacklists.344453/
Here's the script as it is now:
Can someone help me to improve the script so it can also handle the remaining IP-blocks
Code:
cat /usr/local/sbin/dnsbl
#!/bin/bash
BLOCKLIST=/opt/ASSP/files/blockip.txt
DNSBL=dnsbl.blocklist.org
PLESKDNS=/usr/local/psa/bin/dns
LOCALHOST=127.0.0.2
THISSCRIPT="`readlink -f $0`"
SCRIPTNAME=${THISSCRIPT##*/}
BASE=${THISSCRIPT##*/}
[ -z "${BASE}" ] && BASE=${0##*/}
LOG=/var/log/${BASE}.log
if [ ! -e "${BLOCKLIST}" ] ; then
echo "The blocklist ${BLOCKLIST} does not exist, quitting"
exit 1
fi
TMPDIR=`mktemp -t -d ${0//*\/}.XXXXXXXXXX`
TMPLOG=${TMPDIR}/log
date >${TMPLOG}
# Filter IPv4 addresses, 1 per row, only spaces or tabs allowed in front
egrep -o '^\s*[0-9]+\.[0-9]+\.[0-9]+\.([0-9]+|[0-9]+/[0-9]+)(\s|$)' "${BLOCKLIST}" | tr -d ' \t'| sort -uo ${TMPDIR}/all_blocks
echo "Found `grep -c '.' ${TMPDIR}/all_blocks` IP-blocks " | tee -a ${TMPLOG}
# Filter the plain IP's and CIDR with /32,/24,/16 and /8
egrep -o '^[0-9]+\.[0-9]+\.[0-9]+\.([0-9]+|[0-9]+/32|[0-9]+/24|[0-9]+/16|[0-9]+/8)$' ${TMPDIR}/all_blocks >${TMPDIR}/blocks
echo "I was able to use `grep -c '.' ${TMPDIR}/blocks` IP-blocks " | tee -a ${TMPLOG}
echo -e "These CIDR's are ignored:\n`grep -vf ${TMPDIR}/blocks ${TMPDIR}/all_blocks`\n\n" | tee -a ${TMPLOG}
while read BLOCK ; do
# remove the CIDR, Split the IPv4 in 4 segments keeping only the digits and reverse the order (tac)
echo "${BLOCK}" | sed 's/\/.*//g' | egrep -o '[0-9]+($|\.)' | tr -d '.' | tac >${TMPDIR}/ip4
ASTERISKS=0 # /32 or plain
echo "${BLOCK}" | grep -q "/24" && ASTERISKS=1 # /24
echo "${BLOCK}" | grep -q "/16" && ASTERISKS=2 # /16
echo "${BLOCK}" | grep -q "/8" && ASTERISKS=3 # /8
N=1
REV_IP=""
while read IP4 ; do
if [ $N -ge ${ASTERISKS} ] ; then
if [ $N -eq ${ASTERISKS} ] ; then
REV_IP="${REV_IP}*." # Replace whatever is there with an asterisk
else
REV_IP="${REV_IP}${IP4}." # Write the IPv4 segment
fi
fi
let N+=1
done<${TMPDIR}/ip4
# Write the reversed IP to the file after stripping the superfluous last dot
echo "${REV_IP}" | sed 's/\.$//g' >>${TMPDIR}/rev_ip4
done<${TMPDIR}/blocks
if [ -s ${TMPDIR}/rev_ip4 ] ; then
# Add the IPBLOCKS to DNS
N=1
while read IPBLOCK ; do
echo "${N}. Add ${IPBLOCK}.${DNSBL} IN A ${LOCALHOST}" | tee -a ${TMPLOG}
${PLESKDNS} --add ${DNSBL} -a "${IPBLOCK}" -ip ${LOCALHOST} | tee -a ${TMPLOG}
let N+=1
done<${TMPDIR}/rev_ip4
cat ${TMPLOG} >>${LOG} # Write temporary log to log
fi
rm -r ${TMPDIR}