dotvitals

Port Checker

Check which of 21 common TCP ports answer on a host you run, and what each open one exposes.

Only submit a host you own, operate, or have written permission to test. dotvitals cannot tell whether you have that permission, so it is stated as your obligation in the acceptable use policy, and the anonymous check is bounded to make an unauthorised one as harmless as possible: 21 named ports, one TCP connection each, nothing written to the socket.

Acceptable use policy · What the scanner probes

Try

How to fix these

One section per finding above. There is nothing to copy here — these are changes in your own configuration, so each one names where the change is made, what it can break, and how to check it worked.

Close the port, or put an access control in front of it

A port that answers from the public internet is reachable by everyone, continuously. Automated tooling connects to every address on the internet and tries; it does not need to find you first. An exposed database is one credential away from everything it holds, an exposed remote desktop is an interactive session on the machine, and plaintext FTP hands the username, the password and the file contents to anyone on the network path. What we established is narrow and sufficient: a TCP connection completed. We never authenticated, so we make no claim about whether your credentials are strong — the exposure is the finding.

Who makes this change: You — this is a change on your own site. Yours, in two places that both have to agree: the firewall on the machine, and the security group or network ACL in your cloud account. A host firewall does not protect you from a permissive cloud rule and a cloud rule does not protect you from a permissive host firewall. On managed hosting where you cannot reach either, the hosting provider's control panel is where the rule lives — and the service's own bind address is still yours to change.

Linux host — the machine's own firewall

Where: The firewall on the machine (`ufw`, `firewalld` or `nftables`), and the service's own configuration file.

  1. Find out what is listening and on which address: `sudo ss -tlnp | grep :<port>`. An address of `0.0.0.0` or `*` means every interface, including the public one.
  2. Bind the service privately as well as firewalling it. MySQL/MariaDB `bind-address = 127.0.0.1` in my.cnf; PostgreSQL `listen_addresses = 'localhost'` in postgresql.conf; Redis `bind 127.0.0.1` plus `requirepass` in redis.conf; MongoDB `net.bindIp: 127.0.0.1` in mongod.conf. Do both, because a service bound only privately is re-exposed by one package upgrade that restores a default, and a firewall rule alone is undone by one flush.
  3. With ufw, add the allow rule **before** the deny, because ufw evaluates rules in order and the first match wins: `sudo ufw allow proto tcp from 203.0.113.0/24 to any port <port>` then `sudo ufw deny <port>/tcp`. Use `sudo ufw status numbered` to read the order and `sudo ufw insert 1 …` to place a rule at the front. `sudo ufw --dry-run` prints what would change without changing it.
  4. With firewalld, remove the exposure and allow the specific source: `sudo firewall-cmd --permanent --remove-port=<port>/tcp` and `sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="203.0.113.0/24" port port="<port>" protocol="tcp" accept'`, then `sudo firewall-cmd --reload`. Nothing takes effect until the reload, which is itself a safety property.
  5. With nftables, add the accept for the allowed source before tightening the chain policy: `sudo nft 'add rule inet filter input ip saddr 203.0.113.0/24 tcp dport <port> accept'`. Single-quote the whole command so the shell does not eat the semicolons.
  6. Restart the service and confirm: `sudo ss -tlnp | grep :<port>` should now show a loopback or private address.
  7. Assume the credentials are known. Rotate the database or service passwords and read the authentication log for connections from addresses you do not recognise — do that **before** you close the port, not after, because a determined visitor will notice the door shutting.
  8. Where the service genuinely has to be reached across the internet, put it behind a VPN, an SSH tunnel or the provider's private networking rather than an address allow-list. An allow-list is better than nothing and is not an access control: it authenticates a network path, not a person.

If it goes wrong: **Read this before you run anything.** A firewall change can lock you out of the machine, and the documented mitigations differ by tool. firewalld's `--timeout=5m` adds a rule that removes itself automatically and cannot be combined with `--permanent` — it is the one genuinely self-reverting mechanism here, and the right way to test a restrictive rule. ufw prompts before enabling the firewall when you are connected over SSH, and `--dry-run` previews any command. nftables has no documented timeout equivalent. To undo: `sudo ufw status numbered` then `sudo ufw delete <number>`; `sudo firewall-cmd --reload` discards every runtime-only change; for nftables, `sudo nft -a list table inet filter` prints handles and `sudo nft delete rule inet filter input handle <n>` removes one. Keeping a second SSH session open while you work is sound practice and is our advice rather than any vendor's — it is not documented anywhere, and it does not survive a reboot, so know your provider's out-of-band console before you need it.

Cloudflare — Cloudflare is in front of the site, which does not help here

