Browse Source

overrideable dns

Darien Raymond 7 years ago
parent
commit
ab4f245313

+ 0 - 20
app/dns/dns.go

@@ -1,23 +1,3 @@
 package dns
 package dns
 
 
 //go:generate go run $GOPATH/src/v2ray.com/core/common/errors/errorgen/main.go -pkg dns -path App,DNS
 //go:generate go run $GOPATH/src/v2ray.com/core/common/errors/errorgen/main.go -pkg dns -path App,DNS
-
-import (
-	"net"
-
-	"v2ray.com/core/app"
-)
-
-// A Server is a DNS server for responding DNS queries.
-type Server interface {
-	Get(domain string) []net.IP
-}
-
-// FromSpace fetches a DNS server from context.
-func FromSpace(space app.Space) Server {
-	app := space.GetApplication((*Server)(nil))
-	if app == nil {
-		return nil
-	}
-	return app.(Server)
-}

+ 3 - 2
app/dns/server/nameserver.go → app/dns/nameserver.go

@@ -1,4 +1,4 @@
-package server
+package dns
 
 
 import (
 import (
 	"context"
 	"context"
@@ -203,7 +203,8 @@ func (*LocalNameServer) QueryA(domain string) <-chan *ARecord {
 	go func() {
 	go func() {
 		defer close(response)
 		defer close(response)
 
 
-		ips, err := net.LookupIP(domain)
+		resolver := net.SystemIPResolver()
+		ips, err := resolver.LookupIP(domain)
 		if err != nil {
 		if err != nil {
 			newError("failed to lookup IPs for domain ", domain).Base(err).WriteToLog()
 			newError("failed to lookup IPs for domain ", domain).Base(err).WriteToLog()
 			return
 			return

+ 12 - 13
app/dns/server/server.go → app/dns/server.go

@@ -1,4 +1,4 @@
-package server
+package dns
 
 
 //go:generate go run $GOPATH/src/v2ray.com/core/common/errors/errorgen/main.go -pkg server -path App,DNS,Server
 //go:generate go run $GOPATH/src/v2ray.com/core/common/errors/errorgen/main.go -pkg server -path App,DNS,Server
 
 
@@ -10,7 +10,6 @@ import (
 	dnsmsg "github.com/miekg/dns"
 	dnsmsg "github.com/miekg/dns"
 	"v2ray.com/core/app"
 	"v2ray.com/core/app"
 	"v2ray.com/core/app/dispatcher"
 	"v2ray.com/core/app/dispatcher"
-	"v2ray.com/core/app/dns"
 	"v2ray.com/core/common"
 	"v2ray.com/core/common"
 	"v2ray.com/core/common/net"
 	"v2ray.com/core/common/net"
 )
 )
@@ -41,7 +40,7 @@ type CacheServer struct {
 	servers []NameServer
 	servers []NameServer
 }
 }
 
 
-func NewCacheServer(ctx context.Context, config *dns.Config) (*CacheServer, error) {
+func NewCacheServer(ctx context.Context, config *Config) (*CacheServer, error) {
 	space := app.SpaceFromContext(ctx)
 	space := app.SpaceFromContext(ctx)
 	if space == nil {
 	if space == nil {
 		return nil, newError("no space in context")
 		return nil, newError("no space in context")
@@ -79,10 +78,11 @@ func NewCacheServer(ctx context.Context, config *dns.Config) (*CacheServer, erro
 }
 }
 
 
 func (*CacheServer) Interface() interface{} {
 func (*CacheServer) Interface() interface{} {
-	return (*dns.Server)(nil)
+	return (*CacheServer)(nil)
 }
 }
 
 
-func (*CacheServer) Start() error {
+func (s *CacheServer) Start() error {
+	net.RegisterIPResolver(s)
 	return nil
 	return nil
 }
 }
 
 
@@ -116,15 +116,15 @@ func (s *CacheServer) tryCleanup() {
 	}
 	}
 }
 }
 
 
-func (s *CacheServer) Get(domain string) []net.IP {
+func (s *CacheServer) LookupIP(domain string) ([]net.IP, error) {
 	if ip, found := s.hosts[domain]; found {
 	if ip, found := s.hosts[domain]; found {
-		return []net.IP{ip}
+		return []net.IP{ip}, nil
 	}
 	}
 
 
 	domain = dnsmsg.Fqdn(domain)
 	domain = dnsmsg.Fqdn(domain)
 	ips := s.GetCached(domain)
 	ips := s.GetCached(domain)
 	if ips != nil {
 	if ips != nil {
-		return ips
+		return ips, nil
 	}
 	}
 
 
 	s.tryCleanup()
 	s.tryCleanup()
@@ -144,17 +144,16 @@ func (s *CacheServer) Get(domain string) []net.IP {
 			}
 			}
 			s.Unlock()
 			s.Unlock()
 			newError("returning ", len(a.IPs), " IPs for domain ", domain).AtDebug().WriteToLog()
 			newError("returning ", len(a.IPs), " IPs for domain ", domain).AtDebug().WriteToLog()
-			return a.IPs
+			return a.IPs, nil
 		case <-time.After(QueryTimeout):
 		case <-time.After(QueryTimeout):
 		}
 		}
 	}
 	}
 
 
-	newError("returning nil for domain ", domain).AtDebug().WriteToLog()
-	return nil
+	return nil, newError("returning nil for domain ", domain)
 }
 }
 
 
 func init() {
 func init() {
-	common.Must(common.RegisterConfig((*dns.Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
-		return NewCacheServer(ctx, config.(*dns.Config))
+	common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
+		return NewCacheServer(ctx, config.(*Config))
 	}))
 	}))
 }
 }

