Project 5 - Port Scanner
Table of Contents
Project Objectives
In this course project, you will develop a Python script that performs TCP and UDP port scanning.
Description
A port scanner program identifies the status of transport layer ports. A port can be open, closed, filtered, etc. Port scanning logic is discussed in the class. In this project, you will implement such a tool with the following features.
- The tool must be implemented in
python3
and utilizescapy
for custom packet generation. Aside from thesocket
andargparse
libraries, no additional libraries are allowed to be used. - Input Arguments: The tool should accept the following arguments using Pyton's argparse functionality:
- The
--tcp
or--udp
arguments allow the user to select the desired transport layer protocol for scanning. These two options are mutually exclusive. If unspecified, the default should be TCP. - The
--target X
argument allows the user to specify either the IP address or hostname of the target machine to be scanned. If unspecified, localhost (127.0.0.1) should be scanned. - The
--port
argument allows the user to specify a port (--port X
) or range of ports (--port X-Y
) to be scanned. Any other format for this argument must be rejected. If unspecified, the system port range (0-1023) should be scanned. Only valid port numbers in the range 0-65535 should be scannable. - The
--verbose
argument specifies that all scanned ports (open or closed/filtered) are displayed. Otherwise, only open ports are printed.
- The
- Do not probe the target initially to determine if it is online. This is similar to running
nmap
with the-Pn
option. - For the TCP port scan, your program must do stealth scanning. You send a SYN, the target may respond with SYN-ACK if the port is open, and then you send a RST to stop the connection from proceeding. Note that Linux (not your Python script) will send the RST, because from the perspective of Linux, the operating system didn't try to open this connection, and thus the OS will terminate it.
- For TCP scans, your results should be similar in style to a nmap scan run with options
nmap -Pn -sS -p <port(s)> <Host/IP> --reason
. In other words, a TCP stealth scan on a port or range of ports of a given target host, along with the reason for reporting the status of a port in a certain way.
- For TCP scans, your results should be similar in style to a nmap scan run with options
- For the UDP port scan, your technique will differ somewhat from nmap. In nmap UDP port scanning, valid application layer messages are used for well-known UDP ports. For example, a UDP scan of port 53 would utilize a dummy DNS request, in case a DNS server was listening on that well-known port. In this manner, nmap tries to encourage the target to send back a response for the valid query on the well-known open port. In your program, however, you only have to do this for the DNS port (UDP 53). When probing that port, send a legitimate DNS query for a domain name of your choosing. For probes to any other UDP port, you do not have to do this. For those ports, add a dummy application layer message as a payload to all of your UDP probes. This means that most UDP ports, even if there is an application listening there, will probably be silent to the received message. Your program will miss some open UDP ports and instead identify them as “Filtered|Open” because no response was received.
- For UDP scans, your results should be similar in style to a nmap scan run with options
nmap -Pn -sU -p <port(s)> <Host/IP> --reason
, except for open ports. Note that you should also report the reason for the status of each port.
- For UDP scans, your results should be similar in style to a nmap scan run with options
- Similar to the default behavior of nmap, scan the requested port(s) in a random order rather than a sequential order. Print the output of the scan in sorted order.
- At the top of the script file, briefly describe how your tool works.
Tip: Be sure to use argparse to handle the command-line arguments. It's much more robust than rolling your own parsing code.
Resources
Deliverables
Submit a single Python script that implements port scanning to the Canvas CMS Project 5 assignment.
If using PyCharm, do not submit your venv environment. Before submitting, test to ensure you can run your program outside of PyCharm on the command line.
Sample Output
Running the tool may generate an output similar to the following in a terminal in Ubuntu Linux.
Help Mode:
$ ./portscanner.py -h
usage: portscanner.py [-h] [-v] [--target TARGET] [--port PORT] [--tcp | --udp] [--verbose]
Port Scanner
optional arguments:
-h, --help show this help message and exit
-v, --version show program's version number and exit
--target TARGET Hostname or IP to scan
--port PORT Port [X] or Port Range [X-Y] to scan
--tcp TCP port scan (mutually exclusive with --udp)
--udp UDP port scan (mutually exclusive with --tcp)
--verbose Verbose output (Print all ports, not just open ports)
Version Mode:
shafer@ubuntu:~/comp177/project-5-port-scanner$ ./portscanner.py -v
portscanner.py 1.0
Default Scan, No Options Set:
$ sudo ./portscanner.py
Scan type: tcp
Target: localhost (127.0.0.1)
Port(s): 0-1023
TCP Scanning....
TCP Scan, Non-Verbose Mode, Default Ports:
$ sudo ./portscanner.py --tcp --target cyberlab.pacific.edu
Scan type: tcp
Target: ec2-54-148-163-48.us-west-2.compute.amazonaws.com (54.148.163.48)
Port(s): 0-1023
TCP Scanning....
Port: 22 Status: Open Reason: Received TCP SYN-ACK
Port: 80 Status: Open Reason: Received TCP SYN-ACK
Port: 443 Status: Open Reason: Received TCP SYN-ACK
TCP Scan, Non-Verbose Mode, Ports 0-30:
$ sudo ./portscanner.py --tcp --target cyberlab.pacific.edu --port 0-30
Scan type: tcp
Target: ec2-54-148-163-48.us-west-2.compute.amazonaws.com (54.148.163.48)
Port(s): 0-30
TCP Scanning....
Port: 22 Status: Open Reason: Received TCP SYN-ACK
TCP Scan, Verbose Mode, Default Ports:
$ sudo ./portscanner.py --tcp --target cyberlab.pacific.edu --verbose
Scan type: tcp
Target: ec2-54-148-163-48.us-west-2.compute.amazonaws.com (54.148.163.48)
Port(s): 0-1023
TCP Scanning....
Port: 0 Status: Filtered Reason: No response
Port: 1 Status: Filtered Reason: No response
Port: 2 Status: Filtered Reason: No response
Port: 3 Status: Filtered Reason: No response
Port: 4 Status: Filtered Reason: No response
Port: 5 Status: Filtered Reason: No response
Port: 6 Status: Filtered Reason: No response
Port: 7 Status: Filtered Reason: No response
Port: 8 Status: Filtered Reason: No response
Port: 9 Status: Filtered Reason: No response
Port: 10 Status: Filtered Reason: No response
Port: 11 Status: Filtered Reason: No response
Port: 12 Status: Filtered Reason: No response
Port: 13 Status: Filtered Reason: No response
Port: 14 Status: Filtered Reason: No response
Port: 15 Status: Filtered Reason: No response
Port: 16 Status: Filtered Reason: No response
Port: 17 Status: Filtered Reason: No response
Port: 18 Status: Filtered Reason: No response
Port: 19 Status: Filtered Reason: No response
Port: 20 Status: Filtered Reason: No response
Port: 21 Status: Filtered Reason: No response
Port: 22 Status: Open Reason: Received TCP SYN-ACK
Port: 23 Status: Filtered Reason: No response
Port: 24 Status: Filtered Reason: No response
Port: 25 Status: Filtered Reason: No response
...... output continues through port 1023.
UDP Scan, Non-Verbose Mode, Default Ports:
$ sudo ./portscanner.py --udp --target 8.8.8.8
Scan type: udp
Target: dns.google (8.8.8.8)
Port(s): 0-1023
UDP Scanning....
Port: 53 Status: Open Reason: Received DNS Response
nmap Comparison Scans
TCP Scan:
$ sudo nmap -Pn -sS -p 0-1023 cyberlab.pacific.edu --reason
Starting Nmap 7.80 ( https://nmap.org ) at 2020-09-18 11:38 PDT
Nmap scan report for cyberlab.pacific.edu (54.148.163.48)
Host is up, received user-set (0.20s latency).
Other addresses for cyberlab.pacific.edu (not scanned): 2600:1f14:536:b01:9cda:64e:15a9:da0
rDNS record for 54.148.163.48: ec2-54-148-163-48.us-west-2.compute.amazonaws.com
Not shown: 1021 filtered ports
Reason: 1021 no-responses
PORT STATE SERVICE REASON
22/tcp open ssh syn-ack ttl 128
80/tcp open http syn-ack ttl 128
443/tcp open https syn-ack ttl 128
Nmap done: 1 IP address (1 host up) scanned in 10.61 seconds
UDP Scan:
$ sudo nmap -Pn -sU -p 0-1023 dns.google --reason
Starting Nmap 7.80 ( https://nmap.org ) at 2020-09-18 15:03 PDT
Nmap scan report for dns.google (8.8.4.4)
Host is up, received user-set (0.036s latency).
Other addresses for dns.google (not scanned): 8.8.8.8 2001:4860:4860::8888 2001:4860:4860::8844
Not shown: 1022 open|filtered ports
Reason: 1022 no-responses
PORT STATE SERVICE REASON
53/udp open domain udp-response ttl 128
443/udp open https udp-response ttl 128
Nmap done: 1 IP address (1 host up) scanned in 103.91 seconds