A bogon IP is an address that should never appear as a source address on the public internet - either because it belongs to a reserved range (private, loopback, test networks) or because it sits in address space that has never been allocated for use. If a packet arrives claiming to come from a bogon IP, something is wrong: the address was spoofed, a device is misconfigured, or internal traffic is leaking where it should not. This post covers exactly which ranges are bogons, why they still show up in real logs, and how to filter them with a single flag.
The bogon ranges, with their RFCs
"Bogon" is network-operator slang (from "bogus") for two overlapping categories. The first is reserved space - ranges that the standards permanently set aside for purposes other than public routing:
- Private networks:
10.0.0.0/8,172.16.0.0/12,192.168.0.0/16(RFC 1918). These are for internal use behind NAT. Your office LAN and your home router live here; the public internet should never see them as source addresses. - Loopback:
127.0.0.0/8(RFC 1122). Traffic to and from the local host itself. A packet from127.0.0.1arriving on your public interface did not come from "localhost somewhere else" - that is not a thing. - Link-local:
169.254.0.0/16(RFC 3927). Self-assigned addresses used when a host cannot reach a DHCP server. Valid only on the local network segment, never routed. - Carrier-grade NAT:
100.64.0.0/10(RFC 6598). Shared address space for ISPs running large-scale NAT between customers and the internet. Legitimate inside an ISP's network, illegitimate as a public source address. - Documentation ranges:
192.0.2.0/24,198.51.100.0/24,203.0.113.0/24(RFC 5737). The TEST-NET ranges, reserved so that examples in documentation (including the code sample below) can use addresses that will never collide with real hosts.
A few more reserved ranges round out the picture: 198.18.0.0/15 is set aside for network benchmarking (RFC 2544), and 0.0.0.0/8 ("this network", RFC 1122) is likewise never a valid public source. IPv6 has direct equivalents - unique local addresses in fc00::/7 (RFC 4193) play the private-range role, link-local fe80::/10 (RFC 4291) mirrors 169.254.0.0/16, and 2001:db8::/32 (RFC 3849) is the documentation range.
The second category is unallocated space: addresses that IANA or the regional internet registries have not (yet) handed out to anyone. Nobody legitimately announces these prefixes, so no legitimate packet can originate from them - no autonomous system is authorized to route them (our ASN explainer covers how announcement and ownership work). The strict reserved-ranges list plus all unallocated space is what operators call the fullbogons list. If you want to explore how these prefixes and masks break down, our free IP calculator will expand any CIDR range for you, and the WHOIS tool shows the registration status of any address you are curious about.
Why bogon IPs show up anyway
If these addresses cannot legitimately originate traffic, why does every busy edge see them? Three reasons:
- Spoofing in DDoS attacks. Source addresses in IP packets are trivially forgeable, and flood attacks often randomize them to defeat per-source rate limiting and hide the true origin. Randomized 32-bit sources inevitably include reserved and unallocated space, so bogon sources in a traffic spike are a classic fingerprint of spoofed flood traffic.
- Misconfigured NAT and routers. A NAT gateway that fails to translate, or a router that forwards packets it should have dropped, will happily emit RFC 1918 source addresses onto its upstream link. This is the most common benign explanation - and still worth catching, because it means someone's network gear is broken.
- Leaked internal traffic. VPN misroutes, sloppy split-horizon setups, and cloud misconfigurations can push internal traffic out a public interface. Seeing your own private ranges arrive from outside is also a security smell: attackers sometimes spoof internal addresses precisely because badly written firewall rules trust them.
Why you should filter bogon IPs
Two arguments, one for the internet and one for you.
The internet-citizenship argument is BCP 38 (RFC 2827): networks should perform ingress filtering, dropping packets whose source addresses could not legitimately arrive on the interface they came in on. Universal ingress filtering would make source-spoofed DDoS dramatically harder, and bogon filtering is the easiest slice of it - there is no edge case in which a packet from 192.0.2.55 is traffic you wanted.
Where you filter matters as much as whether you do. The right place for packet-level bogon drops is the network edge - router ACLs, firewall rules, or your cloud provider's network policies - because there is no value in carrying the packets any deeper. But applications see addresses too, through proxy headers like X-Forwarded-For, webhook payloads, and user-submitted data, and those values are just strings anyone can forge. An application-layer check catches the bogon "client address" that a spoofed header smuggled past your edge filtering, which is exactly the spot where naive allowlists ("trust internal IPs") get exploited.
The selfish argument is log and data hygiene. Bogon sources pollute everything downstream of your edge: analytics count phantom visitors, geolocation lookups burn quota on addresses that cannot resolve anywhere, abuse tooling chases sources that do not exist, and alert noise goes up. Dropping bogons early keeps every system behind the filter cleaner, and flagging them (rather than silently dropping) tells you when your own infrastructure starts leaking.
Checking is_bogon with the API
Every lookup through The IP API includes an is_bogon flag. For a bogon address the API skips geolocation, ASN, and company enrichment entirely - none of it can exist for a reserved address - and returns a minimal response with only the ip and is_bogon fields in the body:
curl "https://api.theipapi.com/v1/ip/203.0.113.7?api_key=YOUR_API_KEY"
{
"status": "OK",
"body": {
"ip": "203.0.113.7",
"is_bogon": true
},
"response_time_ms": 0
}
That shape makes the check cheap to write - test the flag before touching any of the fields that only exist for real addresses:
import requests
resp = requests.get(
"https://api.theipapi.com/v1/ip/203.0.113.7",
params={"api_key": "YOUR_API_KEY"},
timeout=5,
)
data = resp.json()
body = data.get("body") or {}
if body.get("is_bogon"):
print(f"{body['ip']} is a bogon - drop or investigate this source")
else:
print(f"{body['ip']} location: {body.get('location')}")
The same flag appears (as is_bogon: false) in every normal lookup response, and the batch endpoint returns it per IP, so a log-scoring pipeline gets bogon detection for free alongside geolocation. Full response formats are in the documentation.
Static bogon lists go stale
A tempting shortcut is to paste a bogon list into your firewall config and move on. The reserved ranges above are stable, but the unallocated portion of the list is not: it shrinks whenever IANA and the RIRs allocate address space that was previously bogon. This is not hypothetical - operators who hardcoded fullbogon lists have repeatedly ended up blackholing newly allocated, perfectly legitimate networks, and the affected users have no way to tell why your service is unreachable for them. IPv6 makes it worse: the overwhelming majority of the IPv6 space is unallocated, so the fullbogon set there is both enormous and guaranteed to change.
So either subscribe to a maintained feed and automate updates into your filters, or check at the application layer against data that someone else keeps fresh. The bogon data behind The IP API's is_bogon flag is refreshed daily, so a newly allocated range stops being flagged without you shipping a config change.
Try it now
Grab a free API key - 1,000 requests per day, no card required - and run a few addresses from your own logs through the API. If any of them come back is_bogon: true, you have just learned something about your edge filtering that was worth knowing.