Ports, Protocols & Sockets

How one IP address hosts fifty services — and how to see exactly what's listening on your machines.

The Apartment Building Model

An IP address gets traffic to the right machine; a port gets it to the right program on that machine. Think of the IP as a building's street address and ports as apartment numbers, 1–65535. Your Proxmox host has one IP but serves the web UI on 8006, SSH on 22, and whatever else you've stacked on it — each a different apartment.

A socket is one live conversation: the combination of IP + port on both ends. 192.168.1.50:52814 → 192.168.1.100:8006 is you in the Proxmox UI. Your side uses a random high "ephemeral" port — that's why a server can hold thousands of simultaneous connections on a single listening port: every client pair is unique.

TCP vs UDP

Two transport protocols carry almost everything. TCP is a phone call: connection established first (the three-way handshake), every byte acknowledged, lost pieces re-sent, order guaranteed. UDP is a thrown paper airplane: no setup, no delivery guarantee, minimal overhead.

TCP → web (80/443), SSH (22), databases — correctness matters
UDP → DNS queries (53), DHCP (67/68), WireGuard (51820),
      game/voice traffic — speed matters, a lost packet is no tragedy

# Note the port number alone isn't enough — 53/udp and 53/tcp
# are different doors. Firewall rules must name the protocol.

Port Numbers Worth Memorizing

22    SSH                 443   HTTPS
53    DNS                 445   SMB (Windows/NAS shares)
67/68 DHCP                3306  MySQL / 5432 PostgreSQL
80    HTTP                8006  Proxmox web UI
123   NTP (time)          9090  Prometheus / 3000 Grafana

# 0–1023: "well-known" — binding these requires root
# 1024–49151: registered — where most apps live
# 49152–65535: ephemeral — outbound connection source ports

What's Listening? ss and Friends

A port is only open if a program is listening on it. The modern tool is ss (netstat's replacement) — run it on any lab box and audit what you find:

sudo ss -tulpn              → all listening ports + owning process
#  -t TCP  -u UDP  -l listening  -p process  -n numeric

# Reading the Local Address column:
0.0.0.0:22        → listening on EVERY interface (reachable from LAN)
127.0.0.1:5432    → loopback only (this machine can reach it, LAN cannot)
192.168.1.120:80  → one specific interface only

# Test reachability from another machine
nc -zv 192.168.1.100 8006    → "succeeded" = open, listening
nc -zv 192.168.1.100 3389    → "refused" = nothing listening there

That 0.0.0.0 vs 127.0.0.1 distinction is the single most useful security habit on this page: databases and internal APIs should bind loopback (or a specific internal IP), not every interface. If ss shows a service on 0.0.0.0 that only local apps use, you've found tomorrow's hardening task.

Debugging "Can't Connect" — In Order

# 1. Is the host even reachable?
ping 192.168.1.100

# 2. Is anything listening on that port? (run ON the server)
sudo ss -tulpn | grep 8006

# 3. Bound to the right interface? (127.0.0.1 = not reachable from LAN)

# 4. Firewall in the way? (run ON the server)
sudo ufw status verbose        # or: sudo iptables -L -n

# 5. Reachable from the client?
nc -zv 192.168.1.100 8006

# "connection refused" = host reachable, nothing listening (steps 2-3)
# timeout / hang        = firewall dropping packets (step 4) or routing

Refused vs timeout is the diagnostic gold: refused means the network path is fine and the service is the problem; a silent timeout means something (usually a firewall) is eating your packets. That one distinction routes you to the right fix immediately.

≈·*•—[ A|S ]—•*·≈

- Crafted by Axiom|Spectre