mirror of https://github.com/v2ray/v2ray-core
				
				
				
			overrideable dns
							parent
							
								
									7d11286d80
								
							
						
					
					
						commit
						ab4f245313
					
				| 
						 | 
				
			
			@ -1,23 +1,3 @@
 | 
			
		|||
package 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)
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
package server
 | 
			
		||||
package dns
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"context"
 | 
			
		||||
| 
						 | 
				
			
			@ -203,7 +203,8 @@ func (*LocalNameServer) QueryA(domain string) <-chan *ARecord {
 | 
			
		|||
	go func() {
 | 
			
		||||
		defer close(response)
 | 
			
		||||
 | 
			
		||||
		ips, err := net.LookupIP(domain)
 | 
			
		||||
		resolver := net.SystemIPResolver()
 | 
			
		||||
		ips, err := resolver.LookupIP(domain)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			newError("failed to lookup IPs for domain ", domain).Base(err).WriteToLog()
 | 
			
		||||
			return
 | 
			
		||||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -10,7 +10,6 @@ import (
 | 
			
		|||
	dnsmsg "github.com/miekg/dns"
 | 
			
		||||
	"v2ray.com/core/app"
 | 
			
		||||
	"v2ray.com/core/app/dispatcher"
 | 
			
		||||
	"v2ray.com/core/app/dns"
 | 
			
		||||
	"v2ray.com/core/common"
 | 
			
		||||
	"v2ray.com/core/common/net"
 | 
			
		||||
)
 | 
			
		||||
| 
						 | 
				
			
			@ -41,7 +40,7 @@ type CacheServer struct {
 | 
			
		|||
	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)
 | 
			
		||||
	if space == nil {
 | 
			
		||||
		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{} {
 | 
			
		||||
	return (*dns.Server)(nil)
 | 
			
		||||
	return (*CacheServer)(nil)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (*CacheServer) Start() error {
 | 
			
		||||
func (s *CacheServer) Start() error {
 | 
			
		||||
	net.RegisterIPResolver(s)
 | 
			
		||||
	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 {
 | 
			
		||||
		return []net.IP{ip}
 | 
			
		||||
		return []net.IP{ip}, nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	domain = dnsmsg.Fqdn(domain)
 | 
			
		||||
	ips := s.GetCached(domain)
 | 
			
		||||
	if ips != nil {
 | 
			
		||||
		return ips
 | 
			
		||||
		return ips, nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	s.tryCleanup()
 | 
			
		||||
| 
						 | 
				
			
			@ -144,17 +144,16 @@ func (s *CacheServer) Get(domain string) []net.IP {
 | 
			
		|||
			}
 | 
			
		||||
			s.Unlock()
 | 
			
		||||
			newError("returning ", len(a.IPs), " IPs for domain ", domain).AtDebug().WriteToLog()
 | 
			
		||||
			return a.IPs
 | 
			
		||||
			return a.IPs, nil
 | 
			
		||||
		case <-time.After(QueryTimeout):
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	newError("returning nil for domain ", domain).AtDebug().WriteToLog()
 | 
			
		||||
	return nil
 | 
			
		||||
	return nil, newError("returning nil for domain ", domain)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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))
 | 
			
		||||
	}))
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -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,4 +1,4 @@
 | 
			
		|||
package server_test
 | 
			
		||||
package dns_test
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"context"
 | 
			
		||||
| 
						 | 
				
			
			@ -8,7 +8,6 @@ import (
 | 
			
		|||
	"v2ray.com/core/app/dispatcher"
 | 
			
		||||
	_ "v2ray.com/core/app/dispatcher/impl"
 | 
			
		||||
	. "v2ray.com/core/app/dns"
 | 
			
		||||
	_ "v2ray.com/core/app/dns/server"
 | 
			
		||||
	"v2ray.com/core/app/policy"
 | 
			
		||||
	_ "v2ray.com/core/app/policy/manager"
 | 
			
		||||
	"v2ray.com/core/app/proxyman"
 | 
			
		||||
| 
						 | 
				
			
			@ -6,7 +6,6 @@ import (
 | 
			
		|||
	"context"
 | 
			
		||||
 | 
			
		||||
	"v2ray.com/core/app"
 | 
			
		||||
	"v2ray.com/core/app/dns"
 | 
			
		||||
	"v2ray.com/core/common"
 | 
			
		||||
	"v2ray.com/core/common/net"
 | 
			
		||||
	"v2ray.com/core/proxy"
 | 
			
		||||
| 
						 | 
				
			
			@ -19,7 +18,6 @@ var (
 | 
			
		|||
type Router struct {
 | 
			
		||||
	domainStrategy Config_DomainStrategy
 | 
			
		||||
	rules          []Rule
 | 
			
		||||
	dnsServer      dns.Server
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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.dnsServer = dns.FromSpace(space)
 | 
			
		||||
		if r.dnsServer == nil {
 | 
			
		||||
			return newError("DNS is not found in the space")
 | 
			
		||||
		}
 | 
			
		||||
		return nil
 | 
			
		||||
	})
 | 
			
		||||
	return r, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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 {
 | 
			
		||||
| 
						 | 
				
			
			@ -65,7 +57,10 @@ func (r *ipResolver) Resolve() []net.Address {
 | 
			
		|||
 | 
			
		||||
	newError("looking for IP for domain: ", r.domain).WriteToLog()
 | 
			
		||||
	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 {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -77,9 +72,7 @@ func (r *ipResolver) Resolve() []net.Address {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
func (r *Router) TakeDetour(ctx context.Context) (string, error) {
 | 
			
		||||
	resolver := &ipResolver{
 | 
			
		||||
		dnsServer: r.dnsServer,
 | 
			
		||||
	}
 | 
			
		||||
	resolver := &ipResolver{}
 | 
			
		||||
	if r.domainStrategy == Config_IpOnDemand {
 | 
			
		||||
		if dest, ok := proxy.TargetFromContext(ctx); ok && dest.Address.Family().IsDomain() {
 | 
			
		||||
			resolver.domain = dest.Address.Domain()
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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)
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -13,7 +13,6 @@ var ListenUDP = net.ListenUDP
 | 
			
		|||
 | 
			
		||||
var FileConn = net.FileConn
 | 
			
		||||
 | 
			
		||||
var LookupIP = net.LookupIP
 | 
			
		||||
var ParseIP = net.ParseIP
 | 
			
		||||
 | 
			
		||||
var SplitHostPort = net.SplitHostPort
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,7 +3,8 @@ package all
 | 
			
		|||
import (
 | 
			
		||||
	// The following are necessary as they register handlers in their init functions.
 | 
			
		||||
	_ "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/proxyman/inbound"
 | 
			
		||||
	_ "v2ray.com/core/app/proxyman/outbound"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,7 +6,6 @@ import (
 | 
			
		|||
	"context"
 | 
			
		||||
 | 
			
		||||
	"v2ray.com/core/app"
 | 
			
		||||
	"v2ray.com/core/app/dns"
 | 
			
		||||
	"v2ray.com/core/app/policy"
 | 
			
		||||
	"v2ray.com/core/common"
 | 
			
		||||
	"v2ray.com/core/common/buf"
 | 
			
		||||
| 
						 | 
				
			
			@ -23,7 +22,6 @@ import (
 | 
			
		|||
type Handler struct {
 | 
			
		||||
	domainStrategy Config_DomainStrategy
 | 
			
		||||
	timeout        uint32
 | 
			
		||||
	dns            dns.Server
 | 
			
		||||
	destOverride   *DestinationOverride
 | 
			
		||||
	policy         policy.Policy
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -40,12 +38,6 @@ func New(ctx context.Context, config *Config) (*Handler, error) {
 | 
			
		|||
		destOverride:   config.DestinationOverride,
 | 
			
		||||
	}
 | 
			
		||||
	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)
 | 
			
		||||
		if pm == nil {
 | 
			
		||||
			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))]
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	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 {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										15
									
								
								v2ray.go
								
								
								
								
							
							
						
						
									
										15
									
								
								v2ray.go
								
								
								
								
							| 
						 | 
				
			
			@ -5,11 +5,9 @@ import (
 | 
			
		|||
 | 
			
		||||
	"v2ray.com/core/app"
 | 
			
		||||
	"v2ray.com/core/app/dispatcher"
 | 
			
		||||
	"v2ray.com/core/app/dns"
 | 
			
		||||
	"v2ray.com/core/app/policy"
 | 
			
		||||
	"v2ray.com/core/app/proxyman"
 | 
			
		||||
	"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.
 | 
			
		||||
| 
						 | 
				
			
			@ -84,19 +82,6 @@ func newSimpleServer(config *Config) (*simpleServer, error) {
 | 
			
		|||
		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 {
 | 
			
		||||
		d, err := app.CreateAppFromConfig(ctx, new(dispatcher.Config))
 | 
			
		||||
		if err != nil {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue