diff --git a/option/dns.go b/option/dns.go index e0d237b7d3..4f196fa8a1 100644 --- a/option/dns.go +++ b/option/dns.go @@ -3,11 +3,12 @@ package option import "net/netip" type DNSOptions struct { - Servers []DNSServerOptions `json:"servers,omitempty"` - Rules []DNSRule `json:"rules,omitempty"` - Final string `json:"final,omitempty"` - ReverseMapping bool `json:"reverse_mapping,omitempty"` - FakeIP *DNSFakeIPOptions `json:"fakeip,omitempty"` + Servers []DNSServerOptions `json:"servers,omitempty"` + Rules []DNSRule `json:"rules,omitempty"` + Final string `json:"final,omitempty"` + ReverseMapping bool `json:"reverse_mapping,omitempty"` + FakeIP *DNSFakeIPOptions `json:"fakeip,omitempty"` + StaticIPs map[string][]string `json:"static_ips,omitempty"` DNSClientOptions } diff --git a/route/router.go b/route/router.go index adbdbd2082..8e70a0f294 100644 --- a/route/router.go +++ b/route/router.go @@ -70,6 +70,7 @@ type Router struct { dnsClient *dns.Client defaultDomainStrategy dns.DomainStrategy dnsRules []adapter.DNSRule + staticDns map[string]StaticDNSEntry //Hiddify ruleSets []adapter.RuleSet ruleSetMap map[string]adapter.RuleSet defaultTransport dns.Transport @@ -131,6 +132,7 @@ func NewRouter( needPackageManager: C.IsAndroid && platformInterface == nil && common.Any(inbounds, func(inbound option.Inbound) bool { return len(inbound.TunOptions.IncludePackage) > 0 || len(inbound.TunOptions.ExcludePackage) > 0 }), + staticDns: createEntries(dnsOptions.StaticIPs),//hiddify } router.dnsClient = dns.NewClient(dns.ClientOptions{ DisableCache: dnsOptions.DNSClientOptions.DisableCache, diff --git a/route/router_dns.go b/route/router_dns.go index 8ae9171002..e276a4eda3 100644 --- a/route/router_dns.go +++ b/route/router_dns.go @@ -9,7 +9,7 @@ import ( "github.com/sagernet/sing-box/adapter" C "github.com/sagernet/sing-box/constant" "github.com/sagernet/sing-box/log" - "github.com/sagernet/sing-dns" + dns "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" @@ -131,7 +131,11 @@ func (r *Router) Lookup(ctx context.Context, domain string, strategy dns.DomainS } ctx, cancel := context.WithTimeout(ctx, C.DNSTimeout) defer cancel() - addrs, err := r.dnsClient.Lookup(ctx, transport, domain, strategy) + + addrs, err := lookupStaticIP(domain, strategy, r.staticDns) + if addrs == nil || err != nil { + addrs, err = r.dnsClient.Lookup(ctx, transport, domain, strategy) + } if len(addrs) > 0 { r.dnsLogger.InfoContext(ctx, "lookup succeed for ", domain, ": ", strings.Join(F.MapToString(addrs), " ")) } else if err != nil { diff --git a/route/staticDNS.go b/route/staticDNS.go new file mode 100644 index 0000000000..6f92a8f1a6 --- /dev/null +++ b/route/staticDNS.go @@ -0,0 +1,73 @@ +package route + +import ( + "fmt" + "net/netip" + + dns "github.com/sagernet/sing-dns" +) + +type StaticDNSEntry struct { + IPv4 *netip.Addr + IPv6 *netip.Addr +} + +func createEntries(items map[string][]string) map[string]StaticDNSEntry { + entries := make(map[string]StaticDNSEntry) + + for domain, ips := range items { + entry := StaticDNSEntry{} + + for _, ipString := range ips { + ip, err := netip.ParseAddr(ipString) + if err != nil { + fmt.Printf("Invalid IP address for domain %s: %s\n", domain, ipString) + continue + } + + if ip.Is4() { + entry.IPv4 = &ip + } else { + entry.IPv6 = &ip + } + } + entries[domain] = entry + } + + return entries +} + +func lookupStaticIP(domain string, strategy uint8, entries map[string]StaticDNSEntry) ([]netip.Addr, error) { + + if staticDns, ok := entries[domain]; ok { + addrs := []netip.Addr{} + switch strategy { + case dns.DomainStrategyUseIPv4: + if staticDns.IPv4 != nil { + addrs = append(addrs, *staticDns.IPv4) + } + case dns.DomainStrategyUseIPv6: + if staticDns.IPv6 != nil { + addrs = append(addrs, *staticDns.IPv6) + } + case dns.DomainStrategyPreferIPv6: + if staticDns.IPv6 != nil { + addrs = append(addrs, *staticDns.IPv6) + } + if staticDns.IPv4 != nil { + addrs = append(addrs, *staticDns.IPv4) + } + default: + if staticDns.IPv4 != nil { + addrs = append(addrs, *staticDns.IPv4) + } + if staticDns.IPv6 != nil { + addrs = append(addrs, *staticDns.IPv6) + } + } + return addrs, nil + } else { + return nil, fmt.Errorf("NotFound") + } + +}