LinuxBeginner 11 min Lesson 16 of 24

Ports

See what is listening on a server, understand binding addresses, and diagnose why a connection is refused.

Linux · Lesson 16 of 24
0/24 done(0%)

What is it? #

A port is a number that identifies which program on a machine should receive incoming traffic.

Only one program can listen on a given port and address at a time, which is why starting a second copy of a service fails with "address already in use".

The binding address decides who can reach it. Binding to 127.0.0.1 accepts only local connections; binding to 0.0.0.0 accepts connections from anywhere the network and firewall allow.

Most connection problems come down to four questions: is anything listening, on which address, does the firewall allow it, and is the name resolving correctly.

Think of it like this #

Doors in a building, each numbered. A delivery for door 443 goes to whoever is standing behind it.

Two people cannot stand behind the same door. And a door that opens only onto an internal corridor cannot be used from the street, however much you knock.

Simple example #

Your application is running but the browser says connection refused. You need to determine whether it is listening, on what address, and whether anything between you and it is blocking the traffic.

Code #

BASH
# What is listening on this machine?
sudo ss -tulpn
# -t TCP  -u UDP  -l listening  -p process  -n numeric (no name lookups)

# Example output
# tcp LISTEN 0 511  0.0.0.0:80      users:(("nginx",pid=812,fd=6))
# tcp LISTEN 0 511  127.0.0.1:8000  users:(("gunicorn",pid=1043,fd=5))
# tcp LISTEN 0 244  127.0.0.1:5432  users:(("postgres",pid=640,fd=5))
#                   └── the binding address is the important part

# Who is using a specific port?
sudo ss -tulpn | grep :8000
sudo lsof -i :8000

# Can I reach a port from here?
nc -zv example.com 443
curl -sS -o /dev/null -w "%{http_code}\n" http://localhost:8000/health
TEXT
Binding addresses

127.0.0.1:8000    only this machine — correct for an app behind a proxy
0.0.0.0:80        every interface — correct for the reverse proxy itself
10.0.1.5:5432     one private interface — correct for a database on a
                  private network that other servers must reach
[::]:80           the IPv6 equivalent of 0.0.0.0
TEXT
Well-known ports

22    SSH               80    HTTP            443   HTTPS
25    SMTP              53    DNS             123   NTP
3306  MySQL             5432  PostgreSQL      6379  Redis
27017 MongoDB           9200  Elasticsearch   3000/8000  common app ports

Below 1024 requires privilege to bind, which is why web servers
start as root and then drop to an unprivileged user.
TEXT
Diagnosing "connection refused" in order

1. is the process running?            systemctl status myapp
2. is it listening, and where?        sudo ss -tulpn | grep 8000
3. can it be reached locally?         curl localhost:8000/health
4. does the firewall allow it?        sudo ufw status
5. does the name resolve correctly?   dig +short example.com

"Connection refused" means nothing is listening.
"Connection timed out" usually means a firewall is dropping the traffic.

How it works #

ss -tulpn is the modern replacement for netstat. The -p flag shows the owning process, which is what turns "something is on port 8000" into "gunicorn, PID 1043".

The address column is the part people skim past and should read carefully. An application on 127.0.0.1:8000 is invisible from other machines by design; if you expected it to be reachable, the binding is the problem, not the firewall.

That local binding is usually correct. Applications should sit behind a reverse proxy, and binding to localhost means there is no direct public path to them at all.

Databases should bind to localhost or a private address. A PostgreSQL instance on 0.0.0.0 with a weak password is found by scanners within minutes.

The distinction between refused and timed out is the most useful diagnostic detail here. Refused means the connection reached the machine and nothing was listening. Timed out means the packets went nowhere — almost always a firewall or a security group.

Ports below 1024 need privilege, which is why services like Nginx start as root, bind port 80, and then drop to www-data for the actual work.

Real-world use #

The five-step diagnosis covers nearly every "I cannot reach the service" problem, and doing it in order saves a great deal of guessing.

In cloud environments there are usually two firewalls: the machine's own and the provider's security group. A timeout that persists after opening the local firewall is almost always the security group.

Port conflicts are common in development, where several projects want port 3000 or 8000. lsof -i :3000 identifies the culprit immediately.

In containers, the published port maps a host port to a container port, and a service bound to 127.0.0.1 inside a container is unreachable even when the port is published — the container's localhost is not the host's.

Auditing what is listening is a basic security check. Anything on 0.0.0.0 that does not need to be public should be changed or firewalled.

Common mistakes #

  • Binding an application to 127.0.0.1 and expecting external access.
  • Binding a database to 0.0.0.0 on a public server.
  • Opening firewall ports before checking whether anything is listening.
  • Ignoring the difference between connection refused and timed out.
  • Forgetting the cloud provider’s security group as well as the host firewall.

Practice #

On a machine you control, list every listening socket and note the binding address for each. Identify anything bound to all interfaces that should not be. Then start a service on localhost only and confirm from another machine that it is unreachable.

Quick quiz

  1. 1. What does binding to 127.0.0.1 mean?

  2. 2. What does "connection refused" indicate?

  3. 3. Which command shows listening ports with their processes?

  4. 4. Why do web servers start as root?

  5. 5. In a container, why might a published port still not work?

Summary

  • A port identifies which program receives traffic; only one can listen per address.
  • The binding address decides reachability before any firewall rule.
  • Applications belong on localhost behind a proxy; databases on localhost or a private address.
  • Refused means nothing listening; timed out usually means a firewall.
  • In the cloud, remember both the host firewall and the security group.