CGNAT Configuration
Configure CGNAT VRF steering to hand off subscriber traffic to an external CGNAT appliance.
A future release will include built-in nftables-based deterministic CGNAT. The VRF steering configuration described here will remain supported.
Overview
The cgnat section configures VRF-based traffic steering for subscribers on RFC 6598 (Shared Address Space) IPs. AthenaBNG creates a Linux VRF, marks matching subscriber traffic with nftables, and routes it via a dedicated handoff interface to your external CGNAT appliance for NAT translation.
We recommend NFware vCGNAT for the external appliance — deterministic NAT, DPDK acceleration, and full translation logging for lawful intercept compliance. Any CGNAT appliance that accepts routed traffic on a handoff interface will work.
Configuration Options
enabled
Enable or disable CGNAT (optional).
cgnat:
enabled: true
Type: Boolean
Required: No
Default: false
Valid values: true, false
CLI:
abng# set cgnat enabled true
vrf_name
VRF name for CGNAT traffic (optional).
cgnat:
vrf_name: "cgnat"
Type: String
Required: No
Default: "cgnat"
Constraints: 1-15 characters, alphanumeric and underscores
Purpose: Linux VRF name for CGNAT routing table.
CLI:
abng# set cgnat vrf_name "cgnat"
vrf_table
Routing table ID for CGNAT VRF (optional).
cgnat:
vrf_table: 100
Type: Integer
Required: No
Default: 100
Constraints: Valid routing table ID (1-252)
Purpose: Linux routing table ID for CGNAT routes.
CLI:
abng# set cgnat vrf_table 100
handoff_interface
Interface for CGNAT traffic handoff (optional).
cgnat:
handoff_interface: "eth3"
Type: String (interface name)
Required: No
Default: None
Constraints: Valid interface name
Purpose: Dedicated interface to CGNAT router.
CLI:
abng# set cgnat handoff_interface "eth3"
handoff_gateway
Gateway IP for CGNAT handoff (optional).
cgnat:
handoff_gateway: "10.99.0.1"
Type: IPv4 address
Required: No
Default: None
Constraints: Valid IPv4 address
Purpose: Next-hop IP for CGNAT traffic.
CLI:
abng# set cgnat handoff_gateway "10.99.0.1"
source_range
CGNAT source IP range (optional).
cgnat:
source_range: "100.64.0.0/10"
Type: CIDR notation
Required: No
Default: "100.64.0.0/10"
Constraints: Valid IPv4 CIDR
Purpose: IP range for CGNAT pool (RFC 6598 Shared Address Space).
CLI:
abng# set cgnat source_range "100.64.0.0/10"
fwmark
Firewall mark for CGNAT traffic (optional).
cgnat:
fwmark: "0x64"
Type: String (hex format)
Required: No
Default: "0x64"
Constraints: Valid hex value (0x0-0xffffffff)
Purpose: nftables fwmark for identifying CGNAT traffic.
CLI:
abng# set cgnat fwmark "0x64"
Example Configurations
Minimal CGNAT Configuration
cgnat:
enabled: true
handoff_interface: "eth3"
handoff_gateway: "10.99.0.1"
Uses defaults:
- VRF name: "cgnat"
- VRF table: 100
- Source range: "100.64.0.0/10"
- Fwmark: "0x64"
Full CGNAT Configuration
cgnat:
enabled: true
vrf_name: "cgnat"
vrf_table: 100
handoff_interface: "eth3"
handoff_gateway: "10.99.0.1"
source_range: "100.64.0.0/10"
fwmark: "0x64"
With BGP Aggregate Announcements
cgnat:
enabled: true
vrf_name: "cgnat"
vrf_table: 100
handoff_interface: "eth3"
handoff_gateway: "10.99.0.1"
source_range: "100.64.0.0/10"
fwmark: "0x64"
announce_aggregates:
- "203.0.113.0/24"
Configuration via CLI
Enable CGNAT
abng> configure
abng# set cgnat enabled true
abng# commit
Set Handoff Interface
abng# set cgnat handoff_interface "eth3"
abng# set cgnat handoff_gateway "10.99.0.1"
abng# commit
Set VRF Parameters
abng# set cgnat vrf_name "cgnat"
abng# set cgnat vrf_table 100
abng# commit
Verification
View CGNAT Configuration
abng> show configuration | match "^cgnat:"
cgnat:
enabled: true
vrf_name: cgnat
vrf_table: 100
handoff_interface: eth3
handoff_gateway: 10.99.0.1
source_range: 100.64.0.0/10
fwmark: 0x64
Check VRF Status
ip vrf show
Name Table
cgnat 100
Check CGNAT Routes
ip route show table 100
default via 10.99.0.1 dev eth3
Check nftables Rules
sudo nft list table inet abng_cgnat
table inet abng_cgnat {
chain prerouting {
type nat hook prerouting priority dstnat; policy accept;
...
}
}
Check abngd Logs
sudo journalctl -u abngd -f | grep -i cgnat
Integration with RADIUS
CGNAT assignment can be controlled via RADIUS:
radius:
servers:
- host: "10.255.0.10"
secret: "your-secret"
RADIUS attributes:
- Athena-CGNAT-Enable — Enable CGNAT for subscriber (true/false)
- Athena-CGNAT-Address — Specific CGNAT IP (optional)
How VRF Steering Works
Traffic Flow
Subscriber (100.64.x.x — RFC 6598)
│
▼
BNG checks subscriber IP against source_range
│
├─► If in CGNAT range:
│ ├─► nftables marks packet with fwmark
│ ├─► ip rule steers into CGNAT VRF table
│ └─► VRF default route sends to CGNAT appliance
│
└─► If public IP:
└─► Route normally via default table
Packet Marking
nftables marks packets with fwmark when the subscriber's IP falls within the configured source_range. The mark triggers policy routing into the CGNAT VRF.
VRF Routing
Marked packets are routed via the CGNAT VRF:
ip rulematches fwmark → lookup in CGNAT routing table- Default route in VRF points to
handoff_gatewayviahandoff_interface - External CGNAT appliance (e.g. NFware vCGNAT) performs NAT translation
- Return traffic follows normal routing
RFC 6598 Shared Address Space
The default CGNAT source range (100.64.0.0/10) is defined in RFC 6598:
- Range: 100.64.0.0 to 100.127.255.255
- Purpose: Carrier-Grade NAT (CGN) address space
- Size: 4,194,304 addresses
- Usage: RADIUS assigns addresses from this range to subscribers requiring CGNAT
Validation Rules
| Field | Validation |
|---|---|
enabled | Boolean |
vrf_name | 1-15 characters, alphanumeric and underscores |
vrf_table | Integer 1-252 |
handoff_interface | Valid interface name |
handoff_gateway | Valid IPv4 address |
source_range | Valid CIDR notation |
fwmark | Valid hex value |
Best Practices
- Dedicated Interface — Use a dedicated interface for CGNAT handoff
- VRF Isolation — Use separate VRF for CGNAT traffic
- Fwmark — Use unique fwmark to avoid conflicts
- RADIUS Integration — Use RADIUS to control CGNAT per-subscriber
- Monitoring — Monitor CGNAT session count and translation stats
- Testing — Test with
tracerouteto verify CGNAT routing - Documentation — Document CGNAT pool allocation and management
Troubleshooting
CGNAT Not Translating
- Check CGNAT is enabled:
show configuration | match cgnat - Check VRF exists:
ip vrf show - Check nftables rules:
sudo nft list table inet abng_cgnat - Check RADIUS returns CGNAT attributes:
radtest testuser testpass <radius-ip> 1812 <secret> - Check abngd logs:
journalctl -u abngd -f
CGNAT Traffic Not Reaching Router
- Check handoff interface is up:
ip link show eth3 - Check route exists:
ip route show table 100 - Check gateway is reachable:
ping 10.99.0.1 - Check nftables rules:
sudo nft list table inet abng_cgnat
Return Traffic Not Working
- Check CGNAT router is translating return traffic
- Check reverse route exists:
ip route show table 100 - Check firewall allows return traffic
- Check CGNAT router logs
Next Steps
- Routing Configuration — BGP and OSPF
- REST API Configuration — Management interface
- Configuration Overview — All configuration sections