PortScanner Detector
Your program will be multi-threaded.
One thread of your program will sniff the traffic. For every connection from <srcIP, srcPort> to <dstIP, dstPort>, it records <(srcIP, dstIP, dstPort), timestamp> in a table. We refer to this as first-contact connection request. Every first-contact connection is stored for 5 minutes before being deleted. If (src, dstIP, dstPort) already exists, then you have already recorded the first-contact (do nothing). As a result of this step, you have a table (hashtable are a good option to implement this) of all first-contact connections per every source, along with their updated timestamp within the last 5 minutes. First-contacts that are older than 5 minutes must be constantly deleted (May need another thread).
Another thread will calculate the fan-out rate of each source IP. Fan-out rate is the rate of establishing new connections per time interval. For example, the fan-out rate of 5/s means the source host has made 5 first-contact connections in the last second.
You will calculate the fan-out rate for three different intervals: per second, per minute, per 5 minutes.
If the fan-out rate per sec exceeds 5, or the fan-out rate per minute exceeds 100, or the fan-out rate per 5min exceeds 300 (any of these), the source IP is identified as a port-scanner.
Your program must output the source IP, the average fan-out rates per second in the last 5 minutes, the average fan-out rate per minute in the last 5 minutes, and the fan-out rate per 5 minutes for every detected port-scanner. Note that if a portscanner is detected in less than 5 minutes, some of these fan-out rates may not be applicable. I leave figuring out the details to you. Your program must also output the reason for detection (See example output below).
Example Output:
portscanner detected on source IP x
avg. fan-out per sec: y, avg fan-out per min: z, fan-out per 5min: d
reason: fan-out rate per sec = 6 (must be less than 5).
**ADD TO THIS CODE TO MAKE THE CHANGES ABOVE**
import socket
target = input('Enter Target IP: ')
def tcp_scanner(target, port):
try:
tcp_sock =
socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcp_sock.connect((target,port))
tcp_sock.close()
return True
except:
return False
def udp_scanner(target, port):
try:
udp_sock =
socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
udp_sock.settimeout(2.0)
udp_sock.sendto(bytes("NOTHING",
"utf-8"), (target, port)) # Send a UDP packet to the IP and
port of the target
response, addr =
udp_sock.recvfrom(1024) # If an ICMP message comes back, port
is closed or firewalled
if response != None:
return True
return False
except:
print('no response from udp port {}.
Port may be open but not responding.'.format(port))
for portNumber in range(1, 1024):
if tcp_scanner(target, portNumber):
print('Port ', portNumber, '/tcp is
open\n')
#Then, add the following code to end of main()
for portNumber in range(1, 1024):
if udp_scanner(target, portNumber):
print('Port', portNumber, '/udp', 'is
open')