You opened a port, the firewall says it is allowed, and the connection still times out or gets refused. The firewall rule is only one of several layers a connection passes through. This guide walks through each layer in order, on Linux and Windows, so you can find the one that is actually blocking traffic.
Before you start
- The server's public IP from your VPS provider's control panel. The examples use
203.0.113.10and port8080. - A shell on the server (SSH on Linux, Remote Desktop on
203.0.113.10:3389for Windows). - A second machine outside the server, such as your own computer, to test from.
Warning: While you debug, do not turn on a default-deny policy or reset a firewall without first allowing your way in: SSH on Linux, or TCP 3389 for Remote Desktop on Windows. If you lose access anyway, use the browser console in your VPS provider's control panel.
Read the error first
The error tells you which layer to look at:
- Connection refused: the packet reached the server, but nothing listens on that port and address. Start with the service.
- Timed out: the packet was dropped somewhere. Start with the firewall layers.
- Connects, then the app shows an error: the network is fine. Look at the application's own logs or config.
Layer 1: is the service listening?
Linux
sudo ss -tulpn | grep ':8080'Look at the local address column:
0.0.0.0:8080or[::]:8080or*:8080: listens on all interfaces. Good.127.0.0.1:8080or[::1]:8080: listens on localhost only. Outside clients can never reach it, whatever the firewall says.- No line at all: the service is not running, or uses another port.
To fix a localhost binding, change the service's listen address. Common examples:
- MySQL/MariaDB:
bind-addressin the server config. - Node.js: pass
0.0.0.0as the host tolisten. - Docker: publish
-p 8080:80, not-p 127.0.0.1:8080:80.
Often the safer choice is to keep the service on localhost and put a reverse proxy such as Nginx in front.
Windows
Get-NetTCPConnection -State Listen -LocalPort 8080A LocalAddress of 0.0.0.0 or :: means all interfaces. 127.0.0.1 means localhost only.
Layer 2: test from the server itself
Rule out the application before you blame the network.
curl -v http://127.0.0.1:8080/
nc -vz 127.0.0.1 8080If even this fails, fix the service first. The network is not the problem yet.
Layer 3: the server firewall
Check every firewall tool that might be active. More than one can be running at once, and each can block.
Linux
sudo ufw status verbose
sudo firewall-cmd --list-all
sudo nft list ruleset
sudo iptables -SThings to look for:
- The rule names the right protocol. A
8080/udprule does nothing for TCP. - No
denyordroprule sits above your allow rule. - The rule covers IPv6 too, if the client connects over IPv6.
- On firewalld, the rule is in the zone bound to your public interface, and you ran
--reloadafter a--permanentchange. - Docker publishes ports through its own rules, which UFW does not see. That causes the opposite problem, ports open that you thought closed.
Windows
Get-NetFirewallPortFilter -Protocol TCP |
Where-Object LocalPort -eq 8080 |
Get-NetFirewallRule |
Format-Table DisplayName, Enabled, Direction, Action, ProfileMake sure the rule is enabled, Inbound, set to Allow, and applies to the active profile. Check the profile with Get-NetConnectionProfile. A block rule always wins over an allow rule in Windows Firewall.
Layer 4: other software on the server
- Fail2ban or CrowdSec may have banned your test IP. Run
sudo fail2ban-client statusand check each jail. - SELinux on AlmaLinux and Rocky can stop a service binding to a non-standard port. Check
sudo ausearch -m avc -ts recent. - Antivirus or security suites on Windows can have their own firewall.
- The app's own allowlist, such as
pg_hba.conffor PostgreSQL orbind-addressfor MySQL, may reject your IP.
Layer 5: the client side
The block can be on your side:
- Office, school and hotel networks often allow only a few outbound ports. Test from a phone hotspot.
- A VPN on your computer may route traffic differently.
- A local antivirus or corporate firewall may filter outbound connections.
Test from outside
From your own computer:
nc -vz -w 5 203.0.113.10 8080On Windows:
Test-NetConnection 203.0.113.10 -Port 8080To see whether packets reach the server at all, capture on the server while you test from outside:
sudo tcpdump -ni any tcp port 8080- No packets appear: they are dropped before the server, on the client network or an upstream filter.
- SYN packets arrive but no reply: the server firewall is dropping them.
- SYN arrives and a RST goes back: nothing listens. Go back to layer 1.
Check it works
The port is fixed when:
nc -vzfrom an outside machine reports success.- The application responds normally, for example a page loads in the browser.
- The test still passes after a reboot, which proves the rule and the service settings are saved.
Troubleshooting
- Works on IPv4, fails on IPv6: the service or firewall rule covers only one family. Check both with
ssand your firewall's IPv6 rules. - Works locally, times out remotely, firewall looks right: run
tcpdump. If nothing arrives, the block is upstream or on the client network. Open a ticket with your test results. - Port 25 times out outbound: outgoing mail ports are filtered on many networks. See Port 25 blocked on a VPS.
- Remote Desktop fails: Remote Desktop uses TCP 3389 by default. See Test RDP port 3389.
Next steps
- List everything that listens: Check which ports are open and listening on Linux.
- Test ports from any machine: Test a port with nc and telnet.
- Learn which ports to expose: Common server ports and what uses them.
