mirror of
https://github.com/v2fly/v2ray-core.git
synced 2025-01-02 07:26:24 -05:00
overrideable dns
This commit is contained in:
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,11 +39,6 @@ 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
|
||||
@ -55,7 +48,6 @@ type ipResolver struct {
|
||||
ip []net.Address
|
||||
domain string
|
||||
resolved bool
|
||||
dnsServer dns.Server
|
||||
}
|
||||
|
||||
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()
|
||||
|
44
common/net/dns.go
Normal file
44
common/net/dns.go
Normal file
@ -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
Block a user