Every outbound packet from a private host is rewritten by the NAT router: (src_ip, src_port) is replaced with (public_ip, external_port), and the mapping is stored as a session in the NAT table so the reply can be routed back.
Table entry key (Full-Cone): host
Table entry key (Symmetric): host + destination
Entry lifetime: refreshed on traffic, expires after
the idle-timeout with no packets seen
The pool of external ports behaves exactly like a finite set of servers in a queueing system: sessions arrive at rate λ (connections/sec) and hold a port for an average duration τ (the hold-time slider). By Little's Law the expected number of simultaneously active sessions is L = λ·τ — the offered load, measured in Erlangs (A = λτ).
When every port is busy, a new connection is blocked until one frees up. The exact blocking probability for a loss system with n ports and offered load A is the recursive Erlang-B formula:
B(0, A) = 1
B(n, A) = A·B(n-1, A) / (n + A·B(n-1, A))
Full-Cone NAT reuses one external port per internal host for every destination it talks to. Symmetric NAT allocates a separate port per (host, destination) pair, so the same host visiting three sites at once consumes three ports instead of one — it exhausts the pool faster but is harder for an outsider to map or spoof.
NAT's side effect is an implicit stateful firewall: an inbound packet that arrives at an external port with no matching table entry has nowhere to go and is dropped, which is why unsolicited scans from the internet cannot reach an internal host that never opened a connection out.