3 files changed,
87 insertions(+),
5 deletions(-)
Author:
Oleksandr Smirnov
olexsmir@gmail.com
Committed at:
2026-04-19 12:31:39 +0300
Authored at:
2026-04-18 20:36:59 +0300
Change ID:
pwqmqmyqlzttszzwzkyllxxnonvtpskz
Parent:
c33ca6e
jump to
| M | dns-server/lookup.go |
| M | dns-server/packet.go |
| M | dns-server/server.go |
M
dns-server/lookup.go
··· 6 6 "net" 7 7 ) 8 8 9 -const server = "8.8.8.8:53" 10 - 11 -func Lookup(qname string, qtype QueryType) (Packet, error) { 9 +func Lookup(qname string, qtype QueryType, server string) (Packet, error) { 12 10 conn, _ := net.Dial("udp", server) 13 11 defer conn.Close() 14 12 ··· 38 36 39 37 return ParsePacket(res[:n]) 40 38 } 39 + 40 +func RecursiveLookup(qname string, qtype QueryType) (Packet, error) { 41 + ns := "198.41.0.4" // For now we're always starting with *a.root-servers.net*. 42 + for { 43 + fmt.Printf("attempting lookup of %v %s with ns %s\n", qtype, qname, ns) 44 + 45 + response, err := Lookup(qname, qtype, ns+":53") 46 + if err != nil { 47 + return Packet{}, err 48 + } 49 + 50 + if len(response.Answers) > 0 && response.Header.Rescode == NOERROR { 51 + return response, nil 52 + } 53 + 54 + if response.Header.Rescode == NXDOMAIN { 55 + return response, nil 56 + } 57 + 58 + if newNS, ok := response.GetResolvedNS(qname); ok { 59 + ns = newNS.String() 60 + continue 61 + } 62 + 63 + newNSName, ok := response.GetUnresolvedNS(qname) 64 + if !ok { 65 + return response, nil 66 + } 67 + 68 + recursive, err := RecursiveLookup(newNSName, AType) 69 + if err != nil { 70 + return response, nil 71 + } 72 + 73 + if ip, ok := recursive.GetRandomA(); ok { 74 + ns = ip.String() 75 + } else { 76 + return response, nil 77 + } 78 + } 79 +}
M
dns-server/packet.go
··· 1 1 package main 2 2 3 -import "bytes" 3 +import ( 4 + "bytes" 5 + "net" 6 + "strings" 7 +) 4 8 5 9 type Packet struct { 6 10 Header Header ··· 81 85 82 86 return nil 83 87 } 88 + 89 +func (p Packet) GetRandomA() (net.IP, bool) { 90 + for _, r := range p.Answers { 91 + if r.Type == AType { 92 + return net.ParseIP(r.Data), true 93 + } 94 + } 95 + return nil, false 96 +} 97 + 98 +func (p Packet) GetResolvedNS(qname string) (net.IP, bool) { 99 + for _, ns := range p.getNS(qname) { 100 + host := ns[1] 101 + for _, r := range p.Resources { 102 + if r.Type == AType && r.Name == host { 103 + return net.ParseIP(r.Data), true 104 + } 105 + } 106 + } 107 + return nil, false 108 +} 109 + 110 +func (p Packet) GetUnresolvedNS(qname string) (string, bool) { 111 + ns := p.getNS(qname) 112 + if len(ns) == 0 { 113 + return "", false 114 + } 115 + return ns[0][1], true 116 +} 117 + 118 +func (p Packet) getNS(qname string) [][2]string { 119 + var res [][2]string 120 + for _, r := range p.Authorities { 121 + if r.Type == NSType && strings.HasPrefix(qname, r.Name) { 122 + res = append(res, [2]string{r.Name, r.Data}) 123 + } 124 + } 125 + return res 126 +}