CGNAT Explained: Why Thousands of Customers Share One Public IP Address
Your home router already shares one public address among every device in your house. A provider doing CGNAT does the same trick one level up: hundreds or thousands of households share one public IPv4 address, and the provider tells them apart by port number. That one change explains why port forwarding mysteriously stops working, why an IP address alone no longer identifies a subscriber, and why sizing a CGNAT pool is really an exercise in dividing 64,512 usable ports into blocks nobody wastes.
The short answer
CGNAT is address sharing, run by the provider. NAT (Network Address Translation) is the trick your home router uses: every device in the house has a private address, but the outside world sees one public address, and the router remembers which device each conversation belongs to. CGNAT — carrier-grade NAT, also called large-scale NAT — moves that same trick up one level. The provider gives your router an address that is not public either, then runs its own, much bigger NAT in front of hundreds or thousands of customers at once. From the internet's point of view, all of those households are the same public address. What tells them apart is the port: the number attached to each connection alongside the address. One public address plus one port points at exactly one subscriber's connection — and that pair, address and port together, is the whole game this article is about.
Think of a large apartment building with one street address. The street address alone does not identify anyone; the flat number does. CGNAT is the same building at internet scale: the public IP address is the street address, and the port is the flat number. Everything that follows — the sizing maths, the logging problem, the reason your port-forwarding rule stopped working — comes from the fact that there is only one street address for the whole building, and a fixed number of flats inside it.
Why providers ran out of addresses
IPv4 addresses are 32-bit numbers, so there are about 4.3 billion of them in total, and the free pool is gone: IANA handed out its last free blocks to the regional registries in February 2011. A growing provider — above all a mobile provider, where every phone is a subscriber — simply cannot give every customer a public IPv4 address of their own. IPv6 is the long-term answer, and providers run it alongside, but the IPv4 internet still has to work today. So the provider does what your router does: it puts subscribers behind a translator and shares.
One detail had to be fixed first. The address the provider gives your router cannot be one of the usual private ranges (192.168.x.x, 10.x.x.x), because your own home network may already use exactly that range on the inside, and the same numbers on both sides of a router cause collisions. RFC 6598 solved it by reserving a dedicated range, 100.64.0.0/10 — addresses from 100.64.0.0 to 100.127.255.255 — as shared address space for exactly this provider-to-subscriber link. That gives you a practical test, too: if your router's WAN address sits in 100.64.0.0/10 and the public address a website sees is different, you are behind CGNAT right now.
Ports are the real currency
A NAT sharing one address can only tell subscribers apart by giving each connection a different public port. Ports run from 0 to 65,535, and in the common CGNAT setup the usable range starts at 1024 — the well-known ports below that stay reserved — leaving 64,512 usable ports per public address. That number, not the number of addresses, is what a CGNAT design actually spends. Every open connection holds one port for as long as it lasts, so a subscriber's demand is measured in peak simultaneous ports: a quiet household might peak at a few dozen, a house full of devices, games and cloud backups at a few hundred.
Two consequences follow immediately. First, one heavy subscriber can hurt everyone sharing the address: if a single customer could grab unlimited ports, they could exhaust the pool and everyone else's new connections would fail. That is why the CGNAT requirements in RFC 6888 include a limit on how many ports each subscriber may use. Second, capacity is a division problem: subscribers per address equals usable ports divided by ports per subscriber — with all the rounding pain that dividing into fixed blocks brings, which is where the design gets interesting.
Port blocks: why the NAT deals in bundles
The naive design gives out one port at a time, per connection. It uses ports efficiently, but it creates a second problem that has nothing to do with capacity: logging. When a website or an authority asks "which subscriber used this public address at this time?", the provider can only answer if it recorded the mapping. Logging every single connection sounds thorough until you price it. Using the planner's own estimator inputs as an illustration — 10,000 subscribers, 500 sessions per subscriber per day, 200 bytes per log record — per-session logging produces 1 GB of logs a day, 30 GB a month, and real providers are far larger than 10,000 subscribers. One analysis cited in RFC 7768 put per-session logging for 20,000 subscribers at 42.5 TB over 60 days.
Port block allocation is the standard answer. Instead of a port at a time, the NAT hands a subscriber a whole block — say 512 consecutive ports on one public address — and writes one log record for the block. Every connection inside that block is covered by that one record, so the log volume falls by roughly the block size: the same RFC 7768 analysis put block-based logging at 40.6 GB for the case above, against 42.5 TB per session. When the subscriber outgrows the block, they get another one, and one more record. RFC 6888 states the trade-off plainly as three competing requirements for any port-allocation scheme: maximise port utilisation, minimise log volume, and make port numbers hard for attackers to guess. You cannot have all three at once; block size is where you choose your balance.
Deterministic NAT pushes the logging idea to its limit. Blocks are assigned to subscribers by a fixed rule instead of on demand, so given a public address, a port and the configuration, the operator calculates which subscriber it was — the mapping needs no per-session or per-block log at all (the configuration itself is what is recorded). The price is flexibility: the assignment is fixed whether a subscriber uses their ports or not, so deterministic designs waste more ports to buy near-zero mapping logs.
A worked sizing example, with the planner's numbers
Here is the arithmetic a provider actually runs, using exactly the worked example built into the free planner linked below. Start with a small pool: 16 public addresses, the usual usable range 1024-65535 (64,512 ports per address), and 512-port blocks.
Step one: blocks per address. A block must be consecutive ports on one address — it cannot straddle two — so the division is done per address and rounded down: 64,512 ÷ 512 = 126 blocks per address, exactly, with nothing left over in this case. Step two: total blocks. 126 × 16 addresses = 2,016 blocks. Step three: blocks per subscriber. If a subscriber peaks at 300 ports, one 512-port block covers the peak, so each subscriber needs one block. Guaranteed capacity is therefore 2,016 subscribers — 126 per public address — where "guaranteed" has a precise meaning: every one of them can hit their 300-port peak at the same moment and nobody runs out.
Step four: the waste, stated honestly. Each subscriber is allocated 512 ports and peaks at 300, so 212 ports per subscriber sit unused — a utilisation of 300 ÷ 512 = 58.6%. That waste is the price of the logging win: bigger blocks mean fewer log records and more waste. Watch the trade move: give the same pool a subscriber who peaks at 1,000 ports with 256-port blocks and the maths tightens dramatically — 252 blocks per address, 25,200 blocks across 100 addresses in the planner's second vector, four blocks per subscriber (4 × 256 = 1,024 allocated against a 1,000 peak), 6,300 guaranteed subscribers, only 24 wasted ports each, 97.7% utilisation — but now a busy subscriber triggers four block allocations, and four times the block-log records of a one-block design. Neither answer is "efficient" in the abstract; each is a chosen point on the RFC 6888 trade-off.
Step five: stranded ports, the waste people forget. Rounding down per address leaves a remainder whenever the block size does not divide the range exactly. With 2,048-port blocks, 64,512 ÷ 2,048 = 31.5, so 31 blocks fit and 1,024 ports per address can never be assigned to anyone — stranded. This is also why pooling the arithmetic is a trap: multiply all the ports in a big pool together and divide once, and you get a larger, wrong answer, because real blocks cannot span addresses. Any sizing that does not show its stranded ports is hiding part of its cost.
And a warning about the other capacity number tools show: a statistical capacity, based on the average blocks subscribers actually hold rather than their peak. It is a legitimate planning figure — peaks do not all land at once — but it is oversubscription by definition. If everyone peaks together, the statistical pool runs out first. A design is only honest when both numbers are printed side by side and the guaranteed one is the one the promise is made on.
What CGNAT breaks, felt from the subscriber side
Most subscribers never notice CGNAT — ordinary browsing, streaming and messaging are all outbound connections, which NAT handles fine. The breakage is specific. Inbound connections are the big one: a port-forwarding rule on your home router cannot work on its own, because the provider's NAT in front of it has no mapping for your traffic and does not take instructions from your router — hosting a game server, a camera or a home VPN server over IPv4 stops working unless the provider offers a public address, an opt-out, or a protocol such as PCP to request a mapping. Shared reputation is the quieter one: if one subscriber behind an address abuses a website, the block or rate-limit lands on the address — and therefore on everyone sharing it. And identification changes meaning: an IP address in a log no longer names a subscriber, or even a household. Address, port and an accurate timestamp are the smallest unit that does — which is the whole reason the logging design above matters.
Four CGNAT mistakes that actually happen
1. Sizing on averages and calling it capacity. Average ports per subscriber is a fine input for a statistical estimate, but the number subscribers experience on the worst evening is the peak-based guaranteed figure. Publish both, promise on the guaranteed one.
2. Pooling the ports before dividing. Multiplying pool ports together and dividing by block size once ignores that blocks live on single addresses, and silently invents capacity out of the stranded remainders. Always floor per address first, then multiply.
3. Choosing huge blocks just to cut the logs. Log volume falls as blocks grow, but so does utilisation — a 512-port block for a 300-port peak wastes 212 ports before anyone has done anything wrong, and 4,096-port blocks strand 3,072 ports per address on the standard range. The block size is a three-way trade (utilisation, logs, guessability), not a logging-only dial.
4. Forgetting that identification needs the port. Keeping per-session logs "for compliance" while recording only addresses and timestamps misses the point of a shared address: without the source port, the record cannot identify anyone at all. The allocation scheme and the log format have to be designed together.
Try it yourself
Run the numbers from this article in the free CGNAT Port-Block Planner — it starts on exactly the worked example above (16 public IPs, 512-port blocks, a 300-port peak: 2,016 subscribers guaranteed). Then drag the block size up to 2,048 and watch the stranded ports appear, switch the logging estimator between per-session, per-block and deterministic, and use its reverse lookup to work a public address and port back to the subscriber block it belongs to.
- CGNAT (carrier-grade NAT) is the home-router trick at provider scale: many subscribers share one public IPv4 address, and the NAT tells them apart by source port. The subscriber side usually gets an address from the shared address space 100.64.0.0/10 (RFC 6598), set aside so it cannot collide with the customer's own private ranges.
- A public address has 65,535 ports, and with the common usable range 1024-65535 that is 64,512 ports to divide. Port block allocation hands each subscriber a whole block at a time — with 512-port blocks, one address holds exactly 126 blocks, so 16 public IPs support 2,016 subscribers whose peak is 300 ports each, wasting 212 ports per subscriber (58.6% utilisation).
- Logging is the hidden cost: logging every session for 10,000 subscribers at 500 sessions a day and 200 bytes a record is 1 GB a day. One log record per block allocation instead of per session shrinks that by roughly the block size, and deterministic NAT goes further — the subscriber behind a public IP and port is computed from the configuration, not looked up in per-session logs.
- Blocks cannot span two public addresses, so pooling all the ports first and dividing once overstates capacity. Leftover ports that cannot fill a whole block on an address are stranded: 2,048-port blocks on a 64,512-port range leave 1,024 ports stranded on every address.