Back to tutorials
Tutorial

Firewall troubleshooting tutorial (2026): Diagnose blocked ports, broken DNS, and locked-out SSH on a hosting VPS

Firewall troubleshooting tutorial for VPS: fix blocked ports, DNS failures, and SSH lockouts with practical checks and safe rollback steps.

By Anurag Singh
Updated on Jul 04, 2026
Category: Tutorial
Share article
Firewall troubleshooting tutorial (2026): Diagnose blocked ports, broken DNS, and locked-out SSH on a hosting VPS

Most “firewall problems” on a VPS don’t come from one bad rule. They usually stack up across layers: UFW/firewalld policy, cloud security groups, and service bind addresses. One quiet culprit can also break everything: outbound DNS. This firewall troubleshooting tutorial gives you a repeatable workflow to find what is actually blocking traffic, without “fixing” it by opening the server to the internet.

The examples use Ubuntu 24.04/25.04 tooling (UFW + systemd). The same checks also work on Debian and RHEL-family servers (AlmaLinux/Rocky) with firewalld.

If you host websites, email, or a control panel on a VPS, the goal stays the same. Restore access safely. Then leave a clear audit trail of what changed.

Before you touch rules: map what’s blocked and from where

Write down three things first. It’s faster than guessing. It also prevents “fixes” that only work from your office IP.

  • What protocol/port? (SSH 22, HTTP 80, HTTPS 443, SMTP 587, IMAP 993, cPanel 2083, WHM 2087, etc.)
  • Direction? Inbound (clients can’t reach you) vs outbound (your server can’t resolve DNS, fetch updates, send mail).
  • Scope? Everyone, or only certain networks/countries?

If you don’t have console access, get it now. A hosting VPS needs an out-of-band path.

Use a provider console, rescue mode, or a temporary management IP.

If you don’t want to maintain that operational overhead, managed VPS hosting from HostMyCode is designed for the exact moment you realize you’ve locked yourself out.

Fast triage checklist (10 minutes)

Run these on the server (console/SSH if you still have it). This gives you a baseline before you change anything.

# 1) What is the server actually listening on?
ss -lntup

# 2) Are packets being dropped by nftables/iptables?
sudo nft list ruleset | sed -n '1,160p'

# 3) Is UFW involved?
sudo ufw status verbose

# 4) Is firewalld involved? (RHEL/Alma/Rocky)
sudo systemctl is-active firewalld || true

# 5) Quick local connectivity to your own services
curl -I http://127.0.0.1
curl -Ik https://127.0.0.1

# 6) Can you resolve DNS (outbound UDP/TCP 53)?
resolvectl status || true
getent hosts hostmycode.com

# 7) Can you reach the internet on 443 (outbound)?
curl -sS https://www.example.com/ -o /dev/null -w '%{http_code}\n'

Interpretation hints:

  • If ss -lntup shows nothing on 0.0.0.0:80/443, the firewall might be innocent. Your web server may only bind to localhost, or it may be down.
  • If DNS lookups fail but curl https://1.1.1.1 works, you likely have a resolver issue. Another common cause is outbound UDP/TCP 53 being blocked.
  • If localhost curl works but remote curl fails, that’s almost always firewall or upstream filtering.

Step 1: confirm it’s not a “service bind” issue

A common trap: you open the port, but the service only listens on 127.0.0.1. Check the bind address in ss before you touch any rules.

# Example output patterns:
# LISTEN 0 511 0.0.0.0:443   ...  (good for public HTTPS)
# LISTEN 0 511 127.0.0.1:443 ...  (only local)
ss -lntp | egrep ':22|:80|:443|:2083|:2087|:587|:993' || true

If you see 127.0.0.1:80 or 127.0.0.1:443, fix the web server config first.

For Nginx, this is usually in /etc/nginx/sites-enabled/. Look for listen 80; and listen 443 ssl;.

For Apache, check /etc/apache2/ports.conf and your vhost files.

Once the service listens publicly, test locally and remotely again. Don’t move on until those results line up.