Where: Not the Cloudflare dashboard. The host firewall or the cloud security group — Cloudflare's proxy carries only HTTP and HTTPS.

  1. Rule Cloudflare out first, because it is the reasonable assumption and it is wrong: the proxy carries HTTP and HTTPS traffic only, so no Cloudflare setting closes a database, remote-desktop or FTP port.
  2. Understand why hiding the DNS record did not help. If the origin's address is known — and it is published in certificate transparency logs, old DNS history and mail headers — the port is reachable regardless of what the proxied record says.
  3. Close the port at the host firewall or the cloud security group, as in the path above.
  4. Once the port is closed, Cloudflare Tunnel or Cloudflare Access can give you back remote administration without an inbound port at all, which is a better end state than an allow-list.

If it goes wrong: Nothing is changed in Cloudflare by this path, so there is nothing to revert there. The rollback for the firewall change itself is the one in the host-firewall path above, and it applies unchanged.

Checked 2026-09. Control panels are redesigned without notice, so treat the click path as a snapshot rather than as fact.

We could not tell what runs this machine

Where: Whichever firewall the machine or its cloud account uses, plus the service's own bind address. This check identifies the port and the service by its registered name, not your platform.

  1. Confirm the exposure from outside your own network before changing anything: `nc -z -w 3 <host> <port>` from a different network. A test from inside a VPN or an office network proves nothing about the public internet.
  2. Work out who can close it. If the machine is yours, the firewall is on it; if it is a cloud instance, the security group is in front of it and both need the same rule. On managed or shared hosting, the panel your provider gives you is the only place either exists.
  3. In a cloud account, remove the wide rule rather than adding a narrow one beside it — an allow rule that stays is still an allow rule. On AWS the exact revocation is `aws ec2 revoke-security-group-ingress --group-id sg-… --protocol tcp --port <port> --cidr 0.0.0.0/0`, and security groups permit allow rules only, so there is no deny to add. Both commands accept `--dry-run`.
  4. For FTP specifically, the fix is usually removal rather than restriction: SFTP runs over SSH on port 22 and is already available on any machine you administer that way, so a deployment script that uses FTP can be moved to it without running a new service. An FTP server that offers `AUTH TLS` but does not require it still accepts a plaintext login, which is the condition that matters.
  5. For remote desktop, put a VPN, a bastion or the provider's session-manager service in front of it and confirm you can reach the machine that way **before** closing the port. Note that AWS EC2 Instance Connect is not a rescue path for a closed port 22 — its own documentation requires inbound SSH from the endpoint's security group — whereas the EC2 Serial Console and Systems Manager Session Manager do work without inbound ports, and both have to be enabled in advance.
  6. Re-test from outside afterwards. A rule that looks right in the console and a port that actually refuses are two different statements.

If it goes wrong: Set up your out-of-band access before you need it: on a cloud provider that is the serial or web console, on a dedicated host it is a KVM or a rescue mode, and on managed hosting it is your provider's panel. Every firewall command here is reversible — remove the rule you added, or re-add the one you revoked — but only if you can still reach the machine, which is why the order is: establish the other route, verify it, then close the port. In a cloud account, re-adding a revoked rule restores access in seconds and leaves no trace of the gap; note that AWS canonicalises CIDRs, so re-adding a rule in a slightly different form can be refused as a duplicate.

Checked 2026-09. Control panels are redesigned without notice, so treat the click path as a snapshot rather than as fact.

Check it worked:

  • nc -z -w 3 <host> <port> — run from outside your own network; it should fail with a refusal or a timeout
  • sudo ss -tlnp | grep :<port> — should show 127.0.0.1 or a private address, never 0.0.0.0
  • For a service you still need: connect through the VPN, bastion or tunnel and confirm it still works that way

Test again re-runs the port check from our probe host, which is outside your network, and answers in seconds — so it is the right confirmation that the port is closed to the public internet rather than only to you. It re-checks the same ports it checked before; a port we never tested is not reported closed, it is not reported at all.

Our confidence in what is behind the port is deliberately short of certain. A completed TCP handshake proves an endpoint accepted the connection; it does not prove the software the port number implies is what answered, because a proxy, a load balancer or a honeypot produces the same observation. We never authenticate, never send a protocol probe, and read only a greeting the server volunteers. The correct response is the same either way: nothing should be answering on these ports from the public internet.

NIST SP 800-41 Rev. 1 — Guidelines on Firewalls and Firewall Policy · OWASP Top 10 — A05:2021 Security Misconfiguration · ufw(8) — Ubuntu manual page · firewalld — firewall-cmd(1) · nftables wiki — quick reference · AWS — Security group rules for Amazon EC2 · CISA — Guidance on securing remote access services

About the port checker

