The Ports Every Sysadmin Should Know

A port number is just a 16-bit integer — 0 to 65535 — but in practice a small handful of them come up every single day in real infrastructure. When you're reading firewall rules, debugging a connection timeout, scanning for exposed services, or writing network policies, these are the numbers you'll see repeatedly. Knowing them by heart is a genuine time-saver.

This guide covers the ports that actually matter in production — not an exhaustive IANA reference, but the ones you'll encounter in web servers, databases, caches, message queues, and remote access. For each one: what it is, what the security surface looks like, and what finding it open unexpectedly usually means.

How ports work (in thirty seconds)

Every TCP and UDP connection is identified by a four-tuple: source IP, source port, destination IP, destination port. When a service starts, it binds to a port — it tells the OS "send me anything that arrives on this port." The OS keeps a table of these bindings; ss -tlnp or netstat -tlnp on Linux will show you what's listening where.

Ports 0–1023 are "well-known" ports. On most Unix systems, binding to them requires root or a capability. Ports 1024–49151 are "registered" ports — conventionally assigned to specific services but not OS-protected. Ports 49152–65535 are ephemeral — your OS grabs one of these for the client side of outbound connections.

The reference table

Port Protocol Service Exposure risk
22 TCP SSH High if public
25 TCP SMTP High
53 TCP/UDP DNS Medium
80 TCP HTTP Expected
443 TCP HTTPS Expected
3306 TCP MySQL / MariaDB High
5432 TCP PostgreSQL High
6379 TCP Redis Critical
8080 TCP HTTP alternate Medium
9200 TCP Elasticsearch HTTP Critical
27017 TCP MongoDB High
5672 TCP RabbitMQ AMQP High
9092 TCP Kafka High
2181 TCP ZooKeeper High
2379 TCP etcd client Critical

Port 22 — SSH

SSH is the standard way to get a shell on a remote server. It's encrypted and secure when configured correctly — but port 22 open to the internet draws constant automated scanning and brute-force attempts within minutes of a new server coming online.

What to do: Move SSH off port 22 if you can tolerate the minor friction of specifying a custom port — it eliminates nearly all automated noise. More importantly: disable password authentication and use key-based auth only. PermitRootLogin no in /etc/ssh/sshd_config. If only a small set of IPs needs access, firewall it at the network level rather than relying on the daemon's own auth.

Finding it unexpectedly: If a server that shouldn't have SSH open does, check what's running with ss -tlnp | grep :22 and review recent auth logs at /var/log/auth.log or /var/log/secure.

Port 80 and 443 — HTTP and HTTPS

80 is plain HTTP, 443 is HTTPS (HTTP over TLS). If you're running a web server, both should be open. Port 80 should ideally redirect all traffic to 443 rather than serving content directly — a 301 redirect is standard. Serving real content over port 80 in 2026 is a misconfiguration.

What to do: Your reverse proxy (nginx, Caddy, Traefik) should handle the 80→443 redirect. Let's Encrypt / Certbot or your cloud provider's managed TLS handles certificate renewal. Make sure port 443 is accessible from your CDN or load balancer. Check with the DNS Lookup tool that your A records point where you expect.

Port 3306 — MySQL / MariaDB

MySQL's default port. Database ports are one of the most common misconfigurations in cloud infrastructure — a new server, the database bound to 0.0.0.0 by default, the firewall not yet configured. MySQL has had authentication bypass CVEs in the past, but the far more common issue is simply leaving it reachable from the internet.

What to do: MySQL should bind to 127.0.0.1 or a private network interface only. In /etc/mysql/mysql.conf.d/mysqld.cnf: bind-address = 127.0.0.1. If your app server is on a different host, bind to the private IP and restrict access with a firewall rule, not by relying on database-level auth.

Port 5432 — PostgreSQL

PostgreSQL's default port. Similar considerations to MySQL. PostgreSQL defaults to only accepting local connections (local connections via Unix socket, and TCP on 127.0.0.1 in most default configs), which is safer than MySQL's default, but this varies by distribution and Docker image.

