Monday, 9 March 2009

Firewall port testing #2

Well another week and some more tweaks to my firewall port testing python script. I have added a new column to the input and results, so you can have an info field and also added a header row. Also the results filename will now have a date stamp and if running under windows it will have the host name in the file to help ordering and what now.

PortTester.py
#! /usr/bin/python

import telnetlib
import thread
import os
import datetime


class PortTester(object):

thread_count = 0

def __init__(self, input, log):

for row in input:
thread.start_new(self.testPort, (row['info'], row['host'], row['port'], log))
self.thread_count = self.thread_count + 1
while self.thread_count > 0:
pass


def testPort(self, info, host, port, log):
print 'Testing %s. host %s on port %s' % (info, host, port)
try:
connection = telnetlib.Telnet(host, port)
log.write('%s,%s,%s,pass\n' % (info,host,port))
log.flush()
except:
log.write('%s,%s,%s,fail\n' % (info,host,port))
log.flush()
self.thread_count = self.thread_count - 1

def main():
test_list = readCSV('input.txt', ',', 1)
output = open('results_%s_%s.txt'%(os.getenv('COMPUTERNAME'),datetime.datetime.now().strftime('%Y%m%d-%H%M%S')), 'w')
output.write('info,host,port,result\n')
output.flush()
PortTester(test_list, output)

def readCSV(path, delimiter, header_row):
text = open(path, 'r').read()
text = text.replace('%s%s' % (delimiter, delimiter), '%s %s' % (delimiter, delimiter))
lines = text.split('\n')
rows = []
if header_row:
headers = []
if lines[0] != '':
headers = lines[0].split(delimiter)
tmp = []
for head in headers:
tmp.append(head.strip().lower())
headers = tmp
del lines[0]
for line in lines:
if line != '':
values = line.split(delimiter)
row = {}
for i in range(0, len(headers)):
row[headers[i]] = values[i].strip()
rows.append(row)
else:
for line in lines:
if line != '':
values = line.split(delimiter)
rows.append(values)
return rows

if __name__ == '__main__':
main()


input.txt
  Info      , Host    ,  Port   
Google 81, google.com,81
Google Work,google.com,80
Google 82,google.com,82
Google IP,74.125.67.100,80
Google IP 81 , 74.125.67.100 , 81
Blog Work,blog.karit.geek.nz,80
Blog Fail,blog.karit.geek.nz,81


results.txt
info,host,port,result
Google IP,74.125.67.100,80,pass
Google Work,google.com,80,pass
Blog Work,blog.karit.geek.nz,80,pass
Google IP 81,74.125.67.100,81,fail
Blog Fail,blog.karit.geek.nz,81,fail
Google 81,google.com,81,fail
Google 82,google.com,82,fail

Sunday, 1 March 2009

Firewall port testing

During the week I got the task of testing that some firewalls have been set up between the servers our application runs on and those at a third party which we need to exchange information with. The firewall is pin hole with this source and this destination and port number. There are eight boxes, four destination boxes and five ports on each of the destination boxes. Jumping on each of source boxes and testing each of the 20 destination and port combinations is rather difficult.

So I needed a tool. A quick look around either turned up online port scanners or tools like nmap. What I wanted was something that could take a CSV of IP and port and output a CSV of IP, port and result. Sure would have to run it on each of the source machines but will be far quicker and less manual and I am sure it will come up again.

I did it manually during weeks as I had to do it there and then, so this weekend I wrote a little python script that takes some IPs and port as input and test them all and write a little CSV as output in Python. Though Python wasn't all I needed as Python requires installation of stuff. That is where py2exe comes in it lets you make .py into a exe plus some library stuff. So can drop it onto a server, do your testing and then just delete the directory. This is a must have seeing I am having to do this on production servers before go live.

This script is also threaded so it will try to make connections to all the endpoint simultaneously. This can come in handy as the time out for the connections can be quite a long time. This way you only have to wait for the time out once rather than N*time out.

To use on Windows:
  1. Have Python installed on your desktop
  2. Download and install py2exe
  3. Read the tutorial about how to make Python into exe
  4. Go make you exe and zip up the dist directory
  5. Drop the files on the source computer
  6. Set up the input.txt file (see example below)
  7. Double click the .exe file
  8. Check the results
To use on *nix:
A lot of *nix boxes will have python installed out of the box so can run the .py file all by itself. You will just have to do the input.txt and run it.

PortTester.py
#! /usr/bin/python

import telnetlib
import thread

class PortTester(object):

thread_count = 0

def __init__(self, input, log):

for row in input:
thread.start_new(self.testPort, (row[0], row[1], log))
self.thread_count = self.thread_count + 1
while self.thread_count > 0:
pass


def testPort(self, host, port, log):
print 'Testing %s on port %s' % (host, port)
try:
connection = telnetlib.Telnet(host, port)
log.write('%s,%s,pass\n' % (host,port))
log.flush()
except:
log.write('%s,%s,fail\n' % (host,port))
log.flush()
self.thread_count = self.thread_count - 1

def main():
test_list = readCSV('input.txt', ',')
output = open('results.txt', 'w')
PortTester(test_list, output)

def readCSV(path, delimiter):
text = open(path, 'r').read()
text = text.replace('%s%s' % (delimiter, delimiter), '%s %s' % (delimiter, delimiter))
lines = text.split('\n')
rows = []
for line in lines:
if line != '':
values = line.split(delimiter)
rows.append(values)
return rows

if __name__ == '__main__':
main()


setup.py (for py2exe)
from distutils.core import setup
import py2exe

setup(console=['PortTester.py'])


example input.txt
10.0.0.126,80
10.0.0.126,81
10.0.0.0,80
google.com,81
google.com,80
google.com,82
74.125.67.100,80
74.125.67.100,81
blog.karit.geek.nz,80
blog.karit.geek.nz,81


example results.txt
10.0.0.126,80,pass
10.0.0.126,81,fail
10.0.0.0,80,fail
74.125.67.100,80,pass
blog.karit.geek.nz,80,pass
google.com,80,pass
74.125.67.100,81,fail
blog.karit.geek.nz,81,fail
google.com,81,fail
google.com,82,fail