In a previous blog post, we detailed what port scanning is and why it’s important. The article provided an introduction to the topic without going into much technical detail, and is a good starting point for those unfamiliar with the subject. Having covered the non-technical, general overview, this article will fill in some of the technical details for those who want to have a more in-depth understanding of how exactly port scanning works.
Before we begin, the following thought may occur to you: why do I need to understand how port scanning works? Can’t I just use X or Y tool or product and let that take care of everything for me? The answer is: no, in most cases, you can’t. Most products use tools such as Nmap behind the scenes to perform port scanning, however, without knowing which scanning techniques and options are being used it can be difficult to even know if any scanning is being performed at all. I have had clients who insisted they regularly carry out their own port scans be surprised when they find that their results don’t match mine. The reason for this is that if your scan techniques and tool options aren’t right for your environment, your scanner might report incorrect results. In order for these scan techniques and options to make sense, we need to have a technical understanding of how port scanners work. So, we’ll first explore the general technical details that apply to all port scanning tools before moving on to Nmap (since Nmap is the most widely used network scanner) specific options in an upcoming article.
Transport protocols determine how data is packaged and sent over a network. The two most commonly used transport protocols are Transmission Control Protocol (TCP) and User Datagram Protocol (UDP). TCP is typically used where reliability is important as it has various reliability mechanisms built-in such as same-order delivery, retransmissions, flow control, and others. UDP, on the other hand, is a much simpler protocol, and can be seen as best-effort as it provides no guarantee that data will be delivered to its destination. As you can probably imagine, the added reliability of TCP means that the transmission of data is somewhat more complex and carries more overhead when compared to UDP. Of importance to the topic of this article is the connection-based nature of TCP, and the connectionless nature of UDP. TCP requires a session to be established prior to the transmission of data, whereas UDP does not. We won’t go into all of the specifics surrounding the protocols and their features, but rather focus on the aspects that relate to port scanning in particular.
Before data can be transmitted via the TCP protocol a connection must be established with the intended destination. The process of establishing this connection is known as the TCP three-way handshake, and looks like this from the perspective of the initiator of the connection:
1. Send a TCP SYN (synchronise) packet destined to the IP address and port of the remote service we want to connect to.
2. Receive a TCP SYN ACK (synchronise + acknowledgement) packet back, which informs us that the remote service is accepting connections
3. Finalise the establishment of the connection by sending a TCP ACK (acknowledgement) back. Our connection is now established and we can send our actual application data.
The UDP protocol has no concept of connection establishment, we send our messages towards our intended destination IP address and port and cross our fingers. Let’s use a DNS query as an example. The flow of a DNS query looks something like this from the perspective of a client trying to resolve a domain to an IP address:
1. Send a DNS query message to our DNS resolver requesting the IP address of the domain we want to resolve.
2. Receive a DNS response containing the information we requested.
The differences in how TCP and UDP work mean that we need to employ different techniques in order to detect whether or not a port is open.
If we send a TCP SYN and receive a TCP SYN ACK back, we know that the destination port is open. Easy. So, what happens if we send a TCP SYN packet to a destination IP address and port that isn’t accepting connections? This depends, but typically the destination will either respond to our TCP SYN with a TCP RST (reset), or, we won’t receive any response to our TCP SYN. In either case, we can determine that – for whatever reason – the destination IP address and port will not establish a connection with us.
With this knowledge, we can now understand the basics of how a port scanner might identify whether a TCP port is open on a remote host: send a TCP SYN packet, if we receive a TCP SYN ACK back, consider the port to be open.
As has already been described, there’s no connection setup with UDP, we simply send messages and hope there’s a service on the other side that is listening and will handle our message. If there is no service on the destination host that can handle our message, we will either not receive a response back, or, receive an ICMP Port Unreachable message. If we receive an ICMP Port Unreachable message, we can consider the remote port to be closed. However, most of the time, and on most firewalls or security appliances, the preference is to quietly drop UDP packets without sending any ICMP Port Unreachable message. Hence, the most reliable way of detecting open UDP ports is to send the message type that the target service would typically expect, and see if we get an appropriate service-specific response back. We cannot send random data to random UDP ports and wait for a response. Meaning, if we want to check that a remote host is running DNS, we will need to send a DNS query message to port 53 (DNS typically runs on port 53) and wait for a DNS response. If we receive a DNS response, we’ve successfully identified that port 53 is open and has a DNS service behind it.
Now here’s the problem: although common services run on well-known ports; they don’t have to. For example, the remote host could be running NTP (Network Time Protocol) on port 53 instead of DNS. If we send our DNS query to a port with NTP behind it, it wouldn’t make any sense, and hence we wouldn’t receive a response. We would assume there’s no service listening behind the port, when in fact there is, but we weren’t able to elicit a response because we sent a DNS query message to a service that was expecting an NTP message. We don’t have this problem with TCP because the three-way handshake establishes a connection first, and this process is independent of the underlying service and the types of messages the service expects.
This means that detecting all open UDP ports can be very impractical, or even impossible. If we wanted to perform a comprehensive UDP scan on the entire available port range we would potentially have to send every possible message type to every possible port. Given there are 65,536 potential ports, and thousands of different services with their own defined message types, this would take a very long time even if we're only scanning a single host. Furthermore, we still wouldn’t be able to identify custom services that expect custom message types. All this to say, UDP port scanning cannot provide full coverage and accuracy, and will require some compromise between time spent and effectiveness. A more reasonable approach might be to scan the top 1000 most commonly used ports, while also ensuring we are probing for the most commonly used UDP services. It’s not perfect, but it should identify the majority of commonly used UDP services out on the internet.
In this article we’ve covered some of the more technical aspects of how port scanning works and the general approaches used to detect open TCP and UDP ports. With this knowledge we are in a better position to understand how network scanning tools such as Nmap perform port scans. We will build on this in an upcoming article where we will detail how to use Nmap, as well as the various options it provides, to increase the accuracy of our scans.