When ss Shows No Open TCP Ports Even Though Services Are Running

Why ss Might Show No Open TCP Ports Even When Services Are Running

I’ve seen this happen on fresh installs, on servers that have just rebooted, and even on production machines that have been up for months. The symptom is simple: ss -tuln prints nothing, but systemctl status nginx (or whatever daemon you’re checking) says active (running). The mismatch usually boils down to one of three things:

  1. The service is listening on a non‑TCP socket
  2. The service is bound to a Unix domain socket or a local‑only address
  3. The socket is managed by a socket‑activated unit that isn’t yet in use

Below is a quick checklist that will help you zero in on the culprit, plus a few hardening tips that come with each case.


1. Check the Listening Address

ss only shows IPv4/IPv6 sockets that are listening on a network interface unless you explicitly ask for it. If a service is bound to 127.0.0.1 or ::1, you’ll see it only if you add the -4 or -6 flags:

ss -tuln4
ss -tuln6

If the service is listening on a local‑only address, you’ll spot it here. PostgreSQL, for instance, often defaults to 127.0.0.1:5432. If you’re expecting a public port, double‑check the config file (postgresql.conf, nginx.conf, etc.) for the listen_addresses or server_names directives.

Hardening tip: If a service must stay host‑only, keep it bound to 127.0.0.1 or a Unix socket. It shrinks the attack surface.


2. Unix Domain Sockets

Many daemons expose a Unix domain socket instead of a TCP port. ss can list them with -x:

ss -x

For example, the systemd‑resolved DNS stub listens on /run/systemd/resolve/stub-resolv.conf. These sockets won’t show up in ss -tuln, but they’re real IPC endpoints.

If you’re troubleshooting a service that should expose a TCP port, verify that the configuration explicitly sets listen to a network address and not a socket path.


3. Socket‑Activated Units

Systemd can start a service on demand via a socket unit. In this model, the socket unit creates the listening socket, and the service is spawned when a connection arrives. Until a client connects, the service may appear running but no TCP port will be visible.

systemctl list-units --type=socket

Look for a unit like ssh.socket. If you see it, the port is already open; ss will show it. If the socket unit is missing, the service might be configured to start manually without a socket.

Hardening tip: Disable unnecessary socket units (systemctl disable --now <unit>.socket) to avoid accidental exposure. Use systemctl edit <unit>.socket to bind to a specific interface or port range.


4. SELinux or AppArmor Restrictions

On systems with SELinux or AppArmor enabled, a service might be prevented from binding to a port even though the config says it should. Check the audit log:

ausearch -m avc -ts recent | tail

If you see denied entries for socket_bind, the policy is blocking the bind. Temporarily set SELinux to permissive to confirm:

setenforce 0

If the port appears after this change, adjust the policy with semanage port -a -t http_port_t -p tcp 8080 (example for HTTP on 8080).


5. Firewall Rules Hiding the Port

A firewall can drop SYN packets, making the port appear closed to external scanners while the service is listening. Verify with:

iptables -L -n -v
nft list ruleset

If a rule drops traffic to the port, either adjust the rule or add a REJECT with a comment for clarity.


Quick Troubleshooting Flow

StepCommandWhat to Look For
1ss -tulnNo output?
2ss -tuln4 / ss -tuln6Local‑only binding?
3ss -xUnix socket?
4systemctl list-units --type=socketSocket activation?
5ausearch -m avcSELinux blocking?
6iptables -L -n -vFirewall hiding?

Run through the table until you find the root cause. Once identified, apply the appropriate hardening measure.


Practical Example: A Misconfigured Nginx

Suppose systemctl status nginx shows active, but ss -tuln shows nothing. You discover:

ss -tuln4
# no output

ss -x | grep nginx
# /run/nginx/nginx.sock  (Unix socket)

systemctl list-units --type=socket | grep nginx
# nginx.socket not listed

The config contains:

listen unix:/run/nginx/nginx.sock;

Change to:

listen 80;

Reload:

systemctl reload nginx

Now ss -tuln4 shows LISTEN 0 128 0.0.0.0:80.


Final Thoughts

When ss shows no open TCP ports, it’s almost always a configuration or policy nuance rather than a system failure. Use the checklist above to locate the hidden socket, and then tighten the configuration to expose only what’s necessary. This keeps the network surface minimal while maintaining operational visibility.

See also