@@ -2,6 +2,7 @@ package awldns
22
33import (
44 "net"
5+ "strconv"
56 "strings"
67 "sync/atomic"
78 "time"
@@ -17,6 +18,7 @@ const (
1718 defaultTTL = 60 * time .Second
1819 defaultTTLSeconds = uint32 (defaultTTL / time .Second )
1920 ptrV4Suffix = ".in-addr.arpa."
21+ ptrV6Suffix = ".ip6.arpa."
2022)
2123
2224const (
@@ -41,9 +43,10 @@ type Resolver struct {
4143}
4244
4345type config struct {
44- upstreamDNS string
45- directMapping map [string ]string
46- reverseMapping map [string ]string
46+ upstreamDNS string
47+ directMapping map [string ]string
48+ directMappingV6 map [string ]string
49+ reverseMapping map [string ]string
4750}
4851
4952func NewResolver (dnsAddress string ) * Resolver {
@@ -61,7 +64,8 @@ func NewResolver(dnsAddress string) *Resolver {
6164
6265 mux := dns .NewServeMux ()
6366 mux .HandleFunc (LocalDomain , r .dnsLocalDomainHandler )
64- mux .HandleFunc (strings .TrimPrefix (ptrV4Suffix , "." ), r .ptrv4Handler )
67+ mux .HandleFunc (strings .TrimPrefix (ptrV4Suffix , "." ), r .ptrHandler )
68+ mux .HandleFunc (strings .TrimPrefix (ptrV6Suffix , "." ), r .ptrHandler )
6569 mux .HandleFunc ("." , r .dnsProxyHandler )
6670
6771 r .udpServer = & dns.Server {
@@ -100,9 +104,11 @@ func NewResolver(dnsAddress string) *Resolver {
100104 return r
101105}
102106
103- func (r * Resolver ) ReceiveConfiguration (upstreamDNS string , namesMapping map [string ]string ) {
104- reverseMapping := make (map [string ]string , len (namesMapping ))
107+ func (r * Resolver ) ReceiveConfiguration (upstreamDNS string , namesMapping map [string ]string , namesMappingV6 map [ string ] string ) {
108+ reverseMapping := make (map [string ]string , len (namesMapping )+ len ( namesMappingV6 ) )
105109 directMapping := make (map [string ]string , len (namesMapping ))
110+ directMappingV6 := make (map [string ]string , len (namesMappingV6 ))
111+
106112 for key , ip := range namesMapping {
107113 canonicalName := dns .CanonicalName (key + "." + LocalDomain )
108114 directMapping [canonicalName ] = ip
@@ -116,10 +122,22 @@ func (r *Resolver) ReceiveConfiguration(upstreamDNS string, namesMapping map[str
116122 }
117123 }
118124
125+ for key , ip := range namesMappingV6 {
126+ canonicalName := dns .CanonicalName (key + "." + LocalDomain )
127+ directMappingV6 [canonicalName ] = ip
128+ existedName , exists := reverseMapping [ip ]
129+ if ! exists {
130+ reverseMapping [ip ] = canonicalName
131+ } else if exists && len (canonicalName ) < len (existedName ) {
132+ reverseMapping [ip ] = canonicalName
133+ }
134+ }
135+
119136 cfg := config {
120- upstreamDNS : upstreamDNS ,
121- directMapping : directMapping ,
122- reverseMapping : reverseMapping ,
137+ upstreamDNS : upstreamDNS ,
138+ directMapping : directMapping ,
139+ directMappingV6 : directMappingV6 ,
140+ reverseMapping : reverseMapping ,
123141 }
124142 r .cfg .Store (& cfg )
125143}
@@ -166,7 +184,11 @@ func (r *Resolver) dnsLocalDomainHandler(resp dns.ResponseWriter, req *dns.Msg)
166184
167185 switch qtype {
168186 case dns .TypeA , dns .TypeANY :
187+ _ , foundV6 := cfg .directMappingV6 [hostnameLower ]
169188 if ! found {
189+ if foundV6 {
190+ continue // domain exists but no A record, return NOERROR with 0 answers (NODATA)
191+ }
170192 m .SetRcode (req , dns .RcodeNameError )
171193 continue
172194 }
@@ -183,11 +205,26 @@ func (r *Resolver) dnsLocalDomainHandler(resp dns.ResponseWriter, req *dns.Msg)
183205 })
184206 }
185207 case dns .TypeAAAA :
186- if ! found {
208+ _ , foundV4 := cfg .directMapping [hostnameLower ]
209+ mappedIPv6 , foundV6 := cfg .directMappingV6 [hostnameLower ]
210+ if ! foundV6 {
211+ if foundV4 {
212+ continue // domain exists but no AAAA record, return NOERROR with 0 answers (NODATA)
213+ }
187214 m .SetRcode (req , dns .RcodeNameError )
188215 continue
189216 }
190- // TODO: support IPv6 addresses in cfg.directMapping.
217+ if ip := net .ParseIP (mappedIPv6 ).To16 (); ip != nil {
218+ m .Answer = append (m .Answer , & dns.AAAA {
219+ Hdr : dns.RR_Header {
220+ Name : hostname ,
221+ Rrtype : dns .TypeAAAA ,
222+ Class : dns .ClassINET ,
223+ Ttl : defaultTTLSeconds ,
224+ },
225+ AAAA : ip ,
226+ })
227+ }
191228 }
192229 }
193230
@@ -196,7 +233,7 @@ func (r *Resolver) dnsLocalDomainHandler(resp dns.ResponseWriter, req *dns.Msg)
196233 _ = resp .WriteMsg (m )
197234}
198235
199- func (r * Resolver ) ptrv4Handler (resp dns.ResponseWriter , req * dns.Msg ) {
236+ func (r * Resolver ) ptrHandler (resp dns.ResponseWriter , req * dns.Msg ) {
200237 metrics .DNSQueriesTotal .WithLabelValues ("awl_ptr" ).Inc ()
201238 start := time .Now ()
202239 defer func () {
@@ -211,7 +248,13 @@ func (r *Resolver) ptrv4Handler(resp dns.ResponseWriter, req *dns.Msg) {
211248 name := req .Question [0 ].Name
212249 cfg := r .loadConfig ()
213250
214- ip := ptrV4NameToIP (name )
251+ var ip net.IP
252+ if strings .HasSuffix (strings .ToLower (name ), ptrV6Suffix ) {
253+ ip = ptrV6NameToIP (name )
254+ } else {
255+ ip = ptrV4NameToIP (name )
256+ }
257+
215258 if ip == nil {
216259 r .dnsProxyHandler (resp , req )
217260 return
@@ -312,11 +355,29 @@ func IsValidDomainName(domain string) bool {
312355}
313356
314357func ptrV4NameToIP (name string ) net.IP {
315- s := strings .TrimSuffix (name , ptrV4Suffix )
358+ s := strings .TrimSuffix (strings . ToLower ( name ) , ptrV4Suffix )
316359 revIp := net .ParseIP (s )
317360 revIp = revIp .To4 ()
318361 if revIp == nil {
319362 return nil
320363 }
321364 return net.IP {revIp [3 ], revIp [2 ], revIp [1 ], revIp [0 ]}
322365}
366+
367+ func ptrV6NameToIP (name string ) net.IP {
368+ s := strings .TrimSuffix (strings .ToLower (name ), ptrV6Suffix )
369+ parts := strings .Split (s , "." )
370+ if len (parts ) != 32 {
371+ return nil
372+ }
373+ ip := make (net.IP , 16 )
374+ for i := 0 ; i < 16 ; i ++ {
375+ high , err1 := strconv .ParseUint (parts [31 - (i * 2 )], 16 , 8 )
376+ low , err2 := strconv .ParseUint (parts [31 - (i * 2 )- 1 ], 16 , 8 )
377+ if err1 != nil || err2 != nil {
378+ return nil
379+ }
380+ ip [i ] = byte ((high << 4 ) | low )
381+ }
382+ return ip
383+ }
0 commit comments