Skip to main content

CGNAT Configuration

Configure CGNAT VRF steering to hand off subscriber traffic to an external CGNAT appliance.

Built-in Deterministic CGNAT — Coming Soon

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:

  1. ip rule matches fwmark → lookup in CGNAT routing table
  2. Default route in VRF points to handoff_gateway via handoff_interface
  3. External CGNAT appliance (e.g. NFware vCGNAT) performs NAT translation
  4. 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

FieldValidation
enabledBoolean
vrf_name1-15 characters, alphanumeric and underscores
vrf_tableInteger 1-252
handoff_interfaceValid interface name
handoff_gatewayValid IPv4 address
source_rangeValid CIDR notation
fwmarkValid hex value

Best Practices

  1. Dedicated Interface — Use a dedicated interface for CGNAT handoff
  2. VRF Isolation — Use separate VRF for CGNAT traffic
  3. Fwmark — Use unique fwmark to avoid conflicts
  4. RADIUS Integration — Use RADIUS to control CGNAT per-subscriber
  5. Monitoring — Monitor CGNAT session count and translation stats
  6. Testing — Test with traceroute to verify CGNAT routing
  7. Documentation — Document CGNAT pool allocation and management

Troubleshooting

CGNAT Not Translating

  1. Check CGNAT is enabled: show configuration | match cgnat
  2. Check VRF exists: ip vrf show
  3. Check nftables rules: sudo nft list table inet abng_cgnat
  4. Check RADIUS returns CGNAT attributes: radtest testuser testpass <radius-ip> 1812 <secret>
  5. Check abngd logs: journalctl -u abngd -f

CGNAT Traffic Not Reaching Router

  1. Check handoff interface is up: ip link show eth3
  2. Check route exists: ip route show table 100
  3. Check gateway is reachable: ping 10.99.0.1
  4. Check nftables rules: sudo nft list table inet abng_cgnat

Return Traffic Not Working

  1. Check CGNAT router is translating return traffic
  2. Check reverse route exists: ip route show table 100
  3. Check firewall allows return traffic
  4. Check CGNAT router logs

Next Steps