Projects STRLCPY sing-box Commits d0ecad5e
🤬
Revision indexing in progress... (symbol navigation in revisions will be accurate after indexed)
  • ■ ■ ■ ■ ■
    docs/configuration/dns/index.md
    skipped 9 lines
    10 10   "final": "",
    11 11   "strategy": "",
    12 12   "disable_cache": false,
    13  - "disable_expire": false
     13 + "disable_expire": false,
     14 + "reverse_mapping": false
    14 15   }
    15 16  }
    16 17   
    skipped 27 lines
    44 45  #### disable_expire
    45 46   
    46 47  Disable dns cache expire.
     48 + 
     49 +#### reverse_mapping
     50 + 
     51 +Stores a reverse mapping of IP addresses after responding to a DNS query in order to provide domain names when routing.
     52 + 
     53 +Since this process relies on the act of resolving domain names by an application before making a request, it can be problematic in environments such as macOS, where DNS is proxied and cached by the system.
     54 + 
  • ■ ■ ■ ■ ■
    docs/configuration/dns/index.zh.md
    skipped 9 lines
    10 10   "final": "",
    11 11   "strategy": "",
    12 12   "disable_cache": false,
    13  - "disable_expire": false
     13 + "disable_expire": false,
     14 + "reverse_mapping": false
    14 15   }
    15 16  }
    16 17   
    skipped 27 lines
    44 45  #### disable_expire
    45 46   
    46 47  禁用 DNS 缓存过期。
     48 + 
     49 +#### reverse_mapping
     50 + 
     51 +在响应 DNS 查询后存储 IP 地址的反向映射以为路由目的提供域名。
     52 + 
     53 +由于此过程依赖于应用程序在发出请求之前解析域名的行为,因此在 macOS 等 DNS 由系统代理和缓存的环境中可能会出现问题。
     54 + 
  • ■ ■ ■ ■ ■ ■
    option/dns.go
    skipped 9 lines
    10 10  )
    11 11   
    12 12  type DNSOptions struct {
    13  - Servers []DNSServerOptions `json:"servers,omitempty"`
    14  - Rules []DNSRule `json:"rules,omitempty"`
    15  - Final string `json:"final,omitempty"`
     13 + Servers []DNSServerOptions `json:"servers,omitempty"`
     14 + Rules []DNSRule `json:"rules,omitempty"`
     15 + Final string `json:"final,omitempty"`
     16 + ReverseMapping bool `json:"reverse_mapping,omitempty"`
    16 17   DNSClientOptions
    17 18  }
    18 19   
    skipped 110 lines
  • ■ ■ ■ ■ ■ ■
    route/router.go
    skipped 88 lines
    89 89   transports []dns.Transport
    90 90   transportMap map[string]dns.Transport
    91 91   transportDomainStrategy map[dns.Transport]dns.DomainStrategy
     92 + dnsReverseMapping *DNSReverseMapping
    92 93   interfaceFinder myInterfaceFinder
    93 94   autoDetectInterface bool
    94 95   defaultInterface string
    skipped 171 lines
    266 267   router.transports = transports
    267 268   router.transportMap = transportMap
    268 269   router.transportDomainStrategy = transportDomainStrategy
     270 + 
     271 + if dnsOptions.ReverseMapping {
     272 + router.dnsReverseMapping = NewDNSReverseMapping()
     273 + }
    269 274   
    270 275   needInterfaceMonitor := platformInterface == nil && (options.AutoDetectInterface || common.Any(inbounds, func(inbound option.Inbound) bool {
    271 276   return inbound.HTTPOptions.SetSystemProxy || inbound.MixedOptions.SetSystemProxy || inbound.TunOptions.AutoRoute
    skipped 355 lines
    627 632   buffer.Release()
    628 633   }
    629 634   }
     635 + 
     636 + if r.dnsReverseMapping != nil && metadata.Domain == "" {
     637 + domain, loaded := r.dnsReverseMapping.Query(metadata.Destination.Addr)
     638 + if loaded {
     639 + metadata.Domain = domain
     640 + r.logger.DebugContext(ctx, "found reserve mapped domain: ", metadata.Domain)
     641 + }
     642 + }
     643 + 
    630 644   if metadata.Destination.IsFqdn() && dns.DomainStrategy(metadata.InboundOptions.DomainStrategy) != dns.DomainStrategyAsIS {
    631 645   addresses, err := r.Lookup(adapter.WithContext(ctx, &metadata), metadata.Destination.Fqdn, dns.DomainStrategy(metadata.InboundOptions.DomainStrategy))
    632 646   if err != nil {
    skipped 487 lines
  • ■ ■ ■ ■ ■ ■
    route/router_dns.go
    skipped 3 lines
    4 4   "context"
    5 5   "net/netip"
    6 6   "strings"
     7 + "time"
    7 8   
    8 9   "github.com/sagernet/sing-box/adapter"
    9 10   C "github.com/sagernet/sing-box/constant"
    10 11   "github.com/sagernet/sing-box/log"
    11 12   "github.com/sagernet/sing-dns"
     13 + "github.com/sagernet/sing/common/cache"
    12 14   E "github.com/sagernet/sing/common/exceptions"
    13 15   F "github.com/sagernet/sing/common/format"
     16 + M "github.com/sagernet/sing/common/metadata"
    14 17   
    15 18   mDNS "github.com/miekg/dns"
    16 19  )
     20 + 
     21 +type DNSReverseMapping struct {
     22 + cache *cache.LruCache[netip.Addr, string]
     23 +}
     24 + 
     25 +func NewDNSReverseMapping() *DNSReverseMapping {
     26 + return &DNSReverseMapping{
     27 + cache: cache.New[netip.Addr, string](),
     28 + }
     29 +}
     30 + 
     31 +func (m *DNSReverseMapping) Save(address netip.Addr, domain string, ttl int) {
     32 + m.cache.StoreWithExpire(address, domain, time.Now().Add(time.Duration(ttl)*time.Second))
     33 +}
     34 + 
     35 +func (m *DNSReverseMapping) Query(address netip.Addr) (string, bool) {
     36 + domain, loaded := m.cache.Load(address)
     37 + return domain, loaded
     38 +}
    17 39   
    18 40  func (r *Router) matchDNS(ctx context.Context) (context.Context, dns.Transport, dns.DomainStrategy) {
    19 41   metadata := adapter.ContextFrom(ctx)
    skipped 48 lines
    68 90   }
    69 91   if len(message.Question) > 0 && response != nil {
    70 92   LogDNSAnswers(r.dnsLogger, ctx, message.Question[0].Name, response.Answer)
     93 + }
     94 + if r.dnsReverseMapping != nil && len(message.Question) > 0 && response != nil && len(response.Answer) > 0 {
     95 + for _, answer := range response.Answer {
     96 + switch record := answer.(type) {
     97 + case *mDNS.A:
     98 + r.dnsReverseMapping.Save(M.AddrFromIP(record.A), fqdnToDomain(record.Hdr.Name), int(record.Hdr.Ttl))
     99 + case *mDNS.AAAA:
     100 + r.dnsReverseMapping.Save(M.AddrFromIP(record.AAAA), fqdnToDomain(record.Hdr.Name), int(record.Hdr.Ttl))
     101 + }
     102 + }
    71 103   }
    72 104   return response, err
    73 105  }
    skipped 51 lines
Please wait...
Page is in error, reload to recover