5 Ways to Test TCP and UDP Ports in Linux Using nc, nmap, ss, and Bash

Telnet is missing from almost every modern Linux install, but you can still test TCP or UDP ports with nc, nmap, ss, curl, or even a single line of built-in Bash.

You SSH into a fresh server, type telnet 443 out of habit, and the shell tells you the command doesn’t exist. Now you’re about to install a client for a decades-old protocol just to check whether a port is reachable.

But modern Linux systems already have several faster ways to do the same thing, and some of them give you much more information than Telnet ever did.

Tested on Ubuntu 26.04 and RHEL 10, but these commands work on any modern Linux distribution. Anything inside angle brackets, such as <host> or <port>, is a placeholder. Replace it with your own value and remove the angle brackets when you run the command.

TecMint Weekly Newsletter
Get the Learn Linux 7 Days Crash Course free when you join 34,000+ Linux professionals reading every Thursday.
Check your email for a magic link to get started.
Something went wrong. Please try again.

Why Telnet Isn’t on Your Server Anymore

Telnet sends everything in plaintext, including usernames and passwords, which makes it fundamentally unsuitable for secure remote administration. That’s why modern Linux distributions generally don’t install Telnet by default, especially on minimal server installations.

The habit stuck around because Telnet was also a convenient way to open a raw TCP connection and check whether a service was listening on a particular port. That’s the part you actually want, and you don’t need Telnet for it.

Modern Linux systems provide better tools such as nc (Netcat), nmap, curl, and Bash’s built-in TCP support. These can test connectivity without installing an obsolete remote-login protocol, and several of them provide considerably more useful information than Telnet ever did.

1. Test a Remote Port With nc (Netcat)

Netcat (nc) is the closest replacement for the old Telnet trick. It can open a TCP connection, check whether a port is accepting connections, and report the result without requiring an interactive session.

The package name differs between Debian-based and RHEL-based distributions, which can trip you up.

On Ubuntu/Debian:

sudo apt install netcat-openbsd

On RHEL/Rocky Linux:

sudo dnf install nmap-ncat

sudo runs the command with root privileges, which the package manager needs to install software into system directories. Without it, you’ll typically get a permissions error.

Now point nc at a host and port:

nc -zv 192.168.1.50 22

You should see something similar to:

Connection to 192.168.1.50 22 port [tcp/ssh] succeeded!

Here’s what each part of the command does:

  • nc starts Netcat.
  • -z performs a connection check without sending application data.
  • -v enables verbose output so you can see the result.
  • 192.168.1.50 is the target IP address or hostname.
  • 22 is the TCP port you’re testing.

If you see succeeded, the TCP connection was established successfully. That means the host accepted the connection on port 22, which normally indicates that a service is listening there.

Want to Go Beyond Testing Port 22? If you’re working with SSH servers, knowing that port 22 is open is only the first step; the SSH Complete Course takes you from basic SSH connections to key-based authentication, secure file transfers, SSH hardening, tunneling, troubleshooting, and enterprise-level administration.

A closed port looks different:

nc -zv 192.168.1.50 8080
nc: connect to 192.168.1.50 port 8080 (tcp) failed: Connection refused

Connection refused means the target was reachable and responded to the connection attempt, but nothing accepted the connection on that port or a firewall/device actively rejected it.

A timeout is different:

nc: connect to 192.168.1.50 port 8080 (tcp) timed out

A timeout means no response was received within the connection timeout period. A firewall silently dropping packets is one common cause, but routing problems, network ACLs, security groups, or an unreachable host can produce the same symptom.

That distinction is important when troubleshooting:

Result What it usually means
succeeded TCP connection was established
Connection refused Host responded, but the connection was rejected
timed out No response was received
Important: A successful TCP connection only proves that something accepted the connection. It does not prove that the application itself is healthy or responding correctly. For that, you’ll need a protocol-aware test such as curl for HTTP/HTTPS.

When nc Hangs and Never Comes Back

A filtered port may leave nc waiting until the connection attempt eventually times out. Depending on the network and system configuration, that can take quite a while.

Use -w to set your own timeout:

nc -zvw 3 192.168.1.50 3306

Here, -w 3 tells nc to wait up to 3 seconds for the connection attempt before giving up. This is particularly useful when you’re testing multiple hosts or ports. Instead of waiting for the operating system’s default timeout, you get a predictable response time.

Netcat implementations aren’t completely identical. If the command behaves differently or an option isn’t recognized, run nc -h and check which options your installed version supports. In particular, older netcat-traditional versions can handle some options differently from the OpenBSD version commonly installed today.