What to do: Check pg_hba.conf to understand who can connect from where. The listen_addresses parameter in postgresql.conf controls which interfaces PostgreSQL binds to. In containerized environments, watch for images that set listen_addresses = '*' — they're designed for development and not production.

Port 6379 — Redis

Redis's default port. Redis is the most dangerous item on this list to leave exposed. By default (before Redis 6), Redis has no authentication — it assumes it's running on a trusted private network. Redis with CONFIG SET dir /etc/cron.d and CONFIG SET dbfilename root followed by SAVE can write an arbitrary file to disk as whatever user the Redis process runs as. This has been used to write SSH authorized_keys files and establish persistent access.

What to do: Redis must never be reachable from untrusted networks. Bind to 127.0.0.1 in redis.conf: bind 127.0.0.1. Set requirepass in Redis 6+ or use ACLs. If Redis is exposed on any cloud firewall scan you run, treat it as an active incident — check the Redis keyspace for unfamiliar keys, check cron jobs, check authorized_keys.

Port 9200 — Elasticsearch

Elasticsearch's HTTP API port. Like Redis, early versions of Elasticsearch had no authentication at all. The result was thousands of publicly accessible Elasticsearch clusters storing sensitive data — a major source of data breaches in the 2016–2020 period. Elasticsearch 8+ ships with security enabled by default, but older clusters and self-managed installations vary.

What to do: Elasticsearch should never be reachable from the public internet. It binds to localhost only if network.host is not set — the moment you set network.host: 0.0.0.0 to allow inter-cluster communication, you've also exposed it to the internet unless you have a firewall in front. Enable X-Pack security. Use a reverse proxy with auth if external access is genuinely required.

Port 27017 — MongoDB

MongoDB's default port. MongoDB's early default configuration was similarly permissive — no authentication required, bound to all interfaces. The "MongoDB ransomware" incidents of 2017 involved attackers wiping MongoDB databases that were open to the internet and leaving ransom notes. Secure defaults have improved since, but legacy deployments and misconfigured Docker setups remain common.

What to do: Enable authorization in mongod.conf: security.authorization: enabled. Bind to 127.0.0.1 or a private network interface. Use strong credentials for all database users.

Port 2379 — etcd

etcd is the distributed key-value store that Kubernetes uses as its source of truth. Port 2379 is the client API. If etcd is exposed, an attacker can read the entire Kubernetes cluster state — including all Secrets, which store TLS certificates, service account tokens, and whatever credentials your deployments use. A compromised etcd is a total cluster compromise.

What to do: etcd should only be reachable by the Kubernetes control plane nodes. It must use mutual TLS (mTLS) — both etcd and its clients authenticate with certificates. This is handled automatically by managed Kubernetes services (EKS, GKE, AKS), but if you're running your own cluster, verify it with etcdctl endpoint health --cacert --cert --key and confirm unauthenticated access is rejected.

How to check what's actually listening

On any Linux server:

# All listening TCP ports with process names
ss -tlnp

# All listening UDP ports
ss -ulnp

# Everything (TCP + UDP + Unix)
ss -alnp

# Old-school equivalent
netstat -tlnp

From outside the server, to check if a port is reachable:

# Quick TCP connection test
nc -zv hostname 6379

# With timeout
nc -zv -w 3 hostname 27017

# curl to check an HTTP service
curl -I http://hostname:9200

For checking DNS resolution and which IPs a hostname resolves to before connecting, the DNS Lookup tool will show A, AAAA, MX, and other record types for any domain — useful when you're debugging why a connection goes to an unexpected host.

The rule that covers most of this

Any port that doesn't need to be reachable from the internet should not be reachable from the internet. This sounds obvious, but the gap between "should" and "is" is where most incidents happen. Validate firewall rules regularly — not by reading them, but by scanning. A misconfigured security group that exposes port 6379 is invisible in the config until you try to connect to it.

Port Checker — Test any port on any public host from the internet. Instantly see if it's open, closed, or filtered — no install required.

Check a Port

DNS Lookup — Check A, MX, CNAME, TXT, and NS records for any domain. Useful before debugging a connection to an unexpected IP.

Open Tool