Step 2: identify which firewall layer is blocking you

On VPS hosting, traffic can be filtered in three places:

  1. In-OS firewall (nftables via UFW, or firewalld)
  2. Provider edge filtering (sometimes called “network firewall”)
  3. Per-instance security rules (security groups, ACLs, “allowed ports” in a panel)

A useful rule of thumb: if the server never sees or logs the packet, the drop is probably upstream.

Test from two different sources if you can. Use your home IP and a mobile hotspot.

Add a third viewpoint if possible, such as a monitoring node or a small remote VPS.

If you run production sites, predictable networking pays off. A HostMyCode VPS gives you clean routing, consistent reverse DNS options, and a stable baseline for firewalling and mail deliverability.

Step 3: use logging without flooding your disk

Stop guessing and start collecting evidence. Enable temporary, low-volume logging for the traffic you’re debugging.

Once you confirm the cause, turn logging back down.

On Ubuntu/Debian with UFW

# Set logging to low (not full) to avoid log storms
sudo ufw logging low

# Watch logs in another terminal
sudo journalctl -f | egrep -i 'UFW|BLOCK|DROP'

If UFW logs aren’t specific enough, check nftables counters and rule handles:

sudo nft -a list ruleset | sed -n '1,220p'

On AlmaLinux/Rocky with firewalld

sudo firewall-cmd --state
sudo firewall-cmd --get-active-zones
sudo firewall-cmd --list-all

# System log tail
sudo journalctl -f | egrep -i 'firewalld|DROP|REJECT'

Step 4: safely recover from an SSH lockout (without disabling the firewall)

If you’re already locked out, switch to provider console/rescue mode. The goal isn’t “turn everything off.”