A port check asks whether anything is listening on a given TCP port of a given host, from outside your own network. That is a different question from "is the service running", which you can answer locally, and a more useful one: a database that binds to every interface, a management panel that was opened for one afternoon two years ago, or a remote-desktop service left reachable while somebody waited for a VPN to be set up will all look healthy from inside and be visible to the whole internet from outside.

Without proving anything, this tool checks a fixed list of 21 ports — not a range, and not a sweep. They are 21, 22, 25, 53, 80, 110, 143, 443, 465, 587, 993, 995, 1433, 3306, 3389, 5432, 5900, 6379, 8080, 8443 and 27017: the web, mail and DNS ports a browser or a mail server would connect to anyway, plus the database and remote-administration ports that cause real damage when they answer a stranger. The list is published because a bounded, named list is something a server operator can check against their own expectations, and because it is the ceiling the acceptable use policy sets for a requester who has not proved they control the domain. Checking ports outside that list — 99 in total, covering admin panels, container and orchestration APIs, message brokers, search and monitoring endpoints — requires verifying ownership of the domain first, by publishing a DNS record or a file we name.

Every probe is a single full TCP connection attempt with a one-second timeout, five at a time, with a short random pause before each one. Nothing is ever written to the socket: where a banner appears in the results it is a greeting the server volunteered first, capped at a kilobyte and stripped of control characters. There is no SYN scanning, no UDP, no payload of any kind and no attempt to authenticate to anything that answers. One address is probed per host — IPv4 in preference to IPv6 — so a host with several addresses or a separate IPv6 listener is only partly covered by one run.

A port is reported as open, closed, filtered, or not tested, and those four are kept apart deliberately. Closed means the host actively refused the connection. Filtered means nothing answered within the timeout, which usually means a firewall dropped the packet but can also mean the host was busy or unreachable. Not tested means the scan ran out of its time budget or our own egress policy refused the destination — it never means closed, and a group of ports cannot be reported as clean while any member of it is untested.

What is scored is narrower than what is reported. An exposed database port (MSSQL, MySQL, PostgreSQL, Redis, MongoDB) is a critical finding; RDP or VNC reachable from the internet is high; FTP is a medium warning. SSH is listed and explained but deducts nothing — a reachable SSH port is a normal way to run a server, not a fault — and the web, mail and DNS ports deduct nothing either, because they are the services the host exists to provide. It is entirely possible to have twenty ports answering and a perfect network score.

This check needs the external probe host, because a TCP connection to an arbitrary port is one of the few things the edge cannot make. When that host is not connected, the result says that no port could be tested and names the reason. It does not report the ports as closed: a scanner that reports "nothing is open" when it measured nothing is the single most damaging false pass this product could ship.

Common questions

Which ports does the anonymous check cover?
A fixed list of 21: 21, 22, 25, 53, 80, 110, 143, 443, 465, 587, 993, 995, 1433, 3306, 3389, 5432, 5900, 6379, 8080, 8443 and 27017. It is a named list, never a range, and it is the same list on every run.
Can I scan a wider range of ports?
Yes, after verifying that you control the domain by publishing a DNS record or a file we name. That widens the check to 99 named ports. Verification is per-domain, is re-checked periodically, and lapses when control of the domain does.
Am I allowed to scan any host I like?
No. You must own the target, operate it, or have permission from whoever does. Using this against a host you are not authorised to test — including as reconnaissance — breaks the acceptable use policy and the terms of service.
What is the difference between closed and filtered?
Closed means the host actively refused the connection, so something is there and saying no. Filtered means nothing answered at all within the timeout, which usually means a firewall dropped the packet silently.
Does this send any data to the port?
No. Every probe is a TCP connect and nothing more; nothing is written to the socket. A banner shown in the results is a greeting the server sent unprompted, capped at one kilobyte.
Is an open SSH port a problem?
Not by itself, which is why it is reported and deducts nothing. Running a server usually means SSH is reachable. It is worth knowing it is there, and worth restricting by source address or moving behind a bastion if you can, but it is not a fault.
Why does it say no port could be tested?
The port check runs on an external probe host, and that host was not reachable for this run. The result reports that nothing was measured rather than reporting the ports as closed, because an unmeasured port is not a safe one.
Can I ask you to stop scanning my server?
Yes. The scanner policy page publishes our egress addresses so you can block them, and an opt-out address for a request covering your domain.
What this tool checks (6 rules)
  • net.ports.database-exposed — A database port is reachable from the internet
  • net.ports.ftp-exposed — FTP is reachable from the internet
  • net.ports.open — Ports reachable from the internet
  • net.ports.probe-unavailable — No port could be tested
  • net.ports.remote-admin-exposed — A remote desktop service is reachable from the internet
  • net.ports.ssh-exposed — SSH is reachable from the internet