Nmap

Nmap Port Scanning: SYN vs Connect, Open, Closed, and Filtered

Nmap port scanning - terminal showing open, closed, and filtered ports through a Cisco ASA
Table of Contents
In: Nmap, Network Security, Cisco Modeling Labs

Once you know which hosts are alive, the real work is finding out what each one is listening on. Port scanning is how you build a service inventory, confirm a firewall change did what you expected, and catch the forgotten management port nobody remembers opening. This article is part of the complete Nmap guide, and it covers the core of day-to-day scanning: the SYN scan that does most of the work, how it differs from a connect scan, how to choose which ports to hit, and the one lesson that separates people who read Nmap output correctly from people who guess - the difference between open, closed, and filtered.

The SYN scan is the default workhorse

The SYN scan, -sS, is what Nmap runs by default when you have the privileges for it, and for good reason. It sends a SYN, and if it gets a SYN/ACK back it knows the port is open, but instead of completing the handshake it sends a RST and moves on. The connection is never fully established, which is why it is called a half-open scan. It is fast, it is light on the target, and it is often not logged by applications that only record completed connections.

Here is a real SYN scan of four hosts on a lab LAN, captured live on Cisco Modeling Labs:

$ nmap -sS -T4 10.10.10.1 10.10.10.2 10.10.10.21 10.10.10.24
Starting Nmap 7.95 ( https://nmap.org ) at 2026-06-28 05:51 UTC
Nmap scan report for 10.10.10.1
Host is up (0.0050s latency).
Not shown: 998 closed tcp ports (reset)
PORT   STATE SERVICE
22/tcp open  ssh
23/tcp open  telnet
MAC Address: AA:BB:CC:00:5B:00 (Unknown)

Nmap scan report for 10.10.10.21
Host is up (0.0094s latency).
Not shown: 999 closed tcp ports (reset)
PORT   STATE SERVICE
80/tcp open  http
MAC Address: 52:54:00:A2:2F:84 (QEMU virtual NIC)

Nmap scan report for 10.10.10.24
Host is up (0.0082s latency).
Not shown: 999 closed tcp ports (reset)
PORT   STATE SERVICE
22/tcp open  ssh
MAC Address: 52:54:00:BB:DC:36 (QEMU virtual NIC)

Nmap done: 4 IP addresses (4 hosts up) scanned in 4.16 seconds

Look at how the device profiles fall out of the port list. The Cisco gear at .1 answers on 22 and 23 (SSH and Telnet, the classic router management pair). The host at .21 answers only on 80, so it is a web server (this is the nginx box). The host at .24 answers only on 22, an SSH-only Linux host. You did not run version detection yet, and you can already guess what each device is from its open ports alone.

Now read the line most people skip: Not shown: 998 closed tcp ports (reset). That parenthetical is doing real work. Those 998 ports are closed, and Nmap knows that because the host answered each probe with a RST. Closed means the host is reachable and nothing is listening on that port. It is a completely different state from filtered, and confusing the two is the single most common scanning mistake.

-sS half-open vs -sT full connect

When you cannot run as root, or you are scanning through a proxy that only speaks full connections, you fall back to the TCP connect scan, -sT. Instead of crafting raw packets, it asks the operating system to open a normal connection with connect(), completing the entire three-way handshake. Same result, different mechanics, and two differences that matter in practice.

$ nmap -sT 10.10.10.1
Starting Nmap 7.95 ( https://nmap.org ) at 2026-06-28 07:00 UTC
Nmap scan report for 10.10.10.1
Host is up (0.0029s latency).
Not shown: 998 closed tcp ports (conn-refused)
PORT   STATE SERVICE
22/tcp open  ssh
23/tcp open  telnet
MAC Address: AA:BB:CC:00:5B:00 (Unknown)
Nmap done: 1 IP address (1 host up) scanned in 3.49 seconds

The tell is in the parenthetical again: conn-refused instead of the SYN scan's reset. That is the OS reporting a refused connection rather than Nmap seeing the raw RST itself. The two trade-offs: -sT needs no root privileges, which is its whole reason to exist, but because it completes the handshake, the target application logs a full connection. A SYN scan on the same host would leave far less of a footprint. Reach for -sT when you lack privileges; prefer -sS the rest of the time.

Picking which ports to scan

By default Nmap scans the top 1000 most common ports, not all 65535. That default is a good balance for most work, but you should know how to widen or narrow it deliberately. Here are the port-selection flags you will actually use:

-F (fast)
Top 100 ports only. Roughly a tenth of the default, for a quick pass.
default (no -p)
Top 1000 ports by frequency. The sensible everyday choice.
--top-ports N
The N most common ports. Dial the breadth to the time you have.
-p 22,80,443
An explicit list. Fastest when you already know what to check.
-p-
All 65535 ports. Slow, but the only way to find services hiding high.
-p U:53,T:80
Mixed protocols in one run: UDP 53 and TCP 80 together.

The -F flag maps to a top-100 scan (the lab capture shows it finishing a router in 1.37 seconds), and an explicit -p list is faster still because Nmap only probes what you asked for. Note that only the live hosts should reach this stage, which is why host discovery comes first: scan the confirmed-up list, not empty address space.

Open, closed, filtered: the lesson that matters most

This is the centerpiece. Nmap reports one of three states for a scanned port, and reading them correctly is what makes your scans trustworthy. The cleanest way to see all three at once is to scan a single host through a real firewall. Here is a SYN scan of a DMZ target sitting behind a Cisco ASA, where the firewall permits TCP 22 and 80 to that host and denies everything else:

$ nmap -sS -p 22,23,80,443 10.10.20.32
Starting Nmap 7.95 ( https://nmap.org ) at 2026-06-28 05:53 UTC
Nmap scan report for 10.10.20.32
Host is up (0.0098s latency).

PORT    STATE    SERVICE
22/tcp  open     ssh
23/tcp  filtered telnet
80/tcp  closed   http
443/tcp filtered https

Nmap done: 1 IP address (1 host up) scanned in 1.37 seconds

Four ports, three different states, one host. Here is what each one is telling you:

  • 22 open - the firewall permits it and the target is listening. A SYN/ACK came back.
  • 80 closed - the firewall permits it, the packet reached the host, but nothing is listening, so the host answered with a RST. Closed means "I got to the host and there is no service here."
  • 23 filtered - the firewall dropped the probe silently. No SYN/ACK, no RST, nothing came back. Filtered means "something ate the packet before the host could answer."
  • 443 filtered - same silent drop.

The distinction between closed and filtered is the whole game. Closed is an answer (a RST from a reachable host). Filtered is silence (a firewall or ACL swallowed the probe). If you misread a filtered port as closed, you will conclude a host is reachable and idle when in fact a firewall is standing between you and it. This is exactly the behavior you would map when auditing an ASA policy, and the Cisco ASA firewall guide covers the rule structure that produces these results.

Let --reason prove each state

You do not have to take Nmap's word for it. Add --reason and it prints the exact packet behind every verdict. Here is the same DMZ host with reasons attached:

$ nmap --reason -p 22,23,80,443 10.10.20.32
Nmap scan report for 10.10.20.32
Host is up, received echo-reply ttl 254 (0.0074s latency).

PORT    STATE    SERVICE REASON
22/tcp  open     ssh     syn-ack ttl 254
23/tcp  filtered telnet  no-response
80/tcp  closed   http    reset ttl 254
443/tcp filtered https   no-response
Nmap done: 1 IP address (1 host up) scanned in 1.36 seconds

Now the mapping is spelled out on every line: syn-ack means open, reset means closed, and no-response means filtered. Memorize those three reasons and you can read any port state without second-guessing. When a result surprises you in the field, --reason is the first flag to add.

The top-1000 trap: services live high

Here is the mistake that bites people scanning their own infrastructure. The default top-1000 port list is built from statistical frequency across the internet, and plenty of important services do not live in it. Web apps, dashboards, and management consoles routinely bind to high ports: 8080 and 8443 for alternate HTTP and HTTPS, 9000 and up for a whole zoo of admin panels and app servers. A default scan sails right past all of them and reports a host as running only whatever happened to sit in the top 1000.

The consequence is a false sense of completeness. You scan a server, see only 22 and 80, and call it clean, while an unauthenticated admin panel is sitting on 8443 the whole time. The fix is to run -p- (all 65535 ports) at least once against anything you actually care about, and to add the usual high-port suspects to your targeted scans. It is slower, but on your own network, thoroughness beats speed when the alternative is missing a live service.

Key takeaways

The SYN scan (-sS) is your default half-open workhorse: fast, quiet, and enough to profile a device from its open ports alone (Cisco gear shows 22 and 23, a web server shows 80). Fall back to the connect scan (-sT) only when you lack root, and remember it gets logged as a full connection. Choose ports deliberately with -F, --top-ports, an explicit -p list, or -p- for everything, and never trust the top 1000 to be complete when real services hide on 8080, 8443, and 9000-plus. Above all, read the states correctly: open is a SYN/ACK, closed is a RST from a reachable host, filtered is silence from a firewall, and --reason will prove it. To go deeper on the different probe techniques see scan types and, for hosts that hide behind ACLs, firewall and IDS evasion. For the full workflow and the rest of the cluster, start at the complete Nmap guide.

Written by
More from Ping Labz
Great! You’ve successfully signed up.
Welcome back! You've successfully signed in.
You've successfully subscribed to Ping Labz.
Your link has expired.
Success! Check your email for magic link to sign-in.
Success! Your billing info has been updated.
Your billing was not updated.