Infrastructure Go daemon
SECTION 9.4

Building a DNS Server

2 · Worked example — read every step

Combine UDP + DNS parsing to build a working DNS server:

func main() {
    // Static records
    records := map[string]net.IP{
        "web.local":   net.ParseIP("10.0.0.1"),
        "api.local":   net.ParseIP("10.0.0.2"),
        "redis.local": net.ParseIP("10.0.0.3"),
    }

    pc, err := net.ListenPacket("udp", ":5353")
    if err != nil {
        log.Fatal(err)
    }
    defer pc.Close()
    slog.Info("DNS server listening", "addr", ":5353")

    buf := make([]byte, 512)
    for {
        n, addr, err := pc.ReadFrom(buf)
        if err != nil {
            continue
        }
        go handleDNSQuery(pc, addr, buf[:n], records)
    }
}

func handleDNSQuery(pc net.PacketConn, addr net.Addr, query []byte, records map[string]net.IP) {
    // Parse the question
    domain, _ := decodeDomain(query, 12)

    ip, found := records[domain]
    if !found {
        // Send NXDOMAIN response
        resp := buildNXDomain(query)
        pc.WriteTo(resp, addr)
        return
    }

    resp := buildResponse(query, ip)
    pc.WriteTo(resp, addr)
    slog.Info("resolved", "domain", domain, "ip", ip, "client", addr)
}

Test it: dig @localhost -p 5353 web.local

3 · Fill the gaps
The query handler, from memory — where does the question start, and what if the domain is unknown?
func handleDNSQuery(pc net.PacketConn, addr net.Addr, query []byte, records map[string]net.IP) {
    domain, _ := decodeDomain(query, )

ip, found := records[domain]
if !<span class="gap-slot"><input class="gap-input" data-answer="found" size="7" spellcheck="false" autocomplete="off" autocapitalize="off"></span> {
    pc.WriteTo(buildNXDomain(query), addr)
    <span class="gap-slot"><input class="gap-input" data-answer="return" size="8" spellcheck="false" autocomplete="off" autocapitalize="off"></span>
}

pc.WriteTo(<span class="gap-slot"><input class="gap-input" data-answer="buildResponse(query, ip)" size="26" spellcheck="false" autocomplete="off" autocapitalize="off"></span>, addr)

}