|
Guides All Guides and HOWTO's. |
|
Thread Tools | Display Modes |
|
|||
Script to test whether an IP address has been listed in a DNSBL
1. Script to test whether an IP address has been listed in a DNSBL
If you run a mail or a web server it nice to know in time whether the IP address of your server has been submitted to a so-called DNSBL list. Being listed can mean that one of your network boxes, or that a site you host on your webserver, has been compromised and is sending out spam. Many administrators find out the hard way, that their server has been blacklisted. Customers or users complain about their mail not being accepted by their recipients. Checking the mail logs then usually reveals an pointer to an URL which states something like this Code:
IP Address 1.2.3.4 was found in the CBL. It was detected at 2007-06-16 20:00 GMT (+/- 30 minutes), approximately 8 hours ago. ATTENTION: This IP has an open web or socks proxy which is being hijacked by the 'DMS' spam tool to send spam. This is usually due to proxy trojans being installed on your IP (or a machine "behind" this IP if it is a NAT gateway) via the vulnerabilities described in the Microsoft MS06-040 security bulletin. Please see the top news item on our home page for more information. You need to patch your system, find then fix/remove the proxy, and then contact the CBL at xxxxx@xxxx.org to remove this listing. See http://en.wikipedia.org/wiki/DNSBL and the excellent http://www.spamhaus.org/dnsbl_function.html page for more information about these lists and their role in anti-spam policies. 1.2 Manual DNSBL list check The organizations maintaining these lists, have a page on their website where you can check if your server is on their list. For example http://www.spamhaus.org/lookup.lasso and http://www.spamcop.net/bl.shtml. For a regular check however, for example to be run by 'cron', these facilities are not really helpful. And for a manual check of the IP address from the 'sh' command line you have to do quite some work too. Take as example the IP address 125.175.43.40 that sent me a spam message. For a black list check of this address you have to perform the following steps:
If you are familiar with reverse name lookups, you will noticed that the same mechanism is used here. Instead of appending '.in-addr.arpa.' to the reversed IP, you use the name of the black list. 1.3 The 'blcheck' shell script In the beginning of 2007 I saw an increase of spam in my Gmail spam folders. Because I wanted a comfortable way to find out whether this junk originated from black listed senders, I wrote the following script. Code:
#!/bin/sh # -- $Id: blcheck.xml,v 1.8 2007/06/17 23:38:00 j65nko Exp $ -- # Check if an IP address is listed on one of the following blacklists # The format is chosen to make it easy to add or delete # The shell will strip multiple whitespace BLISTS=" cbl.abuseat.org dnsbl.sorbs.net bl.spamcop.net zen.spamhaus.org combined.njabl.org " # simple shell function to show an error message and exit # $0 : the name of shell script, $1 is the string passed as argument # >&2 : redirect/send the message to stderr ERROR() { echo $0 ERROR: $1 >&2 exit 2 } # -- Sanity check on parameters [ $# -ne 1 ] && ERROR 'Please specify a single IP address' # -- if the address consists of 4 groups of minimal 1, maximal digits, separated by '.' # -- reverse the order # -- if the address does not match these criteria the variable 'reverse will be empty' reverse=$(echo $1 | sed -ne "s~^\([0-9]\{1,3\}\)\.\([0-9]\{1,3\}\)\.\([0-9]\{1,3\}\)\.\([0-9]\{1,3\}\)$~\4.\3.\2.\1~p") if [ "x${reverse}" = "x" ] ; then ERROR "IMHO '$1' doesn't look like a valid IP address" exit 1 fi # Assuming an IP address of 11.22.33.44 as parameter or argument # If the IP address in $0 passes our crude regular expression check, # the variable ${reverse} will contain 44.33.22.11 # In this case the test will be: # [ "x44.33.22.11" = "x" ] # This test will fail and the program will continue # An empty '${reverse}' means that shell argument $1 doesn't pass our simple IP address check # In that case the test will be: # [ "x" = "x" ] # This evaluates to true, so the script will call the ERROR function and quit # -- do a reverse ( address -> name) DNS lookup REVERSE_DNS=$(dig +short -x $1) echo IP $1 NAME ${REVERSE_DNS:----} # -- cycle through all the blacklists for BL in ${BLISTS} ; do # print the UTC date (without linefeed) printf $(env TZ=UTC date "+%Y-%m-%d_%H:%M:%S_%Z") # show the reversed IP and append the name of the blacklist printf "%-40s" " ${reverse}.${BL}." # use dig to lookup the name in the blacklist #echo "$(dig +short -t a ${reverse}.${BL}. | tr '\n' ' ')" LISTED="$(dig +short -t a ${reverse}.${BL}.)" echo ${LISTED:----} done # --- EOT ------ 1.4 Examples of correct and incorrect usage Correct Code:
$ ./blcheck 125.175.43.40 IP 125.175.43.40 NAME p4040-ipbf1108marunouchi.tokyo.ocn.ne.jp. 2007-06-17_01:11:05_UTC 40.43.175.125.cbl.abuseat.org. 127.0.0.2 2007-06-17_01:11:06_UTC 40.43.175.125.dnsbl.sorbs.net. --- 2007-06-17_01:11:07_UTC 40.43.175.125.bl.spamcop.net. 127.0.0.2 2007-06-17_01:11:07_UTC 40.43.175.125.zen.spamhaus.org. 127.0.0.4 2007-06-17_01:11:12_UTC 40.43.175.125.combined.njabl.org. --- $ ./blcheck 80.100.2.99 IP 80.100.2.99 NAME fia99-2-100.dsl.mxposure.nl. 2007-06-17_21:01:42_UTC 99.2.100.80.cbl.abuseat.org. --- 2007-06-17_21:01:42_UTC 99.2.100.80.dnsbl.sorbs.net. --- 2007-06-17_21:01:42_UTC 99.2.100.80.bl.spamcop.net. --- 2007-06-17_21:01:43_UTC 99.2.100.80.zen.spamhaus.org. --- 2007-06-17_21:01:43_UTC 99.2.100.80.combined.njabl.org. --- $ for X in 24.209.96.220 124.160.89.56; do ./blcheck $X; done IP 24.209.96.220 NAME cpe-24-209-96-220.woh.res.rr.com. 2007-06-17_01:18:29_UTC 220.96.209.24.cbl.abuseat.org. 127.0.0.2 2007-06-17_01:18:29_UTC 220.96.209.24.dnsbl.sorbs.net. 127.0.0.10 2007-06-17_01:18:30_UTC 220.96.209.24.bl.spamcop.net. 127.0.0.2 2007-06-17_01:18:30_UTC 220.96.209.24.zen.spamhaus.org. 127.0.0.11 127.0.0.4 2007-06-17_01:18:30_UTC 220.96.209.24.combined.njabl.org. 127.0.0.3 IP 124.160.89.56 NAME --- 2007-06-17_01:18:31_UTC 56.89.160.124.cbl.abuseat.org. 127.0.0.2 2007-06-17_01:18:31_UTC 56.89.160.124.dnsbl.sorbs.net. --- 2007-06-17_01:18:31_UTC 56.89.160.124.bl.spamcop.net. 127.0.0.2 2007-06-17_01:18:31_UTC 56.89.160.124.zen.spamhaus.org. 127.0.0.11 127.0.0.4 2007-06-17_01:18:31_UTC 56.89.160.124.combined.njabl.org. 127.0.0.3 $ while true; do echo IP?; read IP; ./blcheck $IP; done IP? 201.13.22.241 IP 201.13.22.241 NAME 201-13-22-241.dsl.telesp.net.br. 2007-06-17_23:12:10_UTC 241.22.13.201.cbl.abuseat.org. 127.0.0.2 2007-06-17_23:12:11_UTC 241.22.13.201.dnsbl.sorbs.net. 127.0.0.10 2007-06-17_23:12:11_UTC 241.22.13.201.bl.spamcop.net. 127.0.0.2 2007-06-17_23:12:11_UTC 241.22.13.201.zen.spamhaus.org. 127.0.0.11 127.0.0.4 2007-06-17_23:12:11_UTC 241.22.13.201.combined.njabl.org. 127.0.0.3 IP? 67.133.212.132 IP 67.133.212.132 NAME ;; connection timed out; no servers could be reached 2007-06-17_23:14:32_UTC 132.212.133.67.cbl.abuseat.org. 127.0.0.2 2007-06-17_23:14:33_UTC 132.212.133.67.dnsbl.sorbs.net. --- 2007-06-17_23:14:34_UTC 132.212.133.67.bl.spamcop.net. 127.0.0.2 2007-06-17_23:14:34_UTC 132.212.133.67.zen.spamhaus.org. 127.0.0.4 2007-06-17_23:14:34_UTC 132.212.133.67.combined.njabl.org. --- IP? ^C Code:
$ ./blcheck ./blcheck ERROR: Please specify a single IP address $ ./blcheck 1.2.3.4] ./blcheck ERROR: IMHO '1.2.3.4]' doesn't look like a valid IP address $ ./blcheck 1.2.3.4 5.7.7.8 ./blcheck ERROR: Please specify a single IP address Code:
$ ./blcheck 125.175.43.400 IP 125.175.43.400 NAME --- 2007-06-17_01:29:03_UTC 400.43.175.125.cbl.abuseat.org. --- 2007-06-17_01:29:03_UTC 400.43.175.125.dnsbl.sorbs.net. --- 2007-06-17_01:29:04_UTC 400.43.175.125.bl.spamcop.net. --- 2007-06-17_01:29:04_UTC 400.43.175.125.zen.spamhaus.org. --- 2007-06-17_01:29:04_UTC 400.43.175.125.combined.njabl.org. --- To reverse the IP address the script uses 'sed'. The man page tersely describes this program as follows: Code:
DESCRIPTION The sed utility reads the specified files, or the standard input if no files are specified, modifying the input as specified by a list of com- mands. The input is then written to the standard output. A single command may be specified as the first argument to sed. Multiple commands may be specified separated by newlines or semicolons, or by us- ing the -e or -f options. All commands are applied to the input in the order they are specified regardless of their origin. Code:
reverse=$(echo $1 | sed -ne "s~^\([0-9]\{1,3\}\)\.\([0-9]\{1,3\}\)\.\([0-9]\{1,3\}\)\.\([0-9]\{1,3\}\)$~\4.\3.\2.\1~p") Code:
reverse=$( command ) Code:
reverse=`command` $1 is the IP address passed as argument to the 'blcheck' script and is echoed to standard output. The '|' pipe symbol causes it to be fed to 'sed' as standard input for processing. The options used in calling 'sed': Code:
-n By default, each line of input is echoed to the standard output after all of the commands have been applied to it. The -n option suppresses this behavior. -e command Append the editing commands specified by the command argument to the list of commands. 1.6 Explanation of the 'sed' regular expression Code:
s~^\([0-9]\{1,3\}\)\.\([0-9]\{1,3\}\)\.\([0-9]\{1,3\}\)\.\([0-9]\{1,3\}\)$~\4.\3.\2.\1~p" Then do something similar for the remainder of the IP address 3 times: Look for a leading period '.' and a sequence of at least 1, and a maximum of 3 digits and store each of these digit groups (octets) in the containers \2, \3 and \4. Code:
s~^\([0-9]\{1,3\}\)\. s : substitute/replace ~ : our own chosen delimiter denoting start of the subst. pattern : instead of the default "/" ^ : beginning of line (the shell will strip all leading whitespace ) \( : start storing in the first container \1 [0-9] : a character in the range 0-9, a digit \{ : start of quantifier 1,3 : minimal one, maximal 3 \} : end of quantifier \) : end of storing in container \1 \. : a literal period '.' The opposite is true for the quantifier indicators \{ and \} and the grouping indicators \( and \). Here the opening and closing brace and the '(', ')' have no special meaning in the regular expression language To upgrade them to their special meaning, of start and stop storing, they need a leading "\". Code:
\([0-9]\{1,3\}\)\. \( : start storing in next container \2 [0-9] : a character in the range 0-9 \{ : start of quantifier 1,3 : minimal one, maximal 3 \} : end of quantifier \) : end of storing in container \2 \. : a literal '.' escaped with '\' \([0-9]\{1,3\}\)\. \( : start storing in next container \3 [0-9] : a character in the range 0-9 \{ : start of quantifier 1,3 : minimal one, maximal 3 \} : end of quantifier \) : end of storing in container \3 \. : a literal '.' escaped with '\' \([0-9]\{1,3\}\)$ \( : start storing in next container \4 [0-9] : a character in the range 0-9 \{ : start of quantifier 1,3 : minimal one, maximal 3 \} : end of quantifier \) : end of storing in container \4 $ : end of string We only stored the digit groups, not the separating periods or dots. Now we substitute and rearrange them in reverse order and re-insert the periods. Note that in the search or matching pattern, the period "." is a special character, that needs to be escaped if we want to match a real period. That doesn't apply to the substitution or replacement. Here a period is just a plain normal period. Code:
~\4.\3.\2.\1~p ~ : our custom delimiter, marking the end of the matching pattern, and start of the substituting part \4 : 4th digit group first . : a '.' has no special meaning in replacement part, so not escaped with '\') \3 : 3th digit group . : a '.' \2 : 2nd digit group . : a '.' \1 : 1st digit group . : a '.' p : print the matched and substituted pattern 1.7 Alternative approach for this rather long regex Both 'awk' and it's descendant 'perl' have an operator called 'split'. From the 'awk' man page: Code:
split(s, a, fs) Splits the string s into array elements a[1], a[2], ..., a[n] and returns n. The separation is done with the regular expression fs or with the field separator FS if fs is not given. An empty string as field separator splits the string into one array element per character. Both 'sed' and 'awk' are part of the base installation of all Unix-like operating systems, while 'perl' for example is not part of FreeBSD base and needs to be installed separately. This fact made me use 'sed' instead of 'perl' for this particular script.
__________________
You don't need to be a genius to debug a pf.conf firewall ruleset, you just need the guts to run tcpdump Last edited by J65nko; 13th May 2008 at 12:22 AM. Reason: typo |
Tags |
blacklist, rbl, spam |
Thread Tools | |
Display Modes | |
|
|
Similar Threads | ||||
Thread | Thread Starter | Forum | Replies | Last Post |
test port connection | carpman | FreeBSD Security | 5 | 9th February 2009 11:12 AM |
MAC address to IP | rex | FreeBSD General | 9 | 11th November 2008 07:06 PM |
Asking about IPv6 address | berlowin | Off-Topic | 2 | 9th July 2008 02:39 AM |
how extract specific test from Postfix logs with PHP or Perl | marco64 | Programming | 3 | 21st June 2008 12:46 PM |
Sendmail 8.14.2 undisclosed DNSBL lookup failure and NOQUEUE errors (FreeBSD 7.0) | NathanPardoe | FreeBSD General | 9 | 21st May 2008 12:00 AM |