Starphix
Network Engineering / Sources
The Lab / Sources / Network Engineering / Core-Protocols/Ports-And-Services.md

Ports and Services

A port is how one IP address hosts many conversations. It is also the first thing to check when something "cannot connect", and the thing people most often misread.

The mechanics

A TCP or UDP header carries a 16-bit source port and a 16-bit destination port: 0–65535.

Range Name Use
0–1023 Well-known Assigned by IANA to core services; binding needs privilege (or CAP_NET_BIND_SERVICE)
1024–49151 Registered Applications and vendor products
49152–65535 Dynamic / ephemeral Client side of outbound connections

The destination port is chosen by the client and names the service. The source port is chosen by the kernel's ephemeral allocator and identifies this conversation, so 500 browsers can talk to one server on 443 at once.

ss -lntp                  # what is listening, on which address
ss -tn state established  # conversations, with queue depths
cat /proc/sys/net/ipv4/ip_local_port_range   # Linux ephemeral range (32768 60999)
sysctl net.ipv4.ip_local_port_range          # same, as a setting

Ports you will actually meet

Port Protocol Service Common mistake
22 TCP SSH / SFTP Exposed to the internet with passwords enabled
25 TCP SMTP relay Blocked by most providers; use 587 to submit mail
53 TCP+UDP DNS Firewalled "because UDP is enough" — large answers and zone transfers use TCP
67/68 UDP DHCP server / client DHCP relay missing on a routed VLAN
80 TCP HTTP Left open "for redirects" with no redirect configured
123 UDP NTP Blocked, so certificates and logs quietly drift
161/162 UDP SNMP / traps Community string left at public
179 TCP BGP Firewalled between peers; session never establishes
389/636 TCP LDAP / LDAPS Cleartext bind allowed
443 TCP+UDP HTTPS / HTTP/3 UDP 443 blocked, so QUIC silently falls back to TCP
445 TCP SMB Reachable from a user VLAN, which is how ransomware spreads
514 UDP Syslog Unencrypted, unauthenticated, usually unread
3306/5432/1433 TCP MySQL / Postgres / SQL Server Bound to 0.0.0.0 and reachable from the internet
3389 TCP RDP Internet-exposed RDP is a standing invitation
6379/27017/9200 TCP Redis / MongoDB / Elasticsearch Default "no auth, no TLS" deployments found by scanners within hours

Full lists exist, but these are the ones that cause incidents.

Listening address matters as much as port

127.0.0.1:8080   only this host can connect
0.0.0.0:8080     every interface, including the public one
[::]:8080        every IPv6 interface (often dual-stack with 0.0.0.0)
192.168.1.5:8080 only that interface

A database "not exposed to the internet" that binds 0.0.0.0 is exposed to the internet the moment a firewall rule or a security group is wrong. Bind to loopback or the private interface and the mistake becomes impossible.

Reading a connection refusal correctly

Observation Meaning
Connection refused (RST) Something answered: no listener on that port, or a firewall rejected with RST
Timeout, no reply Packet dropped: firewall DROP rule, route missing, host down, or asymmetric path
Connection reset by peer mid-session Listener died, or a middlebox decided to kill the flow
Works from one host, not another Source-based firewall rule, NAT, or routing difference — not the service
address already in use Another process holds the port; ss -lntp names it

Refused vs timeout is the single most useful distinction in troubleshooting, because it tells you whether your packets are being answered at all.

Ephemeral port exhaustion

Every outbound connection consumes a source port for the duration, plus TIME_WAIT afterwards. With ~28,000 ports per destination IP and a workload that opens and abandons connections rapidly, you can run out:

ss -s | head -3                     # total sockets, TIME_WAIT count
netstat -an | grep -c TIME_WAIT

Symptoms: intermittent cannot assign requested address under load, rising latency, retries. Fixes are connection pooling, HTTP keep-alive, more destination IPs, or widening the port range — in that order, because pooling is the real fix.

Where it goes wrong

  • Assuming one port per service. HTTP/3 is UDP 443, DNS is both UDP and TCP 53, and many products listen on dozens of ports plus a dynamic range.
  • Fixing the application firewall and forgetting the network one. Two layers, two sets of rules; the one that blocks is often the one nobody owns.
  • Opening a port "to test" and never closing it. The test that took thirty seconds becomes a permanent ingress rule.
  • Confusing "listening" with "reachable". ss proves the process; it says nothing about routing or policy.
  • Copying a docker-compose from the internet with - "5432:5432". That publishes the database on every interface by default.

From the Network Engineering research vault · CC BY 4.0 · all notes · raw markdown