How to Check Open Ports on Your Server in 2026
Open ports are the most common entry point for attackers. Here is how to find, analyse, and secure them on any Linux server.
Key insight: Port scanning your own server is the first step to understanding your attack surface.
What Are Open Ports?
Every network service on your server communicates through a numbered port. When a service is actively listening for incoming connections, that port is considered open. SSH uses port 22, web servers use port 80 and 443, databases use ports like 3306 or 5432.
The problem is that many servers have far more open ports than the administrator realises. Default package installations, dependency services, and development tools often enable listening services without explicit configuration. Each open port is a potential attack surface — a door that an attacker can try to walk through.
In 2026, automated botnets scan the entire IPv4 address space continuously. Any port left open and unpatched will be discovered and probed within hours of going live. Knowing exactly which ports your server exposes is not optional — it is fundamental to security.
Using ss and nmap to Scan Ports
Two tools form the foundation of port scanning on Linux: ss for local inspection and nmap for remote scanning. Together they give you complete visibility into what your server exposes.
Local scanning with ss
The ss command is pre-installed on every modern Linux distribution. It reads socket information directly from the kernel and is the replacement for the deprecated netstat.
# List all listening TCP and UDP ports with process names
ss -tulnp
# Output columns:
# State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
# LISTEN 0 128 0.0.0.0:22 0.0.0.0:* users:(("sshd",pid=842,fd=3))
# LISTEN 0 511 0.0.0.0:443 0.0.0.0:* users:(("nginx",pid=1205,fd=6))
Key flags explained:
-t— show TCP sockets-u— show UDP sockets-l— show only listening (open) sockets-n— show numeric port numbers (do not resolve service names)-p— show the process using each socket (requires root)
Run ss -tulnp as root to see the process name associated with each port. Without root, you will see the ports but not which process owns them.
Remote scanning with nmap
The ss command only shows what the server itself reports. An external scan verifies what is actually reachable from the network — which is what an attacker sees.
# Install nmap (Debian/Ubuntu)
sudo apt install nmap -y
# Install nmap (RHEL/CentOS/Fedora)
sudo dnf install nmap -y
# Quick scan of common ports
nmap -sT your-server-ip
# Full TCP port scan (all 65,535 ports)
nmap -sT -p- your-server-ip
# TCP and UDP scan of top 1000 ports
nmap -sT -sU --top-ports 100 your-server-ip
# Aggressive scan with service version detection
nmap -sV -sC -p- your-server-ip
A full TCP port scan with -p- takes 5-15 minutes depending on network speed and server location. The results show every port that responds to connection attempts from outside — the true attack surface.
Checking Which Services Are Listening
Once you have a list of open ports, the next step is identifying exactly which service is bound to each one. An open port without a known service behind it is a risk.
# Show listening ports with full process details
sudo ss -tulnp
# Alternative: use lsof to map ports to processes
sudo lsof -i -P -n | grep LISTEN
# Check what is on a specific port (e.g., port 8080)
sudo lsof -i :8080 -P -n
# See which user owns each listening process
sudo ss -tulnp | awk '{print $1, $5, $6}'
Map each port to its purpose. You should be able to explain why every single listening port exists. If you cannot justify a port being open, close the service or block it with a firewall.
Common ports and what they mean:
- 22 — SSH (remote shell access)
- 80 — HTTP (web traffic, usually nginx or Apache)
- 443 — HTTPS (encrypted web traffic)
- 3306 — MySQL/MariaDB database
- 5432 — PostgreSQL database
- 6379 — Redis cache
- 27017 — MongoDB
- 2379 — etcd (Kubernetes)
- 8080, 8443 — Alternative HTTP/HTTPS (proxies, dashboards)
Identifying Unknown or Suspicious Ports
If ss -tulnp shows a port you do not recognise, investigate immediately. Do not assume it is harmless.
# Identify the process on an unknown port (e.g., 4444)
sudo ss -tulnp | grep :4444
sudo lsof -i :4444 -P -n
# Check the binary location of the process
ls -la /proc/$(sudo lsof -t -i :4444)/exe
# Check when the process started
ps -p $(sudo lsof -t -i :4444) -o pid,lstart,cmd
# Look up the port in common service databases
grep 4444 /etc/services
Red flags to watch for:
- High-numbered ports (4000-65535) with unknown processes — common for reverse shells and backdoors
- Processes running from
/tmp,/dev/shm, or/var/tmp— almost certainly malicious - Services bound to
0.0.0.0that should only listen on127.0.0.1— databases exposed to the internet - Multiple instances of the same service on different ports — possible lateral movement or persistence
If you find a process you cannot identify, check the file it is running from. If the binary is in an unusual location or was recently modified, treat it as compromised until proven otherwise. See our guide on how to check if your server is hacked for a full investigation workflow.
Closing Unnecessary Ports
Every open port that is not required for business operations should be closed. This is not optional hardening — it is baseline security hygiene.
Stop and disable unused services
# List all running services
systemctl list-units --type=service --state=running
# Stop a service immediately
sudo systemctl stop servicename
# Prevent it from starting on boot
sudo systemctl disable servicename
# Example: if you do not need a local database exposed remotely
sudo systemctl stop postgresql
sudo systemctl disable postgresql
Bind services to localhost when possible
Many services only need to be accessed locally (by other services on the same machine). Configure them to listen on 127.0.0.1 instead of 0.0.0.0:
# For Redis: edit /etc/redis/redis.conf
bind 127.0.0.1
# For MySQL: edit /etc/mysql/mysql.conf.d/mysqld.cnf
bind-address = 127.0.0.1
# For PostgreSQL: edit /etc/postgresql/*/main/postgresql.conf
listen_addresses = 'localhost'
# Restart the service after changes
sudo systemctl restart redis
This single change — binding to localhost — eliminates the most common database breach pattern: an internet-exposed database with default credentials.
Verify after changes
# Confirm the port is no longer accessible externally
nmap -sT -p 6379 your-server-ip
# Confirm it is still accessible locally
ss -tulnp | grep :6379
Using a Firewall (UFW) to Control Ports
Even after closing unnecessary services, a firewall provides a second layer of defence. UFW (Uncomplicated Firewall) is the standard firewall tool on Ubuntu and Debian-based systems.
Basic UFW setup
# Check current firewall status
sudo ufw status verbose
# Set default policies: deny all incoming, allow all outgoing
sudo ufw default deny incoming
sudo ufw default allow outgoing
# Allow SSH (do this before enabling the firewall or you lock yourself out)
sudo ufw allow 22/tcp
# Allow HTTP and HTTPS
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
# Enable the firewall
sudo ufw enable
# Verify active rules
sudo ufw status numbered
Restrict access by source IP
For services that should only be accessible from specific locations, restrict by source IP:
# Allow SSH only from your office IP
sudo ufw allow from 203.0.113.50 to any port 22
# Allow database port only from localhost
sudo ufw allow from 127.0.0.1 to any port 5432
# Allow admin panel only from a specific IP range
sudo ufw allow from 10.0.0.0/8 to any port 8443
Rate limiting to prevent brute force
# Rate-limit SSH connections (blocks IP after 6 attempts in 30 seconds)
sudo ufw limit 22/tcp
# Verify the rule was added
sudo ufw status numbered
UFW is a wrapper around iptables/nftables. For more advanced configurations, use iptables directly or nftables, but for most servers UFW provides sufficient control with much simpler syntax.
Automated Scanning with RootCrak
Manual port scanning is useful for one-time checks, but production servers need continuous monitoring. New software installations, package updates, and configuration changes can silently open ports without notification.
RootCrak provides automated port scanning as part of its server security platform:
- Continuous port monitoring — scans your server's exposed ports on a schedule you define (hourly, daily, or continuous)
- Change detection — alerts you when a new port opens or an existing port changes its service fingerprint
- Service identification — automatically identifies what is running on each port and flags unexpected services
- External perspective — scans from outside your network, showing exactly what an attacker would see
- Integrated with vulnerability scanning — open ports are cross-referenced with known CVEs for the detected service versions
Automated scanning catches the ports that manual checks miss — the Redis instance someone enabled for debugging and forgot to stop, the database port that reopened after a package update, or the management interface that was accidentally exposed.
RootCrak tip: Run an automated port scan after every deployment or package update. Silent port exposure is one of the most common ways servers get compromised — and one of the easiest to prevent.
Establishing a Regular Audit Cadence
Port scanning is not a one-time task. Your server's port landscape changes with every software update, configuration change, and deployment. Establish a regular cadence:
Recommended audit schedule
- After every deployment — run
ss -tulnpand compare against your known-good baseline - After every package update —
apt upgradeordnf updatecan re-enable disabled services or add new listeners - Weekly — run an external nmap scan to verify your firewall rules are working
- Monthly — full audit of all listening services, firewall rules, and UFW configuration
- Continuously — use an automated tool like RootCrak to monitor in real time
Creating a port baseline
# Generate a baseline of your current listening ports
sudo ss -tulnp | awk 'NR>1 {print $5, $6}' | sort > /root/port-baseline-$(date +%Y%m%d).txt
# Compare current state against baseline
diff /root/port-baseline-*.txt <(sudo ss -tulnp | awk 'NR>1 {print $5, $6}' | sort)
Keep this baseline updated. Any port that appears in a current scan but not in your baseline is a change that needs investigation. Not all changes are malicious — but all changes should be intentional.
Automating the baseline comparison
# Add to /etc/cron.daily/port-check or run via your monitoring system
#!/bin/bash
BASELINE="/root/port-baseline.txt"
CURRENT=$(mktemp)
sudo ss -tulnp | awk 'NR>1 {print $5, $6}' | sort > "$CURRENT"
if ! diff -q "$BASELINE" "$CURRENT" > /dev/null 2>&1; then
echo "PORT CHANGE DETECTED on $(hostname) at $(date)" | mail -s "Port Alert" [email protected]
diff "$BASELINE" "$CURRENT"
fi
rm -f "$CURRENT"
This simple script emails you whenever a new port opens or an existing one closes. For production environments, integrate this with your monitoring stack or use a dedicated tool that provides richer context and faster alerting.
Frequently Asked Questions
How do I check open ports on my server?
Run ss -tulnp to list all listening TCP and UDP ports on your server. For a remote scan, install nmap and run nmap -sT -sU -p- your-server-ip to check all 65,535 TCP and UDP ports. Both commands work on any modern Linux distribution without additional software.
What ports should always be closed on a server?
Close any port you are not actively using. Common ports that should be closed unless explicitly needed include: Telnet (23), FTP (21), MySQL remote (3306), PostgreSQL remote (5432), Redis (6379), and Memcached (11211). If a service only needs to be accessed locally, bind it to 127.0.0.1 instead of 0.0.0.0.
What is the difference between ss and netstat?
ss (socket statistics) is the modern replacement for netstat. It reads directly from kernel netlink interfaces and is significantly faster on systems with many connections. Netstat is deprecated on most distributions and may not be installed by default. Use ss -tulnp as the standard command for port checking.
How often should I scan my server for open ports?
Run a manual port scan at least once per month and after every software installation or configuration change. For production servers, use automated scanning tools that check daily or continuously. New software packages often open ports without explicit notification, and default configurations frequently expose services to the public internet.
Can I check open ports without installing nmap?
Yes. The ss command is pre-installed on all modern Linux distributions and shows all listening ports. You can also use netstat -tulnp (if installed), lsof -i -P -n, or check /proc/net/tcp directly. For remote scanning, nmap or similar tools are required, but for local port checks, built-in tools are sufficient.
Scan your server ports for free
RootCrak scans your server from the outside — showing every open port, identifying the services behind them, and flagging security risks. One scan takes under 60 seconds. No installation required.
Start Free Scan