+ 0 - 7
app/dns/server/errors.generated.go

@@ -1,7 +0,0 @@
-package server
-
-import "v2ray.com/core/common/errors"
-
-func newError(values ...interface{}) *errors.Error {
-	return errors.New(values...).Path("App", "DNS", "Server")
-}

+ 1 - 2
app/dns/server/server_test.go → app/dns/server_test.go

@@ -1,4 +1,4 @@
-package server_test
+package dns_test
 
 
 import (
 import (
 	"context"
 	"context"
@@ -8,7 +8,6 @@ import (
 	"v2ray.com/core/app/dispatcher"
 	"v2ray.com/core/app/dispatcher"
 	_ "v2ray.com/core/app/dispatcher/impl"
 	_ "v2ray.com/core/app/dispatcher/impl"
 	. "v2ray.com/core/app/dns"
 	. "v2ray.com/core/app/dns"
-	_ "v2ray.com/core/app/dns/server"
 	"v2ray.com/core/app/policy"
 	"v2ray.com/core/app/policy"
 	_ "v2ray.com/core/app/policy/manager"
 	_ "v2ray.com/core/app/policy/manager"
 	"v2ray.com/core/app/proxyman"
 	"v2ray.com/core/app/proxyman"

+ 8 - 15
app/router/router.go

@@ -6,7 +6,6 @@ import (
 	"context"
 	"context"
 
 
 	"v2ray.com/core/app"
 	"v2ray.com/core/app"
-	"v2ray.com/core/app/dns"
 	"v2ray.com/core/common"
 	"v2ray.com/core/common"
 	"v2ray.com/core/common/net"
 	"v2ray.com/core/common/net"
 	"v2ray.com/core/proxy"
 	"v2ray.com/core/proxy"
@@ -19,7 +18,6 @@ var (
 type Router struct {
 type Router struct {
 	domainStrategy Config_DomainStrategy
 	domainStrategy Config_DomainStrategy
 	rules          []Rule
 	rules          []Rule
-	dnsServer      dns.Server
 }
 }
 
 
 func NewRouter(ctx context.Context, config *Config) (*Router, error) {
 func NewRouter(ctx context.Context, config *Config) (*Router, error) {
@@ -41,21 +39,15 @@ func NewRouter(ctx context.Context, config *Config) (*Router, error) {
 			}
 			}
 			r.rules[idx].Condition = cond
 			r.rules[idx].Condition = cond
 		}
 		}
-
-		r.dnsServer = dns.FromSpace(space)
-		if r.dnsServer == nil {
-			return newError("DNS is not found in the space")
-		}
 		return nil
 		return nil
 	})
 	})
 	return r, nil
 	return r, nil
 }
 }
 
 
 type ipResolver struct {
 type ipResolver struct {
-	ip        []net.Address
-	domain    string
-	resolved  bool
-	dnsServer dns.Server
+	ip       []net.Address
+	domain   string
+	resolved bool
 }
 }
 
 
 func (r *ipResolver) Resolve() []net.Address {
 func (r *ipResolver) Resolve() []net.Address {
@@ -65,7 +57,10 @@ func (r *ipResolver) Resolve() []net.Address {
 
 
 	newError("looking for IP for domain: ", r.domain).WriteToLog()
 	newError("looking for IP for domain: ", r.domain).WriteToLog()
 	r.resolved = true
 	r.resolved = true
-	ips := r.dnsServer.Get(r.domain)
+	ips, err := net.LookupIP(r.domain)
+	if err != nil {
+		newError("failed to get IP address").Base(err).WriteToLog()
+	}
 	if len(ips) == 0 {
 	if len(ips) == 0 {
 		return nil
 		return nil
 	}
 	}
@@ -77,9 +72,7 @@ func (r *ipResolver) Resolve() []net.Address {
 }
 }
 
 
 func (r *Router) TakeDetour(ctx context.Context) (string, error) {
 func (r *Router) TakeDetour(ctx context.Context) (string, error) {
-	resolver := &ipResolver{
-		dnsServer: r.dnsServer,
-	}
+	resolver := &ipResolver{}
 	if r.domainStrategy == Config_IpOnDemand {
 	if r.domainStrategy == Config_IpOnDemand {
 		if dest, ok := proxy.TargetFromContext(ctx); ok && dest.Address.Family().IsDomain() {
 		if dest, ok := proxy.TargetFromContext(ctx); ok && dest.Address.Family().IsDomain() {
 			resolver.domain = dest.Address.Domain()
 			resolver.domain = dest.Address.Domain()

+ 44 - 0
common/net/dns.go

@@ -0,0 +1,44 @@
+package net
+
+import (
+	"net"
+	"sync/atomic"
+	"unsafe"
+)
+
+// IPResolver is the interface to resolve host name to IPs.
+type IPResolver interface {
+	LookupIP(host string) ([]net.IP, error)
+}
+
+type systemIPResolver int
+
+func (s systemIPResolver) LookupIP(host string) ([]net.IP, error) {
+	return net.LookupIP(host)
+}
+
+const (
+	systemIPResolverInstance = systemIPResolver(0)
+)
+
+// SystemIPResolver returns an IPResolver that resolves IP through underlying system.
+func SystemIPResolver() IPResolver {
+	return systemIPResolverInstance
+}
+
+var (
+	ipResolver unsafe.Pointer
+)
+
+func LookupIP(host string) ([]net.IP, error) {
+	r := (*IPResolver)(atomic.LoadPointer(&ipResolver))
+	return (*r).LookupIP(host)
+}
+
+func RegisterIPResolver(resolver IPResolver) {
+	atomic.StorePointer(&ipResolver, unsafe.Pointer(&resolver))
+}
+
+func init() {
+	RegisterIPResolver(systemIPResolverInstance)
+}

+ 0 - 1
common/net/system.go

@@ -13,7 +13,6 @@ var ListenUDP = net.ListenUDP
 
 
 var FileConn = net.FileConn
 var FileConn = net.FileConn
 
 
-var LookupIP = net.LookupIP
 var ParseIP = net.ParseIP
 var ParseIP = net.ParseIP
 
 
 var SplitHostPort = net.SplitHostPort
 var SplitHostPort = net.SplitHostPort

+ 2 - 1
main/distro/all/all.go

@@ -3,7 +3,8 @@ package all
 import (
 import (
 	// The following are necessary as they register handlers in their init functions.
 	// The following are necessary as they register handlers in their init functions.
 	_ "v2ray.com/core/app/dispatcher/impl"
 	_ "v2ray.com/core/app/dispatcher/impl"
-	_ "v2ray.com/core/app/dns/server"
+	_ "v2ray.com/core/app/dns"
+	_ "v2ray.com/core/app/log"
 	_ "v2ray.com/core/app/policy/manager"
 	_ "v2ray.com/core/app/policy/manager"
 	_ "v2ray.com/core/app/proxyman/inbound"
 	_ "v2ray.com/core/app/proxyman/inbound"
 	_ "v2ray.com/core/app/proxyman/outbound"
 	_ "v2ray.com/core/app/proxyman/outbound"

+ 4 - 9
proxy/freedom/freedom.go

@@ -6,7 +6,6 @@ import (
 	"context"
 	"context"
 
 
 	"v2ray.com/core/app"
 	"v2ray.com/core/app"
-	"v2ray.com/core/app/dns"
 	"v2ray.com/core/app/policy"
 	"v2ray.com/core/app/policy"
 	"v2ray.com/core/common"
 	"v2ray.com/core/common"
 	"v2ray.com/core/common/buf"
 	"v2ray.com/core/common/buf"
@@ -23,7 +22,6 @@ import (
 type Handler struct {
 type Handler struct {
 	domainStrategy Config_DomainStrategy
 	domainStrategy Config_DomainStrategy
 	timeout        uint32
 	timeout        uint32
-	dns            dns.Server
 	destOverride   *DestinationOverride
 	destOverride   *DestinationOverride
 	policy         policy.Policy
 	policy         policy.Policy
 }
 }
@@ -40,12 +38,6 @@ func New(ctx context.Context, config *Config) (*Handler, error) {
 		destOverride:   config.DestinationOverride,
 		destOverride:   config.DestinationOverride,
 	}
 	}
 	space.On(app.SpaceInitializing, func(interface{}) error {
 	space.On(app.SpaceInitializing, func(interface{}) error {
-		if config.DomainStrategy == Config_USE_IP {
-			f.dns = dns.FromSpace(space)
-			if f.dns == nil {
-				return newError("DNS server is not found in the space")
-			}
-		}
 		pm := policy.FromSpace(space)
 		pm := policy.FromSpace(space)
 		if pm == nil {
 		if pm == nil {
 			return newError("Policy not found in space.")
 			return newError("Policy not found in space.")
@@ -68,7 +60,10 @@ func (h *Handler) resolveIP(ctx context.Context, domain string) net.Address {
 		return ips[dice.Roll(len(ips))]
 		return ips[dice.Roll(len(ips))]
 	}
 	}
 
 
-	ips := h.dns.Get(domain)
+	ips, err := net.LookupIP(domain)
+	if err != nil {
+		newError("failed to get IP address for domain ", domain).Base(err).WriteToLog()
+	}
 	if len(ips) == 0 {
 	if len(ips) == 0 {
 		return nil
 		return nil
 	}
 	}

+ 0 - 15
v2ray.go

@@ -5,11 +5,9 @@ import (
 
 
 	"v2ray.com/core/app"
 	"v2ray.com/core/app"
 	"v2ray.com/core/app/dispatcher"
 	"v2ray.com/core/app/dispatcher"
-	"v2ray.com/core/app/dns"
 	"v2ray.com/core/app/policy"
 	"v2ray.com/core/app/policy"
 	"v2ray.com/core/app/proxyman"
 	"v2ray.com/core/app/proxyman"
 	"v2ray.com/core/common"
 	"v2ray.com/core/common"
-	"v2ray.com/core/common/net"
 )
 )
 
 
 // Server is an instance of V2Ray. At any time, there must be at most one Server instance running.
 // Server is an instance of V2Ray. At any time, there must be at most one Server instance running.
@@ -84,19 +82,6 @@ func newSimpleServer(config *Config) (*simpleServer, error) {
 		inboundHandlerManager = o.(proxyman.InboundHandlerManager)
 		inboundHandlerManager = o.(proxyman.InboundHandlerManager)
 	}
 	}
 
 
-	if dns.FromSpace(space) == nil {
-		dnsConfig := &dns.Config{
-			NameServers: []*net.Endpoint{{
-				Address: net.NewIPOrDomain(net.LocalHostDomain),
-			}},
-		}
-		d, err := app.CreateAppFromConfig(ctx, dnsConfig)
-		if err != nil {
-			return nil, err
-		}
-		common.Must(space.AddApplication(d))
-	}
-
 	if disp := dispatcher.FromSpace(space); disp == nil {
 	if disp := dispatcher.FromSpace(space); disp == nil {
 		d, err := app.CreateAppFromConfig(ctx, new(dispatcher.Config))
 		d, err := app.CreateAppFromConfig(ctx, new(dispatcher.Config))
 		if err != nil {
 		if err != nil {