Most people who know about network scanners should have heard the name Nmap. If we were to select the most excellent scanning tool, or the top hacker weapon, Nmap would definitely be on the list.
Nmap is a free, open-source scanning tool with excellent network asset scanning capabilities. In addition to common port scanning, Nmap also supports operating system detection and service identification. Through its built-in probes and fingerprint library, it can accurately identify the fingerprints of most operating systems and application services.
In addition, Nmap supports highly extensible scripting capabilities. It has a large number of built-in community-contributed scripts, and writing plugins via Lua is extremely convenient. Therefore, many scanners integrate Nmap’s scanning functions.
Below, I will share some pitfalls and points to note when using Nmap for scanning, based on actual work experience:
1. The Issue with Default Ping Scanning
Nmap performs a Ping scan by default to discover active hosts. However, if the target host disables Ping (ICMP) response, subsequent port scanning will not be performed.
This is a very common problem. Many people will add the -Pn parameter when using Nmap to disable Ping detection and force a port scan on the target.
However, when integrating Nmap into scanners or automation tools, sometimes we must rely on Ping for host discovery. This creates a contradiction requiring flexible handling based on the specific scenario.
2. Handling tcp-wrapper
If you see “tcp-wrapper” service in Nmap output results, you likely encountered this situation:
After Nmap completes the TCP three-way handshake with the target host, if the target host immediately sends a FIN packet to actively disconnect, Nmap will consider the host protected by tcp-wrapper and terminate the scan.
The source code for this logic (nmap-v7.93) is located in the service_scan.cc file:
static void servicescan_read_handler(nsock_pool nsp, nsock_event nse, void *mydata) {
// ... ...
if (svc->tcpwrap_possible && probe->isNullProbe() && readstrlen == 0 && svc->probe_timemsused(probe) < probe->tcpwrappedms) {
// TODO: Perhaps should do further verification before making this assumption
end_svcprobe(nsp, PROBESTATE_FINISHED_TCPWRAPPED, SG, svc, nsi);
} else {
// Perhaps this service didn't like the particular probe text.
// We'll try the next one
startNextProbe(nsp, nsi, SG, svc, true);
}
// ... ...
}
As you can see, there isn’t much detailed handling here.
3. Encountering Firewalls with “All Ports Open”
When using Nmap for scanning, we often encounter a firewall policy where all ports return an open status, but further service identification gets stuck indefinitely.
Below is a code example using Python+Scapy to simulate this situation:
from scapy.all import *
import os
os.system("iptables -A OUTPUT -p tcp -o enp1s0 --sport 50000:65535 --tcp-flags RST RST -j DROP")
def packet(pkt):
if pkt[TCP].flags == 2:
print('SYN packet detected port : ' + str(pkt[TCP].sport) + ' from IP Src : ' + pkt[IP].src)
send(IP(dst=pkt[IP].src, src=pkt[IP].dst)/TCP(dport=pkt[TCP].sport, sport=pkt[TCP].dport,ack=pkt[TCP].seq + 1, flags='SA'))
sniff(iface="enp1s0", prn=packet, filter="tcp[0xd]&18=2",count=100)
os.system("iptables -D OUTPUT -p tcp -o enp1s0 --sport 1:65535 --tcp-flags RST RST -j DROP")
When encountering such cases, we need to identify and mark it as a firewall, then handle it specially in subsequent scanning logic to avoid long hangs. In short, Nmap is powerful but not perfect. Combining it with the actual network environment to flexibly adjust parameters and handle exceptions is the only way to complete asset scanning work more efficiently.