Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bogon.py updates #45

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 28 additions & 43 deletions kartograf/bogon.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,9 @@
# "fec0::/10",
]

# Sets of networks
SPECIAL_IPV4_NETWORKS = {ipaddress.ip_network(prefix) for prefix in SPECIAL_IPV4}
SPECIAL_IPV6_NETWORKS = {ipaddress.ip_network(prefix) for prefix in SPECIAL_IPV6}

def is_bogon_pfx(prefix):
"""
Expand All @@ -133,19 +136,12 @@ def is_bogon_pfx(prefix):
- https://www.iana.org/assignments/iana-ipv6-special-registry/iana-ipv6-special-registry.xhtml
- https://bgpfilterguide.nlnog.net/guides/bogon_prefixes/
"""
network = ipaddress.ip_network(prefix)
version = network.version

if version == 4:
for ipv4_range in SPECIAL_IPV4:
if network.subnet_of(ipaddress.ip_network(ipv4_range)):
return True
elif version == 6:
for ipv6_range in SPECIAL_IPV6:
if network.subnet_of(ipaddress.ip_network(ipv6_range)):
return True

return False
try:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, this silences the error. I don't think that's what we want here. Generally such an error shouldn't happen here of course but if it does something has been going really wrong and then this function shouldn't pretend that the network is actually fine and not even a bogon. We would probably run into issue later and have a harder time debugging the later that happens.

network = ipaddress.ip_network(prefix)
networks = SPECIAL_IPV4_NETWORKS if network.version == 4 else SPECIAL_IPV6_NETWORKS
return any(network.subnet_of(special_net) for special_net in networks)
except ValueError:
return False


def is_bogon_asn(asn_raw):
Expand All @@ -159,38 +155,27 @@ def is_bogon_asn(asn_raw):
"""
asn = extract_asn(asn_raw)

if asn == 0:
# AS 0 is reserved, RFC7607
return True
if asn == 65535:
# Last 16 bit ASN, RFC7300
return True
if asn == 4294967295:
# Last 32 bit ASN, RFC7300
return True
if asn == 112:
# AS 112 is used by the AS112 project to sink misdirected DNS queries,
# RFC7534
return True
if asn == 23456:
# AS 23456 is reserved as AS_TRANS, RFC6793
return True
if 64496 <= asn <= 64511:
# AS 64496-64511 are reserved for documentation and sample code,
# RFC5398
return True
if 64512 <= asn <= 65534 or 4200000000 <= asn <= 4294967294:
# AS 64512-65534 and AS 4200000000-4294967294 are reserved for private
# use, RFC6996
return True
if 65536 <= asn <= 65551:
# AS 65536-65551 are reserved for documentation and sample code,
# RFC5398
return True
if 65552 <= asn <= 131071:
# IANA reserved ASNs, no RFC
special_asns = {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: reserved_asns

0, # Reserved, RFC7607
112, # AS112 project, RFC7534
23456, # AS_TRANS, RFC6793
65535, # Last 16 bit ASN, RFC7300
4294967295 # Last 32 bit ASN, RFC7300
}

if asn in special_asns:
return True

special_ranges = {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: reserved_asn_ranges

(64496, 64511), # Documentation/Sample, RFC5398
(64512, 65534), # Private use, RFC6996
(65536, 65551), # Documentation/Sample, RFC5398
(65552, 131071), # IANA reserved, no RFC
(4200000000, 4294967294) # Private use, RFC6996
}

if any(start <= asn <= end for start, end in special_ranges):
return True
return False


Expand Down
88 changes: 88 additions & 0 deletions tests/bogon_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
from kartograf.bogon import is_bogon_pfx, is_bogon_asn, extract_asn, is_out_of_encoding_range

def test_special_asns():
special_cases = [0, 112, 23456, 65535, 4294967295]
for asn in special_cases:
assert is_bogon_asn(asn) is True
assert is_bogon_asn(f"AS{asn}") is True

def test_documentation_range():
assert is_bogon_asn(64496) is True
assert is_bogon_asn(64511) is True
assert is_bogon_asn(64503) is True

def test_private_use_range():
assert is_bogon_asn(64512) is True
assert is_bogon_asn(65534) is True
assert is_bogon_asn(4200000000) is True
assert is_bogon_asn(4294967294) is True

def test_valid_asns():
valid_asns = [13335, 15169, 32934, 16509] # Cloudflare, Google, Facebook, Amazon
for asn in valid_asns:
assert is_bogon_asn(asn) is False
assert is_bogon_asn(f"AS{asn}") is False

def test_asn_extraction():
assert extract_asn("AS12345") == 12345
assert extract_asn("as12345") == 12345
assert extract_asn(" AS12345 ") == 12345
assert extract_asn(12345) == 12345

def test_encoding_range():
assert is_out_of_encoding_range(33521665) is True
assert is_out_of_encoding_range(33521664) is False
assert is_out_of_encoding_range(100) is False

def test_bogon_ipv4_prefixes():
bogon_prefixes = [
"0.0.0.0/8", # RFC791
"10.0.0.0/8", # RFC1918 Private-Use
"127.0.0.0/8", # Loopback
"169.254.0.0/16", # Link Local
"192.168.0.0/16", # Private-Use
"224.0.0.0/4", # Multicast
"240.0.0.0/4" # Reserved
]
for prefix in bogon_prefixes:
assert is_bogon_pfx(prefix) is True

def test_valid_ipv4_prefixes():
valid_prefixes = [
"8.8.8.0/24", # Google DNS
"1.1.1.0/24", # Cloudflare
"104.16.0.0/12", # Cloudflare range
"157.240.0.0/16" # Facebook
]
for prefix in valid_prefixes:
assert is_bogon_pfx(prefix) is False

def test_bogon_ipv6_prefixes():
bogon_prefixes = [
"::/8", # IPv4-compatible
"100::/64", # Discard-Only
"2001:db8::/32", # Documentation
"fc00::/7", # Unique-Local
"fe80::/10", # Link-Local Unicast
"ff00::/8" # Multicast
]
for prefix in bogon_prefixes:
assert is_bogon_pfx(prefix) is True

def test_valid_ipv6_prefixes():
valid_prefixes = [
"2606:4700::/32", # Cloudflare
"2620:fe::/48", # Google
"2a03:2880::/32" # Facebook
]
for prefix in valid_prefixes:
assert is_bogon_pfx(prefix) is False

def test_invalid_prefixes():
invalid_prefixes = [
"not.a.prefix",
"300.0.0.0/8", # Invalid IPv4
"2001:xyz::/32" # Invalid IPv6
]
for prefix in invalid_prefixes:
assert is_bogon_pfx(prefix) is False
Loading