An open network port isn’t automatically a security problem.
That’s an important distinction that often gets lost when people talk about port scanning.
A server might legitimately have TCP 443 open because it hosts a website. An application server might need 1433 for SQL Server. A management server might legitimately expose SSH to a restricted administration network.
The question isn’t simply “What ports are open?”
The useful question is:
“What ports are open now, were they supposed to be open, and what has changed since the last scan?”
That’s where Nmap becomes much more useful than a simple troubleshooting tool.
You can use Nmap to build a known-good picture of your environment, save the results, scan it again later, and compare the two. A new listening service, a closed service or a change in the detected application can then become something worth investigating.
This article focuses on that workflow rather than reproducing the basic Nmap command reference.
Before you scan: make sure you are authorised
Only scan systems and networks you own or have explicit permission to test.
Nmap generates network traffic specifically designed to discover hosts, ports and services. Some scans and NSE scripts go considerably further than a normal connection attempt.
That matters particularly when using options such as -A or vulnerability scripts.
For your own network, that’s useful security testing. Against somebody else’s infrastructure, it can be unwanted or unlawful activity.
For an organisation, I’d treat an Nmap scan as an approved security or operational activity, with the source system, target range and scan type documented beforehand.
What are you actually trying to find?
Before opening a terminal, define what you’re looking for.
For example:
- Which hosts are currently reachable?
- Which TCP ports are exposed?
- Are those ports expected?
- Is the service running on the host itself?
- Is it reachable only internally, or from the internet?
- Has anything changed since the last scan?
- Does the firewall exposure match the service’s intended exposure?
That last point is particularly important.
A scan from inside your network and a scan from outside your firewall are not equivalent.
If a server has TCP 3389 open internally but the firewall blocks it from the internet, an internal scan should show the service while an external scan may show the port as filtered.
That difference is useful information.
Scan from the right location
Where you run Nmap from changes what you see.
Internal scan
An internal scan can tell you what services are exposed to systems on the same network or routed internal networks.
For example:
nmap 192.168.1.10
This is useful for identifying services that should perhaps be restricted to a smaller management or application network.
External scan
An external scan tells you what an internet-based attacker can see from outside your perimeter.
If your organisation has a public IP range, scanning that range from inside the network doesn’t necessarily tell you what is actually exposed to the internet.
Firewalls, NAT, reverse proxies, load balancers and security appliances can all change the result.
That means internal and external scans can both be correct while showing completely different results.
If you’re testing an internet-facing service, scan it from an appropriate external vantage point as well.
Start with host discovery
If you’re assessing a subnet rather than a single known server, you don’t necessarily want to perform a full port scan against every address immediately.
Nmap’s ping scan can identify hosts that respond to its host-discovery probes:
nmap -sn 192.168.1.0/24
This is a useful first pass when you’re trying to establish which systems are present.
However, don’t assume that a host that doesn’t respond to these probes is necessarily offline.
Firewalls commonly block ICMP or other discovery traffic.
That’s where -Pn can be useful:
nmap -Pn 192.168.1.10
-Pn skips host discovery and tells Nmap to scan the target without first checking whether it appears to be online.
That’s useful when you already know a host exists but normal discovery probes are being filtered. The distinction matters when scanning a range: with -Pn, Nmap attempts to scan every address rather than first eliminating addresses that don’t respond to host discovery, which can make a subnet scan considerably slower.
Scan the ports you actually care about
A basic scan is a reasonable starting point:
nmap 192.168.1.10
You can specify individual ports:
nmap -p 22,80,443 192.168.1.10
Or a range:
nmap -p 1-1000 192.168.1.10
If you’re establishing a proper baseline, however, limiting yourself to the most common ports can miss exactly the sort of change you’re trying to detect.
For a TCP baseline of a host, you may want to scan all TCP ports:
nmap -p- 192.168.1.10
That’s 65,535 TCP ports.
One important point: Nmap’s normal port scans, including -p-, are TCP scans. UDP is a separate scan type:
nmap -sU 192.168.1.10
UDP scanning can be considerably slower and determining whether a UDP port is actually open can be less straightforward than TCP. If UDP services matter in your environment, treat UDP as a separate part of the assessment rather than assuming a clean TCP scan covers everything.
Whether you scan all TCP ports across an entire subnet depends on the size and sensitivity of the environment. A full-port scan against a single server is very different from launching one against thousands of devices.
Also keep scan time in mind. A -p- -sV scan against one host can take several minutes depending on the target and network conditions. Against a /24, the same approach can take hours.
Understand what open, closed and filtered actually mean
Nmap’s port states are more useful when you understand what they’re telling you, and Nmap’s own documentation on port states is worth reading properly.
Open
An open port means Nmap has determined that an application is listening and accepting the relevant probes.
For example:
443/tcp open https
That doesn’t automatically mean there’s a vulnerability.
The next question is:
Should this service be accessible from where I am scanning?
Closed
A closed port is reachable, but there isn’t currently an application listening on it.
For example:
23/tcp closed telnet
That’s very different from an open Telnet service.
Filtered
A filtered port means Nmap cannot determine whether the port is open because filtering is preventing it from getting a useful response.
For example:
3389/tcp filtered ms-wbt-server
This can be the result of a firewall or another filtering device.
And this is where scanning from different locations becomes valuable.
A port that is:
Internal scan: open
External scan: filtered
may represent exactly the security boundary you intended to build.
The important point is that filtered doesn’t mean closed. It means Nmap couldn’t determine the state because something is filtering the traffic.
Identify the service
Once you’ve found an open port, you usually want to know what is actually running.
Nmap’s service detection can help:
nmap -sV 192.168.1.10
You might get something similar to:
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 9.x
443/tcp open https Microsoft IIS
Don’t treat the detected version as absolute truth.
Service detection is based on network responses and Nmap’s probe database. Applications can be configured to hide or alter their version information, and proxies can make the result more complicated.
It’s an excellent clue, but the host itself should be the authority when you’re validating what is actually installed and listening.
Reconcile Nmap with the host
This is one of the most useful parts of the process.
If Nmap says a Linux server has TCP 8080 open, check the server.
On Linux, for a TCP-only comparison:
sudo ss -tlpn
The -u option is often included in examples as ss -tulpn, but that also displays UDP listeners. If you’re comparing the output against a TCP-only Nmap scan, ss -tlpn keeps the comparison focused. If UDP matters, check it separately.
On Windows:
Get-NetTCPConnection -State Listen |
Select-Object LocalAddress, LocalPort,
@{Name='Process';Expression={(Get-Process -Id $_.OwningProcess).ProcessName}} |
Sort-Object LocalPort
Or:
netstat -ano
The PowerShell version is useful because it connects the listening port to the process that owns it.
You can also use the PID from netstat -ano to identify the corresponding process.
The comparison gives you two different perspectives:
Nmap tells you what is reachable over the network.
The operating system tells you what is actually listening locally.
If the server says nothing is listening on TCP 8080 but Nmap sees it as open, investigate the network path. There could be a NAT rule, proxy, load balancer or another device answering on behalf of the server.
Conversely, a service can be listening locally without being reachable from the network because a host firewall or network firewall is blocking it.
That distinction is much more useful than simply maintaining a list of “dangerous ports”.
Build a baseline with Nmap
This is where I think Nmap becomes genuinely useful as an operational security control.
Rather than running:
nmap 192.168.1.10
and looking at the results once, save the scan.
Nmap’s -oA option writes the results in several useful formats using the same base filename:
nmap -p- -sV -oA baseline-server01 192.168.1.10
You’ll get files including:
baseline-server01.nmap
baseline-server01.xml
baseline-server01.gnmap
The XML file is particularly useful because Nmap and associated tools can process it later.
I’d keep the baseline somewhere that is controlled and dated rather than continually overwriting the same file.
For example:
Nmap-Baselines/
server01/
2026-09-21/
2026-10-21/
2026-11-21/
The exact storage approach isn’t important.
What matters is that you have a known point of comparison.
Use Ndiff to find changes
Nmap includes a companion utility called Ndiff.
This is the part that turns a port scan into something closer to continuous monitoring.
Suppose you created your baseline:
nmap -p- -sV -oA server01-baseline 192.168.1.10
Later, you run the same scan again:
nmap -p- -sV -oA server01-current 192.168.1.10
You can compare the XML files with:
ndiff server01-baseline.xml server01-current.xml
Instead of manually looking through two large scan results, Ndiff highlights changes.
For example, you might discover that TCP 8080 wasn’t present in the baseline but is now open.
That’s the event you care about.
It could be completely legitimate:
- A new application was deployed.
- A developer enabled a service.
- A server role changed.
- A migration is underway.
Or it could be something that needs investigation:
- An administrator installed software outside the change process.
- A firewall rule was changed.
- A service was accidentally exposed.
- Malware or an unauthorised application opened a listener.
Nmap hasn’t told you which explanation is correct.
It has told you something changed.
That’s a much more actionable security signal.
Don’t treat every change as a vulnerability
A new open port isn’t automatically a security incident.
For example, imagine your baseline contains:
443/tcp open https
A month later:
443/tcp open https
8443/tcp open https-alt
The new port deserves investigation, but the correct response isn’t necessarily “close 8443”.
First determine:
- What process is listening?
- Which application owns it?
- Who requested the change?
- What interface is it bound to?
- Is it reachable internally?
- Is it reachable externally?
- Does the firewall permit access intentionally?
- Is the service patched and supported?
Only then can you decide whether the port should remain open.
This is the difference between port scanning and port management.
If the port shouldn’t be open, fix the actual cause
Once you’ve established that a service shouldn’t be exposed, there are usually several possible remediation points.
You might:
- stop or uninstall the unnecessary service
- bind the service only to a required interface
- restrict access with the host firewall
- restrict access through the network firewall
- move the service behind a VPN or private network
- remove an unnecessary NAT or port-forwarding rule
- restrict access to specific management networks
Don’t automatically solve every problem by blocking the port at the firewall.
If the service itself shouldn’t be running, stopping it is generally a better fix.
Be careful when changing a firewall remotely
This is particularly important for SSH, RDP and other remote administration services.
A firewall rule can work exactly as designed and still lock you out.
For example, this kind of Linux rule:
iptables -A INPUT -p tcp --dport 22 -s 192.168.1.100 -j ACCEPT
iptables -A INPUT -p tcp --dport 22 -j DROP
allows SSH from 192.168.1.100 and drops subsequent SSH traffic.
But -A means append.
Existing rules earlier in the chain may already allow the traffic, and the final result depends on the complete firewall rule set rather than these two commands in isolation.
More importantly, if you’re currently connected over SSH from an address other than 192.168.1.100, you could disconnect yourself immediately.
Before making remote firewall changes, have an out-of-band console or another recovery path available.
On systems using iptables, tools such as iptables-apply can also be useful because they provide a mechanism for applying a ruleset and reverting it if connectivity is lost.
Also check which firewall framework the operating system actually uses. Modern Linux distributions may use nftables, firewalld or another management layer rather than having you manually maintain iptables rules.
The principle is more important than the specific command:
Never make a remote firewall change without a tested way back in.
Verify the fix with another scan
After remediation, don’t assume the problem is fixed because the configuration changed.
Scan again.
For example:
nmap -p 22,80,443,8080 192.168.1.10
If TCP 8080 was the unexpected service, you want to see the state change you expected.
And if the issue involved internet exposure, test from the external side of the firewall as well.
This is another reason I prefer the baseline approach.
You can establish:
Before
8080/tcp open
Change
Service disabled / firewall rule changed
After
8080/tcp closed
or, depending on the network design:
8080/tcp filtered
The important thing is that the result now matches the intended exposure.
What about Nmap’s aggressive scan?
Nmap has an -A option that enables several advanced detection capabilities:
nmap -A 192.168.1.10
It can perform OS detection, version detection, script scanning and traceroute.
It’s useful during controlled troubleshooting and assessment work, but I wouldn’t make it the default command for every production scan.
It generates considerably more traffic than a simple port scan and can trigger security controls or interact badly with poorly implemented services.
OS detection also isn’t magic.
For example:
nmap -O 192.168.1.10
can require elevated privileges and depends on being able to send and receive the probes required for fingerprinting. Firewalls and filtering can cause detection to fail or produce an uncertain result.
Treat the output as evidence to investigate, not an infallible identification mechanism.
Be cautious with vulnerability scripts
Nmap’s scripting engine is powerful, but this command shouldn’t be treated as a harmless routine scan:
nmap --script vuln 192.168.1.10
The vuln category contains scripts designed to identify vulnerabilities and weaknesses. Some NSE scripts are considerably more intrusive than basic service discovery.
I would run vulnerability-oriented scripts only against systems you’re authorised to test and only when the impact is understood.
For production systems, particularly critical infrastructure, consider the service owner, maintenance window and monitoring requirements before running intrusive checks.
Also remember that Nmap’s vulnerability detection isn’t a replacement for a dedicated vulnerability management platform. Script coverage and vulnerability data have their own limitations and update cycles.
Use the results as an additional source of information rather than treating “no vulnerability reported” as “the system is secure”.
Make the baseline repeatable
Once you have established a known-good baseline, the next step is automation.
A simple scheduled process can:
- Run the same Nmap scan.
- Save the XML result with a timestamp.
- Compare it with the previous approved baseline.
- Produce an Ndiff report.
- Alert when ports or detected services change.
- Send the change to whoever owns the system for investigation.
The important part is not necessarily the scheduling mechanism.
It’s the approved baseline.
If every scan becomes the new baseline automatically, you can end up normalising an unwanted change before anyone investigates it.
A better process is:
Known-good baseline → new scan → identify differences → investigate → approve or remediate → update baseline
That creates a useful change-detection loop.
Don’t forget the firewall perspective
One of the most useful things you can do with this approach is scan the same system from different network locations.
For example:
| Scan location | Result | What it tells you |
|---|---|---|
| Same server/network | Open | Service is reachable internally |
| Management network | Open | Management access is available |
| User VLAN | Filtered | Network segmentation may be working |
| Internet | Filtered | External firewall may be blocking access |
The exact results will depend on your firewall and network architecture, but differences between vantage points are often more informative than a single scan.
If a management service is supposed to be available only from the IT administration network, the fact that it is also reachable from a user VLAN is a finding even though the port itself isn’t “unexpected”.
The practical workflow
If I were introducing Nmap into an environment, I’d keep the process fairly simple.
First, identify the systems you’re responsible for.
Don’t start by scanning everything blindly.
Second, decide where the scan should originate.
Internal, management, segmented network and external scans answer different questions.
Third, create a baseline.
Use a consistent scan configuration and save the XML output.
Fourth, reconcile unexpected ports with the host.
Check ss, Get-NetTCPConnection, netstat or the relevant platform tools.
Fifth, investigate differences rather than automatically closing them.
A new port might be an approved application deployment.
Sixth, remediate genuine exposure.
Remove unnecessary services, restrict access or correct the firewall configuration.
Finally, scan again.
The final scan is your evidence that the change had the intended effect.
The real value of Nmap
Nmap is often introduced as a command-line tool for discovering open ports.
That’s useful, but it’s only the beginning.
The more interesting security control is knowing what your network normally looks like and being able to identify when that changes.
A server that has had TCP 443 open for six months isn’t particularly interesting just because the port is open.
A server that suddenly starts listening on TCP 8080 at 2am is different.
That doesn’t mean something malicious happened. It means something changed, and you now have a reason to ask why.
That’s where a simple Nmap scan becomes part of a much more useful security process:
baseline → monitor → investigate → remediate → verify
You don’t need to treat every open port as a vulnerability.
You need to know which ones are expected, which ones aren’t, and what changed.

From my early days on the helpdesk through roles as a service desk manager, systems administrator, and network engineer, I’ve spent more than 25 years in the IT world. As I transition into cyber security, my goal is to make tech a little less confusing by sharing what I’ve learned and helping others wherever I can.

