mirror of
https://github.com/v2fly/v2ray-core.git
synced 2025-01-02 07:26:24 -05:00
Feat: routing and freedom outbound ignore Fake DNS (#696)
Turn off fake DNS for request sent from Routing and Freedom outbound. Fake DNS now only apply to DNS outbound. This is important for Android, where VPN service take over all system DNS traffic and pass it to core. "UseIp" option can be used in Freedom outbound to avoid getting fake IP and fail connection. Co-authored-by: loyalsoldier <10487845+Loyalsoldier@users.noreply.github.com>
This commit is contained in:
parent
232ba8c26f
commit
afb8385a7e
@ -8,6 +8,7 @@ package dns
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/v2fly/v2ray-core/v4/app/router"
|
||||
@ -105,6 +106,7 @@ func New(ctx context.Context, config *Config) (*DNS, error) {
|
||||
clients = append(clients, client)
|
||||
}
|
||||
|
||||
// If there is no DNS client in config, add a `localhost` DNS client
|
||||
if len(clients) == 0 {
|
||||
clients = append(clients, NewLocalDNSClient())
|
||||
}
|
||||
@ -141,36 +143,13 @@ func (s *DNS) IsOwnLink(ctx context.Context) bool {
|
||||
}
|
||||
|
||||
// LookupIP implements dns.Client.
|
||||
func (s *DNS) LookupIP(domain string) ([]net.IP, error) {
|
||||
return s.lookupIPInternal(domain, IPOption{
|
||||
IPv4Enable: true,
|
||||
IPv6Enable: true,
|
||||
})
|
||||
}
|
||||
|
||||
// LookupIPv4 implements dns.IPv4Lookup.
|
||||
func (s *DNS) LookupIPv4(domain string) ([]net.IP, error) {
|
||||
return s.lookupIPInternal(domain, IPOption{
|
||||
IPv4Enable: true,
|
||||
IPv6Enable: false,
|
||||
})
|
||||
}
|
||||
|
||||
// LookupIPv6 implements dns.IPv6Lookup.
|
||||
func (s *DNS) LookupIPv6(domain string) ([]net.IP, error) {
|
||||
return s.lookupIPInternal(domain, IPOption{
|
||||
IPv4Enable: false,
|
||||
IPv6Enable: true,
|
||||
})
|
||||
}
|
||||
|
||||
func (s *DNS) lookupIPInternal(domain string, option IPOption) ([]net.IP, error) {
|
||||
func (s *DNS) LookupIP(domain string, option dns.IPOption) ([]net.IP, error) {
|
||||
if domain == "" {
|
||||
return nil, newError("empty domain name")
|
||||
}
|
||||
|
||||
// Normalize the FQDN form query
|
||||
if domain[len(domain)-1] == '.' {
|
||||
if strings.HasSuffix(domain, ".") {
|
||||
domain = domain[:len(domain)-1]
|
||||
}
|
||||
|
||||
@ -192,6 +171,10 @@ func (s *DNS) lookupIPInternal(domain string, option IPOption) ([]net.IP, error)
|
||||
errs := []error{}
|
||||
ctx := session.ContextWithInbound(s.ctx, &session.Inbound{Tag: s.tag})
|
||||
for _, client := range s.sortClients(domain) {
|
||||
if !option.FakeEnable && strings.EqualFold(client.Name(), "FakeDNS") {
|
||||
newError("skip DNS resolution for domain ", domain, " at server ", client.Name()).AtDebug().WriteToLog()
|
||||
continue
|
||||
}
|
||||
ips, err := client.QueryIP(ctx, domain, option)
|
||||
if len(ips) > 0 {
|
||||
return ips, nil
|
||||
|
@ -154,7 +154,11 @@ func TestUDPServerSubnet(t *testing.T) {
|
||||
|
||||
client := v.GetFeature(feature_dns.ClientType()).(feature_dns.Client)
|
||||
|
||||
ips, err := client.LookupIP("google.com")
|
||||
ips, err := client.LookupIP("google.com", feature_dns.IPOption{
|
||||
IPv4Enable: true,
|
||||
IPv6Enable: true,
|
||||
FakeEnable: false,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal("unexpected error: ", err)
|
||||
}
|
||||
@ -209,7 +213,11 @@ func TestUDPServer(t *testing.T) {
|
||||
client := v.GetFeature(feature_dns.ClientType()).(feature_dns.Client)
|
||||
|
||||
{
|
||||
ips, err := client.LookupIP("google.com")
|
||||
ips, err := client.LookupIP("google.com", feature_dns.IPOption{
|
||||
IPv4Enable: true,
|
||||
IPv6Enable: true,
|
||||
FakeEnable: false,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal("unexpected error: ", err)
|
||||
}
|
||||
@ -220,7 +228,11 @@ func TestUDPServer(t *testing.T) {
|
||||
}
|
||||
|
||||
{
|
||||
ips, err := client.LookupIP("facebook.com")
|
||||
ips, err := client.LookupIP("facebook.com", feature_dns.IPOption{
|
||||
IPv4Enable: true,
|
||||
IPv6Enable: true,
|
||||
FakeEnable: false,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal("unexpected error: ", err)
|
||||
}
|
||||
@ -231,7 +243,11 @@ func TestUDPServer(t *testing.T) {
|
||||
}
|
||||
|
||||
{
|
||||
_, err := client.LookupIP("notexist.google.com")
|
||||
_, err := client.LookupIP("notexist.google.com", feature_dns.IPOption{
|
||||
IPv4Enable: true,
|
||||
IPv6Enable: true,
|
||||
FakeEnable: false,
|
||||
})
|
||||
if err == nil {
|
||||
t.Fatal("nil error")
|
||||
}
|
||||
@ -241,8 +257,11 @@ func TestUDPServer(t *testing.T) {
|
||||
}
|
||||
|
||||
{
|
||||
clientv6 := client.(feature_dns.IPv6Lookup)
|
||||
ips, err := clientv6.LookupIPv6("ipv4only.google.com")
|
||||
ips, err := client.LookupIP("ipv4only.google.com", feature_dns.IPOption{
|
||||
IPv4Enable: false,
|
||||
IPv6Enable: true,
|
||||
FakeEnable: false,
|
||||
})
|
||||
if err != feature_dns.ErrEmptyResponse {
|
||||
t.Fatal("error: ", err)
|
||||
}
|
||||
@ -254,7 +273,11 @@ func TestUDPServer(t *testing.T) {
|
||||
dnsServer.Shutdown()
|
||||
|
||||
{
|
||||
ips, err := client.LookupIP("google.com")
|
||||
ips, err := client.LookupIP("google.com", feature_dns.IPOption{
|
||||
IPv4Enable: true,
|
||||
IPv6Enable: true,
|
||||
FakeEnable: false,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal("unexpected error: ", err)
|
||||
}
|
||||
@ -331,7 +354,11 @@ func TestPrioritizedDomain(t *testing.T) {
|
||||
startTime := time.Now()
|
||||
|
||||
{
|
||||
ips, err := client.LookupIP("google.com")
|
||||
ips, err := client.LookupIP("google.com", feature_dns.IPOption{
|
||||
IPv4Enable: true,
|
||||
IPv6Enable: true,
|
||||
FakeEnable: false,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal("unexpected error: ", err)
|
||||
}
|
||||
@ -390,10 +417,12 @@ func TestUDPServerIPv6(t *testing.T) {
|
||||
common.Must(err)
|
||||
|
||||
client := v.GetFeature(feature_dns.ClientType()).(feature_dns.Client)
|
||||
client6 := client.(feature_dns.IPv6Lookup)
|
||||
|
||||
{
|
||||
ips, err := client6.LookupIPv6("ipv6.google.com")
|
||||
ips, err := client.LookupIP("ipv6.google.com", feature_dns.IPOption{
|
||||
IPv4Enable: false,
|
||||
IPv6Enable: true,
|
||||
FakeEnable: false,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal("unexpected error: ", err)
|
||||
}
|
||||
@ -456,7 +485,11 @@ func TestStaticHostDomain(t *testing.T) {
|
||||
client := v.GetFeature(feature_dns.ClientType()).(feature_dns.Client)
|
||||
|
||||
{
|
||||
ips, err := client.LookupIP("example.com")
|
||||
ips, err := client.LookupIP("example.com", feature_dns.IPOption{
|
||||
IPv4Enable: true,
|
||||
IPv6Enable: true,
|
||||
FakeEnable: false,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal("unexpected error: ", err)
|
||||
}
|
||||
@ -563,7 +596,11 @@ func TestIPMatch(t *testing.T) {
|
||||
startTime := time.Now()
|
||||
|
||||
{
|
||||
ips, err := client.LookupIP("google.com")
|
||||
ips, err := client.LookupIP("google.com", feature_dns.IPOption{
|
||||
IPv4Enable: true,
|
||||
IPv6Enable: true,
|
||||
FakeEnable: false,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal("unexpected error: ", err)
|
||||
}
|
||||
@ -682,7 +719,11 @@ func TestLocalDomain(t *testing.T) {
|
||||
startTime := time.Now()
|
||||
|
||||
{ // Will match dotless:
|
||||
ips, err := client.LookupIP("hostname")
|
||||
ips, err := client.LookupIP("hostname", feature_dns.IPOption{
|
||||
IPv4Enable: true,
|
||||
IPv6Enable: true,
|
||||
FakeEnable: false,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal("unexpected error: ", err)
|
||||
}
|
||||
@ -693,7 +734,11 @@ func TestLocalDomain(t *testing.T) {
|
||||
}
|
||||
|
||||
{ // Will match domain:local
|
||||
ips, err := client.LookupIP("hostname.local")
|
||||
ips, err := client.LookupIP("hostname.local", feature_dns.IPOption{
|
||||
IPv4Enable: true,
|
||||
IPv6Enable: true,
|
||||
FakeEnable: false,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal("unexpected error: ", err)
|
||||
}
|
||||
@ -704,7 +749,11 @@ func TestLocalDomain(t *testing.T) {
|
||||
}
|
||||
|
||||
{ // Will match static ip
|
||||
ips, err := client.LookupIP("hostnamestatic")
|
||||
ips, err := client.LookupIP("hostnamestatic", feature_dns.IPOption{
|
||||
IPv4Enable: true,
|
||||
IPv6Enable: true,
|
||||
FakeEnable: false,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal("unexpected error: ", err)
|
||||
}
|
||||
@ -715,7 +764,11 @@ func TestLocalDomain(t *testing.T) {
|
||||
}
|
||||
|
||||
{ // Will match domain replacing
|
||||
ips, err := client.LookupIP("hostnamealias")
|
||||
ips, err := client.LookupIP("hostnamealias", feature_dns.IPOption{
|
||||
IPv4Enable: true,
|
||||
IPv6Enable: true,
|
||||
FakeEnable: false,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal("unexpected error: ", err)
|
||||
}
|
||||
@ -726,7 +779,11 @@ func TestLocalDomain(t *testing.T) {
|
||||
}
|
||||
|
||||
{ // Will match dotless:localhost, but not expectIPs: 127.0.0.2, 127.0.0.3, then matches at dotless:
|
||||
ips, err := client.LookupIP("localhost")
|
||||
ips, err := client.LookupIP("localhost", feature_dns.IPOption{
|
||||
IPv4Enable: true,
|
||||
IPv6Enable: true,
|
||||
FakeEnable: false,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal("unexpected error: ", err)
|
||||
}
|
||||
@ -737,7 +794,11 @@ func TestLocalDomain(t *testing.T) {
|
||||
}
|
||||
|
||||
{ // Will match dotless:localhost, and expectIPs: 127.0.0.2, 127.0.0.3
|
||||
ips, err := client.LookupIP("localhost-a")
|
||||
ips, err := client.LookupIP("localhost-a", feature_dns.IPOption{
|
||||
IPv4Enable: true,
|
||||
IPv6Enable: true,
|
||||
FakeEnable: false,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal("unexpected error: ", err)
|
||||
}
|
||||
@ -748,7 +809,11 @@ func TestLocalDomain(t *testing.T) {
|
||||
}
|
||||
|
||||
{ // Will match dotless:localhost, and expectIPs: 127.0.0.2, 127.0.0.3
|
||||
ips, err := client.LookupIP("localhost-b")
|
||||
ips, err := client.LookupIP("localhost-b", feature_dns.IPOption{
|
||||
IPv4Enable: true,
|
||||
IPv6Enable: true,
|
||||
FakeEnable: false,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal("unexpected error: ", err)
|
||||
}
|
||||
@ -759,7 +824,11 @@ func TestLocalDomain(t *testing.T) {
|
||||
}
|
||||
|
||||
{ // Will match dotless:
|
||||
ips, err := client.LookupIP("Mijia Cloud")
|
||||
ips, err := client.LookupIP("Mijia Cloud", feature_dns.IPOption{
|
||||
IPv4Enable: true,
|
||||
IPv6Enable: true,
|
||||
FakeEnable: false,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal("unexpected error: ", err)
|
||||
}
|
||||
@ -921,7 +990,11 @@ func TestMultiMatchPrioritizedDomain(t *testing.T) {
|
||||
startTime := time.Now()
|
||||
|
||||
{ // Will match server 1,2 and server 1 returns expected ip
|
||||
ips, err := client.LookupIP("google.com")
|
||||
ips, err := client.LookupIP("google.com", feature_dns.IPOption{
|
||||
IPv4Enable: true,
|
||||
IPv6Enable: true,
|
||||
FakeEnable: false,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal("unexpected error: ", err)
|
||||
}
|
||||
@ -932,8 +1005,11 @@ func TestMultiMatchPrioritizedDomain(t *testing.T) {
|
||||
}
|
||||
|
||||
{ // Will match server 1,2 and server 1 returns unexpected ip, then server 2 returns expected one
|
||||
clientv4 := client.(feature_dns.IPv4Lookup)
|
||||
ips, err := clientv4.LookupIPv4("ipv6.google.com")
|
||||
ips, err := client.LookupIP("ipv6.google.com", feature_dns.IPOption{
|
||||
IPv4Enable: true,
|
||||
IPv6Enable: false,
|
||||
FakeEnable: false,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal("unexpected error: ", err)
|
||||
}
|
||||
@ -944,7 +1020,11 @@ func TestMultiMatchPrioritizedDomain(t *testing.T) {
|
||||
}
|
||||
|
||||
{ // Will match server 3,1,2 and server 3 returns expected one
|
||||
ips, err := client.LookupIP("api.google.com")
|
||||
ips, err := client.LookupIP("api.google.com", feature_dns.IPOption{
|
||||
IPv4Enable: true,
|
||||
IPv6Enable: true,
|
||||
FakeEnable: false,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal("unexpected error: ", err)
|
||||
}
|
||||
@ -955,7 +1035,11 @@ func TestMultiMatchPrioritizedDomain(t *testing.T) {
|
||||
}
|
||||
|
||||
{ // Will match server 4,3,1,2 and server 4 returns expected one
|
||||
ips, err := client.LookupIP("v2.api.google.com")
|
||||
ips, err := client.LookupIP("v2.api.google.com", feature_dns.IPOption{
|
||||
IPv4Enable: true,
|
||||
IPv6Enable: true,
|
||||
FakeEnable: false,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal("unexpected error: ", err)
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ package dns
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"golang.org/x/net/dns/dnsmessage"
|
||||
@ -16,7 +17,7 @@ import (
|
||||
|
||||
// Fqdn normalize domain make sure it ends with '.'
|
||||
func Fqdn(domain string) string {
|
||||
if len(domain) > 0 && domain[len(domain)-1] == '.' {
|
||||
if len(domain) > 0 && strings.HasSuffix(domain, ".") {
|
||||
return domain
|
||||
}
|
||||
return domain + "."
|
||||
@ -115,7 +116,7 @@ func genEDNS0Options(clientIP net.IP) *dnsmessage.Resource {
|
||||
return opt
|
||||
}
|
||||
|
||||
func buildReqMsgs(domain string, option IPOption, reqIDGen func() uint16, reqOpts *dnsmessage.Resource) []*dnsRequest {
|
||||
func buildReqMsgs(domain string, option dns_feature.IPOption, reqIDGen func() uint16, reqOpts *dnsmessage.Resource) []*dnsRequest {
|
||||
qA := dnsmessage.Question{
|
||||
Name: dnsmessage.MustNewName(domain),
|
||||
Type: dnsmessage.TypeA,
|
||||
|
@ -13,6 +13,7 @@ import (
|
||||
|
||||
"github.com/v2fly/v2ray-core/v4/common"
|
||||
"github.com/v2fly/v2ray-core/v4/common/net"
|
||||
dns_feature "github.com/v2fly/v2ray-core/v4/features/dns"
|
||||
)
|
||||
|
||||
func Test_parseResponse(t *testing.T) {
|
||||
@ -95,7 +96,7 @@ func Test_buildReqMsgs(t *testing.T) {
|
||||
}
|
||||
type args struct {
|
||||
domain string
|
||||
option IPOption
|
||||
option dns_feature.IPOption
|
||||
reqOpts *dnsmessage.Resource
|
||||
}
|
||||
tests := []struct {
|
||||
@ -103,10 +104,26 @@ func Test_buildReqMsgs(t *testing.T) {
|
||||
args args
|
||||
want int
|
||||
}{
|
||||
{"dual stack", args{"test.com", IPOption{true, true}, nil}, 2},
|
||||
{"ipv4 only", args{"test.com", IPOption{true, false}, nil}, 1},
|
||||
{"ipv6 only", args{"test.com", IPOption{false, true}, nil}, 1},
|
||||
{"none/error", args{"test.com", IPOption{false, false}, nil}, 0},
|
||||
{"dual stack", args{"test.com", dns_feature.IPOption{
|
||||
IPv4Enable: true,
|
||||
IPv6Enable: true,
|
||||
FakeEnable: false,
|
||||
}, nil}, 2},
|
||||
{"ipv4 only", args{"test.com", dns_feature.IPOption{
|
||||
IPv4Enable: true,
|
||||
IPv6Enable: false,
|
||||
FakeEnable: false,
|
||||
}, nil}, 1},
|
||||
{"ipv6 only", args{"test.com", dns_feature.IPOption{
|
||||
IPv4Enable: false,
|
||||
IPv6Enable: true,
|
||||
FakeEnable: false,
|
||||
}, nil}, 1},
|
||||
{"none/error", args{"test.com", dns_feature.IPOption{
|
||||
IPv4Enable: false,
|
||||
IPv6Enable: false,
|
||||
FakeEnable: false,
|
||||
}, nil}, 0},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
|
@ -7,6 +7,7 @@ import (
|
||||
"github.com/v2fly/v2ray-core/v4/common/net"
|
||||
"github.com/v2fly/v2ray-core/v4/common/strmatcher"
|
||||
"github.com/v2fly/v2ray-core/v4/features"
|
||||
"github.com/v2fly/v2ray-core/v4/features/dns"
|
||||
)
|
||||
|
||||
// StaticHosts represents static domain-ip mapping in DNS server.
|
||||
@ -75,7 +76,7 @@ func NewStaticHosts(hosts []*Config_HostMapping, legacy map[string]*net.IPOrDoma
|
||||
return sh, nil
|
||||
}
|
||||
|
||||
func filterIP(ips []net.Address, option IPOption) []net.Address {
|
||||
func filterIP(ips []net.Address, option dns.IPOption) []net.Address {
|
||||
filtered := make([]net.Address, 0, len(ips))
|
||||
for _, ip := range ips {
|
||||
if (ip.Family().IsIPv4() && option.IPv4Enable) || (ip.Family().IsIPv6() && option.IPv6Enable) {
|
||||
@ -93,7 +94,7 @@ func (h *StaticHosts) lookupInternal(domain string) []net.Address {
|
||||
return ips
|
||||
}
|
||||
|
||||
func (h *StaticHosts) lookup(domain string, option IPOption, maxDepth int) []net.Address {
|
||||
func (h *StaticHosts) lookup(domain string, option dns.IPOption, maxDepth int) []net.Address {
|
||||
switch addrs := h.lookupInternal(domain); {
|
||||
case len(addrs) == 0: // Not recorded in static hosts, return nil
|
||||
return nil
|
||||
@ -111,6 +112,6 @@ func (h *StaticHosts) lookup(domain string, option IPOption, maxDepth int) []net
|
||||
}
|
||||
|
||||
// Lookup returns IP addresses or proxied domain for the given domain, if exists in this StaticHosts.
|
||||
func (h *StaticHosts) Lookup(domain string, option IPOption) []net.Address {
|
||||
func (h *StaticHosts) Lookup(domain string, option dns.IPOption) []net.Address {
|
||||
return h.lookup(domain, option, 5)
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ import (
|
||||
. "github.com/v2fly/v2ray-core/v4/app/dns"
|
||||
"github.com/v2fly/v2ray-core/v4/common"
|
||||
"github.com/v2fly/v2ray-core/v4/common/net"
|
||||
"github.com/v2fly/v2ray-core/v4/features/dns"
|
||||
)
|
||||
|
||||
func TestStaticHosts(t *testing.T) {
|
||||
@ -39,7 +40,7 @@ func TestStaticHosts(t *testing.T) {
|
||||
common.Must(err)
|
||||
|
||||
{
|
||||
ips := hosts.Lookup("v2fly.org", IPOption{
|
||||
ips := hosts.Lookup("v2fly.org", dns.IPOption{
|
||||
IPv4Enable: true,
|
||||
IPv6Enable: true,
|
||||
})
|
||||
@ -52,7 +53,7 @@ func TestStaticHosts(t *testing.T) {
|
||||
}
|
||||
|
||||
{
|
||||
ips := hosts.Lookup("www.v2ray.cn", IPOption{
|
||||
ips := hosts.Lookup("www.v2ray.cn", dns.IPOption{
|
||||
IPv4Enable: true,
|
||||
IPv6Enable: true,
|
||||
})
|
||||
@ -65,7 +66,7 @@ func TestStaticHosts(t *testing.T) {
|
||||
}
|
||||
|
||||
{
|
||||
ips := hosts.Lookup("baidu.com", IPOption{
|
||||
ips := hosts.Lookup("baidu.com", dns.IPOption{
|
||||
IPv4Enable: false,
|
||||
IPv6Enable: true,
|
||||
})
|
||||
|
@ -5,6 +5,7 @@ package dns
|
||||
import (
|
||||
"context"
|
||||
"net/url"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
core "github.com/v2fly/v2ray-core/v4"
|
||||
@ -12,21 +13,16 @@ import (
|
||||
"github.com/v2fly/v2ray-core/v4/common/errors"
|
||||
"github.com/v2fly/v2ray-core/v4/common/net"
|
||||
"github.com/v2fly/v2ray-core/v4/common/strmatcher"
|
||||
"github.com/v2fly/v2ray-core/v4/features/dns"
|
||||
"github.com/v2fly/v2ray-core/v4/features/routing"
|
||||
)
|
||||
|
||||
// IPOption is an object for IP query options.
|
||||
type IPOption struct {
|
||||
IPv4Enable bool
|
||||
IPv6Enable bool
|
||||
}
|
||||
|
||||
// Server is the interface for Name Server.
|
||||
type Server interface {
|
||||
// Name of the Client.
|
||||
Name() string
|
||||
// QueryIP sends IP queries to its configured server.
|
||||
QueryIP(ctx context.Context, domain string, clientIP net.IP, option IPOption) ([]net.IP, error)
|
||||
QueryIP(ctx context.Context, domain string, clientIP net.IP, option dns.IPOption) ([]net.IP, error)
|
||||
}
|
||||
|
||||
// Client is the interface for DNS client.
|
||||
@ -47,15 +43,15 @@ func NewServer(dest net.Destination, dispatcher routing.Dispatcher) (Server, err
|
||||
return nil, err
|
||||
}
|
||||
switch {
|
||||
case u.String() == "localhost":
|
||||
case strings.EqualFold(u.String(), "localhost"):
|
||||
return NewLocalNameServer(), nil
|
||||
case u.Scheme == "https": // DOH Remote mode
|
||||
case strings.EqualFold(u.Scheme, "https"): // DOH Remote mode
|
||||
return NewDoHNameServer(u, dispatcher)
|
||||
case u.Scheme == "https+local": // DOH Local mode
|
||||
case strings.EqualFold(u.Scheme, "https+local"): // DOH Local mode
|
||||
return NewDoHLocalNameServer(u), nil
|
||||
case u.Scheme == "quic+local": // DNS-over-QUIC Local mode
|
||||
case strings.EqualFold(u.Scheme, "quic+local"): // DNS-over-QUIC Local mode
|
||||
return NewQUICNameServer(u)
|
||||
case u.String() == "fakedns":
|
||||
case strings.EqualFold(u.String(), "fakedns"):
|
||||
return NewFakeDNSServer(), nil
|
||||
}
|
||||
}
|
||||
@ -173,7 +169,7 @@ func (c *Client) Name() string {
|
||||
}
|
||||
|
||||
// QueryIP send DNS query to the name server with the client's IP.
|
||||
func (c *Client) QueryIP(ctx context.Context, domain string, option IPOption) ([]net.IP, error) {
|
||||
func (c *Client) QueryIP(ctx context.Context, domain string, option dns.IPOption) ([]net.IP, error) {
|
||||
ctx, cancel := context.WithTimeout(ctx, 4*time.Second)
|
||||
ips, err := c.server.QueryIP(ctx, domain, c.clientIP, option)
|
||||
cancel()
|
||||
|
@ -207,7 +207,7 @@ func (s *DoHNameServer) newReqID() uint16 {
|
||||
return uint16(atomic.AddUint32(&s.reqID, 1))
|
||||
}
|
||||
|
||||
func (s *DoHNameServer) sendQuery(ctx context.Context, domain string, clientIP net.IP, option IPOption) {
|
||||
func (s *DoHNameServer) sendQuery(ctx context.Context, domain string, clientIP net.IP, option dns_feature.IPOption) {
|
||||
newError(s.name, " querying: ", domain).AtInfo().WriteToLog(session.ExportIDToError(ctx))
|
||||
|
||||
reqs := buildReqMsgs(domain, option, s.newReqID, genEDNS0Options(clientIP))
|
||||
@ -286,7 +286,7 @@ func (s *DoHNameServer) dohHTTPSContext(ctx context.Context, b []byte) ([]byte,
|
||||
return ioutil.ReadAll(resp.Body)
|
||||
}
|
||||
|
||||
func (s *DoHNameServer) findIPsForDomain(domain string, option IPOption) ([]net.IP, error) {
|
||||
func (s *DoHNameServer) findIPsForDomain(domain string, option dns_feature.IPOption) ([]net.IP, error) {
|
||||
s.RLock()
|
||||
record, found := s.ips[domain]
|
||||
s.RUnlock()
|
||||
@ -329,7 +329,7 @@ func (s *DoHNameServer) findIPsForDomain(domain string, option IPOption) ([]net.
|
||||
}
|
||||
|
||||
// QueryIP implements Server.
|
||||
func (s *DoHNameServer) QueryIP(ctx context.Context, domain string, clientIP net.IP, option IPOption) ([]net.IP, error) { // nolint: dupl
|
||||
func (s *DoHNameServer) QueryIP(ctx context.Context, domain string, clientIP net.IP, option dns_feature.IPOption) ([]net.IP, error) { // nolint: dupl
|
||||
fqdn := Fqdn(domain)
|
||||
|
||||
ips, err := s.findIPsForDomain(fqdn, option)
|
||||
|
@ -22,7 +22,7 @@ func (FakeDNSServer) Name() string {
|
||||
return "FakeDNS"
|
||||
}
|
||||
|
||||
func (f *FakeDNSServer) QueryIP(ctx context.Context, domain string, _ net.IP, _ IPOption) ([]net.IP, error) {
|
||||
func (f *FakeDNSServer) QueryIP(ctx context.Context, domain string, _ net.IP, _ dns.IPOption) ([]net.IP, error) {
|
||||
if f.fakeDNSEngine == nil {
|
||||
if err := core.RequireFeatures(ctx, func(fd dns.FakeDNSEngine) {
|
||||
f.fakeDNSEngine = fd
|
||||
@ -37,5 +37,7 @@ func (f *FakeDNSServer) QueryIP(ctx context.Context, domain string, _ net.IP, _
|
||||
return nil, newError("Unable to convert IP to net ip").Base(err).AtError()
|
||||
}
|
||||
|
||||
newError(f.Name(), " got answer: ", domain, " -> ", ips).AtInfo().WriteToLog()
|
||||
|
||||
return netIP, nil
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ import (
|
||||
"context"
|
||||
|
||||
"github.com/v2fly/v2ray-core/v4/common/net"
|
||||
"github.com/v2fly/v2ray-core/v4/features/dns"
|
||||
"github.com/v2fly/v2ray-core/v4/features/dns/localdns"
|
||||
)
|
||||
|
||||
@ -15,17 +16,9 @@ type LocalNameServer struct {
|
||||
}
|
||||
|
||||
// QueryIP implements Server.
|
||||
func (s *LocalNameServer) QueryIP(ctx context.Context, domain string, clientIP net.IP, option IPOption) ([]net.IP, error) {
|
||||
if option.IPv4Enable && option.IPv6Enable {
|
||||
return s.client.LookupIP(domain)
|
||||
}
|
||||
|
||||
if option.IPv4Enable {
|
||||
return s.client.LookupIPv4(domain)
|
||||
}
|
||||
|
||||
if option.IPv6Enable {
|
||||
return s.client.LookupIPv6(domain)
|
||||
func (s *LocalNameServer) QueryIP(_ context.Context, domain string, _ net.IP, option dns.IPOption) ([]net.IP, error) {
|
||||
if option.IPv4Enable || option.IPv6Enable {
|
||||
return s.client.LookupIP(domain, option)
|
||||
}
|
||||
|
||||
return nil, newError("neither IPv4 nor IPv6 is enabled")
|
||||
|
@ -8,12 +8,13 @@ import (
|
||||
. "github.com/v2fly/v2ray-core/v4/app/dns"
|
||||
"github.com/v2fly/v2ray-core/v4/common"
|
||||
"github.com/v2fly/v2ray-core/v4/common/net"
|
||||
"github.com/v2fly/v2ray-core/v4/features/dns"
|
||||
)
|
||||
|
||||
func TestLocalNameServer(t *testing.T) {
|
||||
s := NewLocalNameServer()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*2)
|
||||
ips, err := s.QueryIP(ctx, "google.com", net.IP{}, IPOption{
|
||||
ips, err := s.QueryIP(ctx, "google.com", net.IP{}, dns.IPOption{
|
||||
IPv4Enable: true,
|
||||
IPv6Enable: true,
|
||||
})
|
||||
|
@ -153,7 +153,7 @@ func (s *QUICNameServer) newReqID() uint16 {
|
||||
return uint16(atomic.AddUint32(&s.reqID, 1))
|
||||
}
|
||||
|
||||
func (s *QUICNameServer) sendQuery(ctx context.Context, domain string, clientIP net.IP, option IPOption) {
|
||||
func (s *QUICNameServer) sendQuery(ctx context.Context, domain string, clientIP net.IP, option dns_feature.IPOption) {
|
||||
newError(s.name, " querying: ", domain).AtInfo().WriteToLog(session.ExportIDToError(ctx))
|
||||
|
||||
reqs := buildReqMsgs(domain, option, s.newReqID, genEDNS0Options(clientIP))
|
||||
@ -223,7 +223,7 @@ func (s *QUICNameServer) sendQuery(ctx context.Context, domain string, clientIP
|
||||
}
|
||||
}
|
||||
|
||||
func (s *QUICNameServer) findIPsForDomain(domain string, option IPOption) ([]net.IP, error) {
|
||||
func (s *QUICNameServer) findIPsForDomain(domain string, option dns_feature.IPOption) ([]net.IP, error) {
|
||||
s.RLock()
|
||||
record, found := s.ips[domain]
|
||||
s.RUnlock()
|
||||
@ -266,7 +266,7 @@ func (s *QUICNameServer) findIPsForDomain(domain string, option IPOption) ([]net
|
||||
}
|
||||
|
||||
// QueryIP is called from dns.Server->queryIPTimeout
|
||||
func (s *QUICNameServer) QueryIP(ctx context.Context, domain string, clientIP net.IP, option IPOption) ([]net.IP, error) {
|
||||
func (s *QUICNameServer) QueryIP(ctx context.Context, domain string, clientIP net.IP, option dns_feature.IPOption) ([]net.IP, error) {
|
||||
fqdn := Fqdn(domain)
|
||||
|
||||
ips, err := s.findIPsForDomain(fqdn, option)
|
||||
|
@ -9,6 +9,7 @@ import (
|
||||
. "github.com/v2fly/v2ray-core/v4/app/dns"
|
||||
"github.com/v2fly/v2ray-core/v4/common"
|
||||
"github.com/v2fly/v2ray-core/v4/common/net"
|
||||
dns_feature "github.com/v2fly/v2ray-core/v4/features/dns"
|
||||
)
|
||||
|
||||
func TestQUICNameServer(t *testing.T) {
|
||||
@ -17,7 +18,7 @@ func TestQUICNameServer(t *testing.T) {
|
||||
s, err := NewQUICNameServer(url)
|
||||
common.Must(err)
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*2)
|
||||
ips, err := s.QueryIP(ctx, "google.com", net.IP(nil), IPOption{
|
||||
ips, err := s.QueryIP(ctx, "google.com", net.IP(nil), dns_feature.IPOption{
|
||||
IPv4Enable: true,
|
||||
IPv6Enable: true,
|
||||
})
|
||||
|
@ -55,7 +55,7 @@ func NewClassicNameServer(address net.Destination, dispatcher routing.Dispatcher
|
||||
Execute: s.Cleanup,
|
||||
}
|
||||
s.udpServer = udp.NewDispatcher(dispatcher, s.HandleResponse)
|
||||
newError("DNS: created UDP client inited for ", address.NetAddr()).AtInfo().WriteToLog()
|
||||
newError("DNS: created UDP client initialized for ", address.NetAddr()).AtInfo().WriteToLog()
|
||||
return s
|
||||
}
|
||||
|
||||
@ -184,7 +184,7 @@ func (s *ClassicNameServer) addPendingRequest(req *dnsRequest) {
|
||||
s.requests[id] = *req
|
||||
}
|
||||
|
||||
func (s *ClassicNameServer) sendQuery(ctx context.Context, domain string, clientIP net.IP, option IPOption) {
|
||||
func (s *ClassicNameServer) sendQuery(ctx context.Context, domain string, clientIP net.IP, option dns_feature.IPOption) {
|
||||
newError(s.name, " querying DNS for: ", domain).AtDebug().WriteToLog(session.ExportIDToError(ctx))
|
||||
|
||||
reqs := buildReqMsgs(domain, option, s.newReqID, genEDNS0Options(clientIP))
|
||||
@ -203,7 +203,7 @@ func (s *ClassicNameServer) sendQuery(ctx context.Context, domain string, client
|
||||
}
|
||||
}
|
||||
|
||||
func (s *ClassicNameServer) findIPsForDomain(domain string, option IPOption) ([]net.IP, error) {
|
||||
func (s *ClassicNameServer) findIPsForDomain(domain string, option dns_feature.IPOption) ([]net.IP, error) {
|
||||
s.RLock()
|
||||
record, found := s.ips[domain]
|
||||
s.RUnlock()
|
||||
@ -242,7 +242,7 @@ func (s *ClassicNameServer) findIPsForDomain(domain string, option IPOption) ([]
|
||||
}
|
||||
|
||||
// QueryIP implements Server.
|
||||
func (s *ClassicNameServer) QueryIP(ctx context.Context, domain string, clientIP net.IP, option IPOption) ([]net.IP, error) {
|
||||
func (s *ClassicNameServer) QueryIP(ctx context.Context, domain string, clientIP net.IP, option dns_feature.IPOption) ([]net.IP, error) {
|
||||
fqdn := Fqdn(domain)
|
||||
|
||||
ips, err := s.findIPsForDomain(fqdn, option)
|
||||
|
@ -10,6 +10,7 @@ import (
|
||||
"github.com/v2fly/v2ray-core/v4/common"
|
||||
"github.com/v2fly/v2ray-core/v4/common/net"
|
||||
"github.com/v2fly/v2ray-core/v4/common/session"
|
||||
"github.com/v2fly/v2ray-core/v4/features/dns"
|
||||
"github.com/v2fly/v2ray-core/v4/features/outbound"
|
||||
routing_session "github.com/v2fly/v2ray-core/v4/features/routing/session"
|
||||
"github.com/v2fly/v2ray-core/v4/testing/mocks"
|
||||
@ -116,7 +117,11 @@ func TestIPOnDemand(t *testing.T) {
|
||||
defer mockCtl.Finish()
|
||||
|
||||
mockDNS := mocks.NewDNSClient(mockCtl)
|
||||
mockDNS.EXPECT().LookupIP(gomock.Eq("v2fly.org")).Return([]net.IP{{192, 168, 0, 1}}, nil).AnyTimes()
|
||||
mockDNS.EXPECT().LookupIP(gomock.Eq("v2fly.org"), dns.IPOption{
|
||||
IPv4Enable: true,
|
||||
IPv6Enable: true,
|
||||
FakeEnable: false,
|
||||
}).Return([]net.IP{{192, 168, 0, 1}}, nil).AnyTimes()
|
||||
|
||||
r := new(Router)
|
||||
common.Must(r.Init(config, mockDNS, nil))
|
||||
@ -151,7 +156,11 @@ func TestIPIfNonMatchDomain(t *testing.T) {
|
||||
defer mockCtl.Finish()
|
||||
|
||||
mockDNS := mocks.NewDNSClient(mockCtl)
|
||||
mockDNS.EXPECT().LookupIP(gomock.Eq("v2fly.org")).Return([]net.IP{{192, 168, 0, 1}}, nil).AnyTimes()
|
||||
mockDNS.EXPECT().LookupIP(gomock.Eq("v2fly.org"), dns.IPOption{
|
||||
IPv4Enable: true,
|
||||
IPv6Enable: true,
|
||||
FakeEnable: false,
|
||||
}).Return([]net.IP{{192, 168, 0, 1}}, nil).AnyTimes()
|
||||
|
||||
r := new(Router)
|
||||
common.Must(r.Init(config, mockDNS, nil))
|
||||
|
@ -7,6 +7,13 @@ import (
|
||||
"github.com/v2fly/v2ray-core/v4/features"
|
||||
)
|
||||
|
||||
// IPOption is an object for IP query options.
|
||||
type IPOption struct {
|
||||
IPv4Enable bool
|
||||
IPv6Enable bool
|
||||
FakeEnable bool
|
||||
}
|
||||
|
||||
// Client is a V2Ray feature for querying DNS information.
|
||||
//
|
||||
// v2ray:api:stable
|
||||
@ -14,21 +21,7 @@ type Client interface {
|
||||
features.Feature
|
||||
|
||||
// LookupIP returns IP address for the given domain. IPs may contain IPv4 and/or IPv6 addresses.
|
||||
LookupIP(domain string) ([]net.IP, error)
|
||||
}
|
||||
|
||||
// IPv4Lookup is an optional feature for querying IPv4 addresses only.
|
||||
//
|
||||
// v2ray:api:beta
|
||||
type IPv4Lookup interface {
|
||||
LookupIPv4(domain string) ([]net.IP, error)
|
||||
}
|
||||
|
||||
// IPv6Lookup is an optional feature for querying IPv6 addresses only.
|
||||
//
|
||||
// v2ray:api:beta
|
||||
type IPv6Lookup interface {
|
||||
LookupIPv6(domain string) ([]net.IP, error)
|
||||
LookupIP(domain string, option IPOption) ([]net.IP, error)
|
||||
}
|
||||
|
||||
// ClientType returns the type of Client interface. Can be used for implementing common.HasType.
|
||||
|
@ -20,58 +20,41 @@ func (*Client) Start() error { return nil }
|
||||
func (*Client) Close() error { return nil }
|
||||
|
||||
// LookupIP implements Client.
|
||||
func (*Client) LookupIP(host string) ([]net.IP, error) {
|
||||
func (*Client) LookupIP(host string, option dns.IPOption) ([]net.IP, error) {
|
||||
ips, err := net.LookupIP(host)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
parsedIPs := make([]net.IP, 0, len(ips))
|
||||
ipv4 := make([]net.IP, 0, len(ips))
|
||||
ipv6 := make([]net.IP, 0, len(ips))
|
||||
for _, ip := range ips {
|
||||
parsed := net.IPAddress(ip)
|
||||
if parsed != nil {
|
||||
parsedIPs = append(parsedIPs, parsed.IP())
|
||||
}
|
||||
}
|
||||
if len(parsedIPs) == 0 {
|
||||
return nil, dns.ErrEmptyResponse
|
||||
}
|
||||
return parsedIPs, nil
|
||||
}
|
||||
|
||||
// LookupIPv4 implements IPv4Lookup.
|
||||
func (c *Client) LookupIPv4(host string) ([]net.IP, error) {
|
||||
ips, err := c.LookupIP(host)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ipv4 := make([]net.IP, 0, len(ips))
|
||||
for _, ip := range ips {
|
||||
if len(ip) == net.IPv4len {
|
||||
ipv4 = append(ipv4, ip)
|
||||
}
|
||||
}
|
||||
if len(ipv4) == 0 {
|
||||
return nil, dns.ErrEmptyResponse
|
||||
}
|
||||
return ipv4, nil
|
||||
}
|
||||
|
||||
// LookupIPv6 implements IPv6Lookup.
|
||||
func (c *Client) LookupIPv6(host string) ([]net.IP, error) {
|
||||
ips, err := c.LookupIP(host)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ipv6 := make([]net.IP, 0, len(ips))
|
||||
for _, ip := range ips {
|
||||
if len(ip) == net.IPv6len {
|
||||
ipv6 = append(ipv6, ip)
|
||||
}
|
||||
}
|
||||
if len(ipv6) == 0 {
|
||||
return nil, dns.ErrEmptyResponse
|
||||
switch {
|
||||
case option.IPv4Enable && option.IPv6Enable:
|
||||
if len(parsedIPs) > 0 {
|
||||
return parsedIPs, nil
|
||||
}
|
||||
case option.IPv4Enable:
|
||||
if len(ipv4) > 0 {
|
||||
return ipv4, nil
|
||||
}
|
||||
case option.IPv6Enable:
|
||||
if len(ipv6) > 0 {
|
||||
return ipv6, nil
|
||||
}
|
||||
}
|
||||
return ipv6, nil
|
||||
return nil, dns.ErrEmptyResponse
|
||||
}
|
||||
|
||||
// New create a new dns.Client that queries localhost for DNS.
|
||||
|
@ -26,7 +26,11 @@ func (ctx *ResolvableContext) GetTargetIPs() []net.IP {
|
||||
}
|
||||
|
||||
if domain := ctx.GetTargetDomain(); len(domain) != 0 {
|
||||
ips, err := ctx.dnsClient.LookupIP(domain)
|
||||
ips, err := ctx.dnsClient.LookupIP(domain, dns.IPOption{
|
||||
IPv4Enable: true,
|
||||
IPv6Enable: true,
|
||||
FakeEnable: false,
|
||||
})
|
||||
if err == nil {
|
||||
ctx.resolvedIPs = ips
|
||||
return ips
|
||||
|
@ -39,26 +39,12 @@ type ownLinkVerifier interface {
|
||||
|
||||
type Handler struct {
|
||||
client dns.Client
|
||||
ipv4Lookup dns.IPv4Lookup
|
||||
ipv6Lookup dns.IPv6Lookup
|
||||
ownLinkVerifier ownLinkVerifier
|
||||
server net.Destination
|
||||
}
|
||||
|
||||
func (h *Handler) Init(config *Config, dnsClient dns.Client) error {
|
||||
h.client = dnsClient
|
||||
ipv4lookup, ok := dnsClient.(dns.IPv4Lookup)
|
||||
if !ok {
|
||||
return newError("dns.Client doesn't implement IPv4Lookup")
|
||||
}
|
||||
h.ipv4Lookup = ipv4lookup
|
||||
|
||||
ipv6lookup, ok := dnsClient.(dns.IPv6Lookup)
|
||||
if !ok {
|
||||
return newError("dns.Client doesn't implement IPv6Lookup")
|
||||
}
|
||||
h.ipv6Lookup = ipv6lookup
|
||||
|
||||
if v, ok := dnsClient.(ownLinkVerifier); ok {
|
||||
h.ownLinkVerifier = v
|
||||
}
|
||||
@ -217,9 +203,17 @@ func (h *Handler) handleIPQuery(id uint16, qType dnsmessage.Type, domain string,
|
||||
|
||||
switch qType {
|
||||
case dnsmessage.TypeA:
|
||||
ips, err = h.ipv4Lookup.LookupIPv4(domain)
|
||||
ips, err = h.client.LookupIP(domain, dns.IPOption{
|
||||
IPv4Enable: true,
|
||||
IPv6Enable: false,
|
||||
FakeEnable: true,
|
||||
})
|
||||
case dnsmessage.TypeAAAA:
|
||||
ips, err = h.ipv6Lookup.LookupIPv6(domain)
|
||||
ips, err = h.client.LookupIP(domain, dns.IPOption{
|
||||
IPv4Enable: false,
|
||||
IPv6Enable: true,
|
||||
FakeEnable: true,
|
||||
})
|
||||
}
|
||||
|
||||
rcode := dns.RCodeFromError(err)
|
||||
|
@ -60,19 +60,26 @@ func (h *Handler) policy() policy.Session {
|
||||
}
|
||||
|
||||
func (h *Handler) resolveIP(ctx context.Context, domain string, localAddr net.Address) net.Address {
|
||||
var lookupFunc func(string) ([]net.IP, error) = h.dns.LookupIP
|
||||
|
||||
var option dns.IPOption = dns.IPOption{
|
||||
IPv4Enable: true,
|
||||
IPv6Enable: true,
|
||||
FakeEnable: false,
|
||||
}
|
||||
if h.config.DomainStrategy == Config_USE_IP4 || (localAddr != nil && localAddr.Family().IsIPv4()) {
|
||||
if lookupIPv4, ok := h.dns.(dns.IPv4Lookup); ok {
|
||||
lookupFunc = lookupIPv4.LookupIPv4
|
||||
option = dns.IPOption{
|
||||
IPv4Enable: true,
|
||||
IPv6Enable: false,
|
||||
FakeEnable: false,
|
||||
}
|
||||
} else if h.config.DomainStrategy == Config_USE_IP6 || (localAddr != nil && localAddr.Family().IsIPv6()) {
|
||||
if lookupIPv6, ok := h.dns.(dns.IPv6Lookup); ok {
|
||||
lookupFunc = lookupIPv6.LookupIPv6
|
||||
option = dns.IPOption{
|
||||
IPv4Enable: false,
|
||||
IPv6Enable: true,
|
||||
FakeEnable: false,
|
||||
}
|
||||
}
|
||||
|
||||
ips, err := lookupFunc(domain)
|
||||
ips, err := h.dns.LookupIP(domain, option)
|
||||
if err != nil {
|
||||
newError("failed to get IP address for domain ", domain).Base(err).WriteToLog(session.ExportIDToError(ctx))
|
||||
}
|
||||
@ -123,7 +130,7 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
|
||||
Address: ip,
|
||||
Port: dialDest.Port,
|
||||
}
|
||||
newError("dialing to to ", dialDest).WriteToLog(session.ExportIDToError(ctx))
|
||||
newError("dialing to ", dialDest).WriteToLog(session.ExportIDToError(ctx))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -9,6 +9,7 @@ import (
|
||||
reflect "reflect"
|
||||
|
||||
gomock "github.com/golang/mock/gomock"
|
||||
dns "github.com/v2fly/v2ray-core/v4/features/dns"
|
||||
)
|
||||
|
||||
// DNSClient is a mock of Client interface.
|
||||
@ -49,18 +50,18 @@ func (mr *DNSClientMockRecorder) Close() *gomock.Call {
|
||||
}
|
||||
|
||||
// LookupIP mocks base method.
|
||||
func (m *DNSClient) LookupIP(arg0 string) ([]net.IP, error) {
|
||||
func (m *DNSClient) LookupIP(arg0 string, arg1 dns.IPOption) ([]net.IP, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "LookupIP", arg0)
|
||||
ret := m.ctrl.Call(m, "LookupIP", arg0, arg1)
|
||||
ret0, _ := ret[0].([]net.IP)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// LookupIP indicates an expected call of LookupIP.
|
||||
func (mr *DNSClientMockRecorder) LookupIP(arg0 interface{}) *gomock.Call {
|
||||
func (mr *DNSClientMockRecorder) LookupIP(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LookupIP", reflect.TypeOf((*DNSClient)(nil).LookupIP), arg0)
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LookupIP", reflect.TypeOf((*DNSClient)(nil).LookupIP), arg0, arg1)
|
||||
}
|
||||
|
||||
// Start mocks base method.
|
||||
|
Loading…
Reference in New Issue
Block a user