Eli Fulkerson .com HomeProjectsPix-conn-summary
 


Cisco Pix "show conn" Summary Tool

Description:

This is a python script that connects via ssh (with the help of plink.exe) to a Cisco Pix and executes the "show conn" command. It then parses the output and presents the totals of the different types of connections in chart form.

Platform:

  • Python + Win32 (because plink.exe is a windows program)
  • Language:

  • Python
  • License:

  • I am making the code to the script 'pix-conn-summary.py', as below, free for anyone to use without restriction.
  • Bugs:

  • The scraping probably will not work if you have users set on your pix besides the default. In that case you probably just need to specify the users as well in that part of the script, it should be a solvable problem if you need it to be.
  • Usage:

    python.exe pix-conn-summary.py -a <address>
    

    Download:

    source code without formatting

    Code:

    """
    
    This script scrapes the output of the Cisco Pix "show connections" command and parses it into
    readable tables.  One of the drawbacks I've run into with "show conn" is that there is too much
    data too quickly determind any sort of idea of what is going on.  This script will auto-summarize
    the data for you in a quickly readable fashion.
    
    The particular need I had for this was detect viruses that would cause a spike in the amount of
    connections on the Pix.  I needed a script that would be able to show me very quickly that 900 of
    the 1000 outgoing connections were on wierd port X so that I could identify the problem without
    paging through acres of output.
    
    Requirements:
      It is assumed that you are running this under win32, as plink.exe is a win32 thing.
      Python Interpreter
      a copy of "plink.exe" from the puTTY tools in the same directory as the script
         (plink available at: http://www.chiark.greenend.org.uk/~sgtatham/putty/ )
      the ability to for the script to write a temporary file into the local directory
    
    Beware!  This script temporarily writes your passwords into a file so that it can feed them into
    plink.  You may consider that to be a problem.  They are deleted after the plink'ing is done.
    
    
    """
    import os
    import string
    import getpass
    import getopt
    import sys
    import time
    
    def printf(format, *args):
        print str(format) % args,
    
    
    def print_sorted_ports(list):
        items = list.items()
        items.sort()
        for key,value in items:
            printf('%10s %10s \n', key, value)
    
    def print_sorted_ips(list, arp):
        items = list.items()
        items.sort()
    
        for key, value in items:
            try:
                mac = arp[key]
            except:
                mac = "Unknown"
            printf ('%20s %20s %10s \n', key, mac, value)
    
    def show_header(pix_address):
        print "Checking connections on pix firewall at " + pix_address + ", please wait..."
        print ""
        print time.strftime("%a, %d %b %Y %H:%M:%S ", time.localtime())
        print ""
    
    def show_results_by_ip(outside_ips, inside_ips, arp):
        print "Connections by Outside IP address:"
        print "----------------------------------"
        printf ('%20s %20s %10s \n', "layer 3", "layer 2", "count")
        print print_sorted_ips(outside_ips,arp)
        #print "Total: " + str(len(outside_ips))
    
        print "Connections by Inside IP address:"
        print "----------------------------------"
        printf ('%20s %20s %10s \n', "layer 3", "layer 2", "count")
        print print_sorted_ips(inside_ips,arp)
        #print "Total: " + str(len(inside_ips))
    
    def show_results_by_port(outside_ports, inside_ports):
        #if show_port_stats == 1:
        print "Connections by Outside TCP/IP Port"
        print "----------------------------------"
        printf('%10s %10s \n', "port", "count")
        print print_sorted_ports(outside_ports)
        #print "Total: " + str(len(outside_ports))
    
        print "Connections by Inside TCP/IP Port"
        print "---------------------------------"
        printf('%10s %10s \n', "port", "count")
        print print_sorted_ports(inside_ports)
        #print "Total: " + str(len(inside_ports))
    
    def usage():
        print "-a <pix address> is a required option"
        sys.exit(2)
    
    def check_connections_on_device(password, enable, pix_address, outside_ips, inside_ips, outside_ports, inside_ports,arp):
        f = open('testcmd.txt', 'w')
        f.write("?\n")
        f.write("enable\n")
        f.write(enable + "\n")
        f.write("no pager\n")
        f.write("show conn\n")
        f.write("show arp\n")
        f.write("exit\n")
        f.close()
    
    
        outside_ips.clear()
        inside_ips.clear()
        outside_ports.clear()
        inside_ports.clear()
        arp.clear()
    
        # remember to set your putty default settings to accept at least DES, (or 3DES if your pix is upgraded with the proper key)
        # otherwise this will silently fail
    
        cmd = "plink -1 -ssh -l pix -pw " + password + " -m testcmd.txt " + pix_address
    
        os.system("cls")
        show_header(pix_address)
    
    
        put,get = os.popen4(cmd)
    
        try:
            del connlist
            del arplist
        except:
            pass
    
        connlist = []
        arplist = []
    
    
        mode = "start"
    
        for line in get.readlines():
            if string.find(line, "show conn") != -1:
                mode = "show conn"
            elif string.find(line, "show arp") != -1:
                mode = "show arp"
            elif string.find(line, "exit") != -1:
                mode = "exit"
            else:
                if mode == "show conn":
                    connlist.append(line)
                if mode == "show arp":
                    arplist.append(line)
    
        # overwrite, and then remove, the original file
        # @@ This could probably be made more robust.
        f = open('testcmd.txt', 'w')
        f.write("asdlfja;sldfja;lsdfja;lsdfja;lsdfjasdf")
        f.write("asdlfja;sldfja;lsdfja;lsdfja;lsdfjasdf")
        f.write("asdlfja;sldfja;lsdfja;lsdfja;lsdfjasdf")
        f.write("asdlfja;sldfja;lsdfja;lsdfja;lsdfjasdf")
        f.write("asdlfja;sldfja;lsdfja;lsdfja;lsdfjasdf")
        f.write("asdlfja;sldfja;lsdfja;lsdfja;lsdfjasdf")
        f.write("asdlfja;sldfja;lsdfja;lsdfja;lsdfjasdf")
        f.write("asdlfja;sldfja;lsdfja;lsdfja;lsdfjasdf")
        f.close()
    
        os.remove('testcmd.txt')
    
    
        # build a dictionary to contain the arp data
        #arp = {}
        for line in arplist:
            line = string.split(line, " ")
            arp[ line[1] ] = line[2]
    
    
    
        conn_total = str(len(connlist))
        for line in connlist:
            if string.find(line, "TCP out") != -1:
                line = string.split(line, " ")
                outside = line[2]
                inside = line[4]
                outside = string.split(outside, ":")
                inside = string.split(inside,":")
    
                try:
                    outside_ips[outside[0]] = outside_ips[outside[0]] + 1
                except:
                    outside_ips[outside[0]] = 1
    
                try:
                    outside_ports[outside[1]] = outside_ports[outside[1]] + 1
                except:
                    outside_ports[outside[1]] = 1
    
                try:
                    inside_ips[inside[0]] = inside_ips[inside[0]] + 1
                except:
                    inside_ips[inside[0]] = 1
    
                try:
                    inside_ports[inside[1]] = inside_ports[inside[1]] + 1
                except:
                    inside_ports[inside[1]] = 1
    
    
    def main():
        pix_address = None
        show_port_stats = 0
    
        try:
            opts, args = getopt.getopt(sys.argv[1:], "pha:", ["ports","help", "address="])
        except getopt.GetoptError:
            # print help information and exit:
            usage()
            sys.exit(2)
        for o, a in opts:
            if o in ("-h", "--help"):
                usage()
                sys.exit()
            if o in ("-a"):
                pix_address = a
            if o in ("-p"):
                show_port_stats = 1
    
        if pix_address == None:
            usage()
    
        print "Checking connections on " + pix_address
        password = getpass.getpass("Line Password: ")
        enable = getpass.getpass("Enable Password: ")
    
        outside_ips = {}
        inside_ips = {}
        outside_ports = {}
        inside_ports = {}
        arp = {}
    
        check_connections_on_device(password, enable, pix_address, outside_ips, inside_ips, outside_ports, inside_ports,arp)
    
    
        #print arp
    
        show_results_by_ip(outside_ips, inside_ips, arp)
    
    
        input = ""
        while input != "q":
            input = raw_input("Please type 'i' to view by ip address, 'p' to view by port,\n'r' to re-query or 'q' to exit.")
            if input == "i":
                os.system("cls")
                show_header(pix_address)
    
                show_results_by_ip(outside_ips,inside_ips,arp)
            if input == "p":
                os.system("cls")
                show_header(pix_address)
    
                show_results_by_port(outside_ports,inside_ports)
    
            if input == "r":
                os.system("cls")
                show_header(pix_address)
    
                #remember to reset your data
    
    
                check_connections_on_device(password, enable, pix_address, outside_ips, inside_ips, outside_ports, inside_ports,arp)
                show_results_by_ip(outside_ips,inside_ips,arp)
    
    
    
    
    if __name__ == "__main__":
        main()