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.
python.exe pix-conn-summary.py -a <address>
source code without formatting
"""
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()