Carrier-Grade NAT (CGNAT) Design and Configuration - 夜莺博客

Carrier-Grade NAT (CGNAT) Design and Configuration

IPv4 exhaustion pushed NAT out of the home router and into the carrier network, where it is now the default tool for delivering IPv4 service to millions of subscribers over a shared pool. CGNAT — also called NAT444 or Large Scale NAT — is a different engineering problem from a single-box PAT: it has to be deterministic enough for law-enforcement logging, scalable enough for hundreds of Gbps, and available enough that a single failure does not take a region offline. RFC 6888 defines the requirements that distinguish a real carrier-grade NAT from a big NAT rule. This article covers the architecture, allocation strategy, logging obligations and a configuration template.

Where CGNAT sits

CPE (private 10/8 or 192.168/16)
   |  "first NAT" at the CPE
Carrier access network (BNG / BRAS / CMTS)
   |  "second NAT" = CGNAT, public pool
  Internet
=> hence NAT444: subscriber is translated twice

The subscriber keeps an RFC 1918 address all the way to the BNG, and the CGNAT device translates that to a public address. Two consequences dominate design: the CPE's own NAT table becomes irrelevant to the carrier, and every log on the internet sees only the CGNAT public address.

Allocation strategy: the core design decision

Port-block allocation (recommended)
  - each subscriber gets a fixed block, e.g. 1024 ports for 10 minutes
  - logging volume is tiny: one record per block transition
  - predictability helps abuse handling and troubleshooting

Dynamic per-flow allocation
  - ports assigned per connection; maximum efficiency
  - logging volume explodes (one record per flow)
  - legally problematic in jurisdictions with data-retention rules

RFC 6888 explicitly references the port-block approach (popularised as "deterministic NAT") because it satisfies address-sharing requirements while keeping logs tractable. In practice, many operators implement the log-port-range (LPR) model: a = starting port, n = number of ports, assigned per subscriber.

Sizing rules of thumb

Concurrent sessions per subscriber (busy hour, real measurements): 300-800
Ports per subscriber needed at 1:1 sharing:               ~1000-2000
At 32:1 sharing:                                           ~32k-64k ports/block? no —
  recalculate per subscriber: keep >=1024 ports and scale the pool, not the block
Public addresses needed = peak concurrent subscribers x sessions
                          ----------------------------------
                          usable ports per address (64511) / block size

The trap is sizing on average usage instead of busy-hour peaks; a CGNAT that runs out of ports under load breaks every streaming session at once, and the symptom (some new connections fail, existing ones survive) looks like a routing problem rather than exhaustion.

Configuration template (vendor-neutral Cisco/Juniper style)

! Cisco IOS-XE / ASR9K style
ip nat pool CGN_POOL 100.64.0.0 100.64.255.255 prefix-length 24
ip nat inside source list SUBSCRIBERS pool CGN_POOL overload
!
! port-block mode (deterministic) — Cisco IOS-XE
ip nat settings mode deterministic
ip nat inside source list SUBSCRIBERS pool CGN_POOL port-block-configuration block-size 1024

! Juniper MX (secure NAT / ms-MPC)
set services nat pool CGN-POOL address 100.64.0.0/24
set services nat rule CGN-RULE match-direction in
set services nat rule CGN-RULE term T1 then translated source-pool CGN-POOL
set services nat rule CGN-RULE term T1 then translated translation-type napt-44
set services deterministic-nat ...

Logging: the part that is not optional

Log per port-block transition (not per flow):
  timestamp, timestamp_msec
  public_ip, public_port_start, public_port_end
  private_ip, private_port_start, private_port_end
  subscriber_id
  event  (BIND / UNBIND)
Ship as high-volume UDP syslog to a collector; at scale this is TB/year.

RFC 6888 requires that a carrier be able to identify the subscriber behind a public IP:port at a given time. If your design cannot answer "who was at 100.64.5.7:4133 at 14:02:11" within seconds, the design is not compliant regardless of throughput.

Failure and availability design

- CGNAT devices are usually deployed in pairs with a shared pool
- stateful failover requires session state sync (heavy) or redundant NAT blocks
- DNS64/NAT64 or DS-Lite are alternatives that avoid double translation for
  dual-stack customers: see the IPv6 transition options below
- monitor: pool utilisation, port-block exhaustion, log drops

If IPv6 is a realistic option, NAT64/464XLAT removes the second NAT entirely for dual-stack clients — covered in NAT64 and 464XLAT. For enterprise-scale PAT fundamentals and port forwarding, see Cisco IOS NAT PAT overload.

FAQ

Q: Can CGNAT break gaming and VoIP? Yes — inbound connections are impossible without port control protocols (PCP, RFC 6887) or UPnP extensions, and some consoles need large port ranges.
Q: What address space should the pool use? The shared 100.64.0.0/10 range (RFC 6598) for internal legs, and your own publicly routed prefixes for the outside leg.
Q: Is 1:64 sharing realistic? It is used, but failure modes are worse and each subscriber's usable port range shrinks; prefer more addresses over deeper sharing.

原文链接:https://www.rfc-editor.org/rfc/rfc6888.html