Learning & reference
Reserved IP addresses: which to use in tests, and which your code must refuse
There are two reasons to look these up. You need an address for a log line, a fixture or an example that can never belong to anyone. Or you are testing that your code treats special addresses specially, which is where the security bugs are. This page covers both.
For documentation, fixtures and logs
Reserved for examples. Never configured on a real network, never routed on the internet.
| Range | Name | Reserved by |
|---|---|---|
| 192.0.2.0/24 | TEST-NET-1 | RFC 5737 |
| 198.51.100.0/24 | TEST-NET-2 | RFC 5737 |
| 203.0.113.0/24 | TEST-NET-3 | RFC 5737 |
| 2001:db8::/32 | IPv6 documentation | RFC 3849 |
| 3fff::/20 | IPv6 documentation, larger | RFC 9637 (2024) |
Three IPv4 blocks exist so you can show three networks. A client at 198.51.100.7 talking
to a server at 203.0.113.10 through a proxy at 192.0.2.1 reads clearly and involves nobody. Use
3fff::/20 when an IPv6 example needs more room than a /32, such as several sites each with their own
large prefix.
Special-purpose ranges
Real, in use, and each with behaviour your code may need to handle.
| Range | Purpose | Why it matters in testing |
|---|---|---|
| 10.0.0.0/8 172.16.0.0/12 192.168.0.0/16 | Private networks (RFC 1918) | Every internal network. An example using them can collide with the reader's own. |
| fc00::/7 | Unique local IPv6 (RFC 4193) | The IPv6 counterpart of private ranges. In practice, addresses start fd. |
| 127.0.0.0/8 ::1 | Loopback | All of 127.x.x.x is loopback, not just 127.0.0.1. Filters that block only the one address miss the rest. |
| 169.254.0.0/16 fe80::/10 | Link-local | Includes 169.254.169.254, the cloud metadata service. |
| 100.64.0.0/10 | Carrier-grade NAT (RFC 6598) | Used by ISPs between you and the internet. Not a test range. |
| 198.18.0.0/15 2001:2::/48 | Benchmarking | For network device testing labs. Not for documentation. |
| 0.0.0.0/8 | "This network" | 0.0.0.0 reaches the local host on many systems, which makes it an SSRF bypass. |
| 224.0.0.0/4 ff00::/8 | Multicast | Not a single host. Should never be accepted as a destination for a request. |
| 240.0.0.0/4 255.255.255.255 | Reserved and broadcast | Not valid host addresses. Test that validation refuses them. |
What an SSRF filter must refuse
If your app fetches URLs a user supplies (webhooks, link previews, image imports), each of these must be blocked. Every one of them reaches the machine itself or its cloud metadata.
| Input | What it really is |
|---|---|
| http://127.0.0.1/ | Loopback, the obvious case. |
| http://localhost/ | A name that resolves to loopback. Check the resolved address, not the name. |
| http://127.1/ | Shortened form of 127.0.0.1, accepted by many parsers. |
| http://2130706433/ | 127.0.0.1 as a single decimal number. |
| http://0x7f000001/ | 127.0.0.1 in hexadecimal. |
| http://0177.0.0.1/ | 127.0.0.1 with an octal first part. |
| http://0.0.0.0/ | Reaches the local host on many systems. |
| http://[::1]/ | IPv6 loopback. |
| http://[::ffff:127.0.0.1]/ | IPv4-mapped IPv6: loopback wearing an IPv6 costume. |
| http://169.254.169.254/ | Cloud instance metadata, where credentials live. |
| http://10.0.0.1/ | Your internal network. |
| A public hostname that resolves to 127.0.0.1 | Checking the name is not enough. Resolve it, check the address, then connect to that same address. |
Check after resolving, and connect to what you checked. A filter that validates the hostname and then lets the HTTP client resolve it again can be beaten by DNS that answers differently the second time. Redirects need the same check: a public URL can redirect to 169.254.169.254.
"Private" is not the same as "not public". In Python, ipaddress reports
is_private as False for 100.64.0.0/10, the carrier-grade NAT range, so a filter built on
is_private lets it through, and Alibaba Cloud's metadata service sits inside it at 100.100.100.200.
Allow only addresses where is_global is True, rather than blocking a list of bad ones.
What an IP validator must get right
| Input | Correct result |
|---|---|
| 256.1.1.1 | Invalid. Each IPv4 part is 0 to 255. |
| 192.0.2.01 | Ambiguous: some parsers read a leading zero as octal. Reject or normalise deliberately. |
| 2001:db8::1 | Valid. :: stands for one run of zero groups. |
| 2001:db8::1::2 | Invalid. :: may appear only once. |
| 2001:DB8::1 | Valid and equal to the lowercase form. Compare parsed values, not strings. |
| fe80::1%eth0 | A link-local address with a zone ID. Valid in some contexts, meaningless in others. |
| ::ffff:192.0.2.1 | IPv4-mapped IPv6. Valid, and equal to 192.0.2.1 for most purposes. |
| 192.0.2.1 | Trim or reject, but never store the whitespace. |
Other network identifiers reserved for documentation
| Identifier | Reserved | By |
|---|---|---|
| MAC addresses | 00:00:5E:00:53:00 to 00:00:5E:00:53:FF | RFC 7042 |
| AS numbers | 64496 to 64511 | RFC 5398 |
| Domain names | .test, .example, .invalid and example.com | RFC 2606 |
Questions
What IP address should I use in documentation?
192.0.2.0/24, 198.51.100.0/24 or 203.0.113.0/24 for IPv4, and 2001:db8::/32 or 3fff::/20 for IPv6.
Is 192.168.1.1 safe to use in test data?
It will not reach the internet, but it is a real private address on millions of home routers. Use 192.0.2.1 in examples.
What is 169.254.169.254?
The cloud instance metadata address used by AWS, Google Cloud and Azure. It is the first thing an SSRF filter must block.
Private or documentation range?
Private ranges are real internal networks; documentation ranges are never configured anywhere. Use documentation ranges in examples.
How can 2130706433 be an IP address?
It is 127.0.0.1 as one decimal number. Parse addresses before checking them, never compare strings.
Keep going
All safe test data Example domains → Test strings →
More from Learning
Guides and references for test data, file handling and AI evals. All free, no sign-up. See the full hub.