Port Scanner in Python
Python is a great tool to do some socket operations. I have written a piece of code by which I can scan a port range.
It is very basic and missing bunch of checks as aim is the simplicity here.
#!/usr/bin/python import socket,sys try: sys.argv[3] except: print "Usage: port_scanner.py [hostname|IP] [port_start] [port_end]" sys.exit() host = sys.argv[1] start_port = int(sys.argv[2]) end_port = int(sys.argv[3]) #CREATE SOCKET try: s = socket.socket(socket.AF_INET,socket.SOCK_STREAM) except socket.error,err_msg: print 'Socket creation failed. Error code: '+ str(err_msg[0]) + ' Error mesage: ' + err_msg[1] sys.exit() #RESOLVE HOSTNAME try: remote_ip = socket.gethostbyname(host) except socket.error,error_msg: print 'ERROR:' print error_msg sys.exit() #ITERATE PORT RANGE end_port+=1 for port in range(start_port,end_port): try: s.connect((remote_ip,port)) print 'port ' + str(port) + ' open' s.close() s = socket.socket(socket.AF_INET,socket.SOCK_STREAM) except socket.error: pass
You can run the script in the following way by which you scan ports between 1 and 1024:
$ ./port_scanner.py remotehost.com 1 1024 port 80 open port 443 open
However I need to give some more info in here. If you send a TCP SYN segment to a closed port, normal behavior is to send a TCP RST segment back to the source. Under normal circumstances script runs through the port range and knocks every port on the remote destination. If a TCP RST is received, socket is closed and script knocks the other port in the list but what if you don’t receive any TCP RST back? For example there is a firewall in between and you can’t even knock some ports. Then what happens? In this case Linux kernel does 5 TCP SYN by default according to my ubuntu sysctl settings;
$ sysctl -a | grep tcp_syn_retries net.ipv4.tcp_syn_retries = 5
This is a terrible setting which causes lots of delay in every port knock. That is why to speed up test I decrease this retry value to 1 temporarily
# sysctl net.ipv4.tcp_syn_retries=1 net.ipv4.tcp_syn_retries = 1
Actually I wanted to set my own retry scheme via python but it seems it isn’t possible to manipulate kernel’s behavior on this. In python there is a “setsockopt” method of socket by which you can send certain options but no related option I could find in socket manual of Linux. There may be a way but I don’t know it yet.
When you run the test, you can check the SYN requests with the following tcpdump command, you can have a better picture of what the script is doing;
#tcpdump -nni any host remotehost.com and 'tcp[tcpflags] & tcp-syn!=0'