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.1nauthor: jason ross <algorythm@gmail.com>n"
   usage="nn%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()