import ipaddress import dns.name def reverse_zone(network): """ Reverse a network zone Takes an network object (`ipaddress.IPv4Network` or `ipaddress.IPv6Network`) as an input and returns a DNS name object (`dns.name.Name`) corresponding to the reverse DNS entry correctly formated. Parameters ---------- network: ipaddress.IPv4Network or ipaddress.IPv6Network The Network IP and mask object Return ------ reversed_zone: dns.name.Name The reverse zone as a DNS Name oject Examples -------- >>> # Some IPv4 Networks >>> net1 = ipaddress.IPv4Network("10.128.12.0/24") >>> net2 = ipaddress.IPv4Network("10.129.0.0/16") >>> net3 = ipaddress.IPv4Network("10.0.0.0/8") >>> # Some IPv6 Networks >>> net4 = ipaddress.IPv6Network("2001:470:142:3::/64") >>> net5 = ipaddress.IPv6Network("2001:470:142::/48") >>> net6 = ipaddress.IPv6Network("2a09:6840::/32") >>> # And the expected outputs >>> reverse_zone(net1) '12.128.10.in-addr.arpa' >>> reverse_zone(net2) '129.10.in-addr.arpa' >>> reverse_zone(net3) '10.in-addr.arpa' >>> reverse_zone(net4) '3.0.0.0.2.4.1.0.0.7.4.0.1.0.0.2.ip6.arpa' >>> reverse_zone(net5) '2.4.1.0.0.7.4.0.1.0.0.2.ip6.arpa' >>> reverse_zone(net6) '0.4.8.6.9.0.a.2.ip6.arpa' See also -------- dnspython: https://dnspython.readthedocs.io ipaddress: https://docs.python.org/3/library/ipaddress.html References ---------- [1] RFC 1035: DOMAIN NAMES - IMPLEMENTATION AND SPECIFICATION, IETF, Network Working Group, November 1987. """ if network.version == 4: boundary = 8 # break to the byte elif network.version == 6: boundary = 4 # break to the nibble assert network.prefixlen % boundary == 0 length = (network.prefixlen // boundary) full_network_reverse = network.network_address.reverse_pointer splitted = full_network_reverse.split(".") splitting_len = int(network.max_prefixlen / boundary) splitted = splitted[splitting_len - length:] reversed_zone = ".".join(splitted) return dns.name.from_text(reversed_zone)