Restore just enough access to get back in. Then tighten the policy again.

  1. Confirm SSH is listening: ss -lntp | grep :22
  2. Confirm SSH config allows your auth: check /etc/ssh/sshd_config and /etc/ssh/sshd_config.d/*.conf
  3. Fix firewall rule for port 22: allow from your IP or a temporary trusted range

UFW: allow SSH from your IP only (recommended)

# Replace with your current public IP
MYIP="203.0.113.10"

sudo ufw allow from "$MYIP" to any port 22 proto tcp
sudo ufw status numbered

If your IP changes often (travel, consumer ISP), treat the rule as temporary. Remove it later.

Don’t leave “anywhere to 22” open unless you also enforce key-only auth and rate limiting.

For a deeper SSH attack/lockout workflow, see our internal guide: SSH brute-force troubleshooting.

firewalld: add SSH to the active zone

# Usually 'public' zone, but confirm first
sudo firewall-cmd --get-active-zones
sudo firewall-cmd --zone=public --add-service=ssh
sudo firewall-cmd --zone=public --add-service=ssh --permanent

Step 5: diagnose “web works locally but not remotely” (HTTP/HTTPS)

This shows up a lot after a migration, an Apache→Nginx switch, or adding a reverse proxy. Local checks pass. The outside world can’t connect.

Confirm the port is allowed inbound

On the server:

sudo ufw status verbose | egrep -i '80|443' || true
sudo firewall-cmd --list-ports || true
sudo firewall-cmd --list-services || true

From a remote machine:

# Replace with your server IP
SERVERIP="198.51.100.20"

curl -I "http://$SERVERIP" --max-time 5
curl -Ik "https://$SERVERIP" --max-time 5

Watch for “REJECT” vs “DROP”

  • REJECT fails fast. That usually points to in-OS firewall policy.
  • DROP hangs until timeout. That can mean upstream filtering or a DROP policy.

Reverse proxy edge case: wrong interface

If you run Nginx in front of Apache/cPanel, keep the split clean. Apache should listen on a private port (like 8080). Only Nginx should be public.

If those roles overlap, it can look like a firewall issue. In reality, it’s often bind/port confusion.

Related internal tutorial: Nginx reverse proxy in front of Apache/cPanel.

Step 6: fix outbound DNS and package updates (the hidden firewall failure)

Outbound DNS failures trigger a chain reaction. Let’s Encrypt renewals die. OS updates fail.

WordPress can’t reach APIs. Mail tools can’t resolve MX records.

People often chase the wrong layer because the website still loads.

Verify resolvers and basic DNS

# Show resolver configuration (systemd-resolved systems)
resolvectl status || true

# Does it resolve at all?
getent ahosts google.com

# Try direct queries if you have dig installed
dig +short A hostmycode.com @1.1.1.1 || true
dig +short A hostmycode.com @8.8.8.8 || true

If direct DNS to 1.1.1.1 works but normal lookups fail

This is usually local resolver plumbing. Common causes include a bad /etc/resolv.conf symlink, broken systemd-resolved, or a stub resolver pointing nowhere.

Fix that first. Changing firewall policy won’t help if the resolver configuration is wrong.

If direct DNS fails too

You’re likely dealing with outbound UDP/TCP 53 being blocked. That’s uncommon on default installs.

It is common on hardened builds and some provider network policies.

Concrete test:

# UDP 53 test (requires netcat-openbsd on Debian/Ubuntu)
# You'll see 'succeeded' or a timeout
nc -vzu 1.1.1.1 53

# TCP 53 test (DNS can fall back to TCP)
nc -vz 1.1.1.1 53

If you intentionally restrict egress, whitelist DNS and HTTPS at minimum. Let’s Encrypt and OS updates depend on 443.

For Let’s Encrypt specifics, keep this bookmarked: SSL renewal troubleshooting.

Step 7: mail ports and control panels—common “it worked yesterday” breakages

Email and admin panels fail in ways that feel random. The causes are usually consistent once you look closely.

Start with ports and connectivity. Then dig into TLS negotiation issues or IP reputation.

Mail ports you typically need open

  • SMTP submission: 587/tcp (recommended)
  • SMTPS: 465/tcp (sometimes used)
  • IMAPS: 993/tcp
  • POP3S: 995/tcp (if you support POP)

Quick remote check from your laptop (macOS/Linux):

SERVER="mail.example.com"

# Check STARTTLS on 587
openssl s_client -starttls smtp -connect "$SERVER:587" -servername "$SERVER" </dev/null

# Check IMAPS
openssl s_client -connect "$SERVER:993" -servername "$SERVER" </dev/null

If 587 is blocked, users often fall back to port 25. Then they hit throttling or outright blocks.

Fix submission first.

Two related internal guides that pair well with this workflow:

cPanel/WHM ports (if you run a control panel)

  • cPanel: 2083/tcp
  • WHM: 2087/tcp
  • Webmail: 2096/tcp

If you lock these down (you should), use allowlists instead of opening them globally. For a clean pattern, see cPanel IP whitelisting.

Step 8: packet path debugging with tcpdump (prove what the server sees)

When a port “looks open” but clients still can’t connect, capture traffic. In a few minutes, you can answer the key question.

Do packets reach the VPS at all?

# Install tcpdump if needed
sudo apt-get update && sudo apt-get install -y tcpdump || true

# Watch SSH attempts hitting the server (replace eth0 if needed)
sudo tcpdump -ni any tcp port 22

# Watch HTTPS attempts
sudo tcpdump -ni any tcp port 443

What you want to see: SYN packets arriving when you try to connect remotely. If you see nothing, the block is upstream.

Common upstream causes include provider firewall rules, security groups, the wrong IP, or routing/DNS issues.

Step 9: common mistakes that cause self-inflicted outages

  • Rule order surprises: a broad deny earlier in the chain overrides a later allow (common in raw nftables/iptables setups).
  • Wrong interface assumptions: on systems with ens3/enp1s0 naming, scripts that assume eth0 can miss rules tied to an interface.
  • IPv6 ignored: you lock down IPv4 but forget IPv6, or the reverse. Users on IPv6-only networks then fail.
  • Blocking outbound 443: breaks updates, Let’s Encrypt, plugin stores, and API calls.
  • Geo-blocking without exceptions: blocks your own payment gateway callbacks, uptime monitors, or CDN PoPs.

Step 10: build a safer rollback plan for firewall changes

If you manage servers long enough, you’ll ship a bad rule. The difference between a scare and an outage is the rollback plan.

Use a timed rollback while testing (simple, effective)

Before applying risky changes over SSH, schedule an automatic rollback for 2–3 minutes later. If you lose access, wait it out and reconnect.

# Example for UFW: disable after 3 minutes unless you cancel
# (Run in a screen/tmux session if possible)

sudo bash -c 'sleep 180; ufw disable' &
ROLLBACK_PID=$!

echo "Rollback PID: $ROLLBACK_PID"

# Apply your change now, test connectivity, then cancel rollback:
# sudo kill $ROLLBACK_PID

On systems where disabling the firewall is too blunt, back up the exact ruleset first:

# Backup nftables ruleset
sudo nft list ruleset > /root/nftables.ruleset.backup.$(date +%F-%H%M)

Document the “known good” baseline

For hosting workloads, a reasonable baseline usually looks like this:

  • Allow inbound: 22 (restricted), 80/443, plus mail/control panel ports you explicitly offer
  • Allow outbound: DNS (53 udp/tcp), HTTP/HTTPS (80/443), NTP (123 udp), SMTP (587/465/25 if needed)
  • Log only what you can act on (otherwise you’ll train yourself to ignore it)

Verification: prove the fix from outside your network

After changes, test from at least two external sources. If you only test from your office, allowlists and geo rules can fool you.

  • Run curl -I against HTTP/HTTPS from a second network
  • Use openssl s_client for mail ports
  • Confirm DNS from the server: getent hosts
  • Confirm the process is listening: ss -lntup

If the issue involved DNS records, set a proper TTL strategy and a rollback plan next time. Our step-by-step approach is here: DNS propagation tutorial.

Summary: your repeatable firewall debugging workflow

  1. Confirm the service listens publicly (not just localhost).
  2. Separate inbound vs outbound failures (DNS/443 egress bites often).
  3. Identify the layer: in-OS firewall vs upstream filtering.
  4. Add temporary, low-volume logging or counters to stop guessing.
  5. Use tcpdump to prove whether packets reach the VPS.
  6. Deploy changes with a rollback timer, then remove temporary rules.

If you want a VPS environment where firewall policy, reverse DNS, and support paths are built for hosting operations, start with HostMyCode VPS.

If you’d rather have an experienced admin handle hardening and recovery playbooks, choose managed VPS hosting and stay focused on your sites and customers.

If you’re dealing with blocked ports or locked-out admin access, you need two things: reliable console access and a network baseline you can predict. HostMyCode offers VPS hosting for hands-on admins and managed VPS hosting for fast recovery when you don’t want to troubleshoot under pressure.

FAQ

How do I tell if the firewall or the service is the problem?

If curl http://127.0.0.1 works but remote curl http://SERVERIP times out, the service is up and the block is on the path (firewall/upstream). If localhost fails, fix the service first.

Why does my website work but Let’s Encrypt and updates fail?

That’s usually outbound DNS (UDP/TCP 53) or outbound 443 being blocked. Websites can still serve traffic while the server can’t resolve names or reach external APIs.

What’s the safest way to change firewall rules over SSH?

Use a timed rollback (sleep + revert) before applying risky changes. Also add a temporary allow rule for your IP to keep an escape hatch.

Do I need to worry about IPv6 firewalling?

Yes. If your VPS has IPv6 enabled, users may connect over IPv6 even when IPv4 is fine. Ensure your policy covers both stacks or explicitly disables IPv6 if you don’t use it.

What ports should I open for a typical hosting VPS?

At minimum: 80/443 for web, 22 for SSH (restricted), and whichever mail/control panel ports you actively provide (587/993, 2083/2087, etc.). Keep everything else closed and document why each open port exists.