Designing a carrier-grade NAT, how would you choose between per-session port allocation, per-subscriber port blocks and fixed port ranges, and how would you size them?
answer
- three goals that pull apart
- utilization, logs, guessability
- peak, not average, port use
- blocks per address
basics
~20 sRFC 6888 asks a carrier-grade NAT's port scheme to maximize port use, minimize log volume and resist guessing; no scheme wins all three: per-session allocation uses ports best, fixed ranges log least, blocks sit between.
solid answer
~50 sRFC 6888 section 5 names three competing goals: maximize port utilization (REQ-13), minimize log volume (REQ-14) and make ports hard to guess (REQ-15). **Per-session** allocation from the whole pool uses ports best and randomises well, but logs every mapping. **Port blocks** give a subscriber, say, 512 ports at a time, logged once per block, with more blocks on demand up to the per-subscriber cap; ports idle inside held blocks are wasted and guessing narrows to the block. **Fixed ranges** computed from the subscriber's address need almost no logging and allow immediate port reuse after state loss, but cap every subscriber permanently. Size from measured peak port use per subscriber, because RFC 6269 notes average and peak differ widely and that higher sharing ratios need more dynamic assignment. With 64,512 ports per address, 512-port blocks give 126 per address.
go deeper
Recall that a carrier-grade NAT hands out ports either one session at a time, in blocks per subscriber, or as fixed ranges, and that this choice affects logging.
Do the block arithmetic, ports per address divided by block size, and explain why a released port is held for a while before it is reused.
Explain how each scheme behaves under a heavy subscriber, a failover and an abuse investigation, and what the per-subscriber cap does to a user who hits it.
Own the tradeoff among utilization, log cost and guessability, set the sharing ratio from measured peak demand, and say when IPv6 investment beats buying more IPv4 addresses.
## The decision A carrier-grade NAT (CGN) is a NAPT shared by thousands of subscribers. Every flow needs an external port, and the operator must later be able to say which subscriber held a given public address and port at a given moment. How ports are handed out decides how many subscribers fit on each public IPv4 address, how much log data the provider stores, and how predictable the ports are to an attacker. RFC 6888 section 5 states the three goals and says outright that they compete, which is why they are SHOULDs: - **REQ-13**: the scheme SHOULD maximize port utilization. - **REQ-14**: the scheme SHOULD minimize log volume. - **REQ-15**: the scheme SHOULD make it hard for attackers to guess port numbers (the attacks of RFC 6056). ## The three families | Scheme | Port utilization | Log volume | Port guessability | |---|---|---|---| | Per-session, from the whole pool | best: a port is held only while a flow needs it | highest: one record per mapping | best: any free port, randomized | | Port blocks on demand | middling: idle ports in a held block are wasted | low: one record per block allocation and release | weaker: randomized only within the block | | Fixed ranges per subscriber | worst: a quiet subscriber's range sits unused, a busy one hits a hard cap | near zero: attribution follows from the range assignment | weakest: each subscriber's candidate ports form a small, stable set | Two RFC 6888 rules interact with the choice: 1. **REQ-8** asks a CGN not to reallocate a released port for **120 seconds**, matching TCP's maximum segment lifetime, so a late packet cannot reach a new subscriber. Exception (b) allows immediate reuse when ports are statically assigned and the assignment survives state loss, which is a real operational advantage of fixed ranges after a crash or failover. 2. **REQ-2** makes **Paired** pooling the default, so by default all of a subscriber's blocks or sessions come from the same public address. That anchors each subscriber's demand to one address's 64,512 ports per protocol. ## Sizing arithmetic Assume a pool of 1024-65535, which is 64,512 ports per address per protocol. - **Fixed share for 5,000 subscribers on one address**: 64,512 / 5,000 leaves 12 ports each (5,000 x 12 = 60,000). A single web page can open more connections than that, so a fixed scheme at that ratio is unusable. - **512-port blocks**: 64,512 / 512 = exactly **126 blocks per address**. If all 5,000 subscribers hold one block at once you need 5,000 / 126, rounded up, = **40 addresses** (39 x 126 = 4,914 is short; 40 x 126 = 5,040). - **Fixed ranges of 1,008 ports**: 64 subscribers per address (64 x 1,008 = 64,512), so 5,000 subscribers need **79 addresses** (78 x 64 = 4,992 is short). RFC 6269 Appendix B calls subscribers-per-address the **address space multiplicative factor**. A provider with a stable base may need a factor under 10; a new entrant may need about 1,000. Because measured port consumption is heavy-tailed, with peak use far above average, RFC 6269 concludes that the larger the factor, the more dynamic the assignment has to be. Static ranges work at a low factor; at a high one only per-session allocation, or small blocks with several per subscriber, keeps heavy users working. ## How I would decide - **Measure first**: the distribution of concurrent ports per subscriber at the busy hour, especially the 99th percentile, not the mean. - **Fix the per-subscriber cap** that REQ-4 obliges the CGN to support, and decide what a subscriber at the cap experiences: RFC 6888 REQ-11 has the CGN drop the new flow, preferably with ICMP Host Unreachable, never evict an existing one. - **Price the logging**: RFC 6269 notes mappings are typically retained for 6-12 months depending on jurisdiction. Per-session logging at CGN scale is a storage and search system in its own right; blocks cut it by roughly the number of mappings each block serves. - **Choose block size against guessability**: smaller blocks waste fewer ports and log more often; larger blocks log less but give an off-path attacker a smaller search space per subscriber than the full pool. - **Plan for failover**: dynamic schemes lose state on a crash and then quarantine ports; deterministic ones recover instantly. - **Shrink the problem**: every flow moved to IPv6 is one that needs no CGN port at all, and a CGN REQ-6 bypass for in-provider destinations removes translation for local services. There is no universally right answer; a common compromise is dynamic blocks with a small first block, more on demand, and a cap.
- Why can a CGN using fixed port ranges reuse ports immediately after it loses state, when a dynamic one should wait?RFC 6888 REQ-8 asks for a 120-second wait before reallocating a released port, so an old session's late packets cannot reach a different subscriber. With a static assignment that survives state loss, a port can only ever go back to the same subscriber, so there is no one to misdeliver to and REQ-8's exception allows immediate reuse.
- How does block size affect an off-path attacker trying to guess a subscriber's ports?Randomization in the spirit of RFC 6056 can only pick within the subscriber's block. If an attacker learns or infers the block, the search space shrinks from the whole pool to the block's size, such as 512 ports. Larger blocks help guessing resistance and logging but waste more ports, which is exactly the REQ-13 to REQ-15 tension.
saying these in an interview costs you the question
- Fixed per-subscriber port ranges give the best port utilization of any CGN scheme.
- Size port blocks from the average ports per subscriber; peaks will even out.
- Per-session port allocation needs no more logging than port blocks.
- Block allocation removes the need to log anything for attribution.
- RFC 6888 mandates one specific port allocation algorithm for every CGN.