-
Notifications
You must be signed in to change notification settings - Fork 2
policy routing
Pre-Alpha. This page describes behavior that may change.
Ze supports policy-based routing (PBR) to steer traffic through alternate routing tables or next-hops based on L3/L4 match criteria. This is used for content filtering, split tunneling, and traffic engineering scenarios where destination-based routing is insufficient.
Under the hood, ze uses nftables packet marking with kernel ip rules. Each matching packet gets an fwmark; a kernel ip rule maps that mark to the target routing table.
policy {
route surfprotect {
interface "l2tp*";
rule bypass-dst {
from {
destination-address @DstBypass;
destination-port 80,443;
protocol tcp;
}
then {
accept;
}
}
rule block-quic {
order 20;
from {
destination-address 0.0.0.0/0;
destination-port 80,443;
protocol udp;
}
then {
drop;
}
}
rule surfprotect-syn {
order 30;
from {
destination-address 0.0.0.0/0;
destination-port 80,443;
protocol tcp;
tcp-flags syn;
}
then {
table 100;
tcp-mss 1436;
}
}
rule surfprotect-tcp {
order 40;
from {
destination-address 0.0.0.0/0;
destination-port 80,443;
protocol tcp;
}
then {
table 100;
}
}
}
}
Table 100 must be populated separately via static routes:
static {
route 0.0.0.0/0 {
table 100;
next-hop tun100 { }
}
}
Each policy route binds to one or more ingress interfaces. A trailing * enables wildcard matching (e.g., l2tp* matches all L2TP interfaces). The interface match is prepended to every rule in the policy.
policy {
route example {
interface "l2tp*";
interface eth1;
}
}
The from block specifies what traffic to match.
| Keyword | Description | Example |
|---|---|---|
source-address |
Source IP prefix or @set reference |
10.0.0.0/8, @AllowedSrc
|
destination-address |
Destination IP prefix or @set reference |
0.0.0.0/0, @DstBypass
|
source-port |
Source port or port range | 1024-65535 |
destination-port |
Destination port, range, or list | 80,443 |
protocol |
L4 protocol |
tcp, udp, icmp
|
tcp-flags |
Comma-separated TCP flags |
syn, syn,ack
|
Set references (@name) resolve against firewall sets defined in the firewall config section.
TCP flag names: fin, syn, rst, psh, ack, urg.
The then block specifies what to do with matched traffic. Only one terminal action (accept, drop, table, or next-hop) is allowed per rule. tcp-mss is a modifier that can be combined with a terminal action.
| Keyword | Description |
|---|---|
accept |
Skip this policy, packet routes normally |
drop |
Drop the packet |
table N |
Route via kernel table N (user must populate the table) |
next-hop IP |
Route via the specified next-hop (table auto-managed) |
tcp-mss N |
Clamp TCP MSS to N bytes |
The table action internally allocates an fwmark from the reserved range 0x50000-0x5FFFF, adds a SetMark action to the nftables rule, and creates a kernel ip rule mapping that fwmark to the table. The user must populate the target table (e.g., via static routes).
The next-hop action works like table but also auto-manages the kernel routing table. Ze allocates a table from range 2000-2999, adds a default route via the specified next-hop, and creates the fwmark and ip rule. Multiple rules targeting the same next-hop share a single auto-allocated table.
The marking rules go in a filter chain, not an nftables route chain. nftables only accepts a route chain on output, where its job is re-routing locally generated packets after a mark change. Forwarded traffic is routed after prerouting, so a filter chain is the standard way to drive ip rule fwmark.
This is worth knowing because earlier builds asked the kernel for a route chain on prerouting, which the kernel rejects with EOPNOTSUPP, and that took the policy-routes plugin down at startup. Policy routing did not work at all on those builds.
Rules are evaluated in order value order (lower first). Rules with equal order are sorted alphabetically by name. If order is omitted, it defaults to 0.
| Range | Owner | Purpose |
|---|---|---|
| Tables 1-999 | user | Explicit table IDs in config |
| Tables 253-255 | kernel | default (253), main (254), local (255) |
| Tables 1000-1999 | ze VRF | Auto-allocated VRF tables |
| Tables 2000-2999 | ze policy-routing | Auto-allocated next-hop tables |
| fwmarks 0x50000-0x5FFFF | ze policy-routing | Packet marks for table steering |
User-specified table IDs in the 1000-2999 range are rejected at config validation time.
ze> show policy-routes
Returns JSON with all configured policy routes, their interface bindings, rules, and actions.
The policy-routes plugin depends on the firewall plugin. Both must be available for policy routing to function. Auto-managed routes use protocol ze-policy-route (RTPROT 252).
-
Firewall for firewall sets referenced by
@namein match criteria. - Static Routes for populating target routing tables.
- Traffic Control for QoS on the same interfaces.
Adapted from main/docs/guide/policy-routing.md.
Unreviewed draft. This wiki was authored in bulk and has not been reviewed. File corrections on the issue tracker.
- Overview
- YANG Model
- Editor Workflow
- Archive and Rollback
- System
- Interfaces
- VRRP
- BFD
- FIB
- OSPF
- IS-IS
- MPLS / LDP / RSVP-TE
- RSVP-TE
- SRv6
- Static Routes
- Policy Routing
- Firewall
- Traffic Control
- Class of Service
- L2TP/PPP
- PPPoE
- VPP Data Plane
- RPKI
- IPsec VPN
- TACACS+ AAA
- RADIUS AAA
- AS112 DNS
- Authorization
- Fleet
- BGP
- Starting and Stopping
- Show Commands
- Monitoring
- Flow Export
- DDoS Mitigation
- Anomaly Detection
- Health Checks
- Audit Trail
- Production Diagnostics
- Logging
- Operational Reports
- Healthcheck
- Self-Update
- Zero-Touch Provisioning
- MRT Analysis
- Upgrade and Restart
- Storage
- Policy
- Core
- Resilience
- Validation
- Capabilities
- Address Families
- Protocol
- Subsystems
- Infrastructure
- Route Server at an IXP
- Transit Edge with RPKI
- Public Looking Glass
- ExaBGP Migration Walkthrough
- FlowSpec Injection
- Chaos-Tested Peering
- AS Path Topology