Skip to content
Deployment
Skill

/firewall-networking

Firewall rules and service-to-service communication on Control Plane. Use when the user asks about inbound/outbound rules, CIDR whitelisting, IP blocking, hostname filtering, geo-blocking, header routing, internal endpoints, or network security.

From plugin
ai-plugin
1132 skills2 agents2 commands1 MCP

Claude Code

$ npx -y skills add controlplane-com/ai-plugin --skill firewall-networking --agent claude-code

SKILL.md

firewall-networking.SKILL.md
name: firewall-networking
description: "Firewall rules and service-to-service communication on Control Plane. Use when the user asks about inbound/outbound rules, CIDR whitelisting, IP blocking, hostname filtering, geo-blocking, header routing, internal endpoints, or network security."

Firewall & Networking

Deep detail for `spec.firewallConfig` and the enforcement model behind it; the `workload` skill owns the summary (deny-by-default, exposure decided at create time, LB picker). Set `firewallConfig` with `create_workload` / `update_workload`, or use the `public` shortcut (mutually exclusive with an explicit `firewallConfig`): `public: true` opens inbound AND outbound to `0.0.0.0/0` (on `update_workload` it adds `0.0.0.0/0` to both external allow lists and keeps every other rule), and `public: false` on `update_workload` removes only `0.0.0.0/0` and `::/0` from external inbound. A firewall change creates a new deployment version — a rolling replace, live in about a minute (`vm` workloads are the exception: firewall updates apply in place without restarting the VM).

How rules are enforced

**Inbound** is checked per request at the mesh sidecar. It counts as fully open only when `inboundAllowCIDR` contains the literal `0.0.0.0/0` AND `inboundBlockedCIDR` is empty; anything else is allow-list mode. Blocked beats allowed; a bare IP means /32. Header and geo filters apply to HTTP traffic only — `tcp`-protocol ports are CIDR-filtered at the connection level instead.

**Outbound** has two separate paths, which is why CIDR rules beat hostname rules:

  • **CIDR path** — traffic to `outboundAllowCIDR` ranges bypasses the sidecar and exits directly, on ALL ports unless `outboundAllowPort` is set.
  • **Hostname path** — everything else transits the sidecar, which only admits `outboundAllowHostname` entries, matched by Host header (HTTP) or TLS SNI, on ports 80, 443, and 445 (SMB) by default.
  • `outboundBlockedCIDR` is subtracted at the network layer and beats both paths — an allowed hostname that resolves into a blocked range still fails.
  • Outbound is fully open only with the literal `0.0.0.0/0` in `outboundAllowCIDR`.

External inbound

firewallConfig:
  external:
    inboundAllowCIDR:        # max 250 entries; deduped and sorted on save
      - 0.0.0.0/0            # or specific: 203.0.113.0/24, 198.51.100.10
    inboundBlockedCIDR:      # no max; wins over the allow list
      - 192.0.2.0/24

External outbound

firewallConfig:
  external:
    outboundAllowCIDR:
      - 198.51.100.0/24      # all ports open to this range while outboundAllowPort is unset
    outboundAllowHostname:   # lowercase; single wildcard on the prefix only; max 128 chars
      - api.stripe.com
      - "*.amazonaws.com"
    outboundBlockedCIDR:
      - 203.0.113.7

Source-verified traps:

  • **`outboundAllowPort` REPLACES the hostname defaults 80/443/445** — re-list 80 and 443 if you still need them. It also restricts the CIDR path to the listed ports. `protocol` is required (`http`, `https`, or `tcp` — how the proxy treats the port); `number` must be 80 to 65000 and not platform-reserved (8012, 8022, 9090, 9091, 15000, 15001, 15006, 15020, 15021, 15090, 41000).
  • **Ports below 80 (22, 25, 53) cannot be listed.** To reach a low port, allow the CIDR and leave `outboundAllowPort` unset — the CIDR path then opens all ports.
  • **Private ranges are silently stripped from `outboundAllowCIDR` on managed locations** (10/8, 172.16/12, 192.168/16, 127/8, 169.254/16, 100.64/10, IPv6 ULA): allowing them does nothing, with no error. Reaching a VPC or datacenter takes a wormhole agent (`native-networking`). BYOK clusters keep private ranges.

