NewHalo Edge 3 is here: HTTP/3 everywhere and 42 edge locations.Learn more
Docs / Tools and troubleshooting

Check open ports and listening services

Tools and troubleshooting6 min readUbuntu 24.04 LTS

Every program that accepts network connections listens on a port, and every open port is a door. This guide shows you how to list what your server is listening on with ss, how to confirm from outside what the internet can actually reach with nmap, and how to close doors you did not mean to open.

Before you begin

  • SSH access to your VPS as a user with sudo rights, such as alex.
  • A second computer or network to scan from. Only scan servers you own or have explicit permission to test.

Step 1: List listening services on the server

ss shows socket statistics and replaces the older netstat tool. The flags mean: -t TCP, -u UDP, -l listening only, -n show numbers instead of names, and -p show the program. Sudo lets you see programs owned by other users.

sudo ss -tulpn
Netid State  Local Address:Port Peer Address:Port Process
tcp   LISTEN 0.0.0.0:22          0.0.0.0:*     users:(("sshd",pid=701,fd=3))
tcp   LISTEN 0.0.0.0:443         0.0.0.0:*     users:(("nginx",pid=812,fd=6))
tcp   LISTEN 127.0.0.1:3306      0.0.0.0:*     users:(("mariadbd",pid=933,fd=21))
tcp   LISTEN 127.0.0.1:8080      0.0.0.0:*     users:(("python3",pid=2210,fd=3))

The most important column is the local address. 0.0.0.0 or [::] means the service accepts connections from any network interface, so it may be reachable from the internet. 127.0.0.1 means it accepts connections only from the server itself, which is much safer for internal services such as databases.

Step 2: Understand what each listener should be

Go through the list and match each entry to a service you chose to run. In the example above, SSH (22) and nginx (443) should be public. MariaDB on 3306 and the Python app on 8080 are bound to 127.0.0.1, so only the server can reach them. Anything you cannot explain is a question to answer before you move on.

systemctl list-units --type=service --state=running --no-pager

That command lists running services, which helps you match them to the ports above.

Step 3: Check the firewall rules

Listening and reachable are not the same thing. A firewall can block a port that a program listens on. Check what UFW allows:

sudo ufw status verbose
Status: active
To                         Action      From
--                         ------      ----
22/tcp                     ALLOW IN    Anywhere
443/tcp                    ALLOW IN    Anywhere

Ports missing from this list are blocked for incoming traffic by the default deny policy, which is the safe default.

Step 4: Scan from outside with nmap

Your own list shows what is listening. A scan from another machine shows what the network actually lets through. Install nmap on your computer, not on the server, and scan only your own VPS. The -Pn flag skips the host discovery step, which helps when a firewall hides the server from ping. Scanning the 1000 most common ports takes under a minute:

sudo apt install -y nmap
nmap -Pn 203.0.113.10
PORT    STATE    SERVICE
22/tcp  open     ssh
80/tcp  open     http
443/tcp open     https
3306/tcp filtered mysql

In the result, open means something answered, closed means the host responded but nothing listens, and filtered means a firewall dropped the probe. For a full check of all 65,535 ports, add -p-, which takes longer. To identify the software on each open port, add -sV.

Step 5: Close what you do not need

If a program listens on a port you do not need, stop it and stop it from starting again. Replace the service name with the real one:

sudo systemctl disable --now service-name.service

If a service must run but should be private, change its listen address in its own configuration to 127.0.0.1. Then re-run sudo ss -tulpn to confirm the change.

Careful: The container engine publishes ports through its own firewall rules, which can bypass UFW. A container started with -p 6379:6379 may be reachable even though UFW shows no rule for it. Run sudo ss -tulpn and an external nmap scan after every container change.
Tip: Run the nmap scan again every few months, and after each new service you install. Compare the results so you notice new openings early.

Troubleshooting

  • nmap shows a port as open that UFW should block. A program or container may be publishing it directly. Check sudo ss -tulpn and docker ps for the process that owns the port.
  • nmap shows every port as filtered. Your own network may block outbound scans, or the firewall drops everything from your address. Try from another network, and confirm SSH still works.
  • ss shows nothing for a service you started. The service may have failed or be listening on a Unix socket instead. Check systemctl status for that service, and look for a socket path in the output.
  • Port 22 shows as open but you want SSH private. Restrict SSH to your own IP with UFW, or add two-factor authentication as described in the SSH guide. Keep the rule that lets you back in.

Next steps

Now that you can see what is exposed, harden it. Add two-factor authentication to SSH to protect your login, and read the guide on recovering access with the console in case a firewall change ever locks you out.

Something not working? Chat or email our support team and we will help you get unstuck.

Contact support