pull/4516/head
风扇滑翔翼 2025-03-18 20:29:58 +00:00 committed by GitHub
parent c3de4b8392
commit d639ccc627
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 24 additions and 18 deletions

View File

@ -35,9 +35,7 @@ type IPRecord struct {
IP []net.Address IP []net.Address
Expire time.Time Expire time.Time
RCode dnsmessage.RCode RCode dnsmessage.RCode
RawHeader *dnsmessage.Header
// Truncated is for udp dns to indicates if the response is truncated and needs to be retried
Truncated bool
} }
func (r *IPRecord) getIPs() ([]net.Address, error) { func (r *IPRecord) getIPs() ([]net.Address, error) {
@ -68,7 +66,6 @@ type dnsRequest struct {
start time.Time start time.Time
expire time.Time expire time.Time
msg *dnsmessage.Message msg *dnsmessage.Message
ctx context.Context
} }
func genEDNS0Options(clientIP net.IP) *dnsmessage.Resource { func genEDNS0Options(clientIP net.IP) *dnsmessage.Resource {
@ -186,7 +183,7 @@ func parseResponse(payload []byte) (*IPRecord, error) {
ReqID: h.ID, ReqID: h.ID,
RCode: h.RCode, RCode: h.RCode,
Expire: now.Add(time.Second * 600), Expire: now.Add(time.Second * 600),
Truncated: h.Truncated, RawHeader: &h,
} }
L: L:

View File

@ -51,7 +51,7 @@ func Test_parseResponse(t *testing.T) {
}{ }{
{ {
"empty", "empty",
&IPRecord{0, []net.Address(nil), time.Time{}, dnsmessage.RCodeSuccess}, &IPRecord{0, []net.Address(nil), time.Time{}, dnsmessage.RCodeSuccess, nil},
false, false,
}, },
{ {
@ -66,12 +66,13 @@ func Test_parseResponse(t *testing.T) {
[]net.Address{net.ParseAddress("8.8.8.8"), net.ParseAddress("8.8.4.4")}, []net.Address{net.ParseAddress("8.8.8.8"), net.ParseAddress("8.8.4.4")},
time.Time{}, time.Time{},
dnsmessage.RCodeSuccess, dnsmessage.RCodeSuccess,
nil,
}, },
false, false,
}, },
{ {
"aaaa record", "aaaa record",
&IPRecord{2, []net.Address{net.ParseAddress("2001::123:8888"), net.ParseAddress("2001::123:8844")}, time.Time{}, dnsmessage.RCodeSuccess}, &IPRecord{2, []net.Address{net.ParseAddress("2001::123:8888"), net.ParseAddress("2001::123:8844")}, time.Time{}, dnsmessage.RCodeSuccess, nil},
false, false,
}, },
} }

View File

@ -27,7 +27,7 @@ type ClassicNameServer struct {
name string name string
address *net.Destination address *net.Destination
ips map[string]*record ips map[string]*record
requests map[uint16]*dnsRequest requests map[uint16]*udpDnsRequest
pub *pubsub.Service pub *pubsub.Service
udpServer *udp.Dispatcher udpServer *udp.Dispatcher
cleanup *task.Periodic cleanup *task.Periodic
@ -35,6 +35,11 @@ type ClassicNameServer struct {
queryStrategy QueryStrategy queryStrategy QueryStrategy
} }
type udpDnsRequest struct {
dnsRequest
ctx context.Context
}
// NewClassicNameServer creates udp server object for remote resolving. // NewClassicNameServer creates udp server object for remote resolving.
func NewClassicNameServer(address net.Destination, dispatcher routing.Dispatcher, queryStrategy QueryStrategy) *ClassicNameServer { func NewClassicNameServer(address net.Destination, dispatcher routing.Dispatcher, queryStrategy QueryStrategy) *ClassicNameServer {
// default to 53 if unspecific // default to 53 if unspecific
@ -45,7 +50,7 @@ func NewClassicNameServer(address net.Destination, dispatcher routing.Dispatcher
s := &ClassicNameServer{ s := &ClassicNameServer{
address: &address, address: &address,
ips: make(map[string]*record), ips: make(map[string]*record),
requests: make(map[uint16]*dnsRequest), requests: make(map[uint16]*udpDnsRequest),
pub: pubsub.NewService(), pub: pubsub.NewService(),
name: strings.ToUpper(address.String()), name: strings.ToUpper(address.String()),
queryStrategy: queryStrategy, queryStrategy: queryStrategy,
@ -101,7 +106,7 @@ func (s *ClassicNameServer) Cleanup() error {
} }
if len(s.requests) == 0 { if len(s.requests) == 0 {
s.requests = make(map[uint16]*dnsRequest) s.requests = make(map[uint16]*udpDnsRequest)
} }
return nil return nil
@ -129,7 +134,7 @@ func (s *ClassicNameServer) HandleResponse(ctx context.Context, packet *udp_prot
} }
// if truncated, retry with EDNS0 option(udp payload size: 1350) // if truncated, retry with EDNS0 option(udp payload size: 1350)
if ipRec.Truncated { if ipRec.RawHeader.Truncated {
// if already has EDNS0 option, no need to retry // if already has EDNS0 option, no need to retry
if ok && len(req.msg.Additionals) == 0 { if ok && len(req.msg.Additionals) == 0 {
// copy necessary meta data from original request // copy necessary meta data from original request
@ -199,7 +204,7 @@ func (s *ClassicNameServer) newReqID() uint16 {
return uint16(atomic.AddUint32(&s.reqID, 1)) return uint16(atomic.AddUint32(&s.reqID, 1))
} }
func (s *ClassicNameServer) addPendingRequest(req *dnsRequest) { func (s *ClassicNameServer) addPendingRequest(req *udpDnsRequest) {
s.Lock() s.Lock()
defer s.Unlock() defer s.Unlock()
@ -214,8 +219,11 @@ func (s *ClassicNameServer) sendQuery(ctx context.Context, domain string, client
reqs := buildReqMsgs(domain, option, s.newReqID, genEDNS0Options(clientIP)) reqs := buildReqMsgs(domain, option, s.newReqID, genEDNS0Options(clientIP))
for _, req := range reqs { for _, req := range reqs {
req.ctx = ctx udpReq := &udpDnsRequest{
s.addPendingRequest(req) dnsRequest: *req,
ctx: ctx,
}
s.addPendingRequest(udpReq)
b, _ := dns.PackMessage(req.msg) b, _ := dns.PackMessage(req.msg)
s.udpServer.Dispatch(toDnsContext(ctx, s.address.String()), *s.address, b) s.udpServer.Dispatch(toDnsContext(ctx, s.address.String()), *s.address, b)
} }