ip-restriction
Restricts access based on context.request.remote_addr, matching it against configured allow and deny lists of exact IPs or CIDR blocks. Denied clients receive a 403 through the node's denied port. Place it at the front of the pipeline, before auth and upstream nodes.
Configuration
Both keys are optional; the constructor never fails. With both lists empty, all traffic is permitted.
| Key | Type | Default | Description |
|---|---|---|---|
allow | array of strings | [] | IPs or CIDR blocks (e.g. "10.0.0.0/8") that may pass. When non-empty, the list acts as a whitelist: everything else is rejected. |
deny | array of strings | [] | IPs or CIDR blocks that are always rejected. Takes precedence over allow. |
type: ip-restriction
config:
allow: ["10.0.0.0/8", "192.168.1.5"]
deny: ["10.1.2.3"]
Matching
The client address is parsed as an IP; a trailing :port suffix is stripped if present. Each pattern is either an exact IP or a net/bits CIDR block — both IPv4 and IPv6 are supported, and an IPv4 pattern never matches an IPv6 client (or vice versa). An unparseable remote address never matches any pattern: it passes the deny check, but is rejected whenever the allow list is non-empty.
Behavior
Checks run in order:
- Deny list first — if
denyis non-empty and the client matches, the request is rejected with error codeIP_DENIED. - Allow list — if
allowis non-empty and the client does not match, the request is rejected with error codeIP_NOT_ALLOWED.
Either rejection writes a 403 JSON response onto context.response ({"error": "forbidden", ...} with content-type: application/json) and exits through the denied port. Permitted requests pass through the success port with the Context untouched. The plugin does not write to context.message.
Older UI builds saved the keys mode and rules, which the plugin ignores - nodes saved with them apply no restriction. Re-save the node (the editor now uses allow and deny lists) or update the YAML.
Ports
ip-restriction declares three output ports: success, denied (a rejection is prepared), and error (never actually used — the plugin never fails). Like success, denied is a mandatory port: the policy compiler rejects any policy that leaves it unwired. Wire ip-restriction.denied straight to client so the prepared 403 reaches the caller instead of continuing into upstream:
edges:
- from: ip-restriction.success
to: upstream.in
- from: ip-restriction.denied
to: client.in
Errors
This node never fails at execution time: it always returns through success, so its error port is never taken.