Short answer: the ports a server admin meets most are 22 (SSH), 80 and 443 (HTTP and HTTPS), 25, 465 and 587 (mail), 53 (DNS), 3306 and 5432 (MySQL and PostgreSQL) and 3389 (RDP). The table below lists the common ones with their transport and, the part most lists skip, whether the port should be reachable from the internet at all. Ports 0 to 1023 are the well-known ports, 1024 to 49151 registered ports, and 49152 to 65535 dynamic ports that no service owns.
List of common ports
“Yes” means the port exists to be public. “Allowlist” means reachable only from your own addresses or through a VPN. “Never” means the service should listen on 127.0.0.1 or a private network and nothing on the internet should reach it.
| Port | Transport | Service | Expose to the internet? |
|---|---|---|---|
| 20, 21 | TCP | FTP data and control (990 for implicit FTPS) | Avoid: use SFTP on 22. If FTP must stay, FTPS with an allowlist |
| 22 | TCP | SSH, and SFTP, scp and rsync inside it | Yes, with key-only login. Allowlist if your addresses are fixed |
| 23 | TCP | Telnet | Never: logins cross the network unencrypted |
| 25 | TCP | SMTP between mail servers | Yes on a mail server (incoming mail), closed everywhere else |
| 53 | UDP + TCP | DNS | Only on an authoritative name server. Never as an open resolver |
| 67, 68 | UDP | DHCP server, DHCP client | Never: a DHCP server belongs on a private network, and a DHCP client needs no rule of your own |
| 80 | TCP | HTTP | Yes on a web server, to redirect to HTTPS |
| 110, 995 | TCP | POP3, POP3 over TLS | 995 yes on a mail server that offers POP3; leave 110 closed |
| 111, 2049 | TCP + UDP | rpcbind, NFS | Never |
| 123 | UDP | NTP | Not needed unless the server is a time server: syncing its own clock is outbound |
| 135, 137–139, 445 | TCP + UDP | Windows RPC, NetBIOS, SMB file sharing (and Samba) | Never |
| 143, 993 | TCP | IMAP, IMAP over TLS | 993 yes on a mail server; leave 143 closed |
| 161, 162 | UDP | SNMP, SNMP traps | Never, or allowlist your monitoring host |
| 389, 636 | TCP | LDAP, LDAP over TLS | Allowlist |
| 443 | TCP + UDP | HTTPS; UDP for HTTP/3 (QUIC) | Yes on a web server |
| 465 | TCP | Mail submission over implicit TLS | Yes on a mail server, for your users' mail clients |
| 500, 4500 | UDP | IPsec IKE and NAT traversal (IKEv2 VPNs such as strongSwan) | Yes on a VPN server |
| 587 | TCP | Mail submission with STARTTLS | Yes on a mail server, for your users' mail clients |
| 873 | TCP | rsync daemon | Allowlist. rsync over SSH needs no extra port |
| 1194 | UDP (TCP possible) | OpenVPN | Yes on a VPN server |
| 1433 | TCP | Microsoft SQL Server | Never: allowlist or tunnel |
| 2083, 2087 | TCP | cPanel and WHM over HTTPS (2096 for webmail) | 2083 and 2096 for your users; WHM on 2087 allowlisted where you can |
| 2375, 2376 | TCP | Docker API, plain and TLS | 2375 never: it is root on the host. 2376 only with client certificates and an allowlist |
| 3000, 5000, 8000 | TCP | App and dev servers (Grafana, Node.js apps, Flask, Django runserver) | Never directly: put nginx in front |
| 3306 | TCP | MySQL, MariaDB | Never: keep it on 127.0.0.1 |
| 3389 | TCP + UDP | RDP (Windows Remote Desktop) | Allowlist, or reach it through a VPN |
| 5432 | TCP | PostgreSQL | Never: keep it on localhost |
| 5900 and up | TCP | VNC (display :0 is 5900, :1 is 5901) | Never: tunnel it over SSH |
| 5985, 5986 | TCP | WinRM over HTTP, over HTTPS | Allowlist |
| 6379 | TCP | Redis | Never |
| 8006 | TCP | Proxmox VE web interface | Allowlist |
| 8080, 8443 | TCP | HTTP and HTTPS alternates; 8443 is also Plesk's panel | Only if a service needs it; usually behind a reverse proxy instead |
| 9000 | TCP | PHP-FPM (its upstream default; Debian and Ubuntu use a Unix socket instead) | Never: an open FastCGI port lets anyone run PHP on the server |
| 9090, 10000 | TCP | Cockpit and Webmin web consoles | Allowlist |
| 9200 | TCP | Elasticsearch, OpenSearch HTTP API | Never |
| 11211 | TCP | Memcached (UDP is off by default since 1.5.6) | Never |
| 25565 / 19132 | TCP / UDP | Minecraft Java / Bedrock | Yes on a game server |
| 27017 | TCP | MongoDB | Never |
| 51820 | UDP | WireGuard (a convention, not an IANA assignment) | Yes on a VPN server |
Mail ports have one catch: many hosting providers restrict outgoing connections on port 25, so check your provider’s acceptable use policy or ask support before you build a mail server. Many numbers in the table are conventions rather than IANA assignments: 51820 (WireGuard), 25565 and 19132 (Minecraft) are not registered at all, and IANA lists 8443, 9000, 9200 and the cPanel ports under other services, yet these are the ports the software uses out of the box.
Which ports does my server need open?
Fewer than the table suggests. Most servers have one job, and the job decides the ports; everything else stays closed. Your own way in, SSH or RDP, belongs in the right-hand column whenever your addresses allow it.
| Server role | Open to everyone | Open to your addresses only |
|---|---|---|
| Web server or reverse proxy | 80/TCP, 443/TCP, 443/UDP if you serve HTTP/3 | 22/TCP |
| Mail server | 25/TCP, 465/TCP, 587/TCP, 993/TCP | 22/TCP |
| Authoritative DNS server | 53/UDP, 53/TCP | 22/TCP |
| VPN server | 51820/UDP (WireGuard), 1194/UDP (OpenVPN) or 500 and 4500/UDP (IPsec) | 22/TCP, or nothing else once the VPN is up |
| Windows server you use over RDP | Nothing | 3389/TCP and 3389/UDP |
| Game server | The game's port, e.g. 25565/TCP for Minecraft Java | 22/TCP, RCON ports |
| Database server for your other servers | Nothing | 22/TCP, and the database port from your app servers' addresses |
Why the “never” ports are never
Databases, caches and admin APIs were built for trusted networks. Some have no password by default, all of them are scanned for constantly, and an exposed one tends to end as a ransom note in place of your data. Most of them already start safe:
- MariaDB on Debian has
bind-address = 127.0.0.1in/etc/mysql/mariadb.conf.d/50-server.cnf. - PostgreSQL defaults to
listen_addresses = 'localhost'. - Redis ships with
bind 127.0.0.1 -::1andprotected-mode yes. - MongoDB binds to localhost by default.
The risk is the one line you change to make a remote client work. Leave the bind address alone and reach the database through an SSH tunnel instead; replace YOUR_USER and YOUR_SERVER_IP with your login and the server’s address, and use another local port on the left, such as 15432, if PostgreSQL also runs on your own computer:
ssh -N -L 5432:127.0.0.1:5432 YOUR_USER@YOUR_SERVER_IPYour client then connects to 127.0.0.1:5432 on your own machine, and port 5432 stays closed on the server.
Port number ranges: well-known, registered and dynamic
Port numbers are 16 bits, so they run from 0 to 65535, separately for TCP and UDP. RFC 6335 splits them into three ranges:
| Range | Name | What it means |
|---|---|---|
| 0–1023 | System ports (well-known) | Assigned by IANA to core services: 22, 25, 53, 80, 443 |
| 1024–49151 | User ports (registered) | Assigned by IANA on request: 3306, 3389, 5432 |
| 49152–65535 | Dynamic ports (private, ephemeral) | Never assigned; free for temporary client ports |
Operating systems do not follow that last line exactly. When your server opens an outgoing connection, the kernel picks a temporary source port from its own ephemeral range: on Linux that is 32768–60999 by default, on Windows 49152–65535. On Linux, ports below 1024 also need root or the CAP_NET_BIND_SERVICE capability to listen on.
sysctl net.ipv4.ip_local_port_range net.ipv4.ip_unprivileged_port_startnet.ipv4.ip_local_port_range = 32768 60999
net.ipv4.ip_unprivileged_port_start = 1024netsh int ipv4 show dynamicport tcpProtocol tcp Dynamic Port Range
---------------------------------
Start Port : 49152
Number of Ports : 16384That has a practical consequence when you pick a port for your own service on Linux: choose one between 1024 and 32767 that nothing else uses. Linux’s ephemeral range overlaps the top of the registered range, so a service on, say, 45000 can find its port already taken by an outgoing connection at startup and fail with Address already in use. If a service must live in that range, list its port in net.ipv4.ip_local_reserved_ports so the kernel stops handing it out.
TCP, UDP or both?
The Transport column matters for two reasons. A firewall rule is per protocol, so a service listed as TCP + UDP needs both rules: DNS answers large replies and zone transfers over TCP, and RDP adds UDP for a faster picture. And the two behave differently when you test them. TCP starts with a handshake, so a test either connects, is refused or times out. UDP has no handshake: a silent UDP port looks the same whether it is open or filtered, unless the test speaks the service’s own protocol, such as dig for DNS or the game client for a game server. Ping is neither: it uses ICMP, which has no ports at all, so a server that ignores ping can still have every port in this table open.
How to see which ports are open on your server
Ask the kernel which sockets are listening, with the process behind each:
sudo ss -tulpnNetid State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
udp UNCONN 0 0 127.0.0.53%lo:53 0.0.0.0:* users:(("systemd-resolve",pid=402,fd=13))
udp UNCONN 0 0 0.0.0.0:51820 0.0.0.0:*
tcp LISTEN 0 4096 127.0.0.53%lo:53 0.0.0.0:* users:(("systemd-resolve",pid=402,fd=14))
tcp LISTEN 0 128 0.0.0.0:22 0.0.0.0:* users:(("sshd",pid=611,fd=3))
tcp LISTEN 0 511 0.0.0.0:443 0.0.0.0:* users:(("nginx",pid=902,fd=7))
tcp LISTEN 0 151 127.0.0.1:3306 0.0.0.0:* users:(("mariadbd",pid=755,fd=20))
tcp LISTEN 0 511 127.0.0.1:6379 0.0.0.0:* users:(("redis-server",pid=698,fd=6))Read the Local Address column. 0.0.0.0 or [::] is every address, so the service is reachable from outside unless a firewall stops it. 127.0.0.1 and 127.0.0.53 are loopback, unreachable from the network whatever the firewall says, which is where MariaDB and Redis belong. The UDP line on 51820 without a process is WireGuard, which runs in the kernel. Checking open ports on Linux explains every flag and the lsof and netstat equivalents.
On Windows Server, the same in PowerShell:
Get-NetTCPConnection -State Listen | Sort-Object LocalPort | Select-Object LocalAddress, LocalPort, OwningProcess
Get-NetUDPEndpoint | Sort-Object LocalPort | Select-Object LocalAddress, LocalPort, OwningProcessHow to check a port from outside
Listening is half the answer; the firewall, the provider’s network and the bind address decide the rest. Test from a machine outside the server. Replace YOUR_SERVER_IP and PORT:
nc -vz -w 5 YOUR_SERVER_IP PORTnc -vz -G 5 YOUR_SERVER_IP PORTTest-NetConnection YOUR_SERVER_IP -Port PORTOr use the open port checker, which opens one TCP connection from our server in Amsterdam to any public IP address and port and tells you whether it was accepted, refused or got no answer. It tests TCP only, for the reason above, one port per check, and its rate limits are sized for testing your own services, not for sweeping a network.
Turn the table into firewall rules
Start from “deny everything incoming” and open only the rows you need. With UFW on Debian or Ubuntu, a web server with SSH restricted to your office address looks like this. Replace YOUR_IP with your own public address, which the what is my IP page shows. Debian does not ship UFW; install it with sudo apt install ufw first.
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow from YOUR_IP to any port 22 proto tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enableufw enable asks for confirmation, which is why it comes last: pasted as a block, any line after it would be read as the answer. Then check the result with sudo ufw status numbered.
The “never” rows need no rule at all: under a deny default they stay closed, and bound to 127.0.0.1 they are unreachable even without a firewall. The full walkthrough, with rate limits and source-restricted rules, is the UFW firewall guide.
On Rocky Linux and AlmaLinux with firewalld running (sudo firewall-cmd --state says so), the default zone already allows SSH and Cockpit on 9090. Open the web ports and drop Cockpit if you do not use it:
sudo firewall-cmd --permanent --add-service=http --add-service=https
sudo firewall-cmd --permanent --remove-service=cockpit
sudo firewall-cmd --reloadGuides to individual ports
- SSH port 22: checking, testing and connecting on another port with ssh, scp and rsync.
- RDP port 3389: TCP and UDP, RD Gateway, and the ports Remote Desktop does not need.
- Ports 443 and 80: HTTP, HTTPS, HTTP/3 on UDP, redirects and Cloudflare’s port list.
- DNS port 53: why DNS needs UDP and TCP, how to test it, and how to free it from systemd-resolved.
- SMTP ports 25, 465, 587 and 2525: which one delivers, which one submits, and how to test them.
- FTP port 21: the data ports, passive mode, FTPS and why SFTP on 22 is simpler.
On a Standard KVM VPS at VMHeaven the firewall on the server is yours to configure, the panel has packet rules of its own, and always-on DDoS protection is included. The VNC console in the panel still reaches the server when a rule goes wrong.
Frequently asked
What are the most common ports?
22 for SSH, 80 and 443 for HTTP and HTTPS, 25, 465 and 587 for mail, 53 for DNS, 3306 for MySQL, 5432 for PostgreSQL and 3389 for Remote Desktop. Which of them to open depends on the server's job: web ports on a web server, mail ports on a mail server, while database ports stay closed to the internet.
What is the difference between well-known, registered and dynamic ports?
Under RFC 6335, ports 0-1023 are system (well-known) ports for core services, 1024-49151 are user (registered) ports assigned on request, and 49152-65535 are dynamic ports that are never assigned. Linux itself picks temporary client ports from 32768-60999 by default.
Which ports should never be open to the internet?
Database and cache ports such as 3306, 5432, 6379, 27017 and 9200, the Docker API on 2375, SMB on 445 and VNC on 5900. Keep those services on 127.0.0.1 or a private network and reach them through an SSH tunnel or a VPN; Telnet on 23 should not run at all.