diff --git a/config/config.go b/config/config.go index e43006a7..d0260b86 100644 --- a/config/config.go +++ b/config/config.go @@ -441,21 +441,21 @@ func parseHosts(cfg *RawConfig) (*trie.Trie, error) { return tree, nil } -func hostWithDefaultPort(host string, defPort string) (string, string, error) { +func hostWithDefaultPort(host string, defPort string) (string, error) { if !strings.Contains(host, ":") { host += ":" } hostname, port, err := net.SplitHostPort(host) if err != nil { - return "", "", err + return "", err } if port == "" { port = defPort } - return net.JoinHostPort(hostname, port), hostname, nil + return net.JoinHostPort(hostname, port), nil } func parseNameServer(servers []string) ([]dns.NameServer, error) { @@ -471,21 +471,20 @@ func parseNameServer(servers []string) ([]dns.NameServer, error) { return nil, fmt.Errorf("DNS NameServer[%d] format error: %s", idx, err.Error()) } - var addr, dnsNetType, host string + var addr, dnsNetType string switch u.Scheme { case "udp": - addr, host, err = hostWithDefaultPort(u.Host, "53") + addr, err = hostWithDefaultPort(u.Host, "53") dnsNetType = "" // UDP case "tcp": - addr, host, err = hostWithDefaultPort(u.Host, "53") + addr, err = hostWithDefaultPort(u.Host, "53") dnsNetType = "tcp" // TCP case "tls": - addr, host, err = hostWithDefaultPort(u.Host, "853") + addr, err = hostWithDefaultPort(u.Host, "853") dnsNetType = "tcp-tls" // DNS over TLS case "https": clearURL := url.URL{Scheme: "https", Host: u.Host, Path: u.Path} addr = clearURL.String() - _, host, err = hostWithDefaultPort(u.Host, "853") dnsNetType = "https" // DNS over HTTPS default: return nil, fmt.Errorf("DNS NameServer[%d] unsupport scheme: %s", idx, u.Scheme) @@ -500,7 +499,6 @@ func parseNameServer(servers []string) ([]dns.NameServer, error) { dns.NameServer{ Net: dnsNetType, Addr: addr, - Host: host, }, ) } @@ -552,7 +550,8 @@ func parseDNS(cfg RawDNS) (*DNS, error) { } // check default nameserver is pure ip addr for _, ns := range dnsCfg.DefaultNameserver { - if net.ParseIP(ns.Host) == nil { + host, _, err := net.SplitHostPort(ns.Addr) + if err != nil || net.ParseIP(host) == nil { return nil, errors.New("default nameserver should be pure IP") } } diff --git a/dns/client.go b/dns/client.go index 6341b657..3546adbf 100644 --- a/dns/client.go +++ b/dns/client.go @@ -2,6 +2,8 @@ package dns import ( "context" + "fmt" + "net" "strings" "github.com/Dreamacro/clash/component/dialer" @@ -12,7 +14,7 @@ import ( type client struct { *D.Client r *Resolver - addr string + port string host string } @@ -21,18 +23,24 @@ func (c *client) Exchange(m *D.Msg) (msg *D.Msg, err error) { } func (c *client) ExchangeContext(ctx context.Context, m *D.Msg) (msg *D.Msg, err error) { - network := "udp" - if strings.HasPrefix(c.Client.Net, "tcp") { - network = "tcp" - } - - ip, err := c.r.ResolveIP(c.host) - if err != nil { - return nil, err + var ip net.IP + if c.r == nil { + // a default ip dns + ip = net.ParseIP(c.host) + } else { + var err error + if ip, err = c.r.ResolveIP(c.host); err != nil { + println("?") + return nil, fmt.Errorf("use default dns resolve failed: %w", err) + } } d := dialer.Dialer() if dialer.DialHook != nil { + network := "udp" + if strings.HasPrefix(c.Client.Net, "tcp") { + network = "tcp" + } dialer.DialHook(d, network, ip) } @@ -46,7 +54,7 @@ func (c *client) ExchangeContext(ctx context.Context, m *D.Msg) (msg *D.Msg, err } ch := make(chan result, 1) go func() { - msg, _, err := c.Client.Exchange(m, c.addr) + msg, _, err := c.Client.Exchange(m, net.JoinHostPort(ip.String(), c.port)) ch <- result{msg, err} }() diff --git a/dns/resolver.go b/dns/resolver.go index 7d5fbc9c..fefdafdc 100644 --- a/dns/resolver.go +++ b/dns/resolver.go @@ -263,7 +263,6 @@ func (r *Resolver) asyncExchange(client []dnsClient, msg *D.Msg) <-chan *result type NameServer struct { Net string Addr string - Host string } type FallbackFilter struct { diff --git a/dns/util.go b/dns/util.go index 2cf0cd9b..00ac4566 100644 --- a/dns/util.go +++ b/dns/util.go @@ -4,6 +4,7 @@ import ( "crypto/tls" "encoding/json" "errors" + "net" "time" "github.com/Dreamacro/clash/common/cache" @@ -125,6 +126,7 @@ func transform(servers []NameServer, resolver *Resolver) []dnsClient { continue } + host, port, _ := net.SplitHostPort(s.Addr) ret = append(ret, &client{ Client: &D.Client{ Net: s.Net, @@ -136,8 +138,9 @@ func transform(servers []NameServer, resolver *Resolver) []dnsClient { UDPSize: 4096, Timeout: 5 * time.Second, }, - addr: s.Addr, - host: s.Host, + port: port, + host: host, + r: resolver, }) } return ret