chore: sync dns code

This commit is contained in:
wwqgtxx 2022-11-12 21:31:07 +08:00
parent 7300c917dc
commit a3425c0e78
2 changed files with 168 additions and 169 deletions

View file

@ -3,12 +3,13 @@ package resolver
import ( import (
"context" "context"
"errors" "errors"
"fmt"
"math/rand" "math/rand"
"net" "net"
"net/netip" "net/netip"
"strings"
"time" "time"
"github.com/Dreamacro/clash/common/nnip"
"github.com/Dreamacro/clash/component/trie" "github.com/Dreamacro/clash/component/trie"
) )
@ -45,39 +46,164 @@ type Resolver interface {
ResolveIPv6(ctx context.Context, host string) (ip netip.Addr, err error) ResolveIPv6(ctx context.Context, host string) (ip netip.Addr, err error)
} }
// LookupIPv4WithResolver same as LookupIPv4, but with a resolver
func LookupIPv4WithResolver(ctx context.Context, host string, r Resolver) ([]netip.Addr, error) {
if node := DefaultHosts.Search(host); node != nil {
if ip := node.Data(); ip.Is4() {
return []netip.Addr{node.Data()}, nil
}
}
ip, err := netip.ParseAddr(host)
if err == nil {
if ip.Is4() || ip.Is4In6() {
return []netip.Addr{ip}, nil
}
return []netip.Addr{}, ErrIPVersion
}
if r != nil {
return r.LookupIPv4(ctx, host)
}
if DefaultResolver != nil {
return DefaultResolver.LookupIPv4(ctx, host)
}
ctx, cancel := context.WithTimeout(context.Background(), DefaultDNSTimeout)
defer cancel()
ipAddrs, err := net.DefaultResolver.LookupNetIP(ctx, "ip4", host)
if err != nil {
return nil, err
} else if len(ipAddrs) == 0 {
return nil, ErrIPNotFound
}
return ipAddrs, nil
}
// LookupIPv4 with a host, return ipv4 list
func LookupIPv4(ctx context.Context, host string) ([]netip.Addr, error) {
return LookupIPv4WithResolver(ctx, host, DefaultResolver)
}
// ResolveIPv4WithResolver same as ResolveIPv4, but with a resolver
func ResolveIPv4WithResolver(ctx context.Context, host string, r Resolver) (netip.Addr, error) {
ips, err := LookupIPv4WithResolver(ctx, host, r)
if err != nil {
return netip.Addr{}, err
} else if len(ips) == 0 {
return netip.Addr{}, fmt.Errorf("%w: %s", ErrIPNotFound, host)
}
return ips[rand.Intn(len(ips))], nil
}
// ResolveIPv4 with a host, return ipv4 // ResolveIPv4 with a host, return ipv4
func ResolveIPv4(ctx context.Context, host string) (netip.Addr, error) { func ResolveIPv4(ctx context.Context, host string) (netip.Addr, error) {
return ResolveIPv4WithResolver(ctx, host, DefaultResolver) return ResolveIPv4WithResolver(ctx, host, DefaultResolver)
} }
func ResolveIPv4WithResolver(ctx context.Context, host string, r Resolver) (netip.Addr, error) { // LookupIPv6WithResolver same as LookupIPv6, but with a resolver
if ips, err := LookupIPv4WithResolver(ctx, host, r); err == nil { func LookupIPv6WithResolver(ctx context.Context, host string, r Resolver) ([]netip.Addr, error) {
return ips[rand.Intn(len(ips))], nil if DisableIPv6 {
} else { return nil, ErrIPv6Disabled
return netip.Addr{}, err
} }
if node := DefaultHosts.Search(host); node != nil {
if ip := node.Data(); ip.Is6() {
return []netip.Addr{ip}, nil
}
}
if ip, err := netip.ParseAddr(host); err == nil {
if strings.Contains(host, ":") {
return []netip.Addr{ip}, nil
}
return nil, ErrIPVersion
}
if r != nil {
return r.LookupIPv6(ctx, host)
}
if DefaultResolver != nil {
return DefaultResolver.LookupIPv6(ctx, host)
}
ctx, cancel := context.WithTimeout(context.Background(), DefaultDNSTimeout)
defer cancel()
ipAddrs, err := net.DefaultResolver.LookupNetIP(ctx, "ip6", host)
if err != nil {
return nil, err
} else if len(ipAddrs) == 0 {
return nil, ErrIPNotFound
}
return ipAddrs, nil
}
// LookupIPv6 with a host, return ipv6 list
func LookupIPv6(ctx context.Context, host string) ([]netip.Addr, error) {
return LookupIPv6WithResolver(ctx, host, DefaultResolver)
}
// ResolveIPv6WithResolver same as ResolveIPv6, but with a resolver
func ResolveIPv6WithResolver(ctx context.Context, host string, r Resolver) (netip.Addr, error) {
ips, err := LookupIPv6WithResolver(ctx, host, r)
if err != nil {
return netip.Addr{}, err
} else if len(ips) == 0 {
return netip.Addr{}, fmt.Errorf("%w: %s", ErrIPNotFound, host)
}
return ips[rand.Intn(len(ips))], nil
} }
// ResolveIPv6 with a host, return ipv6
func ResolveIPv6(ctx context.Context, host string) (netip.Addr, error) { func ResolveIPv6(ctx context.Context, host string) (netip.Addr, error) {
return ResolveIPv6WithResolver(ctx, host, DefaultResolver) return ResolveIPv6WithResolver(ctx, host, DefaultResolver)
} }
func ResolveIPv6WithResolver(ctx context.Context, host string, r Resolver) (netip.Addr, error) { // LookupIPWithResolver same as LookupIP, but with a resolver
if ips, err := LookupIPv6WithResolver(ctx, host, r); err == nil { func LookupIPWithResolver(ctx context.Context, host string, r Resolver) ([]netip.Addr, error) {
return ips[rand.Intn(len(ips))], nil if node := DefaultHosts.Search(host); node != nil {
} else { return []netip.Addr{node.Data()}, nil
return netip.Addr{}, err
} }
if r != nil {
if DisableIPv6 {
return r.LookupIPv4(ctx, host)
}
return r.LookupIP(ctx, host)
} else if DisableIPv6 {
return LookupIPv4(ctx, host)
}
if ip, err := netip.ParseAddr(host); err == nil {
return []netip.Addr{ip}, nil
}
ips, err := net.DefaultResolver.LookupNetIP(ctx, "ip", host)
if err != nil {
return nil, err
} else if len(ips) == 0 {
return nil, ErrIPNotFound
}
return ips, nil
}
// LookupIP with a host, return ip
func LookupIP(ctx context.Context, host string) ([]netip.Addr, error) {
return LookupIPWithResolver(ctx, host, DefaultResolver)
} }
// ResolveIPWithResolver same as ResolveIP, but with a resolver // ResolveIPWithResolver same as ResolveIP, but with a resolver
func ResolveIPWithResolver(ctx context.Context, host string, r Resolver) (netip.Addr, error) { func ResolveIPWithResolver(ctx context.Context, host string, r Resolver) (netip.Addr, error) {
if ip, err := ResolveIPv4WithResolver(ctx, host, r); err == nil { ips, err := LookupIPWithResolver(ctx, host, r)
return ip, nil if err != nil {
} else { return netip.Addr{}, err
return ResolveIPv6WithResolver(ctx, host, r) } else if len(ips) == 0 {
return netip.Addr{}, fmt.Errorf("%w: %s", ErrIPNotFound, host)
} }
return ips[rand.Intn(len(ips))], nil
} }
// ResolveIP with a host, return ip // ResolveIP with a host, return ip
@ -121,142 +247,6 @@ func ResolveProxyServerHost(ctx context.Context, host string) (netip.Addr, error
return ResolveIP(ctx, host) return ResolveIP(ctx, host)
} }
func LookupIPv6WithResolver(ctx context.Context, host string, r Resolver) ([]netip.Addr, error) {
if DisableIPv6 {
return []netip.Addr{}, ErrIPv6Disabled
}
if node := DefaultHosts.Search(host); node != nil {
if ip := node.Data(); ip.Is6() {
return []netip.Addr{ip}, nil
}
}
ip, err := netip.ParseAddr(host)
if err == nil {
if ip.Is6() {
return []netip.Addr{ip}, nil
}
return []netip.Addr{}, ErrIPVersion
}
if r != nil {
return r.LookupIPv6(ctx, host)
}
if DefaultResolver == nil {
ipAddrs, err := net.DefaultResolver.LookupIP(ctx, "ip6", host)
if err != nil {
return []netip.Addr{}, err
} else if len(ipAddrs) == 0 {
return []netip.Addr{}, ErrIPNotFound
}
addrs := make([]netip.Addr, 0, len(ipAddrs))
for _, ipAddr := range ipAddrs {
addrs = append(addrs, nnip.IpToAddr(ipAddr))
}
rand.Shuffle(len(addrs), func(i, j int) {
addrs[i], addrs[j] = addrs[j], addrs[i]
})
return addrs, nil
}
return []netip.Addr{}, ErrIPNotFound
}
func LookupIPv4WithResolver(ctx context.Context, host string, r Resolver) ([]netip.Addr, error) {
if node := DefaultHosts.Search(host); node != nil {
if ip := node.Data(); ip.Is4() {
return []netip.Addr{node.Data()}, nil
}
}
ip, err := netip.ParseAddr(host)
if err == nil {
if ip.Is4() || ip.Is4In6() {
return []netip.Addr{ip}, nil
}
return []netip.Addr{}, ErrIPVersion
}
if r != nil {
return r.LookupIPv4(ctx, host)
}
if DefaultResolver == nil {
ipAddrs, err := net.DefaultResolver.LookupIP(ctx, "ip4", host)
if err != nil {
return []netip.Addr{}, err
} else if len(ipAddrs) == 0 {
return []netip.Addr{}, ErrIPNotFound
}
addrs := make([]netip.Addr, 0, len(ipAddrs))
for _, ipAddr := range ipAddrs {
addrs = append(addrs, nnip.IpToAddr(ipAddr))
}
rand.Shuffle(len(addrs), func(i, j int) {
addrs[i], addrs[j] = addrs[j], addrs[i]
})
return addrs, nil
}
return []netip.Addr{}, ErrIPNotFound
}
func LookupIPWithResolver(ctx context.Context, host string, r Resolver) ([]netip.Addr, error) {
if node := DefaultHosts.Search(host); node != nil {
return []netip.Addr{node.Data()}, nil
}
ip, err := netip.ParseAddr(host)
if err == nil {
return []netip.Addr{ip}, nil
}
if r != nil {
if DisableIPv6 {
return r.LookupIPv4(ctx, host)
}
return r.LookupIP(ctx, host)
} else if DisableIPv6 {
return LookupIPv4(ctx, host)
}
if DefaultResolver == nil {
ipAddrs, err := net.DefaultResolver.LookupIP(ctx, "ip", host)
if err != nil {
return []netip.Addr{}, err
} else if len(ipAddrs) == 0 {
return []netip.Addr{}, ErrIPNotFound
}
addrs := make([]netip.Addr, 0, len(ipAddrs))
for _, ipAddr := range ipAddrs {
addrs = append(addrs, nnip.IpToAddr(ipAddr))
}
rand.Shuffle(len(addrs), func(i, j int) {
addrs[i], addrs[j] = addrs[j], addrs[i]
})
return addrs, nil
}
return []netip.Addr{}, ErrIPNotFound
}
func LookupIP(ctx context.Context, host string) ([]netip.Addr, error) {
return LookupIPWithResolver(ctx, host, DefaultResolver)
}
func LookupIPv4(ctx context.Context, host string) ([]netip.Addr, error) {
return LookupIPv4WithResolver(ctx, host, DefaultResolver)
}
func LookupIPv6(ctx context.Context, host string) ([]netip.Addr, error) {
return LookupIPv6WithResolver(ctx, host, DefaultResolver)
}
func LookupIPv6ProxyServerHost(ctx context.Context, host string) ([]netip.Addr, error) { func LookupIPv6ProxyServerHost(ctx context.Context, host string) ([]netip.Addr, error) {
if ProxyServerHostResolver != nil { if ProxyServerHostResolver != nil {
return LookupIPv6WithResolver(ctx, host, ProxyServerHostResolver) return LookupIPv6WithResolver(ctx, host, ProxyServerHostResolver)

View file

@ -3,6 +3,7 @@ package dns
import ( import (
"context" "context"
"errors" "errors"
"fmt"
"go.uber.org/atomic" "go.uber.org/atomic"
"math/rand" "math/rand"
"net/netip" "net/netip"
@ -93,39 +94,47 @@ func (r *Resolver) LookupIP(ctx context.Context, host string) (ips []netip.Addr,
return ips, nil return ips, nil
} }
func (r *Resolver) LookupIPv4(ctx context.Context, host string) (ips []netip.Addr, err error) {
return r.lookupIP(ctx, host, D.TypeA)
}
func (r *Resolver) LookupIPv6(ctx context.Context, host string) (ips []netip.Addr, err error) {
return r.lookupIP(ctx, host, D.TypeAAAA)
}
// ResolveIP request with TypeA and TypeAAAA, priority return TypeA // ResolveIP request with TypeA and TypeAAAA, priority return TypeA
func (r *Resolver) ResolveIP(ctx context.Context, host string) (ip netip.Addr, err error) { func (r *Resolver) ResolveIP(ctx context.Context, host string) (ip netip.Addr, err error) {
if ips, err := r.LookupIPPrimaryIPv4(ctx, host); err == nil { ips, err := r.LookupIPPrimaryIPv4(ctx, host)
return ips[rand.Intn(len(ips))], nil if err != nil {
} else {
return netip.Addr{}, err return netip.Addr{}, err
} else if len(ips) == 0 {
return netip.Addr{}, fmt.Errorf("%w: %s", resolver.ErrIPNotFound, host)
} }
return ips[rand.Intn(len(ips))], nil
}
// LookupIPv4 request with TypeA
func (r *Resolver) LookupIPv4(ctx context.Context, host string) ([]netip.Addr, error) {
return r.lookupIP(ctx, host, D.TypeA)
} }
// ResolveIPv4 request with TypeA // ResolveIPv4 request with TypeA
func (r *Resolver) ResolveIPv4(ctx context.Context, host string) (ip netip.Addr, err error) { func (r *Resolver) ResolveIPv4(ctx context.Context, host string) (ip netip.Addr, err error) {
if ips, err := r.LookupIPv4(ctx, host); err == nil { ips, err := r.lookupIP(ctx, host, D.TypeA)
return ips[rand.Intn(len(ips))], nil if err != nil {
} else {
return netip.Addr{}, err return netip.Addr{}, err
} else if len(ips) == 0 {
return netip.Addr{}, fmt.Errorf("%w: %s", resolver.ErrIPNotFound, host)
} }
return ips[rand.Intn(len(ips))], nil
}
// LookupIPv6 request with TypeAAAA
func (r *Resolver) LookupIPv6(ctx context.Context, host string) ([]netip.Addr, error) {
return r.lookupIP(ctx, host, D.TypeAAAA)
} }
// ResolveIPv6 request with TypeAAAA // ResolveIPv6 request with TypeAAAA
func (r *Resolver) ResolveIPv6(ctx context.Context, host string) (ip netip.Addr, err error) { func (r *Resolver) ResolveIPv6(ctx context.Context, host string) (ip netip.Addr, err error) {
if ips, err := r.LookupIPv6(ctx, host); err == nil { ips, err := r.lookupIP(ctx, host, D.TypeAAAA)
return ips[rand.Intn(len(ips))], nil if err != nil {
} else {
return netip.Addr{}, err return netip.Addr{}, err
} else if len(ips) == 0 {
return netip.Addr{}, fmt.Errorf("%w: %s", resolver.ErrIPNotFound, host)
} }
return ips[rand.Intn(len(ips))], nil
} }
func (r *Resolver) shouldIPFallback(ip netip.Addr) bool { func (r *Resolver) shouldIPFallback(ip netip.Addr) bool {