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.

RangeNameReserved by
192.0.2.0/24TEST-NET-1RFC 5737
198.51.100.0/24TEST-NET-2RFC 5737
203.0.113.0/24TEST-NET-3RFC 5737
2001:db8::/32IPv6 documentationRFC 3849
3fff::/20IPv6 documentation, largerRFC 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.

RangePurposeWhy 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::/7Unique local IPv6 (RFC 4193)The IPv6 counterpart of private ranges. In practice, addresses start fd.
127.0.0.0/8
::1
LoopbackAll 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-localIncludes 169.254.169.254, the cloud metadata service.
100.64.0.0/10Carrier-grade NAT (RFC 6598)Used by ISPs between you and the internet. Not a test range.
198.18.0.0/15
2001:2::/48
BenchmarkingFor 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
MulticastNot a single host. Should never be accepted as a destination for a request.
240.0.0.0/4
255.255.255.255
Reserved and broadcastNot 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.

InputWhat 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.1Checking 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

InputCorrect result
256.1.1.1Invalid. Each IPv4 part is 0 to 255.
192.0.2.01Ambiguous: some parsers read a leading zero as octal. Reject or normalise deliberately.
2001:db8::1Valid. :: stands for one run of zero groups.
2001:db8::1::2Invalid. :: may appear only once.
2001:DB8::1Valid and equal to the lowercase form. Compare parsed values, not strings.
fe80::1%eth0A link-local address with a zone ID. Valid in some contexts, meaningless in others.
::ffff:192.0.2.1IPv4-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

IdentifierReservedBy
MAC addresses00:00:5E:00:53:00 to 00:00:5E:00:53:FFRFC 7042
AS numbers64496 to 64511RFC 5398
Domain names.test, .example, .invalid and example.comRFC 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.