Check Open Ports in Linux: nmap, netcat, and Bash

Whether you are troubleshooting network connectivity issues or configuring a firewall, one of the first things to check is what ports are actually open on your system.
This guide covers the command-line tools for checking open ports on a Linux system: nmap, netcat, telnet, and the Bash /dev/tcp pseudo-device. It also shows how to distinguish a closed port from traffic filtered by a firewall or another network device.
What Is an Open Port
A listening port is a network port that an application listens on. You can get a list of the listening ports
on your system by querying the network stack with commands such as ss
or netstat
. A listening port can still appear filtered to a remote scanner when a firewall or another network device blocks the probes.
An open port is a network port that accepts incoming packets from remote locations. When nothing listens on a port, or a firewall rejects the request outright, the client is refused immediately, which is what produces errors such as SSH connection refused .
For example, if you are running a web server that listens on ports 80 and 443 and those ports are open on your firewall, anyone (except blocked IPs) will be able to access websites hosted on your web server using their browser. In this case, both 80 and 443 are open ports.
Open ports may pose a security risk because each one can be used by attackers to exploit a vulnerability. You should expose only the ports needed for your application and close all others.
Check Open Ports with nmap
Nmap is a powerful network scanning tool that can scan single hosts and large networks. It is mainly used for security audits and penetration testing.
If available, nmap
is usually the most complete tool for port scanning. Beyond basic port discovery, it can also perform service detection, version probing, and host discovery.
The following command scans for all TCP ports on a remote host:
nmap -sT -p- 10.10.8.8The -sT flag tells nmap to scan for TCP connections and -p- scans all 65535 ports. Without -p-, nmap scans only the 1000 most common ports.
Starting Nmap 7.95 ( https://nmap.org ) at 2026-03-01 21:00 CET
Nmap scan report for 10.10.8.8
Host is up (0.0012s latency).
Not shown: 65533 closed tcp ports (conn-refused)
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
Nmap done: 1 IP address (1 host up) scanned in 0.41 secondsThe output above shows that only ports 22 and 80 are open on the target system.
To scan for UDP ports, use -sU instead of -sT:
sudo nmap -sU -p- 10.10.8.8Scanning all 65535 ports takes a while, and most of the time you only care about one of them. Pass the port number to -p to check a single port:
nmap -p 80 10.10.8.8Starting Nmap 7.95 ( https://nmap.org ) at 2026-09-01 14:12 CEST
Nmap scan report for 10.10.8.8
Host is up (0.0011s latency).
PORT STATE SERVICE
80/tcp open http
Nmap done: 1 IP address (1 host up) scanned in 0.06 secondsThe STATE column is the part to read. open means a service accepted the connection, and closed means the host answered but nothing is listening on that port. A filtered result means a firewall, router rule, or another network obstacle prevented nmap from determining whether the port is open or closed.
For more information, visit the nmap man page to read about all available options.
Check Open Ports with netcat
netcat
(or nc) is a command-line tool that can read and write data across network connections using the TCP or UDP protocols.
With netcat you can scan a single port or a port range. To scan for open TCP ports on a remote machine with IP address 10.10.8.8 in the range 20-80, run:
nc -z -v 10.10.8.8 20-80The -z option tells nc to scan only for open ports without sending any data, and -v enables verbose output.
The output will look something like this:
nc: connect to 10.10.8.8 port 20 (tcp) failed: Connection refused
nc: connect to 10.10.8.8 port 21 (tcp) failed: Connection refused
Connection to 10.10.8.8 22 port [tcp/ssh] succeeded!
...
Connection to 10.10.8.8 80 port [tcp/http] succeeded!To print only the open ports, filter the results with the grep command
:
nc -z -v 10.10.8.8 20-80 2>&1 | grep succeededConnection to 10.10.8.8 22 port [tcp/ssh] succeeded!
Connection to 10.10.8.8 80 port [tcp/http] succeeded!To scan for UDP ports, pass the -u flag:
nc -z -v -u 10.10.8.8 20-80 2>&1 | grep succeededBecause UDP has no connection handshake, a probe that returns no error does not prove that a service is listening. Treat this as a preliminary check and confirm the result with a protocol-specific request or an nmap -sU -sV scan.
2>&1
construct redirects standard error to standard output, which is necessary here because nc writes connection status to stderr.Check a Single Port on a Remote Server with telnet
When you need to test a single TCP port on a remote server, telnet can open the connection without scan options. Provide the host and port as arguments:
telnet 10.10.8.8 22If the port is open, telnet completes the connection and hands you the raw session, which is why you can see the SSH banner in the output below:
Trying 10.10.8.8...
Connected to 10.10.8.8.
Escape character is '^]'.
SSH-2.0-OpenSSH_9.6p1 Ubuntu-3ubuntu13.5Press Ctrl+] to get back to the telnet> prompt, then type quit to close the session.
When nothing listens on the port, or the firewall rejects the packet outright, the attempt fails right away:
Trying 10.10.8.8...
telnet: Unable to connect to remote host: Connection refusedIf telnet remains on the Trying line until it times out, no TCP connection was established. A firewall that drops packets can cause this behavior, but so can a routing problem, an unavailable host, packet loss, or an upstream network filter. Check host reachability and the network path before deciding where the connection was blocked.
Two limits are worth knowing before you rely on this method. telnet speaks only TCP, so it cannot test UDP ports, and it is no longer installed by default on most current distributions. Install it with sudo apt install telnet on Ubuntu, Debian, and Derivatives, or sudo dnf install telnet on Fedora, RHEL, and Derivatives.
Check Open Ports with Bash /dev/tcp
Another way to check whether a specific TCP port is open is to use the Bash /dev/tcp/HOST/PORT pseudo-device.
When you open this pseudo-device, Bash attempts a TCP connection to the specified host and port. If the connection succeeds, the remote host accepted the connection.
Bash also supports /dev/udp/HOST/PORT, but opening a UDP socket alone does not show whether a service is listening. UDP has no connection handshake, so use a protocol-specific request or a UDP-aware scanner when you need to test a UDP service.
The following if..else
statement checks whether port 443 on kernel.org is open:
if timeout 5 bash -c '</dev/tcp/kernel.org/443 &>/dev/null'
then
echo "Port is open"
else
echo "Port is closed"
fiPort is openThe default connection timeout for pseudo-devices is very long, so the timeout
command is used to abort the attempt after 5 seconds. If the connection to kernel.org port 443 succeeds, the test returns true.
To check a range of ports, use a for loop :
for PORT in {20..80}; do
timeout 1 bash -c "</dev/tcp/10.10.8.8/$PORT &>/dev/null" && echo "port $PORT is open"
doneport 22 is open
port 80 is openCheck Which Ports the Firewall Allows
Scanning tells you what a client can reach, but it does not identify the device that blocked a probe. When a port comes back as filtered, check the firewall on the target host as well as any cloud firewall, router, or other filter along the network path.
On Ubuntu and other systems configured with ufw
, display its status and rules with:
sudo ufw statusWhen firewalld is active, find the zone attached to the incoming interface before listing its rules:
sudo firewall-cmd --get-active-zones
sudo firewall-cmd --zone=public --list-allReplace public with the active zone shown on your system. Read both the services and ports lines because a named service such as ssh can allow a port without listing its number under ports.
If nftables manages the firewall directly, inspect the complete ruleset:
sudo nft list rulesetUse iptables
only when maintaining a legacy iptables ruleset. The iptables command covers IPv4, while IPv6 rules require ip6tables.
Firewall rules alone do not prove that a port is reachable because the service must also be listening on the correct address. When you need to add a rule, opening a port in the firewall covers ufw, firewalld, nftables, and legacy iptables, along with local and remote verification.
Troubleshooting
nmap: command not foundnmap is not installed by default on all distributions. Install it with sudo apt install nmap on Ubuntu, Debian, and Derivatives, or sudo dnf install nmap on Fedora, RHEL, and Derivatives.
nc is not available or behaves differently
Some distributions ship ncat (from the nmap project) instead of the traditional netcat. The flags are similar but not identical. On systems without either, use the Bash /dev/tcp method instead.
nmap shows a port as filtered instead of open or closed
A filtered state means packet filtering or another network obstacle prevents nmap from determining whether the port is open or closed. The service may be listening, but its host firewall, a router, or an upstream filter can block the probes. Check each filtering layer along the network path.
UDP scan results are unreliable
UDP scanning is inherently less reliable than TCP scanning because UDP has no handshake. nmap marks ports as open|filtered when there is no response. Use -sV to attempt service detection and get a more definitive result.
nc -z shows a port as open but the service is unreachable
The port is listening but the application may require TLS, authentication, or a specific protocol. Use nmap -sV to probe the service version and confirm what is running.
Quick Reference
For a printable quick reference, see the nmap cheatsheet and the netcat cheatsheet .
| Command | Description |
|---|---|
nmap -sT -p- HOST | Scan all TCP ports on a host |
sudo nmap -sU -p- HOST | Scan all UDP ports on a host |
nmap -p PORT HOST | Check the state of a single TCP port |
nc -z -v HOST PORT_RANGE | Scan a TCP port range with netcat |
nc -z -v -u HOST PORT_RANGE | Probe a UDP port range with netcat |
nc -z -v HOST PORT_RANGE 2>&1 | grep succeeded | Show only open ports |
telnet HOST PORT | Test a single TCP port on a remote server |
timeout 5 bash -c '</dev/tcp/HOST/PORT' | Test a single TCP port with Bash |
sudo ufw status | Show ufw status and rules |
sudo firewall-cmd --get-active-zones | Find the active firewalld zones |
sudo firewall-cmd --zone=ZONE --list-all | List rules for a firewalld zone |
sudo nft list ruleset | Inspect the complete nftables ruleset |
FAQ
What is the difference between a listening port and an open port?
A listening port is one that a local application has bound to and is waiting for connections. An open port is a listening port that is reachable from the scanner. A listening port can appear filtered externally when a firewall or another network device prevents the scanner from determining its state. A closed result means the host was reachable but no application accepted the connection on that port.
How do I check if a specific port is open on my own machine?
Use ss -tlnp | grep PORT or netstat -tlnp | grep PORT to check listening ports locally. See How to Check Listening Ports in Linux
for more detail.
Can I scan ports without installing nmap?
Yes. Use nc -z -v HOST PORT_RANGE for a range scan, telnet HOST PORT for one port on a remote server, or the Bash /dev/tcp/HOST/PORT pseudo-device. The Bash example avoids a dedicated scanner when both Bash and the timeout command are already installed.
Do I need root to scan ports?
TCP connect scans (nmap -sT) and nc work as a regular user. UDP scans (nmap -sU) and SYN scans (nmap -sS) require root or sudo because they send raw packets.
Conclusion
Use nmap for thorough port scanning, netcat for quick range checks, telnet for a single TCP port, and the Bash /dev/tcp pseudo-device when Bash and timeout are already available. When a port scans as filtered, check the host firewall and the rest of the network path before you assume the service is down, and use tcpdump
when you need to watch the packets themselves.
Linuxize Weekly Newsletter
A quick weekly roundup of new tutorials, news, and tips.
About the authors

Dejan Panovski
Dejan Panovski is the founder of Linuxize, an RHCSA-certified Linux system administrator and DevOps engineer based in Skopje, Macedonia. Author of 1000+ Linux tutorials with 20+ years of experience turning complex Linux tasks into clear, reliable guides.
View author page