Canadian KVM VPS in Montréal from 8.50 CAD/month

API

Firewalls

Filter what comes into and out of your machines: reusable rules, enforced by the hypervisor, attached in one call.

A firewall is a reusable set of rules, inbound and outbound, that you attach to your machines. It is enforced by the hypervisor, before traffic reaches the system: nothing to install, it works the same on Linux, Windows and BSD, and a mistake inside the machine cannot switch it off.

How it filters

  • A machine without a firewall accepts all inbound traffic, as before.
  • As soon as a machine has at least one firewall, inbound traffic no rule opens is dropped. With several firewalls, their rules add up.
  • Replies to the machine's own connections always get through: updates, downloads and outgoing API calls need no rule.
  • Its private networks are never filtered, and neither is the web console of the panel, which reaches the machine even if every rule is closed.
  • Outbound traffic is free until one of the machine's firewalls has an outbound rule.

Create a firewall

A rule lets in one protocol (tcp, udp, icmp for ping in IPv4 and IPv6, or any), on ports ("22", "80,443", a range "8000-8100"; omitted: all ports), from sources (IPv4 and IPv6 addresses or ranges; omitted: anywhere).

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", "sources": ["203.0.113.0/24", "2001:db8::/32"], "description": "SSH from the office"},
             {"protocol": "tcp", "ports": "80,443", "description": "Web"},
             {"protocol": "icmp", "description": "Ping"}
           ]
         }'
bash
{
  "data": {
    "id": 7,
    "name": "web",
    "rules": [
      { "protocol": "tcp", "ports": "22", "sources": ["203.0.113.0/24", "2001:db8::/32"], "description": "SSH from the office" },
      { "protocol": "tcp", "ports": "80,443", "sources": ["0.0.0.0/0", "::/0"], "description": "Web" },
      { "protocol": "icmp", "ports": null, "sources": ["0.0.0.0/0", "::/0"], "description": "Ping" }
    ],
    "members": []
  }
}

Without rules, the firewall starts with SSH (TCP 22) and ping open from anywhere; send "rules": [] for none. Addresses are brought back to their network address (203.0.113.7/24 becomes 203.0.113.0/24). Ten firewalls per account, fifty rules per firewall, twenty sources per rule.

Keep a way in. A firewall that does not open TCP 22 (or 3389 for Windows) cuts SSH (or remote desktop) to every machine it protects. The web console still works, but a script or an agent working over SSH loses its machine.

Protect a machine

bash
curl -s -X POST https://api.ffxf.net/v1/firewalls/7/members \
     -H "Authorization: Bearer $FFXF_TOKEN" \
     -H "Content-Type: application/json" \
     -d '{"vm": 4821}'
bash
{ "data": { "vm": 4821, "hostname": "web-1", "status": "applied" } }

The rules are in place when the call returns. Attaching a firewall already attached returns 200: a script can replay its configuration safely. Up to five firewalls per machine. A machine without a public address cannot get one: it has nothing to filter (409).

Change the rules

PUT /firewalls/{id} with rules replaces the whole list: describe the state you want, the API applies it to every attached machine before answering. Send every rule you keep, not only the new one.

bash
curl -s -X PUT https://api.ffxf.net/v1/firewalls/7 \
     -H "Authorization: Bearer $FFXF_TOKEN" \
     -H "Content-Type: application/json" \
     -d '{"rules": [{"protocol": "tcp", "ports": "22"}, {"protocol": "tcp", "ports": "443"}]}'

pending_machines counts the machines the new rules have not reached yet (hypervisor unreachable); they show "status": "error" in members and are retried automatically within minutes.

Detach, delete

ActionCallGood to know
DetachDELETE /firewalls/{id}/members/{vm}The firewall's rules leave the machine. With no other firewall, it accepts all inbound traffic again.
RenamePUT /firewalls/{id} with nameRules untouched when rules is omitted.
DeleteDELETE /firewalls/{id}Refused (409) while it protects a machine: deleting it would open them all at once.

Outbound rules

A rule with "direction": "out" lets traffic out, to destinations instead of coming from sources. As long as none of a machine's firewalls has an outbound rule, everything may go out. As soon as one does, only what outbound rules open goes out, plus what is always allowed:

  • DNS (port 53) to the resolvers FFxF configures on the machine;
  • replies to inbound connections the firewall let in;
  • the private network.
bash
{
  "rules": [
    {"protocol": "tcp", "ports": "22"},
    {"direction": "out", "protocol": "tcp", "ports": "80,443", "description": "Updates and HTTPS"},
    {"direction": "out", "protocol": "tcp", "ports": "5432", "destinations": ["198.51.100.20"], "description": "External database"}
  ]
}

The first outbound rule closes everything else: without the 80,443 rule above, package updates and downloads stop. Sending sources on an outbound rule, or destinations on an inbound one, is refused (validation_failed) rather than silently ignored. On a machine without IPv4, an IPv4 destination also allows its NAT64 address (64:ff9b::/96), the way such a machine reaches IPv4 hosts. Port 25 stays closed whatever the rules say.

Useful details

Read calls need the vms.read scope; creating, changing, attaching and deleting need network.write. The MCP server exposes the same actions: see MCP tools.

Support & discussions

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