Skip to main content

Network Port

A network port is a 16-bit number (0-65535) that identifies a specific service or process on a host within a TCP/IP connection. Ports allow a single IP address to host multiple services simultaneously. Ports below 1024 are privileged and require root to bind.

Understanding Network Ports

What Is a Network Port in Simple Terms

If an IP address is like a building's street address, a port is the apartment number inside. Two services on the same server can both be reached at 10.0.1.50 — but nginx on port 80 and PostgreSQL on port 5432 are completely separate services on separate ports.

When you type https://razorpay.com, your browser connects to Razorpay's server IP on port 443 (HTTPS). The server knows which service to route the connection to because the port number tells it.

How It Works

◈ DIAGRAM
+------------------------------------------+
| Server at 10.0.1.50 |
| |
| Port 22 <- sshd (SSH connections) |
| Port 80 <- nginx (HTTP traffic) |
| Port 443 <- nginx (HTTPS traffic) |
| Port 4000 <- payment-api (Node.js app) |
| Port 5432 <- postgresql (database) |
| Port 6379 <- redis (cache) |
+------------------------------------------+
Incoming connection:
Source: 203.0.113.45:52341 (client IP:ephemeral port)
Dest: 10.0.1.50:443 (server IP:HTTPS port)
Kernel routes to nginx based on destination port

Port ranges:

TEXT
0-1023 Well-known ports -- require root to bind
22=SSH, 80=HTTP, 443=HTTPS, 25=SMTP, 53=DNS
1024-49151 Registered ports -- standard for many apps
3306=MySQL, 5432=PostgreSQL, 6379=Redis
8080=HTTP alt, 9090=Prometheus
49152-65535 Ephemeral ports -- auto-assigned to clients
When your browser makes a connection, the OS
picks one of these as the source port

Practical Commands

Bash
## Show all listening ports and which process owns them
ss -tulpn
## -t TCP -u UDP -l listening -p process -n numeric
## Output:
## Netid State Recv-Q Send-Q Local Address:Port Process
## tcp LISTEN 0 128 0.0.0.0:22 users:(("sshd",pid=892))
## tcp LISTEN 0 511 0.0.0.0:443 users:(("nginx",pid=1100))
## tcp LISTEN 0 128 127.0.0.1:5432 users:(("postgres",pid=1350))
## Find what is using a specific port
ss -tulpn | grep :8080
sudo lsof -i :8080
## Check if a remote port is open
nc -zv 10.0.1.50 5432
## Connection to 10.0.1.50 5432 port [tcp/postgresql] succeeded!
## Test connection with timeout
nc -zv -w3 10.0.1.50 5432
## Check multiple ports
for port in 22 80 443 5432 6379; do
nc -zv -w1 10.0.1.50 $port 2>&1 | grep -E 'succeeded|failed'
done
## Port forwarding: access remote DB locally
ssh -L 5433:localhost:5432 rahul@10.0.1.50
## Now connect to localhost:5433 to reach 10.0.1.50:5432
## Which process is using a port (requires root for other users' processes)
sudo ss -tlpn | grep :443
sudo fuser 443/tcp

Troubleshooting

Symptom Command What to Check
Port already in use error `ss -tulpn grep :PORT`
Service unreachable nc -zv host port Firewall blocking or service not running
Cannot bind port < 1024 Run as root or use authbind Privileged port restriction
Connection refused `ss -tulpn grep :PORT`
Tip

ss -tulpn is faster and more accurate than netstat -tulpn. Both show the same information but ss queries the kernel directly without reading /proc. On a busy server with thousands of connections, ss is noticeably faster.

Remember

A service bound to 127.0.0.1:5432 is only accessible from the local machine. A service bound to 0.0.0.0:5432 is accessible from any network interface. PostgreSQL defaults to 127.0.0.1 for security — changing it to 0.0.0.0 exposes the database to the network and requires firewall rules to be safe.

Frequently Asked Questions

Why are ports below 1024 restricted to root, and what problem does that prevent?

Ports 0-1023 are the 'well-known' or privileged range historically reserved for standard services (22 for SSH, 80 for HTTP, 443 for HTTPS), and Unix systems require root privileges to bind them so that an unprivileged user or compromised process can't impersonate a trusted service on a machine. This is why many application servers (Node, Java, Python web frameworks) default to listening on a high port like 8080 or 3000 and rely on a reverse proxy running as root, or with elevated capabilities, to forward from port 80/443.

What's a common port-related mistake in production troubleshooting?

Confusing 'port is open in the security group/firewall' with 'a process is actually listening on that port' is a frequent source of wasted debugging time — a connection refused error usually means nothing's bound to the port locally, while a timeout usually points to a network or firewall rule blocking it upstream. Tools like `ss -tlnp` (or the older `netstat`) show what's actually listening locally, which is the first thing to check before blaming the network layer.