1 # PyNSC: Generator of sink zones
2 # (c) 2024 Martin Mareš <mj@ucw.cz>
4 from typing import List
6 from nsconfig.core import Nsc, NscZonePrimary
7 from nsconfig.util import IPNetwork, parse_network
9 # Networks which should have blackhole reverse zones as recommended by RFC 6303
10 BLACKHOLE_NETWORKS = [
11 '0.0.0.0/8', # IPv4 reserved
12 '10.0.0.0/8', # IPv4 private
13 '169.254.0.0/16', # IPv4 link-local
14 '192.0.2.0/24', # IPv4 test
15 '192.168.0.0/16', # IPv4 private
16 '198.51.100.0/24', # IPv4 test
17 '203.0.113.0/24', # IPv4 test
18 '255.255.255.255/32', # IPv4 broadcast
19 '::0/128', # IPv6 unspecified
20 '2001:0db8::/32', # IPv6 example
21 'fd00::/8', # IPv6 unique local
22 'fe80::/12', # IPv6 link-local
26 ] + [f'172.{i}.0.0/16' for i in range(16, 32)] # IPv4 private
29 def generate_localhost(nsc) -> None:
30 z = nsc.add_zone('localhost')
32 .NS(z.config.origin_server)
33 .A('127.0.0.1', '::1'))
35 r4 = nsc.add_zone(reverse_for='127.0.0.0/8')
36 r4[""].NS(z.config.origin_server)
38 r6 = nsc.add_zone(reverse_for='::1/128')
39 r6[""].NS(z.config.origin_server)
42 def generate_blackhole(nsc: Nsc,
43 skip_networks: List[IPNetwork] = [],
44 admin_email: str = 'nobody@invalid',
46 invalid_zone = nsc.add_zone('invalid', admin_email=admin_email, **kwargs)
47 invalid_zone[""].NS(invalid_zone.config.origin_server)
48 assert isinstance(invalid_zone, NscZonePrimary)
49 for raw_net in BLACKHOLE_NETWORKS:
50 net = parse_network(raw_net)
51 if net not in skip_networks:
52 nsc.add_zone(reverse_for=net, alias_for=invalid_zone)