Header filters (inbound, HTTP only)

Each filter names a header `key` (max 128 chars) plus exactly ONE of `allowedValues` or `blockedValues` — RE2 regexes; anchor with `^...$` (a bare `bar` also matches `barbell`).

firewallConfig:
  external:
    inboundAllowCIDR: [0.0.0.0/0]
    http:
      inboundHeaderFilter:
        - key: x-api-version
          allowedValues: ["^v2$"]
        - key: user-agent
          blockedValues: ["^BadBot.*", "^Scraper.*"]

Matching is OR across everything: a request is rejected if ANY `blockedValues` pattern matches (checked first), and — once at least one allow filter exists — admitted only if ANY `allowedValues` pattern matches. Two allow filters on different headers are alternatives, not both-required; a request missing the header fails its allow filter. **Mesh-internal traffic (10.0.0.0/8 sources) bypasses header filters entirely** — test from outside, not from another workload.

Geo filtering (country / region / city / ASN)

Two steps: enable geo headers on the workload load balancer (you pick the header names), then filter on those names:

spec:
  loadBalancer:
    geoLocation:
      enabled: true
      headers:               # at least one; names unique; values overwrite client-sent headers
        country: x-country
  firewallConfig:
    external:
      inboundAllowCIDR: [0.0.0.0/0]
      http:
        inboundHeaderFilter:
          - key: x-country
            allowedValues: ["^US$", "^CA$"]

The proxy resolves values from MaxMind GeoLite2 on each request: `country` is the two-letter ISO code (`US`, never `United States`), `region` the subdivision code, `city` the English city name, `asn` the AS number. Echo the headers from the app once before writing filters. HTTP ports only.

Internal firewall (workload to workload)

`internal.inboundAllowType`: `none` (default), `same-gvc`, `same-org`, or `workload-list`. The admitted identity is the calling workload itself — all its replicas.

firewallConfig:
  internal:
    inboundAllowType: workload-list
    inboundAllowWorkload:
      - //gvc/GVC/workload/frontend      # GVC segment REQUIRED; //workload/NAME is rejected
      - /org/ORG/gvc/OTHER-GVC/workload/backend
      - cpln://internal/keda             # required when a KEDA trigger
Read more
@controlplane-com
Ships withai-plugin

Run containerized workloads across AWS, GCP, Azure, OCI, and your own hardware under one API.

1132 skills2 agents1 MCP
Get the whole plugin

Stars on GitHub

Momentum

stars in total
11
Star history of controlplane-com/ai-plugin on GitHub, a chart by star-history.com

Other skills on ai-plugin.

cpln

cpln

Writes cpln CLI commands and workflows for Control Plane. Use when the user asks about cpln login, cpln apply, cpln workload, CLI…

create-app

create-app

Writes, builds, and deploys an app the user asks for in the chat, with no repository and no image yet. Use when the user asks to…

More skills from other plugins.

configuring-horizon

configuring-horizon

Use this skill whenever the user mentions Horizon by name in a Laravel context. Covers the full Horizon lifecycle: installing…

coolify10d66k
@coollabsio@coollabsioInstall Skill
vercel-cli

vercel-cli

Guides deployment, configuration, and troubleshooting with the Vercel CLI. Use when operating Vercel projects or resources…

vercel12d16k
@vercel@vercelInstall Skill
skypilot

skypilot

Use when launching cloud VMs, Kubernetes pods, or Slurm jobs for GPU/TPU/CPU workloads, training or fine-tuning models on cloud…

@skypilot-org@skypilot-orgInstall Skill
pinme

pinme

Use this skill when the user mentions "pinme", or needs to upload files, store to IPFS, create/publish/deploy websites or…

pinme2mo3.8k
@glitternetwork@glitternetworkInstall Skill

Questions about firewall-networking.

Which coding agents can use firewall-networking?
firewall-networking installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.