Refactor to miekg/dns

This commit is contained in:
世界 2022-09-13 16:18:39 +08:00
parent 1db7f45370
commit 007a278ac8
No known key found for this signature in database
GPG Key ID: CD109927C34A63C4
9 changed files with 55 additions and 119 deletions

View File

@ -11,7 +11,7 @@ import (
"github.com/sagernet/sing/common/control"
N "github.com/sagernet/sing/common/network"
"golang.org/x/net/dns/dnsmessage"
mdns "github.com/miekg/dns"
)
type Router interface {
@ -27,7 +27,7 @@ type Router interface {
GeoIPReader() *geoip.Reader
LoadGeosite(code string) (Rule, error)
Exchange(ctx context.Context, message *dnsmessage.Message) (*dnsmessage.Message, error)
Exchange(ctx context.Context, message *mdns.Msg) (*mdns.Msg, error)
Lookup(ctx context.Context, domain string, strategy dns.DomainStrategy) ([]netip.Addr, error)
LookupDefault(ctx context.Context, domain string) ([]netip.Addr, error)

View File

@ -13,7 +13,7 @@ import (
"github.com/sagernet/sing/common/buf"
"github.com/sagernet/sing/common/task"
"golang.org/x/net/dns/dnsmessage"
mDNS "github.com/miekg/dns"
)
func StreamDomainNameQuery(readCtx context.Context, reader io.Reader) (*adapter.InboundContext, error) {
@ -44,18 +44,10 @@ func StreamDomainNameQuery(readCtx context.Context, reader io.Reader) (*adapter.
}
func DomainNameQuery(ctx context.Context, packet []byte) (*adapter.InboundContext, error) {
var parser dnsmessage.Parser
_, err := parser.Start(packet)
var msg mDNS.Msg
err := msg.Unpack(packet)
if err != nil {
return nil, err
}
question, err := parser.Question()
if err != nil {
return nil, os.ErrInvalid
}
domain := question.Name.String()
if question.Class == dnsmessage.ClassINET && IsDomainName(domain) {
return &adapter.InboundContext{Protocol: C.ProtocolDNS /*, Domain: domain*/}, nil
}
return nil, os.ErrInvalid
return &adapter.InboundContext{Protocol: C.ProtocolDNS}, nil
}

View File

@ -7,11 +7,11 @@ import (
"crypto/tls"
"strings"
"github.com/sagernet/certmagic"
"github.com/sagernet/sing-box/adapter"
"github.com/sagernet/sing-box/option"
E "github.com/sagernet/sing/common/exceptions"
"github.com/caddyserver/certmagic"
"github.com/mholt/acmez/acme"
)

View File

@ -18,7 +18,6 @@ import (
E "github.com/sagernet/sing/common/exceptions"
mDNS "github.com/miekg/dns"
"golang.org/x/net/dns/dnsmessage"
)
type echClientConfig struct {
@ -170,15 +169,15 @@ const typeHTTPS = 65
func fetchECHClientConfig(router adapter.Router) func(ctx context.Context, serverName string) ([]cftls.ECHConfig, error) {
return func(ctx context.Context, serverName string) ([]cftls.ECHConfig, error) {
message := &dnsmessage.Message{
Header: dnsmessage.Header{
message := &mDNS.Msg{
MsgHdr: mDNS.MsgHdr{
RecursionDesired: true,
},
Questions: []dnsmessage.Question{
Question: []mDNS.Question{
{
Name: dnsmessage.MustNewName(serverName + "."),
Type: typeHTTPS,
Class: dnsmessage.ClassINET,
Name: serverName + ".",
Qtype: mDNS.TypeHTTPS,
Qclass: mDNS.ClassINET,
},
},
}
@ -186,19 +185,10 @@ func fetchECHClientConfig(router adapter.Router) func(ctx context.Context, serve
if err != nil {
return nil, err
}
if response.RCode != dnsmessage.RCodeSuccess {
return nil, dns.RCodeError(response.RCode)
if response.Rcode != mDNS.RcodeSuccess {
return nil, dns.RCodeError(response.Rcode)
}
content, err := response.Pack()
if err != nil {
return nil, err
}
var mMsg mDNS.Msg
err = mMsg.Unpack(content)
if err != nil {
return nil, err
}
for _, rr := range mMsg.Answer {
for _, rr := range response.Answer {
switch resource := rr.(type) {
case *mDNS.HTTPS:
for _, value := range resource.Value {

View File

@ -53,17 +53,6 @@ we need to do this.
The library needs to be updated with the upstream.
#### certmagic
Link: [GitHub repository](https://github.com/SagerNet/certmagic)
Fork of `caddyserver/certmagic`
Since upstream uses `miekg/dns` and we use `x/net/dnsmessage`, we need to replace its DNS part with our own
implementation.
The library needs to be updated with the upstream.
#### smux
Link: [GitHub repository](https://github.com/SagerNet/smux)

4
go.mod
View File

@ -4,6 +4,7 @@ go 1.18
require (
berty.tech/go-libtor v1.0.385
github.com/caddyserver/certmagic v0.17.1
github.com/cloudflare/circl v1.2.1-0.20220831060716-4cf0150356fc
github.com/cretz/bine v0.2.0
github.com/database64128/tfo-go v1.1.2
@ -20,11 +21,10 @@ require (
github.com/oschwald/maxminddb-golang v1.10.0
github.com/pires/go-proxyproto v0.6.2
github.com/refraction-networking/utls v1.1.2
github.com/sagernet/certmagic v0.0.0-20220819042630-4a57f8b6853a
github.com/sagernet/quic-go v0.0.0-20220818150011-de611ab3e2bb
github.com/sagernet/shadowsocksr v0.0.0-20220912092645-c9ab93f81bb0
github.com/sagernet/sing v0.0.0-20220913004915-27ddefbb8921
github.com/sagernet/sing-dns v0.0.0-20220822023312-3e086b06d666
github.com/sagernet/sing-dns v0.0.0-20220913080251-628caf4acef7
github.com/sagernet/sing-shadowsocks v0.0.0-20220819002358-7461bb09a8f6
github.com/sagernet/sing-tun v0.0.0-20220911034209-c7dd5d457e24
github.com/sagernet/sing-vmess v0.0.0-20220913015714-c4ab86d40e12

8
go.sum
View File

@ -10,6 +10,8 @@ github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHG
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
github.com/caddyserver/certmagic v0.17.1 h1:VrWANhQAj3brK7jAUKyN6XBHg56WsyorI/84Ilq1tCQ=
github.com/caddyserver/certmagic v0.17.1/go.mod h1:pSS2aZcdKlrTZrb2DKuRafckx20o5Fz1EdDKEB8KOQM=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cloudflare/circl v1.2.1-0.20220831060716-4cf0150356fc h1:307gdRLiZ08dwOIKwc5lAQ19DRFaQQvdhHalyB4Asx8=
@ -133,8 +135,6 @@ github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6L
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sagernet/abx-go v0.0.0-20220819185957-dba1257d738e h1:5CFRo8FJbCuf5s/eTBdZpmMbn8Fe2eSMLNAYfKanA34=
github.com/sagernet/abx-go v0.0.0-20220819185957-dba1257d738e/go.mod h1:qbt0dWObotCfcjAJJ9AxtFPNSDUfZF+6dCpgKEOBn/g=
github.com/sagernet/certmagic v0.0.0-20220819042630-4a57f8b6853a h1:SE3Xn4GOQ+kxbgGa2Xp0H2CCsx1o2pVTt0f+hmfuHH4=
github.com/sagernet/certmagic v0.0.0-20220819042630-4a57f8b6853a/go.mod h1:Q+ZXyesnkjV5B70B1ixk65ecKrlJ2jz0atv3fPKsVVo=
github.com/sagernet/go-tun2socks v1.16.12-0.20220818015926-16cb67876a61 h1:5+m7c6AkmAylhauulqN/c5dnh8/KssrE9c93TQrXldA=
github.com/sagernet/go-tun2socks v1.16.12-0.20220818015926-16cb67876a61/go.mod h1:QUQ4RRHD6hGGHdFMEtR8T2P6GS6R3D/CXKdaYHKKXms=
github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97 h1:iL5gZI3uFp0X6EslacyapiRz7LLSJyr4RajF/BhMVyE=
@ -147,8 +147,8 @@ github.com/sagernet/sing v0.0.0-20220812082120-05f9836bff8f/go.mod h1:QVsS5L/ZA2
github.com/sagernet/sing v0.0.0-20220817130738-ce854cda8522/go.mod h1:QVsS5L/ZA2Q5UhQwLrn0Trw+msNd/NPGEhBKR/ioWiY=
github.com/sagernet/sing v0.0.0-20220913004915-27ddefbb8921 h1:xUHzlIbdlPV/fkToIO9futp9lmKIY+72ezk/whQ8XsI=
github.com/sagernet/sing v0.0.0-20220913004915-27ddefbb8921/go.mod h1:kZvzh1VDa/Dg/Bt5WaYKU0jl5ept8KKDpl3Ay4gRtRQ=
github.com/sagernet/sing-dns v0.0.0-20220822023312-3e086b06d666 h1:XUTocA/Ek0dFxUX+xJCWMPPFZCn2GC/uLrBjTSr1vHY=
github.com/sagernet/sing-dns v0.0.0-20220822023312-3e086b06d666/go.mod h1:eDyH7AJmqBGjZQdQmpZIzlbTREudZuWDExMuGKgjRVM=
github.com/sagernet/sing-dns v0.0.0-20220913080251-628caf4acef7 h1:hGmqtoGifhIy/XFczifR4coknjBIE8f1Suyd1SJc2F4=
github.com/sagernet/sing-dns v0.0.0-20220913080251-628caf4acef7/go.mod h1:NxH8BRDCYo28ZoojuNdRZEt9zbYgyAvC7WxEEkaUBCM=
github.com/sagernet/sing-shadowsocks v0.0.0-20220819002358-7461bb09a8f6 h1:JJfDeYYhWunvtxsU/mOVNTmFQmnzGx9dY034qG6G3g4=
github.com/sagernet/sing-shadowsocks v0.0.0-20220819002358-7461bb09a8f6/go.mod h1:EX3RbZvrwAkPI2nuGa78T2iQXmrkT+/VQtskjou42xM=
github.com/sagernet/sing-tun v0.0.0-20220911034209-c7dd5d457e24 h1:LsmPeFvj4GhiV5Y7Rm8I845XysdxVN4MQmfZ36P5bmw=

View File

@ -16,7 +16,7 @@ import (
N "github.com/sagernet/sing/common/network"
"github.com/sagernet/sing/common/task"
"golang.org/x/net/dns/dnsmessage"
mDNS "github.com/miekg/dns"
)
var _ adapter.Outbound = (*DNS)(nil)
@ -72,7 +72,7 @@ func (d *DNS) handleConnection(ctx context.Context, conn net.Conn, metadata adap
if err != nil {
return err
}
var message dnsmessage.Message
var message mDNS.Msg
err = message.Unpack(buffer.Bytes())
if err != nil {
return err
@ -88,7 +88,7 @@ func (d *DNS) handleConnection(ctx context.Context, conn net.Conn, metadata adap
responseBuffer := common.Dup(_responseBuffer)
defer responseBuffer.Release()
responseBuffer.Resize(2, 0)
n, err := response.AppendPack(responseBuffer.Index(0))
n, err := response.PackBuffer(responseBuffer.FreeBytes())
if err != nil {
return err
}
@ -117,7 +117,7 @@ func (d *DNS) NewPacketConnection(ctx context.Context, conn N.PacketConn, metada
if err != nil {
return err
}
var message dnsmessage.Message
var message mDNS.Msg
err = message.Unpack(buffer.Bytes())
if err != nil {
return err
@ -131,7 +131,7 @@ func (d *DNS) NewPacketConnection(ctx context.Context, conn N.PacketConn, metada
}
timeout.Update()
responseBuffer := buf.NewPacket()
n, err := response.AppendPack(responseBuffer.Index(0))
n, err := response.PackBuffer(responseBuffer.FreeBytes())
if err != nil {
responseBuffer.Release()
return err

View File

@ -12,7 +12,7 @@ import (
E "github.com/sagernet/sing/common/exceptions"
F "github.com/sagernet/sing/common/format"
"golang.org/x/net/dns/dnsmessage"
mDNS "github.com/miekg/dns"
)
func (r *Router) matchDNS(ctx context.Context) (context.Context, dns.Transport, dns.DomainStrategy) {
@ -40,29 +40,29 @@ func (r *Router) matchDNS(ctx context.Context) (context.Context, dns.Transport,
return ctx, r.defaultTransport, r.defaultDomainStrategy
}
func (r *Router) Exchange(ctx context.Context, message *dnsmessage.Message) (*dnsmessage.Message, error) {
if len(message.Questions) > 0 {
r.dnsLogger.DebugContext(ctx, "exchange ", formatDNSQuestion(message.Questions[0]))
func (r *Router) Exchange(ctx context.Context, message *mDNS.Msg) (*mDNS.Msg, error) {
if len(message.Question) > 0 {
r.dnsLogger.DebugContext(ctx, "exchange ", formatQuestion(message.Question[0].String()))
}
ctx, metadata := adapter.AppendContext(ctx)
if len(message.Questions) > 0 {
switch message.Questions[0].Type {
case dnsmessage.TypeA:
if len(message.Question) > 0 {
switch message.Question[0].Qtype {
case mDNS.TypeA:
metadata.IPVersion = 4
case dnsmessage.TypeAAAA:
case mDNS.TypeAAAA:
metadata.IPVersion = 6
}
metadata.Domain = string(message.Questions[0].Name.Data[:message.Questions[0].Name.Length-1])
metadata.Domain = fqdnToDomain(message.Question[0].Name)
}
ctx, transport, strategy := r.matchDNS(ctx)
ctx, cancel := context.WithTimeout(ctx, C.DNSTimeout)
defer cancel()
response, err := r.dnsClient.Exchange(ctx, transport, message, strategy)
if err != nil && len(message.Questions) > 0 {
r.dnsLogger.ErrorContext(ctx, E.Cause(err, "exchange failed for ", message.Questions[0].Name.String()))
if err != nil && len(message.Question) > 0 {
r.dnsLogger.ErrorContext(ctx, E.Cause(err, "exchange failed for ", formatQuestion(message.Question[0].String())))
}
if len(message.Questions) > 0 && response != nil {
LogDNSAnswers(r.dnsLogger, ctx, message.Questions[0].Name.String(), response.Answers)
if len(message.Question) > 0 && response != nil {
LogDNSAnswers(r.dnsLogger, ctx, message.Question[0].Name, response.Answer)
}
return response, err
}
@ -93,61 +93,26 @@ func (r *Router) LookupDefault(ctx context.Context, domain string) ([]netip.Addr
return r.Lookup(ctx, domain, dns.DomainStrategyAsIS)
}
func LogDNSAnswers(logger log.ContextLogger, ctx context.Context, domain string, answers []dnsmessage.Resource) {
for _, rawAnswer := range answers {
var content string
switch answer := rawAnswer.Body.(type) {
case *dnsmessage.AResource:
content = netip.AddrFrom4(answer.A).String()
case *dnsmessage.NSResource:
content = answer.NS.String()
case *dnsmessage.CNAMEResource:
content = answer.CNAME.String()
case *dnsmessage.SOAResource:
content = answer.MBox.String()
case *dnsmessage.PTRResource:
content = answer.PTR.String()
case *dnsmessage.MXResource:
content = answer.MX.String()
case *dnsmessage.TXTResource:
content = strings.Join(answer.TXT, " ")
case *dnsmessage.AAAAResource:
content = netip.AddrFrom16(answer.AAAA).String()
case *dnsmessage.SRVResource:
content = answer.Target.String()
case *dnsmessage.UnknownResource:
content = answer.Type.String()
default:
continue
}
rType := formatDNSType(rawAnswer.Header.Type)
if rType == "" {
logger.InfoContext(ctx, "exchanged ", domain, " ", rType)
} else {
logger.InfoContext(ctx, "exchanged ", domain, " ", rType, " ", content)
}
func LogDNSAnswers(logger log.ContextLogger, ctx context.Context, domain string, answers []mDNS.RR) {
for _, answer := range answers {
logger.InfoContext(ctx, "exchanged ", domain, " ", mDNS.Type(answer.Header().Rrtype).String(), " ", formatQuestion(answer.String()))
}
}
func formatDNSQuestion(question dnsmessage.Question) string {
var qType string
qType = question.Type.String()
if len(qType) > 4 {
qType = qType[4:]
func fqdnToDomain(fqdn string) string {
if mDNS.IsFqdn(fqdn) {
return fqdn[:len(fqdn)-1]
}
var qClass string
qClass = question.Class.String()
if len(qClass) > 5 {
qClass = qClass[5:]
}
return string(question.Name.Data[:question.Name.Length-1]) + " " + qType + " " + qClass
return fqdn
}
func formatDNSType(qType dnsmessage.Type) string {
qTypeName := qType.String()
if len(qTypeName) > 4 {
return qTypeName[4:]
} else {
return F.ToString("unknown (type ", qTypeName, ")")
func formatQuestion(string string) string {
if strings.HasPrefix(string, ";") {
string = string[1:]
}
string = strings.ReplaceAll(string, "\t", " ")
for strings.Contains(string, " ") {
string = strings.ReplaceAll(string, " ", " ")
}
return string
}