@@ -91,11 +91,19 @@ func (h *Handler) handleQuery(w dns.ResponseWriter, req *dns.Msg) {
91
91
Class : q .Qclass ,
92
92
Ttl : 5 ,
93
93
}
94
- switch q .Qtype {
94
+ qtype := q .Qtype
95
+ switch qtype {
95
96
case dns .TypeAAAA :
96
97
if ! h .IPv6 {
97
- handled = true
98
- break
98
+ // A "correct" answer would be to set `handled = true` and return a NODATA response.
99
+ // Unfortunately some older resolvers use a slow random source to set the transaction id.
100
+ // This creates a problem on M1 computers, which are too fast for that implementation:
101
+ // Both the A and AAAA queries might end up with the same id. Returning NODATA for AAAA
102
+ // is faster, so would arrive first, and be treated as the response to the A query.
103
+ // To avoid this, we will treat an AAAA query as an A query when IPv6 has been disabled.
104
+ // This way it is either a valid response for an A query, or the A records will be discarded
105
+ // by a genuine AAAA query, resulting in the desired NODATA response.
106
+ qtype = dns .TypeA
99
107
}
100
108
fallthrough
101
109
case dns .TypeCNAME , dns .TypeA :
@@ -129,7 +137,7 @@ func (h *Handler) handleQuery(w dns.ResponseWriter, req *dns.Msg) {
129
137
reply .Answer = append (reply .Answer , a )
130
138
handled = true
131
139
}
132
- if q . Qtype == dns .TypeCNAME {
140
+ if qtype == dns .TypeCNAME {
133
141
break
134
142
}
135
143
hdr .Name = cname
@@ -144,13 +152,13 @@ func (h *Handler) handleQuery(w dns.ResponseWriter, req *dns.Msg) {
144
152
for _ , ip := range addrs {
145
153
var a dns.RR
146
154
ipv6 := ip .To4 () == nil
147
- if q . Qtype == dns .TypeA && ! ipv6 {
155
+ if qtype == dns .TypeA && ! ipv6 {
148
156
hdr .Rrtype = dns .TypeA
149
157
a = & dns.A {
150
158
Hdr : hdr ,
151
159
A : ip .To4 (),
152
160
}
153
- } else if q . Qtype == dns .TypeAAAA && ipv6 {
161
+ } else if qtype == dns .TypeAAAA && ipv6 {
154
162
hdr .Rrtype = dns .TypeAAAA
155
163
a = & dns.AAAA {
156
164
Hdr : hdr ,
0 commit comments