mirror of
https://github.com/SagerNet/sing-box.git
synced 2024-11-16 09:12:23 +08:00
Improve DNS caching
This commit is contained in:
parent
f949ddc0ab
commit
6f1b258501
|
@ -4,6 +4,7 @@ import (
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
|
|
||||||
|
"github.com/sagernet/sing/common/bufio"
|
||||||
"github.com/sagernet/sing/common/x/list"
|
"github.com/sagernet/sing/common/x/list"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -42,7 +43,7 @@ func (c *PacketConn) Close() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *PacketConn) Upstream() any {
|
func (c *PacketConn) Upstream() any {
|
||||||
return c.PacketConn
|
return bufio.NewPacketConn(c.PacketConn)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *PacketConn) ReaderReplaceable() bool {
|
func (c *PacketConn) ReaderReplaceable() bool {
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
"strategy": "",
|
"strategy": "",
|
||||||
"disable_cache": false,
|
"disable_cache": false,
|
||||||
"disable_expire": false,
|
"disable_expire": false,
|
||||||
|
"independent_cache": false,
|
||||||
"reverse_mapping": false,
|
"reverse_mapping": false,
|
||||||
"fakeip": {}
|
"fakeip": {}
|
||||||
}
|
}
|
||||||
|
@ -48,6 +49,10 @@ Disable dns cache.
|
||||||
|
|
||||||
Disable dns cache expire.
|
Disable dns cache expire.
|
||||||
|
|
||||||
|
#### independent_cache
|
||||||
|
|
||||||
|
Make each DNS server's cache independent for special purposes. If enabled, will slightly degrade performance.
|
||||||
|
|
||||||
#### reverse_mapping
|
#### reverse_mapping
|
||||||
|
|
||||||
Stores a reverse mapping of IP addresses after responding to a DNS query in order to provide domain names when routing.
|
Stores a reverse mapping of IP addresses after responding to a DNS query in order to provide domain names when routing.
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
"strategy": "",
|
"strategy": "",
|
||||||
"disable_cache": false,
|
"disable_cache": false,
|
||||||
"disable_expire": false,
|
"disable_expire": false,
|
||||||
|
"independent_cache": false,
|
||||||
"reverse_mapping": false,
|
"reverse_mapping": false,
|
||||||
"fakeip": {}
|
"fakeip": {}
|
||||||
}
|
}
|
||||||
|
@ -47,6 +48,10 @@
|
||||||
|
|
||||||
禁用 DNS 缓存过期。
|
禁用 DNS 缓存过期。
|
||||||
|
|
||||||
|
#### independent_cache
|
||||||
|
|
||||||
|
使每个 DNS 服务器的缓存独立,以满足特殊目的。如果启用,将轻微降低性能。
|
||||||
|
|
||||||
#### reverse_mapping
|
#### reverse_mapping
|
||||||
|
|
||||||
在响应 DNS 查询后存储 IP 地址的反向映射以为路由目的提供域名。
|
在响应 DNS 查询后存储 IP 地址的反向映射以为路由目的提供域名。
|
||||||
|
|
4
go.mod
4
go.mod
|
@ -24,8 +24,8 @@ require (
|
||||||
github.com/sagernet/gomobile v0.0.0-20230413023804-244d7ff07035
|
github.com/sagernet/gomobile v0.0.0-20230413023804-244d7ff07035
|
||||||
github.com/sagernet/quic-go v0.0.0-20230202071646-a8c8afb18b32
|
github.com/sagernet/quic-go v0.0.0-20230202071646-a8c8afb18b32
|
||||||
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691
|
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691
|
||||||
github.com/sagernet/sing v0.2.5-0.20230425122720-bf0aaacc6754
|
github.com/sagernet/sing v0.2.5-0.20230501044132-8365dd48a17a
|
||||||
github.com/sagernet/sing-dns v0.1.5-0.20230415085626-111ecf799dfc
|
github.com/sagernet/sing-dns v0.1.5-0.20230426113254-25d948c44223
|
||||||
github.com/sagernet/sing-mux v0.0.0-20230517134606-1ebe6bb26646
|
github.com/sagernet/sing-mux v0.0.0-20230517134606-1ebe6bb26646
|
||||||
github.com/sagernet/sing-shadowsocks v0.2.2-0.20230417102954-f77257340507
|
github.com/sagernet/sing-shadowsocks v0.2.2-0.20230417102954-f77257340507
|
||||||
github.com/sagernet/sing-shadowtls v0.1.2-0.20230417103049-4f682e05f19b
|
github.com/sagernet/sing-shadowtls v0.1.2-0.20230417103049-4f682e05f19b
|
||||||
|
|
8
go.sum
8
go.sum
|
@ -111,10 +111,10 @@ github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691 h1:5Th31OC6yj8byL
|
||||||
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691/go.mod h1:B8lp4WkQ1PwNnrVMM6KyuFR20pU8jYBD+A4EhJovEXU=
|
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691/go.mod h1:B8lp4WkQ1PwNnrVMM6KyuFR20pU8jYBD+A4EhJovEXU=
|
||||||
github.com/sagernet/sing v0.0.0-20220817130738-ce854cda8522/go.mod h1:QVsS5L/ZA2Q5UhQwLrn0Trw+msNd/NPGEhBKR/ioWiY=
|
github.com/sagernet/sing v0.0.0-20220817130738-ce854cda8522/go.mod h1:QVsS5L/ZA2Q5UhQwLrn0Trw+msNd/NPGEhBKR/ioWiY=
|
||||||
github.com/sagernet/sing v0.1.8/go.mod h1:jt1w2u7lJQFFSGLiRrRIs5YWmx4kAPfWuOejuDW9qMk=
|
github.com/sagernet/sing v0.1.8/go.mod h1:jt1w2u7lJQFFSGLiRrRIs5YWmx4kAPfWuOejuDW9qMk=
|
||||||
github.com/sagernet/sing v0.2.5-0.20230425122720-bf0aaacc6754 h1:y89Ntm1rrZPQVb1f+TKd4DH6NwX5XCyMIwoseTQd/5U=
|
github.com/sagernet/sing v0.2.5-0.20230501044132-8365dd48a17a h1:s2kkd/eR3mWGkYioknxhgQzG8uft4VRx9skhqxxeyVQ=
|
||||||
github.com/sagernet/sing v0.2.5-0.20230425122720-bf0aaacc6754/go.mod h1:Ta8nHnDLAwqySzKhGoKk4ZIB+vJ3GTKj7UPrWYvM+4w=
|
github.com/sagernet/sing v0.2.5-0.20230501044132-8365dd48a17a/go.mod h1:Ta8nHnDLAwqySzKhGoKk4ZIB+vJ3GTKj7UPrWYvM+4w=
|
||||||
github.com/sagernet/sing-dns v0.1.5-0.20230415085626-111ecf799dfc h1:hmbuqKv48SAjiKPoqtJGvS5pEHVPZjTHq9CPwQY2cZ4=
|
github.com/sagernet/sing-dns v0.1.5-0.20230426113254-25d948c44223 h1:L4eMuM07iSHY3UCknFnuFuHoe5clZuF2Xnf2wwA6Lwc=
|
||||||
github.com/sagernet/sing-dns v0.1.5-0.20230415085626-111ecf799dfc/go.mod h1:ZKuuqgsHRxDahYrzgSgy4vIAGGuKPlIf4hLcNzYzLkY=
|
github.com/sagernet/sing-dns v0.1.5-0.20230426113254-25d948c44223/go.mod h1:ZKuuqgsHRxDahYrzgSgy4vIAGGuKPlIf4hLcNzYzLkY=
|
||||||
github.com/sagernet/sing-mux v0.0.0-20230517134606-1ebe6bb26646 h1:X3ADfMqeGns1Q1FlXc9kaL9FwW1UM6D6tEQo8jFstpc=
|
github.com/sagernet/sing-mux v0.0.0-20230517134606-1ebe6bb26646 h1:X3ADfMqeGns1Q1FlXc9kaL9FwW1UM6D6tEQo8jFstpc=
|
||||||
github.com/sagernet/sing-mux v0.0.0-20230517134606-1ebe6bb26646/go.mod h1:pF+RnLvCAOhECrvauy6LYOpBakJ/vuaF1Wm4lPsWryI=
|
github.com/sagernet/sing-mux v0.0.0-20230517134606-1ebe6bb26646/go.mod h1:pF+RnLvCAOhECrvauy6LYOpBakJ/vuaF1Wm4lPsWryI=
|
||||||
github.com/sagernet/sing-shadowsocks v0.2.2-0.20230417102954-f77257340507 h1:bAHZCdWqJkb8LEW98+YsMVDXGRMUVjka8IC+St6ot88=
|
github.com/sagernet/sing-shadowsocks v0.2.2-0.20230417102954-f77257340507 h1:bAHZCdWqJkb8LEW98+YsMVDXGRMUVjka8IC+St6ot88=
|
||||||
|
|
|
@ -20,9 +20,10 @@ type DNSServerOptions struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type DNSClientOptions struct {
|
type DNSClientOptions struct {
|
||||||
Strategy DomainStrategy `json:"strategy,omitempty"`
|
Strategy DomainStrategy `json:"strategy,omitempty"`
|
||||||
DisableCache bool `json:"disable_cache,omitempty"`
|
DisableCache bool `json:"disable_cache,omitempty"`
|
||||||
DisableExpire bool `json:"disable_expire,omitempty"`
|
DisableExpire bool `json:"disable_expire,omitempty"`
|
||||||
|
IndependentCache bool `json:"independent_cache,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type DNSFakeIPOptions struct {
|
type DNSFakeIPOptions struct {
|
||||||
|
|
|
@ -104,18 +104,18 @@ func (d *DNS) handleConnection(ctx context.Context, conn net.Conn, metadata adap
|
||||||
func (d *DNS) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error {
|
func (d *DNS) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error {
|
||||||
var reader N.PacketReader = conn
|
var reader N.PacketReader = conn
|
||||||
var counters []N.CountFunc
|
var counters []N.CountFunc
|
||||||
var cachedBuffer []*N.PacketBuffer
|
var cachedPackets []*N.PacketBuffer
|
||||||
for {
|
for {
|
||||||
reader, counters = N.UnwrapCountPacketReader(reader, counters)
|
reader, counters = N.UnwrapCountPacketReader(reader, counters)
|
||||||
if cachedReader, isCached := reader.(N.CachedPacketReader); isCached {
|
if cachedReader, isCached := reader.(N.CachedPacketReader); isCached {
|
||||||
packet := cachedReader.ReadCachedPacket()
|
packet := cachedReader.ReadCachedPacket()
|
||||||
if packet != nil {
|
if packet != nil {
|
||||||
cachedBuffer = append([]*N.PacketBuffer{packet}, cachedBuffer...)
|
cachedPackets = append(cachedPackets, packet)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if readWaiter, created := bufio.CreatePacketReadWaiter(reader); created {
|
if readWaiter, created := bufio.CreatePacketReadWaiter(reader); created {
|
||||||
return d.newPacketConnection(ctx, conn, readWaiter, counters, cachedBuffer, metadata)
|
return d.newPacketConnection(ctx, conn, readWaiter, counters, cachedPackets, metadata)
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
|
@ -111,7 +111,12 @@ func NewRouter(
|
||||||
defaultMark: options.DefaultMark,
|
defaultMark: options.DefaultMark,
|
||||||
platformInterface: platformInterface,
|
platformInterface: platformInterface,
|
||||||
}
|
}
|
||||||
router.dnsClient = dns.NewClient(dnsOptions.DNSClientOptions.DisableCache, dnsOptions.DNSClientOptions.DisableExpire, router.dnsLogger)
|
router.dnsClient = dns.NewClient(dns.ClientOptions{
|
||||||
|
DisableCache: dnsOptions.DNSClientOptions.DisableCache,
|
||||||
|
DisableExpire: dnsOptions.DNSClientOptions.DisableExpire,
|
||||||
|
IndependentCache: dnsOptions.DNSClientOptions.IndependentCache,
|
||||||
|
Logger: router.dnsLogger,
|
||||||
|
})
|
||||||
for i, ruleOptions := range options.Rules {
|
for i, ruleOptions := range options.Rules {
|
||||||
routeRule, err := NewRule(router, router.logger, ruleOptions)
|
routeRule, err := NewRule(router, router.logger, ruleOptions)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -73,23 +73,31 @@ func (r *Router) Exchange(ctx context.Context, message *mDNS.Msg) (*mDNS.Msg, er
|
||||||
if len(message.Question) > 0 {
|
if len(message.Question) > 0 {
|
||||||
r.dnsLogger.DebugContext(ctx, "exchange ", formatQuestion(message.Question[0].String()))
|
r.dnsLogger.DebugContext(ctx, "exchange ", formatQuestion(message.Question[0].String()))
|
||||||
}
|
}
|
||||||
ctx, metadata := adapter.AppendContext(ctx)
|
var (
|
||||||
if len(message.Question) > 0 {
|
response *mDNS.Msg
|
||||||
metadata.QueryType = message.Question[0].Qtype
|
cached bool
|
||||||
switch metadata.QueryType {
|
err error
|
||||||
case mDNS.TypeA:
|
)
|
||||||
metadata.IPVersion = 4
|
response, cached = r.dnsClient.ExchangeCache(ctx, message)
|
||||||
case mDNS.TypeAAAA:
|
if !cached {
|
||||||
metadata.IPVersion = 6
|
ctx, metadata := adapter.AppendContext(ctx)
|
||||||
|
if len(message.Question) > 0 {
|
||||||
|
metadata.QueryType = message.Question[0].Qtype
|
||||||
|
switch metadata.QueryType {
|
||||||
|
case mDNS.TypeA:
|
||||||
|
metadata.IPVersion = 4
|
||||||
|
case mDNS.TypeAAAA:
|
||||||
|
metadata.IPVersion = 6
|
||||||
|
}
|
||||||
|
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.Question) > 0 {
|
||||||
|
r.dnsLogger.ErrorContext(ctx, E.Cause(err, "exchange failed for ", formatQuestion(message.Question[0].String())))
|
||||||
}
|
}
|
||||||
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.Question) > 0 {
|
|
||||||
r.dnsLogger.ErrorContext(ctx, E.Cause(err, "exchange failed for ", formatQuestion(message.Question[0].String())))
|
|
||||||
}
|
}
|
||||||
if len(message.Question) > 0 && response != nil {
|
if len(message.Question) > 0 && response != nil {
|
||||||
LogDNSAnswers(r.dnsLogger, ctx, message.Question[0].Name, response.Answer)
|
LogDNSAnswers(r.dnsLogger, ctx, message.Question[0].Name, response.Answer)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user