79 lines
2.3 KiB
Python
79 lines
2.3 KiB
Python
#!/usr/bin/env python3
|
|
|
|
###############
|
|
# RFC7050 ipv6 prefix discovery
|
|
# Prefixes can have lengths 32, 40, 48, 56, 64, or 96 per RFC6052
|
|
# IMPORTANT: THIS DOES NOT HANDLE THE SUFFIX ASPECTS THAT MAY COME INTO PLAY ON SOME NETWORKS
|
|
###############
|
|
|
|
##########
|
|
# Dependencies
|
|
##########
|
|
# pip3 install dnspython
|
|
|
|
##########
|
|
# Sample T-Mobile record
|
|
##########
|
|
# ipv4only.arpa
|
|
# 192.0.0.170
|
|
# 192.0.0.171
|
|
# 2607:7700:0:26::c000:aa
|
|
# 2607:7700:0:26::c000:ab
|
|
|
|
##########
|
|
import ipaddress
|
|
import dns.resolver
|
|
|
|
##########
|
|
# Discovery of DNS records
|
|
##########
|
|
#TODO: Swap this to a well-known address that is ISP independent
|
|
# Sub domain with only an A record somewhere?
|
|
Update to handle the tweaked approach
|
|
resolver = dns.resolver.Resolver()
|
|
a_recs = resolver.query("ipv4only.arpa", "A")
|
|
aaaa_recs = resolver.query("ipv4only.arpa", "AAAA")
|
|
|
|
##########
|
|
# Process DNS records for prefix discovery process
|
|
##########
|
|
a_addresses = []
|
|
aaaa_addresses = []
|
|
|
|
for a in a_recs:
|
|
print(a)
|
|
a_addresses.append(ipaddress.IPv4Address(a.to_text()))
|
|
|
|
for aaaa in aaaa_recs:
|
|
print(aaaa)
|
|
aaaa_addresses.append(ipaddress.IPv6Address(aaaa.to_text()))
|
|
|
|
##########
|
|
# Figure out published prefixes
|
|
##########
|
|
prefixes = []
|
|
|
|
for aaaa in aaaa_addresses:
|
|
ipv6_bytes = aaaa.packed
|
|
for a in a_addresses:
|
|
ipv4_bytes = a.packed
|
|
# Split the bytes so we can find the prefix minus the ipv4 address and following info
|
|
partition = ipv6_bytes.partition(ipv4_bytes)
|
|
if partition[0] != ipv6_bytes:
|
|
# Padded to a full 16 bytes needed by the Python ipaddress module
|
|
mask_number_bytes = 16 - len(partition[0])
|
|
# Figure out the actual integer mask
|
|
mask = 128 - (mask_number_bytes * 8)
|
|
# Pad the prefix with 0's
|
|
prefix_bytes = partition[0] + bytearray(mask_number_bytes)
|
|
# Get the /128 address
|
|
address = ipaddress.IPv6Address(prefix_bytes)
|
|
# Build the compressed address + mask for output
|
|
prefix = '/'.join([str(address), str(mask)])
|
|
# De-duplicate the prefixes
|
|
# Some ISPs publish multiple records that result in identical prefixes
|
|
if prefix not in prefixes:
|
|
prefixes.append(prefix)
|
|
|
|
print(prefixes)
|