NetGrid Host

Open ports, firewalls and "why my port shows closed from outside"

We don't manage your VPS ports — every port is open by default except the SMTP family. If an external port checker shows your port as closed, it's almost always one of three things inside your VM: nothing actually listening, the wrong firewall is on, or the service is bound to localhost only. Here's how to diagnose each case.

9 min read·Last updated 2026-05-03

Several times a week we get a ticket that says some variant of: "I opened port 8080 but Yougetsignal/CanYouSeeMe shows it as closed, please open it on your side". The honest answer is that there is no "our side" to toggle. On the OUTER firewall (our network edge), every TCP and UDP port is open inbound and outbound by default — only outbound SMTP is restricted on consumer plans. There is also an INNER firewall living inside the operating system of your VPS (ufw / firewalld / iptables / Windows Defender) which we don't have access to and cannot touch. When an external checker says "closed", the inner firewall or a missing/misconfigured listener inside the VPS is what's blocking. This article explains both layers and how to debug each one.

Two firewalls, two different owners — read this first

Between the public internet and a service running inside your VPS there are TWO firewall layers, owned by two different parties. Confusing them is the single most common reason these tickets exist:

Outer layer — OUR network firewall (datacenter edge)Owned by us. All TCP/UDP ports open inbound and outbound by default. ICMP allowed both ways. No per-customer toggles, no "security groups". Only outbound SMTP is blocked for consumer plans (see the SMTP section below).
Inner layer — the OS firewall INSIDE your VPSOwned by you. ufw, firewalld, iptables/nftables on Linux; Windows Defender / Windows Firewall on Windows; plus per-service rules (SELinux, Docker, application-level binds). We don't have access to your operating system, we don't see your rules, we cannot change them.

Practical consequence: when an external port checker says "closed", the layer that's blocking it is almost always the inner one — the OS firewall inside the VPS, or the service not listening. We cannot see or fix that from our side; the diagnosis steps below run inside the VPS and they are yours to perform.

