1. Formål
DNS/DHCP(at)Work er en DNS-server og en DHCPv4-server for lukkede testnett og lab. Den svarer fra egne soner og poster, og den kan gi feil svar med vilje – NXDOMAIN, SERVFAIL, REFUSED, ingen svar, trege svar, avkortede svar eller andre adresser – slik at man kan teste hvordan utstyr og programmer håndterer feil i navneoppslag og adressetildeling.
Løsningen leveres som en offline-pakke for Rocky Linux 9 og bruker bare Python 3.9+ og standardbiblioteket. Den bruker ikke dnsmasq, BIND eller Kea.
2. Oppbygning
Én Python-prosess (python3 -m dnsdhcp serve) med tre
deler som deler innstillinger og hendelseslogg: DNS-serveren,
DHCP-serveren og web-grensesnittet.
+--------------------------- dns-dhcp-tester.service ---------------------------+
DNS-klienter -> | UDP/TCP 53 dns_server.py -- regler -> poster -> PTR -> soner -> videresending |
DHCP-klienter ->| UDP 67 dhcp_server.py -- adressevalg, leier, feilmodus --> navn til DNS |
nettleser -> | TCP 8053 web.py -- JSON-API + static/ (EN/NO) |
| store.py (config.json) eventlog.py (events.jsonl) |
+-----------------------------------------------------------------------------------+
| Modul | Innhold |
|---|---|
dnsproto.py |
DNS-meldinger (RFC 1035, 3596 AAAA, 2782 SRV, 6891 EDNS): les spørringer med navnekomprimering og løkkevern, bygg svar, avkort (TC) når svaret er for stort |
dns_server.py |
UDP- og TCP-lytter (2-byte lengdefelt), trådbasseng med 64 tråder, regler, oppslag, videresending, statistikk |
dhcpproto.py |
DHCPv4-pakker (RFC 2131/2132), opsjoner over 255 byte (RFC 3396), klientside for selvtest og probe |
dhcp_server.py |
DISCOVER/OFFER/REQUEST/ACK/NAK, RELEASE, DECLINE, INFORM, relé (giaddr), reservasjoner, feilmoduser |
store.py |
standardverdier, kontroll av alle innstillinger, atomisk lagring av JSON (tmp + rename) |
eventlog.py |
ringbuffer med 5000 hendelser i minnet og events.jsonl
på disk med rotasjon (5 × 10 MB) |
web.py |
HTTP-server, JSON-API, innlogging, CSRF-vern og sikkerhetshoder |
static/ |
web-grensesnittet: HTML, CSS og JavaScript på engelsk og norsk, uten eksterne filer |
Innstillingene leses på nytt for hver spørring og hver DHCP-melding. Endringer i poster, regler, område og feilmodus gjelder derfor straks. Bare endret adresse, port eller grensesnitt starter lytteren på nytt.
3. DNS
3.1. Rekkefølge for en spørring
- Regler, ovenfra og ned. Den første regelen som
passer på navn (mønster med
*og?), type og klientnett, bestemmer. - Egne data: postene og navnene fra DHCP (leier og
reservasjoner med vertsnavn). Først eksakt navn, ellers nærmeste
*.-jokertegn. CNAME følges inntil 8 ledd. Et navn som finnes, men uten den typen det spørres etter, gir NODATA (NOERROR uten svar) med SOA. - Automatisk PTR fra A- og AAAA-postene, for
in-addr.arpaogip6.arpa. - Egne soner: et navn i en sone som ikke finnes, gir NXDOMAIN med SOA. SOA og NS for sonetoppen lages automatisk.
- Andre navn sendes videre til oppgitte servere (UDP, 2 s tidsavbrudd per server). Uten videresending svarer serveren REFUSED, eller NXDOMAIN eller SERVFAIL hvis det er valgt.
Svar fra egne data og soner har AA-flagget satt. RA settes når videresending er slått på.
3.2. Regler
| Handling | Svar |
|---|---|
| NXDOMAIN, SERVFAIL, REFUSED | svarkoden med en gang (eller etter forsinkelsen) |
| DROP | ingen svar; spørringen telles som «ikke besvart» |
| DELAY | vanlig oppslag, sendt etter forsinkelse ms |
| TRUNCATE | tomt svar med TC-flagg over UDP; over TCP går spørringen til vanlig oppslag |
| ANSWER | A- og/eller AAAA-svar med adressene i regelen, med AA-flagg |
Forsinkelse ms (0–30 000) gjelder for alle handlinger. Klientfeltet tar adresser og nett (CIDR) for IPv4 og IPv6. Regelen som traff, vises i loggen og telles i statistikken.
3.3. Svarstørrelse og TCP
Over UDP er grensen 512 byte, eller EDNS-størrelsen klienten oppgir (512–4096). Blir svaret større, sendes det uten poster og med TC-flagg, og klienten spør igjen over TCP. Har spørringen en OPT-post, har svaret også en (UDP-størrelse 1232). Over TCP brukes 2-byte lengdefelt (RFC 1035 4.2.2), og flere spørringer kan sendes på samme forbindelse.
3.4. Posttyper
| Type | Verdi | Kontroll |
|---|---|---|
| A / AAAA | IPv4 / IPv6-adresse | gyldig adresse |
| CNAME, NS, PTR | domenenavn | gyldig navn |
| MX | prioritet navn |
0–65535 og gyldig navn |
| SRV | prioritet vekt port mål |
tre tall 0–65535 og gyldig navn |
| TXT | tekst | deles i biter på 255 byte |
4. DHCP
- Adressevalg: reservasjon → klientens eksisterende lei → ønsket adresse (opsjon 50) → første ledige adresse i området.
- Et tilbud (OFFER) holdes i 60 s. En adresse som klienten avviser med DECLINE, holdes tilbake i 600 s.
- REQUEST med en annen servers identifikator frigjør tilbudet. Er serveren autoritativ, får en klient som ber om en adresse som ikke er gyldig her, NAK.
- Svaret sendes til relé-agenten (giaddr, port 67), til klientens adresse (ciaddr, port 68) ved fornyelse, og ellers som kringkasting til 255.255.255.255, port 68.
- Opsjoner: 1 nettmaske, 3 ruter, 6 DNS, 12 vertsnavn, 15 domene, 28 kringkastingsadresse, 42 NTP, 51 leietid, 54 serveridentifikator, 58 T1, 59 T2, 66 TFTP-server, 67 oppstartsfil.
- Uten oppgitte DNS-servere får klientene serverens egen adresse, når DNS-serveren er på.
- Med valgt grensesnitt bindes lytteren med
SO_BINDTODEVICE, og serveradressen hentes fra grensesnittet (SIOCGIFADDR). Ellers brukes adressen mot ruteren. - Leier lagres i
leases.jsonog overlever omstart.
| Feilmodus | Oppførsel |
|---|---|
| normal | vanlig DHCP |
| silent | meldingene logges, men besvares ikke |
| nak | DISCOVER får OFFER, men hver REQUEST får NAK |
| delay | alle svar sendes etter forsinkelse ms (0–60 000) |
| exhausted | DISCOVER besvares ikke, som om området var fullt |
DHCP-klienter som sender vertsnavn (opsjon 12), får navnet
<vertsnavn>.<domene> i DNS så lenge leien er
gyldig. Reservasjoner med vertsnavn er alltid med.
5. Innstillinger og kontroll
Innstillingene ligger i
/var/lib/dns-dhcp-tester/config.json, med én del for DNS og
én for DHCP. Alt som kommer fra web-grensesnittet kontrolleres før det
lagres. Feil gir HTTP 400 med en lesbar melding, og ingenting
lagres.
- Navn, soner og navnemønstre kontrolleres mot tillatte tegn og lengder.
- Adresser, nett, porter, TTL, forsinkelser og leietid kontrolleres mot gyldige verdier.
- DHCP-området må ligge i ett nett, starten må komme før slutten, og området kan ha høyst 65 536 adresser. Reservasjoner må ligge i nettet, og ingen MAC- eller IP-adresse kan brukes to ganger.
- Er filen ødelagt eller ugyldig ved oppstart, brukes standardverdiene, og en advarsel vises i web-grensesnittet og loggen.
6. Web-API
Alle kall krever innlogging. Alle POST-kall krever i tillegg hodet
X-Requested-With: dnsdhcp-ui.
| Metode | Sti | Innhold |
|---|---|---|
| GET | /api/status |
versjon, status og tellere for DNS og DHCP, nettkort |
| GET | /api/config |
alle innstillinger og lovlige valg |
| POST | /api/config/dns, /api/config/dhcp |
lagre innstillinger |
| GET | /api/dhcp/leases |
leier |
| POST | /api/dhcp/leases/delete |
{"mac": "..."} |
| POST | /api/dns/test |
{"name", "type", "client"} – svaret uten å sende noe på
nettet |
| GET | /api/log?since=ID&kind=dns\|dhcp\|system |
hendelser etter ID |
| POST | /api/log/clear |
tøm visning og tellere |
| GET | /api/log/download |
events.jsonl |
7. Sikkerhet
- Innlogging: HTTP Basic med brukeren
admin. Passordet lagres som PBKDF2-SHA256 med 200 000 runder og tilfeldig salt. Ti feil passord i løpet av ett minutt fra samme adresse gir ett minutts pause. - CSRF: POST uten hodet
X-Requested-With: dnsdhcp-uiavvises med 403. Andre nettsteder kan ikke sette hodet. - Hoder: Content-Security-Policy uten inline-skript og -stil og uten eksterne kilder, X-Frame-Options DENY, nosniff, no-referrer og no-store.
- Tjenesten kjører som systembrukeren
dnsdhcpmed bareCAP_NET_BIND_SERVICE(port 53 og 67) ogCAP_NET_RAW(binding til grensesnitt), og med full systemd-herding. Den kan bare skrive i/var/lib/dns-dhcp-tester. - DHCP er av etter installasjon, og web-grensesnittet spør før det slås på.
- Web-grensesnittet bruker HTTP. Begrens tilgangen med
install.sh --admin-net <nett>eller et eget administrasjonsnett.
8. Filer og tjeneste
| Sti | Innhold | Eier |
|---|---|---|
/opt/dns-dhcp-tester/app/ |
programmet | root |
/opt/dns-dhcp-tester/tools/ |
selftest.py, probe.py |
root |
/opt/dns-dhcp-tester/docs/ |
brukermanual og teknisk beskrivelse | root |
/var/lib/dns-dhcp-tester/config.json |
innstillinger | dnsdhcp, 0640 |
/var/lib/dns-dhcp-tester/leases.json |
DHCP-leier | dnsdhcp |
/var/lib/dns-dhcp-tester/log/events.jsonl |
hendelseslogg | dnsdhcp |
/etc/dns-dhcp-tester/auth |
passord-hash | root:dnsdhcp, 0640 |
/etc/dns-dhcp-tester/initial-password |
passordet fra installasjonen | root, 0600 |
/etc/dns-dhcp-tester/install.conf |
valgene fra siste install.sh |
root |
/etc/systemd/system/dns-dhcp-tester.service |
tjenesten | root |
install.sh kontrollerer sjekksummene i pakken og at
portene er ledige, viser hvilken prosess som eventuelt bruker port 53,
8053 eller 67, åpner portene i firewalld eller ufw og avslutter med en
kontroll av web-grensesnittet og DNS. En ny install.sh er
en oppgradering som beholder innstillinger, leier, logg og passord.
9. Portkart for (at)Work-verktøyene
| Verktøy | Web | Andre porter |
|---|---|---|
| Iperf(at)Work | 80 | 5201/5202 |
| Multicast(at)Work | 5152 | |
| Chrony-Time-Service(at)Work | 5032 | |
| SYSLOG Receiver | 8080 | UDP/TCP 514, TLS 6514 |
| SYSLOG Sender | 8000 | |
| SNMP Receiver / Sender | 8081 / 8082 | |
| Ping(at)Work | 443 | |
| DNS/DHCP(at)Work | 8053 | UDP/TCP 53, UDP 67 |
Alle verktøyene kan dermed kjøre på samme server.
10. Selvtest og verktøy
python3 tools/selftest.py starter DNS, DHCP og web på
tilfeldige høye porter på 127.0.0.1 og kjører 44 tester uten å berøre
tjenesten:
- oppslag av alle posttyper, CNAME, jokertegn, NXDOMAIN, NODATA, SOA/NS, PTR, avkorting og EDNS;
- alle regelhandlinger, typefilter, klientfilter og rekkefølge;
- videresending (når testen kjøres som root og port 53 er ledig);
- DHCP-forløpet DISCOVER–OFFER–REQUEST–ACK, reservasjon, NAK, fullt område, RELEASE, DECLINE og alle feilmoduser;
- kontroll av innstillinger, innlogging, CSRF-vern og API.
tools/probe.py dns <navn> spør en DNS-server over
UDP eller TCP. tools/probe.py dhcp sender en DISCOVER og
viser alle tilbud, uten å ta noen adresse.
11. Begrensninger i utkastet
- DHCP bare for IPv4 og ett nett. Ingen DHCPv6.
- DNS uten DNSSEC, soneoverføring (AXFR) og dynamisk oppdatering (RFC 2136).
- Videresending over UDP til port 53, uten hurtigbuffer.
- Web-grensesnittet bruker HTTP, ikke HTTPS.