Core CS · Computer Networks
Your address is not the address the Internet sees
Your laptop says 192.168.1.10. A website says you came from somewhere else entirely. One box on the border of your network rewrites the first into the second, writes down what it did, and undoes it on the way back. Watch it happen field by field.
Watch three hosts share one public address, step by step →01 The idea
There were never enough addresses to go round
An IPv4 address is 32 bits. That fixes the entire supply at 2³² = 4,294,967,296, about 4.3 billion, for every phone, laptop, server, router, camera and card machine on the planet. It is worse than that number suggests, because large blocks were carved out and can never be assigned to a host on the Internet: 127.0.0.0/8 is loopback, 224.0.0.0/4 is multicast, 240.0.0.0/4 is reserved. IANA handed the last of its free blocks to the regional registries on 3 February 2011. There has been no free pool since.
Now put that number next to the world it has to cover. There are more active mobile connections on the planet than there are IPv4 addresses in existence, before you count a single laptop, server, printer or router. So the address on the machine in front of you cannot be one of those 4.3 billion in any exclusive sense, and it is not. Run ipconfig or ip addr and you get something like 192.168.1.10. Open a page that reports your address and you get a completely different number. Two addresses, one machine, and nothing is broken. This lesson is about which is which, and about the box that turns one into the other.
The first half of the answer is RFC 1918. It sets aside three blocks of address space that anybody may use inside their own network without asking anybody, on one condition: those addresses are not allowed onto the public Internet. Every router in the middle of the Internet is configured to drop a packet whose destination is one of them. That is the whole deal, and it is a trade rather than a gift. You give up being reachable from outside, and in exchange you get an unlimited local supply that nobody has to allocate to you. Because they are dropped out there, they can be reused everywhere in here. Your college, your hostel Wi-Fi and a bank in Frankfurt can all be running 192.168.1.1 right now, and none of them collide, because no packet carrying that address ever crosses between them.
The second half is NAT, Network Address Translation. Something has to stand on the boundary and rewrite, because a packet with a private source address can leave your network but nothing out there can answer it. So the border router rewrites the source address of every packet on the way out, remembers what it did, and rewrites the destination address of every reply on the way back in. In its plainest form that is one private address swapped for one public address, which conserves nothing. The version that actually runs everywhere rewrites the source port number too, and that single extra field is what lets three hundred machines share one public address, because the port is what tells their replies apart.
02 Worked example
One packet, two source addresses, and only one of them survives the border
This is the scene for the rest of the lesson, including the console in section 04 and every address in the cheat sheet. One office network, 192.168.1.0/24, mask 255.255.255.0. Three machines on it, one router on the border, and exactly one public address for the whole office. All three machines are about to open a connection to the same web server, on the same port 80, which is the case that makes port translation necessary rather than merely convenient.
| Device | Address | Kind of address | Reachable from the Internet? |
|---|---|---|---|
| Host 1 | 192.168.1.10 | private, RFC 1918 | no |
| Host 2 | 192.168.1.11 | private, RFC 1918 | no |
| Host 3 | 192.168.1.12 | private, RFC 1918 | no |
| Router, inside interface | 192.168.1.1 | private, and the default gateway | no |
| Router, outside interface | 203.0.113.5 | public, globally unique | yes |
| Web server | 198.51.100.7:80 | public, globally unique | yes |
Follow one packet from Host 1, left to right. Watch what changes in it and what does not.
Two things in the highlighted node are worth slowing down on, because both get answered wrongly under pressure. First, only the source is rewritten on the way out. The destination 198.51.100.7:80 is carried through untouched, which is why the server sees a normal request to itself. On the way back the mirror holds: only the destination is rewritten, and the server’s address is untouched. Second, the row is written before the packet is forwarded, not after. It has to be, because the reply can arrive within milliseconds and the router has no other way to know where it belongs.
Now make it three hosts instead of one, and the reason for the port comes out. Host 1, Host 2 and Host 3 all connect to 198.51.100.7:80. Each picks its own source port, and a source port only has to be unique on the host that picked it. Nothing coordinates the three machines, so it is entirely legal, and quite likely, that two of them pick the same number. Say Host 1 and Host 2 both choose 50000.
If the router rewrote only the address, all three packets would leave with source 203.0.113.5 and two of them would leave with source port 50000. The server would then send two replies to 203.0.113.5:50000, and the router would have two rows matching the same public port and no way to choose between them. That is not a rare edge case; with hundreds of hosts it is a certainty. So the router does the only thing that works: when the public port it would like is already in use, it allocates a different one, writes that into the row, and rewrites the packet to match. Host 1 keeps 50000 because it asked first, Host 2 is moved to 50001, and Host 3 keeps 51234 because nothing else wanted it.
Count what the server sees at the end of that: one source address, three source ports, and no way whatsoever to tell that there are three machines rather than one very busy one. Count what the router holds: three rows and three public ports in use out of a 16-bit space. The port field, which was invented so one host could run many conversations, is being used here so one address can serve many hosts. That reuse is the whole trick, and it is what section 04 walks through one packet at a time.
03 Mechanics
The three ranges, the three flavours of NAT, and what it costs
Start with the ranges, because every question on this topic begins by asking whether an address is private, and one of the three is stated wrongly more often than it is stated correctly. Work each one from the mask rather than from memory: the network address is the address ANDed with the mask, the last address is the address ORed with the inverted mask.
| Block | Mask | First address | Last address | How many | Classful equivalent |
|---|---|---|---|---|---|
| 10.0.0.0/8 | 255.0.0.0 |
10.0.0.0 | 10.255.255.255 |
24 host bits, 2²⁴ = 16,777,216 |
one Class A network |
| 172.16.0.0/12 | 255.240.0.0 |
172.16.0.0 | 172.31.255.255 |
20 host bits, 2²⁰ = 1,048,576 |
16 contiguous Class B networks, 172.16 to 172.31 |
| 192.168.0.0/16 | 255.255.0.0 |
192.168.0.0 | 192.168.255.255 |
16 host bits, 2¹⁶ = 65,536 |
256 contiguous Class C networks |
| 169.254.0.0/16 link-local, RFC 3927, not RFC 1918 | 255.255.0.0 |
169.254.0.0 | 169.254.255.255 |
16 host bits, 2¹⁶ = 65,536 |
self-assigned; no router forwards it, not even yours |
| 100.64.0.0/10 carrier-grade NAT, RFC 6598 | 255.192.0.0 |
100.64.0.0 | 100.127.255.255 |
22 host bits, 2²² = 4,194,304 |
shared space for an ISP, not for you |
The 172 block, bit by bit, because this is the one that gets marked wrong. A /12 mask is 255.240.0.0, so the boundary falls in the middle of the second octet: eight fixed bits in the first octet and four more in the second. Write it out. 172 = 10101100 and 16 = 00010000, so the fixed part is 10101100 0001. To get the last address, set every remaining bit to one: 10101100 00011111 . 11111111 . 11111111, and 00011111 = 31. So the block runs 172.16.0.0 to 172.31.255.255, not to 172.16.255.255 and not to 172.32.255.255. Test the two neighbours the same way. For 172.15.255.254: 15 = 00001111, ANDed with 11110000 gives 00000000, so its /12 network is 172.0.0.0, which is not 172.16.0.0. Public. For 172.32.0.1: 32 = 00100000, ANDed with 11110000 gives 00100000, so its network is 172.32.0.0. Also public. The private block is the sixteen values 16 to 31 in that octet and nothing else. Across all three RFC 1918 blocks that is 16,777,216 + 1,048,576 + 65,536 = 17,891,328 addresses, roughly four tenths of one per cent of the IPv4 space, reused by everybody at once.
And the one that means something has failed. 169.254.0.0/16 is link-local, from RFC 3927, and Microsoft’s name for it is APIPA. A host uses it when it asked DHCP for an address and got no answer: rather than sit with no address at all, it picks one at random from that range, ARPs to check nobody else has it, and keeps it. It is not a private address in the RFC 1918 sense, and the difference is not pedantry. An RFC 1918 address is administered and your own router will happily route between two RFC 1918 subnets. A link-local address is self-assigned and scoped to a single link, so no router forwards it anywhere, including yours, and a host holding one has no default gateway. RFC 3927 also reserves the first and last /24 of the block, leaving 169.254.1.0 to 169.254.254.255, which is 254 × 256 = 65,024 usable addresses. Seeing one of these on a machine is a diagnosis, not a configuration.
That is the address space. Now the box that bridges it. There are three flavours and interviewers ask you to separate them, so keep the middle column straight: what does it rewrite, and how many inside hosts can be active per public address.
| Flavour | What it rewrites | The mapping | Inside hosts per public address | What it is actually for |
|---|---|---|---|---|
| Static NAT | source address outbound, destination address inbound | one private address to one public address, fixed, configured by hand, and it exists before any traffic does | 1 |
publishing an inside server. It is the only flavour where an outsider can start the conversation, because the row is already there. |
| Dynamic NAT | source address outbound, destination address inbound | one private address to one public address taken from a pool, allocated on the first packet, returned to the pool on timeout | 1 at a time |
a site with fewer public addresses than hosts but not far fewer. When the pool is empty the next host is refused outright. |
| PAT NAT overloading, NAPT | source address and source port outbound; destination address and port inbound | (private IP, private port) to (public IP, public port), allocated per flow | thousands |
every network you have ever used. This is what people mean when they say “NAT” without qualifying it. |
Why the pool runs out and the port range does not. Dynamic NAT with a pool of four public addresses supports four concurrent inside hosts, full stop, however little traffic each is sending. PAT with one public address is bounded by the port space instead, and a port is 16 bits, so there are 2¹⁶ = 65,536 values per transport protocol per public address, of which port 0 is not used. Routers allocate from the ephemeral range rather than the whole space: IANA designates 49152 to 65535 as the dynamic range, Linux defaults to 32768 to 60999 in net.ipv4.ip_local_port_range, and Windows uses the IANA range. That is why the middle row of the table caps at one and the bottom row is measured in thousands, from exactly the same number of public addresses.
Cisco’s four names for the four addresses in a row are worth memorising, because show ip nat translations prints all four on every line and half the confusion on this topic is people meaning different things by “the outside address”.
| Term | Which address | In the section 02 scene | The point |
|---|---|---|---|
| Inside local | the inside host, as the inside sees it | 192.168.1.10:50000 | the private address. Never appears in a packet outside the border. |
| Inside global | the inside host, as the outside sees it | 203.0.113.5:50000 | the public address the router lends it. This is the column an arriving reply is matched against. |
| Outside local | the outside host, as the inside sees it | 198.51.100.7:80 | equal to outside global here, because nothing is translating the far end. |
| Outside global | the outside host, as the outside sees it | 198.51.100.7:80 | the server’s real address. The two outside columns only differ when a second NAT is in the path. |
Read “local” as inside-facing and “global” as outside-facing, and “inside” and “outside” as whose address it is. Inside global is therefore the inside host wearing a public address, which is the one people get wrong by reading it as the router’s own. It is not: it is this flow’s loan of the router’s address and one of its ports, and it is released when the flow goes quiet.
Now the honest part, which is the half that separates a good answer from a recited one. NAT solves the address problem by breaking something the Internet was designed around, and the breakages are specific.
The end-to-end model is gone. IP was designed so any host could address any other host directly, and so that routers in the middle only looked at the destination address. A NAT reads and rewrites the transport header, so it is no longer a router in that sense; it is a device that has to understand your connections. Two consequences follow. Addresses are no longer meaningful end to end, so a packet’s source address means “this NAT” and not “this host”. And the NAT holds state that neither endpoint holds: pull its power and the connections die even though both endpoints are perfectly healthy.
Unsolicited inbound traffic has nothing to translate to. A packet arriving from outside is matched against the inside global column. If no row matches, the router cannot rewrite the destination, because there is no correct answer to rewrite it to, so it drops the packet. That is why running a game server or an SSH daemon on a machine behind a home router and handing a friend the address does not work. Two things exist to work around it. Port forwarding is static NAT applied to one port: you configure in advance that 203.0.113.5:22 maps to 192.168.1.10:22, so the row exists before the traffic does. NAT traversal is the automatic version, and it works by having both sides send outward first so that both routers write rows, then getting them to reuse those rows. A STUN server (RFC 8489) with a public address tells a host what public address and port its own router assigned it, which the host cannot otherwise discover; TURN (RFC 8656) relays the traffic when that fails; ICE (RFC 8445) is the procedure that tries the options in order. This is the machinery underneath every video call you have made.
Protocols that carry addresses inside their payload need help. NAT rewrites headers. It does not read your data, so any protocol that writes an IP address or a port into its payload will hand the far end a number that stopped being true at the border. Active-mode FTP is the standard example: the client sends a PORT command containing its own address and a port for the server to connect back to, and after translation that address is a private one the server cannot reach. SIP does the same inside SDP for voice calls. The workaround is an ALG, an application-level gateway, which is the NAT reaching into the payload and rewriting the number there too, and it is fragile by construction. IPsec is worse: the AH protocol authenticates the IP header including the addresses, so any rewrite invalidates it and AH cannot pass through a NAT at all. ESP survives only with NAT traversal, which wraps it in UDP on port 4500 while IKE negotiates on UDP 500.
NAT is address conservation. The privacy is a side effect and it is not a firewall. Say this plainly in an interview, because the opposite is a very common claim. It is true that inside hosts are not directly reachable and that their addresses do not appear on the Internet. But a NAT inspects nothing, filters nothing on the way out, and knows nothing about what a connection is carrying. Any inside machine can open any outbound connection to anywhere, which is how essentially all modern malware communicates, and a payload arriving on a connection the inside host requested is delivered without a second look. A stateful firewall enforces a policy about what is allowed; a NAT drops unmatched inbound packets because it has no answer, which is a side effect of bookkeeping rather than a decision. Relying on it as security is the mistake, and the honest sentence is that NAT bought the IPv4 Internet decades of extra life at the cost of the end-to-end model.
Which is why IPv6 removes the need for it. An IPv6 address is 128 bits, giving 2¹²⁸, about 3.4 × 10³⁸ addresses, so there is no scarcity to conserve and every host can hold a globally unique address again. IPv6 deployments use a stateful firewall for the inbound blocking rather than a translator, which is the correct tool for that job and always was. One thing to know for the meantime: when even an ISP runs short of public addresses it puts a second NAT of its own in front of yours and gives your router an address from 100.64.0.0/10, which is called carrier-grade NAT. Both your outside columns are then translated by somebody else, port forwarding on your router stops working entirely, and that is the situation on most Indian mobile data connections today.
05 Cheat sheet
Thirteen answers to have ready
Every row is something you can be asked to state or compute in under ten seconds. The right-hand column is the specific wrong answer that gets given, not a general caution.
| What they ask | The answer | The trap |
|---|---|---|
| Size of an IPv4 address and the total supply | 32 bits, 2³² = 4,294,967,296 | Quoting 4.3 billion as if all of it were assignable. Loopback, multicast and reserved blocks are carved out of that total. |
| The three private ranges | 10.0.0.0/8 · 172.16.0.0/12 · 192.168.0.0/16 | writing the middle one as 172.16.0.0/16 so it stops at 172.16.255.255 |
| Where the 172 block ends | 172.31.255.255 | saying 172.32.255.255 — 172.32.0.0 is public address space |
| How many addresses in each block | 2²⁴ · 2²⁰ · 2¹⁶ = 16,777,216 · 1,048,576 · 65,536 | Guessing instead of counting host bits. The exponent is 32 minus the prefix length, every time. |
| Usable hosts on a /24 | 2⁸ − 2 = 254 | answering 256 — the all-zeros network address and the all-ones broadcast address are not assignable |
| What 169.254.x.x means | link-local, RFC 3927, self-assigned because DHCP did not answer | Calling it private. It is a different thing, from a different RFC, and no router forwards it including your own. |
| What plain NAT rewrites | source address going out, destination address coming back | Saying it rewrites both addresses in every packet. The far end’s address is never touched. |
| What PAT rewrites in addition | the source port | forgetting the port — and then being unable to explain how the reply finds the right host |
| The four Cisco terms | inside local, inside global, outside local, outside global | Reading inside global as the router’s own address. It is the inside host wearing a public address for one flow. |
| Which field disambiguates the return traffic | the inside global port | saying the private IP address — it never appears in any packet on the public side |
| How many flows one public address supports under PAT | bounded by the port space: 2¹⁶ values per transport protocol | Answering “unlimited”. It is large, not infinite, and the practical range is narrower than the full 16 bits. |
| Why an unsolicited inbound connection fails | no row matches, so there is nothing to translate the destination into | “the firewall blocks it” — there may be no firewall in the path at all |
| Carrier-grade NAT space | 100.64.0.0/10, RFC 6598, 100.64.0.0 to 100.127.255.255 | Filing it under RFC 1918. It is shared space assigned by an ISP, and you never choose it. |
06 Where & why
The translation table is a command you can run today
None of this is a teaching abstraction. Every system below prints the same table with different column names, and the limits quoted are documented defaults you can look up in the product that ships them.
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE is PAT in a single line; MASQUERADE is the variant that takes whatever address the outgoing interface currently has, which is what you want on a link whose public address changes. The translation table lives in the kernel’s connection tracker and conntrack -L prints it, one line per flow with both address and port pairs. It is finite and it is tunable: net.netfilter.nf_conntrack_max caps the number of rows, and a busy gateway that hits that cap starts dropping new connections while old ones keep working, which is a genuinely confusing failure to diagnose.
ip nat inside source list 1 interface GigabitEthernet0/0 overload configures exactly the scene in section 04, and the word overload is what turns dynamic NAT into PAT. show ip nat translations then prints Pro, Inside global, Inside local, Outside local and Outside global, which is where those four terms in your interview come from. Static NAT is a separate statement, ip nat inside source static, and the difference is visible in the output: a static row is present with no traffic at all, while dynamic rows appear on the first packet and age out on a timer.
You give a VPC a private CIDR block such as 10.0.0.0/16, and instances in a private subnet get addresses from it and no route to the Internet Gateway. A NAT Gateway placed in a public subnet gives them outbound access with the same one-way property as your home router: they can reach out, nothing can reach in. AWS documents the ceiling in the terms of this lesson, up to 55,000 simultaneous connections to each unique destination, and the way past it is more destinations or more addresses rather than a bigger box. Inbound access needs a load balancer or a public address, which is static NAT wearing a cloud name.
Log into a home router on a mobile connection and the WAN address is often something like 100.94.13.7, inside 100.64.0.0/10. That is RFC 6598 shared space, not RFC 1918 and not public, and it means the ISP is running carrier-grade NAT with your traffic translated a second time upstream. The practical consequence is immediate: port forwarding configured on your own router does nothing, because the row you created is on the wrong translator, and the address the outside world would have to aim at is not yours to configure. It is also the clearest demonstration in daily life that address exhaustion is a live constraint and not a story about 2011.
07 Interview questions
What they ask, and what they follow up with
This topic has one favourite follow-up: you explain NAT, and the interviewer asks how the reply gets back to the right machine. Everything else is a range you either know exactly or do not. Say the numbers, then say the mechanism.
What is the difference between a private and a public IP address?
Give me the private address ranges exactly.
Two different colleges both use 192.168.1.1 for their gateway. Is that a conflict?
A laptop shows 169.254.4.19. What does that tell you?
What problem does NAT actually solve?
Static NAT, dynamic NAT and PAT. Separate them for me.
Three machines behind one public address all connect to the same web server on port 80. How does a reply find the right machine?
What do inside local, inside global, outside local and outside global mean?
Is NAT a firewall?
Which protocols break under NAT, and why?
Does IPv6 need NAT?
08 Practice problems
Six to work out on paper
For every one: write the addresses in binary before you decide anything, and keep the mask you are applying labelled, because two of these apply two different masks to the same address for two different reasons. Where a count is asked for, say whether you are counting addresses or usable hosts.