DEV Community

dpm_bush
dpm_bush

Posted on Originally published at sshflow.com

Checking Open Ports on Linux: Listening vs. Reachable

A service can be listening on a Linux server and still be unreachable from your laptop. The quickest way to diagnose a port is to check both sides of that distinction: what the server has bound locally, and whether a client can connect over the network.

Start with ss

On Ubuntu and most current Linux distributions, use ss to inspect sockets:

ss -tuln
Enter fullscreen mode Exit fullscreen mode

The options mean:

  • -t: TCP sockets
  • -u: UDP sockets
  • -l: listening TCP sockets and unconnected UDP sockets
  • -n: numeric addresses and port numbers

Example output might look like this:

Netid  State   Recv-Q  Send-Q  Local Address:Port  Peer Address:Port
tcp    LISTEN  0       128     127.0.0.1:631       0.0.0.0:*
tcp    LISTEN  0       128     0.0.0.0:22         0.0.0.0:*
udp    UNCONN  0       0       0.0.0.0:68         0.0.0.0:*
Enter fullscreen mode Exit fullscreen mode

Focus on Local Address:Port: it shows the address and port the socket is bound to. For a TCP-only view, use ss -tln; for UDP, use ss -uln.

If you want to understand the options and other useful filters, see this practical reference to the Linux ss command.

Find the service using a port

Add -p to request process information:

sudo ss -tulpn
Enter fullscreen mode Exit fullscreen mode

Root privileges matter for the process details: without sudo, you may see socket and port information but not the process name or PID for sockets owned by other users.

To check one port, use a port filter instead of grep:

sudo ss -tulpn sport = :2222
Enter fullscreen mode Exit fullscreen mode

Replace 2222 with the port you care about. If there’s no output, no matching socket is listening on that port. Filtering directly avoids accidental matches—for example, searching for :22 can also match :2200.

For a quick check that also identifies the owner, lsof is another option:

sudo lsof -i :2222
Enter fullscreen mode Exit fullscreen mode

No output means lsof found no matching socket. If a service should be listening but neither command shows it, check whether the service is running and configured for the port you expect.

Read the bind address before changing a firewall

The address a service binds to determines which interfaces can accept connections:

  • 127.0.0.1 and ::1 are loopback addresses. The service is limited to local connections.
  • 0.0.0.0 listens on all configured IPv4 addresses.
  • :: listens on IPv6 interfaces; whether that also accepts IPv4 can depend on the system and socket configuration.

A wildcard bind does not guarantee that another machine can connect. It only means the service isn’t restricted to loopback. A host firewall, cloud security rule, router, NAT, or routing issue can still block traffic.

This distinction helps avoid a common mistake: opening a firewall rule for a service that only listens on 127.0.0.1. In that situation, the service’s bind configuration is the first thing to investigate. If the listener is on a network interface but connections still fail, then examine the path between client and server.

Test from the client’s network

To check whether a TCP port is reachable, run nc from the machine that needs to connect—not from the server itself:

nc -zv SERVER_IP 22
Enter fullscreen mode Exit fullscreen mode

-z asks nc to check the connection without sending application data, and -v prints the result. A successful connection means the TCP port was reachable from that client at that moment. It does not prove that an SSH login will succeed or that the application is healthy.

A refusal or timeout means the connection did not succeed, but doesn’t identify the exact cause. Check whether a service is listening, then investigate the bind address, firewall, routing, NAT, and any cloud firewall or security-group rules. A firewall may be the blocker; on Ubuntu, the UFW port rules guide explains how to allow traffic and verify the rule.

For an actual SSH connection test, use the SSH client:

ssh -v -p 22 USER@SERVER_IP
Enter fullscreen mode Exit fullscreen mode

Replace the port if the server uses a nonstandard one. The verbose output can help distinguish a network connection problem from a later authentication problem.

UDP needs extra care. Unlike TCP, it has no connection handshake, so a simple nc check is weaker evidence: no response doesn’t necessarily mean a service is listening. When it matters, confirm with a request appropriate to the UDP protocol.

A quick troubleshooting path

  1. No matching entry in ss: Check the service status and its configured port.
  2. Listener is on 127.0.0.1 or ::1: Check the service’s bind or listen-address setting.
  3. Listener uses a wildcard or network address, but remote TCP tests fail: Investigate firewall rules, routing, NAT, cloud rules, and interface or address-family mismatches.
  4. TCP test succeeds but the application fails: The port is reachable; check the application protocol, service configuration, and authentication separately.

ss answers what is listening on the Linux machine. A test from the intended client answers whether that client can reach it. Using both gives you a much clearer diagnosis than treating “open port” as a single state.

I originally published a more detailed version of this guide on the SSHFlow blog.

I'm also building SSHFlow — an SSH client where every server gets its own workspace for terminals, SFTP, code, and databases.

Top comments (0)