Move predefined DNS server to rule action

This commit is contained in:
世界
2025-02-26 08:59:21 +08:00
parent d52322112e
commit 1069b7d712
15 changed files with 289 additions and 282 deletions

View File

@@ -190,6 +190,8 @@ func (r *Router) matchDNS(ctx context.Context, allowFakeIP bool, ruleIndex int,
}
case *R.RuleActionReject:
return nil, currentRule, currentRuleIndex
case *R.RuleActionPredefined:
return nil, currentRule, currentRuleIndex
}
}
}
@@ -260,6 +262,21 @@ func (r *Router) Exchange(ctx context.Context, message *mDNS.Msg, options adapte
case C.RuleActionRejectMethodDrop:
return nil, tun.ErrDrop
}
case *R.RuleActionPredefined:
return &mDNS.Msg{
MsgHdr: mDNS.MsgHdr{
Id: message.Id,
Response: true,
Authoritative: true,
RecursionDesired: true,
RecursionAvailable: true,
Rcode: action.Rcode,
},
Question: message.Question,
Answer: action.Answer,
Ns: action.Ns,
Extra: action.Extra,
}, nil
}
}
var responseCheck func(responseAddrs []netip.Addr) bool
@@ -376,6 +393,20 @@ func (r *Router) Lookup(ctx context.Context, domain string, options adapter.DNSQ
case C.RuleActionRejectMethodDrop:
return nil, tun.ErrDrop
}
case *R.RuleActionPredefined:
if action.Rcode != mDNS.RcodeSuccess {
err = RcodeError(action.Rcode)
} else {
for _, answer := range action.Answer {
switch record := answer.(type) {
case *mDNS.A:
responseAddrs = append(responseAddrs, M.AddrFromIP(record.A))
case *mDNS.AAAA:
responseAddrs = append(responseAddrs, M.AddrFromIP(record.AAAA))
}
}
}
goto response
}
}
var responseCheck func(responseAddrs []netip.Addr) bool
@@ -395,6 +426,7 @@ func (r *Router) Lookup(ctx context.Context, domain string, options adapter.DNSQ
printResult()
}
}
response:
printResult()
if len(responseAddrs) > 0 {
r.logger.InfoContext(ctx, "lookup succeed for ", domain, ": ", strings.Join(F.MapToString(responseAddrs), " "))

View File

@@ -1,83 +0,0 @@
package transport
import (
"context"
"github.com/sagernet/sing-box/adapter"
C "github.com/sagernet/sing-box/constant"
"github.com/sagernet/sing-box/dns"
"github.com/sagernet/sing-box/log"
"github.com/sagernet/sing-box/option"
"github.com/sagernet/sing/common"
E "github.com/sagernet/sing/common/exceptions"
mDNS "github.com/miekg/dns"
)
var _ adapter.DNSTransport = (*PredefinedTransport)(nil)
func RegisterPredefined(registry *dns.TransportRegistry) {
dns.RegisterTransport[option.PredefinedDNSServerOptions](registry, C.DNSTypePreDefined, NewPredefined)
}
type PredefinedTransport struct {
dns.TransportAdapter
responses []*predefinedResponse
}
type predefinedResponse struct {
questions []mDNS.Question
answer *mDNS.Msg
}
func NewPredefined(ctx context.Context, logger log.ContextLogger, tag string, options option.PredefinedDNSServerOptions) (adapter.DNSTransport, error) {
var responses []*predefinedResponse
for _, response := range options.Responses {
questions, msg, err := response.Build()
if err != nil {
return nil, err
}
responses = append(responses, &predefinedResponse{
questions: questions,
answer: msg,
})
}
if len(responses) == 0 {
return nil, E.New("empty predefined responses")
}
return &PredefinedTransport{
TransportAdapter: dns.NewTransportAdapter(C.DNSTypePreDefined, tag, nil),
responses: responses,
}, nil
}
func (t *PredefinedTransport) Reset() {
}
func (t *PredefinedTransport) Exchange(ctx context.Context, message *mDNS.Msg) (*mDNS.Msg, error) {
for _, response := range t.responses {
for _, question := range response.questions {
if func() bool {
if question.Name == "" && question.Qtype == mDNS.TypeNone {
return true
} else if question.Name == "" {
return common.Any(message.Question, func(it mDNS.Question) bool {
return it.Qtype == question.Qtype
})
} else if question.Qtype == mDNS.TypeNone {
return common.Any(message.Question, func(it mDNS.Question) bool {
return it.Name == question.Name
})
} else {
return common.Contains(message.Question, question)
}
}() {
copyAnswer := *response.answer
copyAnswer.Id = message.Id
copyAnswer.Question = message.Question
return &copyAnswer, nil
}
}
}
return nil, dns.RcodeNameError
}