03 March 2009

ASNCheck Script

While working on a project today I decided that it would be handy to have a script that could take an AS number (from stdin or from a list of them) and check the health status of it (via things like DNSBL for example), specifically gathering information that could lead one to determine the relative infection/compromise level.

Ideally, such a script would be able to alternatively take an IP address, determine the AS for it and then report on both the IP provided as well as the overall "health" of the AS associated with it.

Well, some of that I managed to whip out tonight, though not all.

I'll keep working on this, but I think it's useful enough now to warrant posting (I normally do *not* make code public in this raw a state, so take note that there are very likely bugs in this).

That said, here's 'asncheck.py'.
In its current state, it just returns a list of IP addresses from a given AS which are in the dShield current watchlist.

#! /usr/bin/env python
# ------------------------------------------------
# asncheck:
# retrieves the current dshield watchlist for
# a given AS, returning just the IP addresses.
# sample url:
# https://secure.dshield.org/asdetailsascii.html?as=123
# ------------------------------------------------
# written by:
# jason ross (algorythm@gmail.com)
# ------------------------------------------------
import sys

def main():
# here beginneth the script
opts = parmsdealer()

if (opts.verbose == 1):
print "\nRetrieving information for AS Number " + opts.asn + ":\n"

if (opts.infile):
try:
filedata = open(opts.infile, 'rU')
except IOError:
print "unable to open input file \'" + opts.infile + "\'\n"
sys.exit(1)
except:
print "Unexpected error:", sys.exc_info()[0]
sys.exit(1)
else:
for line in filedata:
print line
asn = line.split(opts.delim, 3)[int(opts.col)]

if (opts.asn):
asn = opts.asn

dshield(asn, opts.verbose)

#print '{0}.{1}.{2}.{3}'.format(oct1.zfill(3),oct2.zfill(3),oct3.zfill(3),oct4.zfill(3))


def parmsdealer():
import sys
from optparse import OptionParser
version="\nasncheck: version 0.1\nauthor: jason ross \n"
usage="\n\n%prog [OPTIONS]\n"
parser = OptionParser(usage=usage, version=version)

# set up command line arguments
parser.set_defaults(col=0)
parser.set_defaults(delim="|")
parser.set_defaults(verbose=0)

parser.add_option("-v", "--verbose", dest="verbose",
action="store_true", help="turn on/off verbosity (default: off)")
parser.add_option("-a", "--asn", dest="asn",
action="store", help="specify the AS to retrieve data for (just the number, or with 'AS' prepended)")
parser.add_option("-f", "--infile", dest="infile",
action="store", help="get the AS from the specified file (can be a list)")
parser.add_option("-c", "--col", dest="col",
action="store", help="[required with -f] specifies which column in an input file contains the AS (default is to use the first column: '0')")
parser.add_option("-d", "--delim", dest="delim",
action="store", help="[required with -f] specifies the delimiter to use when parsing the input file (default is to use the ASCII pipe character (0x7c): '|')")

# process command line arguments
(options, args) = parser.parse_args()

# exit if we're missing options
if (not options.asn and not options.infile):
print "\n" + sys.argv[0] + ": missing parameter(s)\n"
parser.print_help()
print "\n"
sys.exit(1)

# exit if we've got conflicting options
if (options.asn and options.infile):
print "\n" + sys.argv[0] + ": can't set both an asn and an input file (there can be only one!)\n"
parser.print_help()
print "\n"
sys.exit(1)

return options


def dshield(asn, verbose):
import socket
import urllib
import urllib2
import re

# urllib2 calls socket, so we can set the timeout here
timeout = 5
socket.setdefaulttimeout(timeout)

baseuri = 'https://secure.dshield.org/asdetailsascii.html'

params = {}
params['as'] = asn
encparams = urllib.urlencode(params)

requri = baseuri + '?' + encparams
req = urllib2.Request(requri)

if (verbose == 1):
print "opening " + requri + "\n"

try:
res = urllib2.urlopen(req)
except urllib2.URLError, e:
if hasattr(e, "code"):
print "site borked! HTTP error: "
print e.code
elif hasattr(e, "reason"):
print "server borked! reason: "
print e.reason
else:
data = res.readlines()
# print data
for line in data:
if ( re.match(r"[0-9]", line) ):
ip = line.split()
print ip[0]


if __name__ == "__main__":
main()

No comments:

Post a Comment