The CGNAT problem is that a big box at the ISP has to track the state of all communications on the network. This is expensive. It is also unnecessary. It’s 2025-10-13, and here’s an answer.
Executive summary for TL;DR:
- Customer NAT must use assigned port range,
- Customer NAT public addresses must be re-used,
- The upstream network router must route by destination IP and by destination port
Port routing for no-CGNAT
On the consumer NAT router:
- Old: A CGNAT IP address is assigned as usual (RFC6598)
- Old: NAT rules are configured as usual
- New: A custom NAT rules must be added to the router, to use the assigned port range only, e.g:
iptables -t NAT -I POSTROUTING -p tcp -j SNAT --to-source 192.0.2.88:2048-3071
iptables -t NAT -I POSTROUTING -p udp -j SNAT --to-source 192.0.2.88:2048-3071
iptables -t NAT -I POSTROUTING -p sctp -j SNAT --to-source 192.0.2.88:2048-3071
On the network:
- The CGNAT address is the next-hop for policy based routing rules (e.g. 100.65.0.4)
- Traffic to 192.0.2.0 would be routed to a next-hop from 100.65.0.1 to 100.65.0.63, based on the destination
- The policy based routing says that for shared(!) destination IP address (192.0.2.0) and a destination port range (e.g. 2048-3191), for TCP, UDP and SCTP the next hop is the CGNAT address (e.g. 100.65.0.2).
PBR configuration would be something like this, on the switch that is immediately adjacent to the NAT users:
# Incoming policy based route for port routing
pbr dst ip 192.0.2.0 tcp/udp/sctp dst port 1024-2047 route nexthop 100.65.0.1
pbr dst ip 192.0.2.0 tcp/udp/sctp dst port 2048-3191 route nexthop 100.65.0.2
pbr dst ip 192.0.2.0 tcp/udp/sctp dst port 3191-4095 route nexthop 100.65.0.3
pbr dst ip 192.0.2.0 tcp/udp/sctp dst port 4096-5120 route nexthop 100.65.0.4
# ...
pbr dst ip 192.0.2.0 tcp/udp/sctp dst port 64512-65535 route nexthop 100.65.0.63
# privileged ports unused ...
pbr dst ip 192.0.2.1 tcp/udp/sctp dst port 1024-2047 route nexthop 100.65.0.65
pbr dst ip 192.0.2.1 tcp/udp/sctp dst port 2048-3191 route nexthop 100.65.0.66
pbr dst ip 192.0.2.1 tcp/udp/sctp dst port 3191-4095 route nexthop 100.65.0.67
# ...
# Outgoing policy based routing for unconfigured devices
pbr src ip 100.65.0.0/16 nexthop 100.127.127.126 # CGNAT server
- Other traffic from net CGNAT IP address is policy routed to regular CGNAT infrastructure.
- Router must advertise the target shared public IP range 192.0.2.0/24
Network router implementation
For a group of 992 users with a 63:1 sharing ratio, the amount of configuration would be:
- 16 public IP addresses (e.g. 192.0.2.0 to 192.0.2.15)
- 63 users per shared IP address
- 1024 unique ports per user
- 992 CGNAT IP addresses for nexthop (e.g. 10.65.0.1)
- 992 PBR rules specifying port ranges per router
If vendor extensions can be made, then the port routing rule that is needed would say to derive the nexthop IP from the destination port:
pbr dst 192.0.2.0/28 tcp/udp/sctp nexthop 100.65.0.0+($dstport>>10) + ($dstip-192.0.2.0)<<6
Here’s a table of destinations and port ranges that would result:
| Destination-IP | Port range | Next hop |
| 192.0.2.0 | 1024-2047 | 100.65.0.1 |
| 192.0.2.0 | 2048-3191 | 100.65.0.2 |
| 192.0.2.0 | 3192-4095 | 100.65.0.3 |
| … | … | … |
| 192.0.2.0 | 64512-65535 | 100.65.0.63 |
| 192.0.2.1 | 0-1023 | 100.65.0.64 (unused) |
| 192.0.2.1 | 1024-2047 | 100.65.0.65 |
| 192.0.2.1 | 2048-3191 | 100.65.0.66 |
| 192.0.2.1 | 3192-4095 | 100.65.0.67 |
| … | … | … |
| 192.0.2.2 | 1024-2047 | 100.65.0.129 |
Router configuration implementation
Two methods:
- New DHCP extensions to specify the port range and public IP address
- An administrative script that would log in to each router when it renews its DHCP lease, and configure the required rules. CPE router vendors can enable SSH if they set their mind to it.
Expected problems
Current status of this device is planning. There are some problems that are expected already:
- This scheme has no ICMP for TCP and UDP packets. This means no path MTU discovery, no “no route to host” and no “ICMP-port unreachable”. (It might be possible to overcome this by indiscriminately broadcasting ICMP to all that share an IP address, but that’s not going to be immediately available.)
- Non TCP, UDP and SCTP protocols must be handled by a regular NAT box. This includes GRE for PPTP
- Client-to-client communication might fail on a shared public IP (hair-pinning)
- Router credentials must be handed to the ISP
- Vendor support: CPE’s
- Vendor support: Port based PBR calculation on aggregation switch
RFC support
RFC 7618 specifies a port range from the DHCP server to the router for a “DHCP 4 over 6” IPv4 to IPv6 transition mechanism – the router does the stateful part, and the upstream magic box unwraps it for public after it crosses the network as IPv6.
The RFC specifies option 159 OPTION_V4_PORTPARAMS that lists bits and offset. All it needs is a little tweak to also specify a supplementary IP address in a longer expanded option:
The format of OPTION_V4_PORTPARAMS is shown in Figure 1.
0 1
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| option-code | option-len |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| offset | PSID-len |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| PSID |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| SHARED IP |
| (new idea) |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
Figure 1: DHCPv4 Port Parameters Option
o option-code: OPTION_V4_PORTPARAMS (159)
o option-len: 4 means regular, 8 means use specific shared IP
o offset: PSID offset bits
o PSID-len: Bit length value of the number of significant bits ..
o PSID: Explicit 16-bit (unsigned word) PSID value ...
It will be a better idea to have the client say that it supports port routing for NAT in a new DHCP option, and “public IP for NAT” in its own DHCP option. That way the client router can indicate that it supports the scheme.
CGNAT review
Just for everyone that’s lost, here’s a picture of the layout of an end-user fibre system using CGNAT (before this scheme):
- End user devices have RFC1918 addresses (e.g. 192.168.0.0/24)
- End user routers are assigned RFC6598 addresses (e.g. 100.64.0.0/10).
- Multiple CGNAT routers receive traffic by policy based routing (PBR)
- CGNAT routers translate connections to public IP addresses for regular internet routing
End-user devices on RFC1918 addresses
X X X X
| X X | | X | X X
X | | | | | | | X | X |
| | | | | | | | | | | |
+-----------+ +----------+ +----------+ +----------+
|192.168.0.1| | | | | | |
| | | | | | | |
| router 1 | | router 2 | | router 3 | ... | router n |
| | | | | | | |
|100.65.0.2 | | | | | | |
+-----------+ +----------+ +----------+ +----------+
| | | |
| | | |
| | | |
+-------------------------------------------------------------------+
| |
| Consumer aggregation network |
| (RFC6598 IP addresses 100.64.0.0/10) |
| |
+---------------+----------------+------------+---------------------+
| | |
| policy | |
| based | | CGNAT IP addresses
| routing | |
| (PBR) | |
| | |
+----+-----+ +------+---+ +----+-----+ these boxes
| | | | | | are big and
| | | | | | expensive -
| CGNAT 1 | | CGNAT 2 | | CGNAT 3 | let's get
| | | | | | rid of them
| | | | | |
+----------+ +----------+ +----------+
| | |
| | | Public IP addresses
| | |
+------------------------------+
| |
| |
| |
| Public internet |
| |
Update: 2025-11-12 – added worked example for 1024 ports per user.