← All labs
MediumNetwork Scanning ~30 min

nmap SYN Scan Dissection

Run a SYN scan against a target VM, capture it in Wireshark, and identify open/closed/filtered ports from the raw packets.

↳ Based on the lesson: TCP, UDP & the Handshake

Legal Use Only

Packet capture and port scanning must only be performed on networks and systems you own or have explicit written authorization to test. Capturing traffic on shared networks without authorization violates wiretapping laws in most jurisdictions. This lab requires a private, isolated VM lab network.

Scenario

You know nmap's SYN scan sends SYN packets and reads the reply. But knowing it intellectually and seeing it in Wireshark are different things. This lab makes the TCP handshake theory visible: you'll run a SYN scan, capture the raw packets simultaneously, and correlate nmap's open/closed/filtered output with the actual TCP flags in each exchange.

Requirements:

  • Kali Linux (attacker) and a target VM on a shared host-only network (VirtualBox or VMware)
  • wireshark or tcpdump installed on Kali
  • Target VM with at least one open port (SSH on 22), one closed port (try 9999), and if possible a firewall dropping traffic on another port (configure with iptables -A INPUT -p tcp --dport 8080 -j DROP)

Your Objective

  1. Start a Wireshark capture on the interface facing the target
  2. Run nmap -sS against ports 22, 9999, and 8080 on the target
  3. In Wireshark, identify the exact packet exchange for each port state
  4. Screenshot or note the TCP flags that distinguish open / closed / filtered

Hints

Wireshark display filter

Use tcp and host 192.168.56.101 as your Wireshark display filter to see only traffic between your Kali box and the target. This eliminates noise from other traffic on the interface.

tcpdump as a lightweight alternative

If Wireshark's GUI is too heavy for your VM, use sudo tcpdump -i eth0 -n "host 192.168.56.101 and tcp" -w scan.pcap to capture to a file, then open it in Wireshark later for analysis.

nmap timing and verbosity

Use nmap -sS -T2 -v (slower timing) to give Wireshark time to capture all packets cleanly. -v adds verbose output so you see nmap's port state determination in real time alongside the capture.

Walkthrough

Step 1: Set up packet capture

Open a second terminal (or a tmux pane) and start tcpdump before running nmap:

# Terminal 1 - start capture
$ sudo tcpdump -i eth0 -n "host 192.168.56.101 and tcp" -w syn-scan.pcap
tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes

Or open Wireshark with the filter already set:

$ sudo wireshark -i eth0 -k -f "tcp and host 192.168.56.101" &
Step 2: Run the SYN scan
# Terminal 2 - run the scan
$ sudo nmap -sS -T2 -v -p 22,9999,8080 192.168.56.101
Starting Nmap 7.94
Initiating SYN Stealth Scan at 10:00:00
Scanning 192.168.56.101 [3 ports]
Discovered open port 22/tcp on 192.168.56.101
SYN Stealth Scan Timing: About 33.00% done
Completed SYN Stealth Scan at 10:00:05, 5.21s elapsed (3 total ports)
 
PORT     STATE    SERVICE
22/tcp   open     ssh
9999/tcp closed   abyss
8080/tcp filtered http-proxy
 
Nmap done: 1 IP address (1 host up) scanned in 5.34 seconds
Step 3: Stop capture and open in Wireshark
# Terminal 1 - Ctrl+C to stop capture
^C 12 packets captured
 
# Open the capture file
$ wireshark syn-scan.pcap &

Apply the display filter: tcp and host 192.168.56.101

Step 4: Identify the packet exchange for each port state

Port 22 - OPEN:

In Wireshark, filter tcp.port == 22. You'll see exactly 3 packets:

No.  Time    Src              Dst              Info
1    0.001   192.168.56.4     192.168.56.101   22 SYN
2    0.002   192.168.56.101   192.168.56.4     22 SYN, ACK
3    0.002   192.168.56.4     192.168.56.101   22 RST

Nmap sent SYN, received SYN-ACK (service is listening), immediately sent RST to abort - never completing the handshake. The RST prevents the application from logging a connection.

Port 9999 - CLOSED:

Filter tcp.port == 9999:

No.  Time    Src              Dst              Info
4    0.100   192.168.56.4     192.168.56.101   9999 SYN
5    0.101   192.168.56.101   192.168.56.4     9999 RST, ACK

The target's OS immediately responded with RST-ACK - nothing is listening on 9999. Two packets, done. The host is reachable; that port is empty.

Port 8080 - FILTERED:

Filter tcp.port == 8080:

No.  Time    Src              Dst              Info
6    0.200   192.168.56.4     192.168.56.101   8080 SYN
7    1.200   192.168.56.4     192.168.56.101   8080 SYN  [retransmission]
8    2.200   192.168.56.4     192.168.56.101   8080 SYN  [retransmission]

No response at all - nmap retransmits the SYN twice and then times out. The firewall (iptables -j DROP) silently drops the packets. nmap marks the port filtered. Note the time gap: each retry adds ~1 second - this is why filtered ports make scans slow.

Step 5: Verify RST immediately follows SYN-ACK for open ports

In Wireshark, click the RST packet for port 22. In the TCP header detail:

  • Flags: 0x004 = RST only (not RST+ACK)
  • Sequence number equals the ACK number from the SYN-ACK
  • This confirms nmap crafted this RST at the IP layer - the OS didn't generate it (the OS would normally send RST-ACK)

This is the fingerprint of a raw-socket SYN scan: the RST has different flags than what the OS would send organically.

Solution

The three port states produce three distinct packet patterns:

StatePacketsTCP Flags Seen
Open3 (SYN → SYN-ACK → RST)SYN, SYN+ACK, RST
Closed2 (SYN → RST-ACK)SYN, RST+ACK
Filtered1-3 (SYN × retries, no response)SYN only (no reply)

Takeaway: The packet capture makes the theory concrete. When you run nmap in production, you now know exactly what traffic pattern each port state represents - and exactly what a network defender's IDS sees when you scan. Understanding this helps you tune your scan timing, choose between SYN and connect scans, and interpret nmap output accurately.