diff --git a/config/config.go b/config/config.go index 8b918dd0..8b1ed89c 100644 --- a/config/config.go +++ b/config/config.go @@ -477,6 +477,10 @@ func parseNameServer(servers []string) ([]dns.NameServer, error) { return nil, fmt.Errorf("DNS NameServer[%d] format error: %s", idx, err.Error()) } + // parse with specific interface + // .e.g 10.0.0.1#en0 + interfaceName := u.Fragment + var addr, dnsNetType string switch u.Scheme { case "udp": @@ -506,8 +510,9 @@ func parseNameServer(servers []string) ([]dns.NameServer, error) { nameservers = append( nameservers, dns.NameServer{ - Net: dnsNetType, - Addr: addr, + Net: dnsNetType, + Addr: addr, + Interface: interfaceName, }, ) } diff --git a/dns/doh.go b/dns/doh.go index 94312355..99c22cb1 100644 --- a/dns/doh.go +++ b/dns/doh.go @@ -79,7 +79,7 @@ func (dc *dohClient) doRequest(req *http.Request) (msg *D.Msg, err error) { return msg, err } -func newDoHClient(url string, r *Resolver) *dohClient { +func newDoHClient(url, iface string, r *Resolver) *dohClient { return &dohClient{ url: url, transport: &http.Transport{ @@ -95,7 +95,12 @@ func newDoHClient(url string, r *Resolver) *dohClient { return nil, err } - return dialer.DialContext(ctx, "tcp", net.JoinHostPort(ip.String(), port)) + options := []dialer.Option{} + if iface != "" { + options = append(options, dialer.WithInterface(iface)) + } + + return dialer.DialContext(ctx, "tcp", net.JoinHostPort(ip.String(), port), options...) }, }, } diff --git a/dns/util.go b/dns/util.go index d11870f8..d25f5731 100644 --- a/dns/util.go +++ b/dns/util.go @@ -51,7 +51,7 @@ func transform(servers []NameServer, resolver *Resolver) []dnsClient { for _, s := range servers { switch s.Net { case "https": - ret = append(ret, newDoHClient(s.Addr, resolver)) + ret = append(ret, newDoHClient(s.Addr, s.Interface, resolver)) continue case "dhcp": ret = append(ret, newDHCPClient(s.Addr))