DigitalOcean offers cloud VPS plans starting at $4/month, with $200 in free credits available to TecMint Pro members. You can use a small VPS to practice these port-testing and troubleshooting commands in a real Linux environment.
If this cleared up the difference between a refused port and a filtered port, share it with a teammate who’s still guessing.

2. Test a Port With Bash and /dev/tcp

Bash has a built-in TCP client mechanism called /dev/tcp, so there’s nothing to install. This makes it especially useful on locked-down servers where you don’t have package-manager access or permission to install additional tools.

Try:

timeout 3 bash -c "echo > /dev/tcp/192.168.1.50/22" && echo "Port open" || echo "Port closed"

If the connection succeeds:

Port open

Here’s what each part does:

  • timeout 3 stops the test after 3 seconds, preventing a filtered or unreachable port from leaving you waiting indefinitely.
  • bash -c runs the command explicitly inside Bash because /dev/tcp is a Bash feature, not a real device or file on disk.
  • echo > /dev/tcp/192.168.1.50/22 makes Bash attempt a TCP connection to 192.168.1.50 on port 22.
  • && echo "Port open" runs when the connection attempt succeeds, and returns exit status 0.
  • || echo "Port closed" runs when the connection attempt fails, including cases such as a refused connection or timeout.

The trick is that Bash recognizes /dev/tcp// as a special redirection target. When you redirect output to it, Bash attempts to establish a TCP connection rather than writing to an actual file. If the TCP connection succeeds, Bash returns a successful exit status, and you get:

Port open
Running Linux commands manually is useful, but scripting is where they become truly powerful. With the Bash Scripting Course on Pro Tecmint, you’ll learn how to combine commands, variables, conditions, loops, functions, and error handling to automate repetitive Linux administration tasks.

Two Limitations to Know

First, this is Bash-specific; it won’t work under plain sh or dash. On Debian and Ubuntu, /bin/sh typically points to dash, not Bash.

Second, /dev/tcp isn’t guaranteed to be available in every Bash build. Some hardened or specially compiled environments may disable network redirections.

So this is an excellent zero-install TCP connectivity check, but nc is generally the better choice when you need more control, diagnostics, or UDP testing.

If you want to go deeper into Linux commands and shell techniques, check out the 100+ Essential Linux Commands course. It covers 100+ essential commands with practical, real-world examples to help you become more confident at the Linux command line.

3. Scan a Range of Ports With nmap

nc is great when you want to check one port at a time. When you’re troubleshooting a service that uses several ports or you want more information about why a port isn’t responding, nmap is the better tool.

Install it with your distribution’s package manager:

On Ubuntu/Debian:

sudo apt install nmap

On RHEL/Rocky Linux:

sudo dnf install nmap

You can give nmap a comma-separated list of ports with -p:

nmap -p 22,80,443,3306 192.168.1.50

A typical result looks like this:

