Canadian cloud in Montréal · VMs from 8.50 CAD/month

Cloud firewall: protecting a VM, a walkthrough

A test service forgotten on port 8080, visible to the whole Internet. We put on a firewall from the console, check from the outside, restrict SSH and filter outbound traffic, with the real output at each step.

Three streams facing a barrier: two reach the machine, the third is stopped

A service started for a test, an admin panel left on its default port, a database listening on every interface: on a machine exposed to the Internet, the trouble rarely comes from the services you meant to run. It comes from the others. A firewall closes by default everything you did not decide to open.

The FFxF firewall is managed from the console, with nothing to install in the machine. It protects Linux, Windows or BSD the same way, and a mistake in the system's configuration cannot switch it off. This guide puts one on a real machine, from the starting point to outbound rules, with the actual output at each step.

1. What the Internet sees

The demo machine runs SSH, plus a small HTTP service on port 8080, started for a test and forgotten. On the system side, both listen on every address:

bash
$ ss -ltn
LISTEN  0  128   0.0.0.0:22     0.0.0.0:*
LISTEN  0  5     0.0.0.0:8080   0.0.0.0:*
LISTEN  0  128      [::]:22        [::]:*

From another machine, anywhere on the Internet, both ports answer, and the internal page shows up:

bash
$ for p in 22 8080; do timeout 5 bash -c "</dev/tcp/23.159.52.19/$p" && echo "$p open"; done
22 open
8080 open
$ curl http://23.159.52.19:8080/
admin interne

Without a firewall, an FFxF machine accepts all inbound traffic: that is what a bare server does, and choosing what stays open is up to you.

2. Create the firewall

In the console, under Firewalls, create a firewall named web. It starts with SSH and ping open. The shortcuts above the rule form fill in protocol and ports in one click: Web adds TCP 80 and 443. The same through the API:

bash
curl -s -X POST https://api.ffxf.net/v1/firewalls \
     -H "Authorization: Bearer $FFXF_TOKEN" \
     -H "Content-Type: application/json" \
     -d '{
           "name": "web",
           "rules": [
             {"protocol": "tcp", "ports": "22", "description": "SSH"},
             {"protocol": "tcp", "ports": "80,443", "description": "Web"},
             {"protocol": "icmp", "description": "Ping"}
           ]
         }'

A firewall is a reusable set of rules. Until it is attached to a machine, it filters nothing.

3. Attach it to the machine

On the firewall's page, pick the machine from the list and click Attach. Through the API, it is one call:

bash
curl -s -X POST https://api.ffxf.net/v1/firewalls/3/members \
     -H "Authorization: Bearer $FFXF_TOKEN" \
     -H "Content-Type: application/json" \
     -d '{"vm": 150}'

{"data":{"vm":150,"hostname":"lb-test","status":"applied"}}

applied means the rules are saved. They take effect within about ten seconds. As soon as a machine has at least one firewall, any inbound traffic no rule opens is dropped.

4. Check from the outside

bash
$ for p in 22 8080; do timeout 5 bash -c "</dev/tcp/23.159.52.19/$p" && echo "$p open" || echo "$p filtered"; done
22 open
8080 filtered
$ curl -m 5 http://23.159.52.19:8080/
curl: (28) Connection timed out after 5002 milliseconds

Port 8080 no longer answers at all: the connection gets no reply at all, so there is no refusal to confirm a machine sits behind it. SSH and ping still work. The forgotten service still runs inside the machine; it just cannot be reached from the Internet anymore.

Three things are never filtered: replies to connections the machine opens itself (updates, downloads, API calls), its private networks, and the panel's web console, which reaches the machine even with every rule closed.

5. Restrict SSH to one address

A rule can accept only some sources: an address or a range, IPv4 or IPv6. To open SSH to the office only:

bash
{"protocol": "tcp", "ports": "22", "sources": ["203.0.113.0/24", "2001:db8::/32"], "description": "SSH office"}

Always keep a way in. A firewall that does not open TCP 22 (or 3389 on Windows) cuts SSH to every machine it protects. The web console is still there to fix it, but a script or an agent working over SSH loses its machine.

6. Outbound rules

By default, everything may go out. As soon as one of the machine's firewalls has an outbound rule, only what outbound rules open can leave, plus DNS to FFxF's resolvers and the private network. Let us add a single rule: HTTPS out.

bash
{"direction": "out", "protocol": "tcp", "ports": "443", "description": "HTTPS out"}

From the machine, a few seconds later:

bash
$ curl -s -o /dev/null -w "%{http_code}\n" https://deb.debian.org/
200
$ curl -m 6 http://deb.debian.org/
curl: (28) Connection timed out after 6002 milliseconds
$ getent hosts deb.debian.org
2a04:4e42:400::644 debian.map.fastlydns.net

HTTPS goes through, HTTP is blocked, and name resolution still works. The first outbound rule closes everything else: on a machine that installs packages over HTTP, open port 80 as well. Port 25 stays closed whatever the rules say.

7. One firewall, many machines

One firewall attaches to as many machines as you like, and a machine can carry up to five, whose rules add up. A base firewall (SSH from the office, ping) on every machine, plus a web firewall on those serving pages: when the office address changes, one edit updates the whole fleet.

Firewalls are included at no extra cost. Ten per account, fifty rules per firewall and twenty sources per rule; beyond that, the Firewalls page offers to request an increase in one click.

8. From an AI agent

The FFxF MCP server exposes the same actions: create_firewall, update_firewall, attach_firewall and the rest. You can ask Claude Code or Codex to "close everything but SSH and web on my production machines"; the server's instructions tell them to keep TCP 22 open, so they do not lose the machine they are working on.

Checklist

  • List what actually listens with ss -ltn.
  • A firewall with SSH (or RDP) and only your services' ports.
  • Attached, then checked from another machine.
  • SSH restricted to your addresses when possible.
  • Outbound rules only if you know what the machine must reach.

The FFxF firewall and the system's own firewall work together: the first holds even if the machine is misconfigured, the second filters traffic between services on the machine. For the second, see securing an Ubuntu VPS. The full reference is in the firewall documentation.

One incoming stream shared by a load balancer across three machines, one drained

Load balancer: several servers behind one address

A load balancer takes traffic on its own address and shares it across your machines. Pools and health checks, an HTTPS listener with an automatic certificate, path routing, maintenance without downtime: a complete setup, at 0.010 CAD an hour.

Read the article 8 min read

Support & discussions

Technical questions, incident reports, or infrastructure discussions, the team is reachable on Discord, Telegram, X, Instagram, Reddit, and IRC.