What our outer network layer does (and doesn't do)

  • All TCP ports 1–65535: open inbound and outbound by default at the network edge.
  • All UDP ports 1–65535: open inbound and outbound by default at the network edge.
  • ICMP (ping/traceroute): allowed in both directions.
  • Single exception: outbound SMTP ports are blocked at the network edge for non-corporate plans (see next section).
  • We don't inspect, throttle or filter any other traffic on this layer. What you put on a port, how you bind it, and how you secure it inside the VPS is entirely your responsibility.
If you can't reach your service from outside, the problem is inside the VPS in 99% of cases
We can confirm this in one second from our side: if our network monitoring shows the VM is up and reachable, the path between the public internet and your VM's network interface is working. The packet is arriving at the VPS. What happens after it arrives is determined by your OS firewall, your service binding, and your application — none of which we touch.

Why outbound SMTP is blocked (and how to lift it)

Outbound SMTP — the protocol used to deliver email — is the one network restriction we apply by default on consumer plans. Specifically:

TCP port 25Plain SMTP between mail servers (MX delivery) — BLOCKED outbound by default
TCP port 465SMTP over implicit TLS (legacy submission) — BLOCKED outbound by default
TCP port 587SMTP submission with STARTTLS (modern client→relay) — BLOCKED outbound by default
TCP port 2525Common alternative submission port used by some relays — BLOCKED outbound by default

Why this exists: a freshly-rented VPS is one of the most common places to launch outbound spam from. A single compromised customer can poison the entire IP block's reputation in hours — Spamhaus, SpamCop, Barracuda and Microsoft will list it, and every other customer sharing the same /24 starts seeing their legitimate mail bounced for weeks afterwards. We block port 25 and friends by default specifically so that one careless customer cannot ruin email deliverability for everyone else on the block.

If you have a legitimate need to send mail directly (your own corporate mail server, a high-volume newsletter platform, a transactional mail backend), we can lift the SMTP restriction after a brief verification of the company / project. Open a ticket from your client area and tell us which domain you'll send from, what kind of volume, and which provider you're migrating from — typical turnaround is the same day.

If you don't need to send mail directly — don't fight us on this
Use a transactional mail provider (Postmark, Mailgun, SendGrid, Brevo, Resend, AWS SES). They give you better deliverability than any single self-hosted setup, they handle the IP reputation problem for you, and most of them have a free tier that fits hobby projects. Trying to push raw SMTP from a fresh VPS in 2026 is a losing battle even when nobody is blocking it for you.

"Open port" vs "service listening" — the most common confusion

An external port checker (yougetsignal.com, canyousee.me, nmap from another machine) reports "open" only if a process is actually accepting connections on that port. Just "opening" the port in a firewall is not enough — somebody has to be listening on the other side. If nothing is listening, the kernel sends back a TCP RST and the checker says "closed", regardless of any firewall rule.

The correct mental model is two separate questions:

  1. Is a process listening on the port? (your application's job)
  2. Does the firewall allow incoming traffic to that port? (your OS's job)

Both must be true simultaneously. Most "closed port" tickets fail on question 1, not question 2.

Step 1 — check what's actually listening

Run this from inside the VM:

# Modern systems (Linux):
ss -tlnp                # TCP listeners with process names
ss -ulnp                # UDP listeners with process names

# Old/portable:
netstat -tlnp

# Filter to a specific port:
ss -tlnp | grep :8080

Read the output carefully. The Local Address column tells you not just the port but also which interface the process is bound to:

0.0.0.0:8080Listening on ALL IPv4 interfaces — reachable from outside ✓
[::]:8080Listening on ALL IPv6 interfaces — reachable from outside (over IPv6) ✓
127.0.0.1:8080Listening only on localhost loopback — NOT reachable from outside ✗
[::1]:8080IPv6 localhost only — NOT reachable from outside ✗
<your-public-ip>:8080Bound to the public IP only — reachable from outside ✓
(no output for the port)Nothing is listening — your service hasn't started, or it crashed
Bound to 127.0.0.1 — the silent killer
Many default configurations of nginx, Apache, MySQL, PostgreSQL, Redis, Node.js, Flask, Django, FastAPI bind to 127.0.0.1 only — for security. The service runs, you see it locally, but the outside world will never reach it. Common fixes: nginx → listen 0.0.0.0:80; mysql/mariadb → bind-address = 0.0.0.0 in my.cnf; PostgreSQL → listen_addresses = '*' in postgresql.conf + matching pg_hba.conf line; Node/Python apps → bind to 0.0.0.0 instead of localhost or 127.0.0.1.

Step 2 — figure out which firewall is actually active

On a fresh Linux VPS you can have any combination of these in play, often without realising it:

  • iptables — the classic Linux packet filter. Even if you've never touched it, distros sometimes ship default rules.
  • nftables — the modern replacement for iptables. Debian 11+, Ubuntu 22.04+, RHEL 8+ ship nftables by default and may translate iptables rules through it.
  • ufw (Ubuntu / Debian) — a friendly wrapper over iptables/nftables. If you ran `ufw enable` and forgot, all incoming traffic except what you explicitly allowed is dropped.
  • firewalld (CentOS, RHEL, Rocky, AlmaLinux, Fedora) — zone-based wrapper over nftables. Default zone often allows only ssh + dhcpv6-client.
  • iptables-services legacy package — sometimes installed alongside firewalld and one of them will actually be enforcing.
  • Container-level rules (Docker, Podman) — Docker rewrites iptables to expose container ports. A `docker run -p 80:80` adds rules; `docker run -p 127.0.0.1:80:80` exposes only on localhost (see Step 1).

Quick survey commands:

# Is ufw active?  (returns 'Status: active' or 'Status: inactive')
sudo ufw status verbose

# Is firewalld active?
sudo systemctl is-active firewalld
sudo firewall-cmd --state
sudo firewall-cmd --list-all       # rules in the default zone

# What rules are actually loaded in the kernel?
sudo iptables -L -n -v             # IPv4 (also shows nftables-translated rules)
sudo ip6tables -L -n -v            # IPv6
sudo nft list ruleset              # native nftables view

# Did Docker add any rules?
sudo iptables -L DOCKER -n -v 2>/dev/null
sudo iptables -L DOCKER-USER -n -v 2>/dev/null

If `iptables -L` shows policy ACCEPT and no DROP/REJECT rules, no firewall is blocking inbound traffic — your problem is somewhere else (most likely Step 1, listener binding). If you see lines with `target=DROP` or `target=REJECT` matching your port — that's your culprit.

Step 3 — open the port in the firewall (if you actually need to)

# ufw (Ubuntu/Debian):
sudo ufw allow 8080/tcp
sudo ufw reload

# firewalld (RHEL/CentOS/Rocky):
sudo firewall-cmd --permanent --add-port=8080/tcp
sudo firewall-cmd --reload

# nftables direct:
sudo nft add rule inet filter input tcp dport 8080 accept

# iptables direct (volatile — won't survive reboot without iptables-persistent):
sudo iptables -I INPUT -p tcp --dport 8080 -j ACCEPT

Other classic gotchas we see in tickets

  • SELinux blocking the bind itself. On RHEL/Rocky/AlmaLinux a service may refuse to bind to a non-default port because SELinux policy doesn't allow it. Check with `sudo ausearch -m AVC -ts recent` or temporarily `setenforce 0` to test (don't leave it that way).
  • Service listens on IPv6 only and you're testing over IPv4. Common with Java apps and some Python frameworks. Check `ss -tlnp` for `[::]:port` vs `0.0.0.0:port`.
  • Cloud-init or your hosting panel re-enables a firewall on reboot. If your service worked yesterday and stopped today after a reboot — `systemctl status ufw firewalld iptables`.
  • You're testing from inside the same VPS with `curl http://your-public-ip` and getting connection refused. Some routing setups don't allow loopback through the public IP. Test from a different machine or `curl https://canyousee.me` from your laptop.
  • A DNS A record points to the wrong IP. The port is open but you're testing the wrong server. Confirm with `dig +short yourdomain.com` from your laptop.
  • UDP service with no conntrack rule. UDP is connectionless; some firewall setups need an explicit return-path rule. Most distros handle this automatically, but custom setups can drop the reply.
  • Wrong network interface. On a multi-NIC VPS or with VPN/WireGuard interfaces present, your service may bind to the wrong one. Check the interface name in `ip -br addr` and bind your service explicitly.

Quick decision tree

  1. External checker says "closed". Run `ss -tlnp | grep :PORT` inside the VM. No output? → start your service. Bound to 127.0.0.1? → rebind to 0.0.0.0. Bound to 0.0.0.0? → continue.
  2. Service is on 0.0.0.0:PORT. Run `sudo ufw status` and `sudo systemctl is-active firewalld`. Either active and missing a rule? → add the rule above.
  3. Both clean. Run `curl -v http://YOUR-PUBLIC-IP:PORT` from a DIFFERENT machine (not the VPS itself). If it works — the original checker was confused (or DNS is wrong). If it fails with `Connection refused` — re-check Step 1; with `Connection timed out` — re-check Step 2.
  4. Still nothing? Then it's worth opening a ticket. Include: output of `ss -tlnp`, output of `sudo iptables -L -n -v`, the exact public IP you're trying to reach, and the test command you ran from the external machine.

Related: the network layer underneath all this is covered in How shared 1 Gbps ports work in VPS hosting. If your problem is "the port works but it's slow", that's the internet speed article, not this one.

Bottom line
We don't gatekeep your ports — everything except the SMTP family is open by default. "Port closed from outside" almost always means one of: nothing is listening on the port, the service is bound to 127.0.0.1, or you have a local firewall (ufw / firewalld) running that you forgot about. The four commands `ss -tlnp`, `sudo ufw status`, `sudo firewall-cmd --list-all` and `sudo iptables -L -n -v` will diagnose 95% of these cases in under a minute.

NetGrid Host

VPS from€1.99/ month

Unlimited traffic, a 1 Gbps port and NVMe storage. 12 locations across Europe & the US.

Unlimited traffic·1 Gbps port·12 locations