Add week 7 materials
This commit is contained in:
@@ -0,0 +1,69 @@
|
||||
"""Run BIND as an authoritative server or a separate caching resolver."""
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
import socket
|
||||
import sys
|
||||
import time
|
||||
|
||||
ROOT = Path("/tmp/dns-lab")
|
||||
# A fixed key is only used by rndc on loopback inside these disposable lab containers.
|
||||
KEY = 'key "lab-control" { algorithm hmac-sha256; secret "c2VtaW5hci03LWxvY2FsLWRucy1jb250cm9sLWtleSE="; };'
|
||||
|
||||
|
||||
def write_zone(address, ttl):
|
||||
old = json.loads((ROOT / "state.json").read_text()) if (ROOT / "state.json").exists() else {}
|
||||
serial = max(int(time.time()), old.get("serial", 0) + 1)
|
||||
(ROOT / "lab.test.zone").write_text(f"""$TTL {ttl}
|
||||
@ IN SOA ns.lab.test. hostmaster.lab.test. ({serial} 60 60 3600 {ttl})
|
||||
IN NS ns.lab.test.
|
||||
ns IN A {socket.gethostbyname(socket.gethostname())}
|
||||
orders IN A {address}
|
||||
www IN CNAME orders.lab.test.
|
||||
""")
|
||||
(ROOT / "state.json").write_text(json.dumps({"address": address, "ttl": ttl, "serial": serial}))
|
||||
|
||||
|
||||
def main():
|
||||
role = sys.argv[1]
|
||||
ROOT.mkdir(parents=True, exist_ok=True)
|
||||
control = KEY + '\ncontrols { inet 127.0.0.1 port 953 allow { 127.0.0.1; } keys { "lab-control"; }; };\n'
|
||||
(ROOT / "rndc.conf").write_text(KEY + '\noptions { default-server 127.0.0.1; default-key "lab-control"; };\n')
|
||||
common = f"""directory "{ROOT}";
|
||||
listen-on {{ any; }};
|
||||
listen-on-v6 {{ none; }};
|
||||
allow-query {{ any; }};
|
||||
minimal-responses no;
|
||||
dnssec-validation no;
|
||||
empty-zones-enable no;
|
||||
pid-file "{ROOT}/named.pid";
|
||||
session-keyfile "{ROOT}/session.key";
|
||||
"""
|
||||
if role == "auth":
|
||||
write_zone("192.0.2.10", 60)
|
||||
options = "recursion no;"
|
||||
zones = f'zone "lab.test" {{ type primary; file "{ROOT}/lab.test.zone"; }};'
|
||||
elif role in ("root", "tld"):
|
||||
address = socket.gethostbyname(socket.gethostname())
|
||||
zone, ns = (".", "ns.root.") if role == "root" else ("test", "ns.test.")
|
||||
child, child_ns, child_host = ("test.", "ns.test.", "tld-dns") if role == "root" else ("lab.test.", "ns.lab.test.", "auth")
|
||||
child_address = socket.gethostbyname(child_host)
|
||||
records = f"$TTL 60\n@ IN SOA {ns} hostmaster.{ns} (1 60 60 3600 60)\n@ IN NS {ns}\n{ns} IN A {address}\n{child} IN NS {child_ns}\n{child_ns} IN A {child_address}\n"
|
||||
(ROOT / "hierarchy.zone").write_text(records)
|
||||
options = "recursion no;"
|
||||
zones = f'zone "{zone}" {{ type primary; file "{ROOT}/hierarchy.zone"; }};'
|
||||
elif role == "resolver":
|
||||
address = socket.gethostbyname("auth")
|
||||
options = """recursion yes; allow-recursion { any; }; allow-query-cache { any; };
|
||||
prefetch 0; stale-answer-enable no; stale-cache-enable no; servfail-ttl 0;"""
|
||||
zones = "\n".join(f'zone "{name}" {{ type forward; forward only; forwarders {{ {address}; }}; }};'
|
||||
for name in ("lab.test", "broken.test"))
|
||||
else:
|
||||
raise ValueError("Unknown DNS role")
|
||||
config = control + f"options {{ {common}\n{options} }};\n" + zones
|
||||
(ROOT / "named.conf").write_text(config)
|
||||
os.execvp("named", ["named", "-g", "-c", str(ROOT / "named.conf"), "-u", "root", "-n", "1"])
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user