Add dns reverse mapping

This commit is contained in:
世界 2023-03-23 19:08:48 +08:00
parent 4395db3206
commit e6e556215b
No known key found for this signature in database
GPG Key ID: CD109927C34A63C4
3 changed files with 50 additions and 3 deletions

View File

@ -13,6 +13,7 @@ type DNSOptions struct {
Servers []DNSServerOptions `json:"servers,omitempty"`
Rules []DNSRule `json:"rules,omitempty"`
Final string `json:"final,omitempty"`
ReverseMapping bool `json:"reverse_mapping,omitempty"`
DNSClientOptions
}

View File

@ -89,6 +89,7 @@ type Router struct {
transports []dns.Transport
transportMap map[string]dns.Transport
transportDomainStrategy map[dns.Transport]dns.DomainStrategy
dnsReverseMapping *DNSReverseMapping
interfaceFinder myInterfaceFinder
autoDetectInterface bool
defaultInterface string
@ -267,6 +268,10 @@ func NewRouter(
router.transportMap = transportMap
router.transportDomainStrategy = transportDomainStrategy
if dnsOptions.ReverseMapping {
router.dnsReverseMapping = NewDNSReverseMapping()
}
needInterfaceMonitor := platformInterface == nil && (options.AutoDetectInterface || common.Any(inbounds, func(inbound option.Inbound) bool {
return inbound.HTTPOptions.SetSystemProxy || inbound.MixedOptions.SetSystemProxy || inbound.TunOptions.AutoRoute
}))
@ -627,6 +632,15 @@ func (r *Router) RouteConnection(ctx context.Context, conn net.Conn, metadata ad
buffer.Release()
}
}
if r.dnsReverseMapping != nil && metadata.Domain == "" {
domain, loaded := r.dnsReverseMapping.Query(metadata.Destination.Addr)
if loaded {
metadata.Domain = domain
r.logger.DebugContext(ctx, "found reserve mapped domain: ", metadata.Domain)
}
}
if metadata.Destination.IsFqdn() && dns.DomainStrategy(metadata.InboundOptions.DomainStrategy) != dns.DomainStrategyAsIS {
addresses, err := r.Lookup(adapter.WithContext(ctx, &metadata), metadata.Destination.Fqdn, dns.DomainStrategy(metadata.InboundOptions.DomainStrategy))
if err != nil {

View File

@ -4,17 +4,39 @@ import (
"context"
"net/netip"
"strings"
"time"
"github.com/sagernet/sing-box/adapter"
C "github.com/sagernet/sing-box/constant"
"github.com/sagernet/sing-box/log"
"github.com/sagernet/sing-dns"
"github.com/sagernet/sing/common/cache"
E "github.com/sagernet/sing/common/exceptions"
F "github.com/sagernet/sing/common/format"
M "github.com/sagernet/sing/common/metadata"
mDNS "github.com/miekg/dns"
)
type DNSReverseMapping struct {
cache *cache.LruCache[netip.Addr, string]
}
func NewDNSReverseMapping() *DNSReverseMapping {
return &DNSReverseMapping{
cache: cache.New[netip.Addr, string](),
}
}
func (m *DNSReverseMapping) Save(address netip.Addr, domain string, ttl int) {
m.cache.StoreWithExpire(address, domain, time.Now().Add(time.Duration(ttl)*time.Second))
}
func (m *DNSReverseMapping) Query(address netip.Addr) (string, bool) {
domain, loaded := m.cache.Load(address)
return domain, loaded
}
func (r *Router) matchDNS(ctx context.Context) (context.Context, dns.Transport, dns.DomainStrategy) {
metadata := adapter.ContextFrom(ctx)
if metadata == nil {
@ -69,6 +91,16 @@ func (r *Router) Exchange(ctx context.Context, message *mDNS.Msg) (*mDNS.Msg, er
if len(message.Question) > 0 && response != nil {
LogDNSAnswers(r.dnsLogger, ctx, message.Question[0].Name, response.Answer)
}
if r.dnsReverseMapping != nil && len(message.Question) > 0 && response != nil && len(response.Answer) > 0 {
for _, answer := range response.Answer {
switch record := answer.(type) {
case *mDNS.A:
r.dnsReverseMapping.Save(M.AddrFromIP(record.A), fqdnToDomain(record.Hdr.Name), int(record.Hdr.Ttl))
case *mDNS.AAAA:
r.dnsReverseMapping.Save(M.AddrFromIP(record.AAAA), fqdnToDomain(record.Hdr.Name), int(record.Hdr.Ttl))
}
}
}
return response, err
}