# # This script written by Eli Fulkerson. # http://www.elifulkerson.com for more. # """ 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 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()