Starting Nmap 7.95 ( https://nmap.org ) at 2026-08-18 10:14 IST
Nmap scan report for 192.168.1.50
Host is up (0.00042s latency).

PORT     STATE    SERVICE
22/tcp   open     ssh
80/tcp   open     http
443/tcp  closed   https
3306/tcp filtered mysql

The STATE column is the important part. Unlike a simple Telnet connection test, nmap distinguishes between several useful states:

  • open – A service is accepting connections on the port.
  • closed – The host is reachable, but nothing is listening on that port.
  • filterednmap cannot determine whether the port is open because packet filtering is preventing it from getting a definitive response.

That last state is especially useful when troubleshooting. If you see:

3306/tcp  filtered  mysql

Don’t immediately restart MySQL. The database might be running perfectly well; a firewall, security group, or network ACL could be blocking traffic before it reaches the server.

To scan a larger range, specify the starting and ending ports:

nmap -p 1-1000 192.168.1.50

This checks ports 1 through 1000 in a single scan, giving you a much broader picture of what the host is exposing.

If the open, closed, and filtered breakdown finally made a stubborn firewall issue make sense, pass this along to a teammate who might be troubleshooting the same problem.

4. See Which Ports Are Open on the Local Machine With ss

Everything so far has tested a port from another machine. When you’re already logged into the server, ss command gives you a direct view of the sockets currently listening on that machine.

The older netstat utility has largely been replaced by ss on modern Linux distributions, so there’s usually no reason to install net-tools just to run netstat.

Run:

sudo ss -tulnp

You might see:

Netid State  Recv-Q Send-Q  Local Address:Port  Peer Address:Port Process
tcp   LISTEN 0      4096        127.0.0.1:3306       0.0.0.0:*     users:(("mariadbd",pid=812,fd=21))
tcp   LISTEN 0      128           0.0.0.0:22         0.0.0.0:*     users:(("sshd",pid=744,fd=3))
udp   UNCONN 0      0             0.0.0.0:53         0.0.0.0:*     users:(("named",pid=690,fd=513))

The options work together:

  • -t shows TCP sockets.
  • -u shows UDP sockets.
  • -l limits the output to listening sockets.
  • -n displays numeric addresses and port numbers instead of resolving service names.
  • -p shows the process using each socket. sudo may be required to see processes owned by other users.

Pay close attention to the Local Address:Port column. It often explains the classic “the service is running, but I can’t connect to it” problem.

For example:

127.0.0.1:3306

Means MariaDB is listening only on the loopback interface. Connections from the same machine can reach it, but remote clients cannot connect directly.

By contrast:

0.0.0.0:22

Means sshd is listening on all IPv4 interfaces, so the service can accept connections arriving through any of them, subject to firewall and other network controls.

Check One Port

You don’t have to read through the entire output when you’re troubleshooting a specific service. Pipe the result through grep command:

sudo ss -tulnp | grep :3306

Here’s what the pipeline does:

  • sudo ss -tulnp lists listening TCP and UDP sockets and their owning processes.
  • | sends that output to the next command.
  • grep :3306 keeps only lines containing :3306.

This makes ss particularly useful for answering a question that nc or nmap cannot answer by themselves: “Is the service actually listening on this machine, and which process owns the port?”.

Want to Master More Linux Commands? If commands like nc, ss, curl, and grep are becoming part of your daily Linux toolkit, take the next step with the 100+ Essential Linux Commands course. It covers the most useful Linux commands with practical examples to help you work faster and troubleshoot systems with confidence.

5. Test a Port With curl

curl is already installed on many Linux systems, including some minimal environments and container images where nc isn’t available. While curl is primarily an application-protocol client, it can also use its Telnet protocol handler to establish a raw TCP connection.

Try:

curl -v telnet://192.168.1.50:22 --connect-timeout 3

A successful connection might look like:

* Trying 192.168.1.50:22...
* Connected to 192.168.1.50 (192.168.1.50) port 22
SSH-2.0-OpenSSH_9.9

The important line is:

* Connected to 192.168.1.50 (192.168.1.50) port 22

That confirms the TCP connection was established. In this example, the SSH banner immediately following it also tells you what service answered.

That’s useful when troubleshooting because you’re not just learning that the port is reachable, you can sometimes see exactly which service is responding. If the banner identifies an unexpected service, you may have discovered that you’re connecting to the wrong host or port.

Check Whether Your curl Supports Telnet

Not every curl build includes the Telnet protocol handler. Check the supported protocols with:

curl --version

Look at the Protocols line. If telnet isn’t listed, you can’t use the telnet:// form with that particular build.

For HTTP or HTTPS services, you can test the application directly instead:

curl -sv --connect-timeout 3 http://192.168.1.50:80

This has an important advantage over a generic TCP test: curl can tell you whether the HTTP service itself responds, rather than merely confirming that something accepted the TCP connection.

Note: Use nc for a quick TCP connection check, nmap when you need to investigate multiple ports, ss to inspect local listeners, and curl when you’re testing an HTTP/HTTPS service or need to inspect an application-level response.
If this saved you from installing anything on a stripped-down container, share it with someone who’s debugging one right now.

Testing UDP Ports

UDP works differently from TCP because there is no three-way handshake. Nothing has to establish a connection before data can be sent, so simply getting no response doesn’t tell you whether the port is open.

Both nc and nmap can test UDP, but you need to interpret the results differently from TCP.

With nmap, use -sU for a UDP scan:

sudo nmap -sU -p 53 192.168.1.50

You might see:

PORT   STATE         SERVICE
53/udp open|filtered domain

The open|filtered result is nmap being honest about what it can determine from the outside. The target didn’t send back a response that lets nmap distinguish between these two possibilities:

  • A service is listening on UDP port 53 but didn’t respond to the probe.
  • A firewall or other filter silently dropped the packet.

With TCP, the handshake gives you much clearer signals. With UDP, silence can mean several different things.

The Reliable Check: Look at the Server

If you have access to the target machine, check its sockets directly:

sudo ss -ulnp

Look for the UDP port in the output. For example:

udp   UNCONN  0  0  0.0.0.0:53  0.0.0.0:*  users:(("named",pid=690,fd=513))

That tells you a process is actually bound to UDP port 53 on the server. So when troubleshooting UDP, remember:

  • From the outside: nmap -sU can tell you open|filtered, but not always which one.
  • On the server: ss -ulnp tells you whether a local process is actually bound to the UDP port.

That distinction can save you from chasing a firewall problem when the service isn’t even listening; or blaming the service when the firewall is the real issue.

The Port Answers Locally but Not Remotely

Here’s a common troubleshooting situation:
ss shows that a service is listening, but a remote nc connection still times out. If the service is bound to 0.0.0.0 or the appropriate network interface, the firewall is one of the next things to check. Don’t guess; look at the active rules.

On Ubuntu/Debian:

sudo ufw status verbose

On RHEL/Rocky Linux:

sudo firewall-cmd --list-all

Look at the ports, services, and other relevant rules in the output, if the port you’re testing isn’t allowed by the firewall, the firewall may be dropping the incoming connection before it reaches the application. From a remote machine, that often appears as a timeout or an nmap result such as filtered.

For example, the troubleshooting chain might look like this:

ss        → Service is listening
nc        → Remote connection times out
nmap      → Port is filtered
firewall  → Port isn't allowed

That’s a much better diagnosis than repeatedly restarting the service.

Remember: ss tells you whether something is listening locally. It does not tell you whether remote clients are allowed to reach it. You need to check the firewall and, depending on the environment, cloud security groups, network ACLs, or other filtering rules too.
Knowing how to reach an SSH port is one thing; securing what happens after that connection is another. The SSH Complete Course on Pro Tecmint goes deeper into key-based authentication, SSH hardening, firewall protection, tunneling, MFA, and troubleshooting—taking you from basic SSH access to secure, production-ready administration.
If a firewall rule turned out to be the culprit on your box too, share this with the person who wrote that rule.
Conclusion

You now have five practical ways to test ports without Telnet, and each tool answers a slightly different question.

nc and Bash /dev/tcp give you a quick TCP connectivity check. nmap goes further by distinguishing between open, closed, and filtered ports.

ss shows what’s actually listening on the local machine and which interface it’s bound to, while curl lets you test application-level services such as HTTP and inspect responses or service banners when available.

The most useful part is knowing which tool to reach for when troubleshooting:

  • nc – Is this TCP port reachable?
  • Bash /dev/tcp – Can I test TCP without installing anything?
  • nmap – Is the port open, closed, or filtered?
  • ss – Is something actually listening locally, and where?
  • curl – Does the application itself respond?

Try these commands on a server you already manage. Start with sudo ss -tulnp then look closely at the Local Address column. If a service you expected to be reachable remotely is bound to 127.0.0.1, you’ve probably found the problem: the service is running, but it’s listening only for local connections.

That’s one of those small Linux details that can save you a lot of unnecessary troubleshooting.

Which tool do you reach for first when a port isn’t responding? And has ss ever revealed a service listening on loopback when you expected it to be public? Let us know in the comments.

If this article helped, with someone on your team.

TecMint Weekly Newsletter
Get the Learn Linux 7 Days Crash Course free when you join 34,000+ Linux professionals reading every Thursday.
Check your email for a magic link to get started.
Something went wrong. Please try again.
TecMint has been free for 14 years. Help keep it that way.
Google AI Overviews and tools like ChatGPT have cut into search traffic for independent tech sites like TecMint. Running this site costs over $2,000 every month for hosting, infrastructure, and paying authors to keep the content accurate and tested.

There are two ways to help:
Ravi Saive
I'm Ravi Saive, an award-winning entrepreneur and founder of several successful 5-figure online businesses, including TecMint.com, GeeksMint.com, UbuntuMint.com, and the premium learning hub Pro.Tecmint.com.

Each tutorial at TecMint is created by a team of experienced Linux system administrators so that it meets our high-quality standards.

Got Something to Say? Join the Discussion...

Thank you for taking the time to share your thoughts with us. We appreciate your decision to leave a comment and value your contribution to the discussion. It's important to note that we moderate all comments in accordance with our comment policy to ensure a respectful and constructive conversation.

Rest assured that your email address will remain private and will not be published or shared with anyone. We prioritize the privacy and security of our users.

Free Course
Get a free Linux course before you go.
Subscribe to TecMint Weekly and get the Learn Linux 7 Days Crash Course free. Read by 34,000+ Linux professionals every Thursday.
Something went wrong. Please try again.
Check your email for a magic link to get started.