Ver Fonte

dns cache

v2ray há 10 anos atrás
pai
commit
e1c58fae2b

+ 10 - 0
app/dns.go

@@ -0,0 +1,10 @@
+package app
+
+import (
+	"net"
+)
+
+type DnsCache interface {
+	Get(domain string) net.IP
+	Add(domain string, ip net.IP)
+}

+ 5 - 0
app/dns/config.go

@@ -0,0 +1,5 @@
+package dns
+
+type CacheConfig interface {
+	TrustedSource() []string
+}

+ 88 - 0
app/dns/dns.go

@@ -0,0 +1,88 @@
+package dns
+
+import (
+	"net"
+	"sync"
+	"time"
+)
+
+type entry struct {
+	domain     string
+	ip         net.IP
+	validUntil time.Time
+}
+
+func newEntry(domain string, ip net.IP) *entry {
+	this := &entry{
+		domain: domain,
+		ip:     ip,
+	}
+	this.Extend()
+	return this
+}
+
+func (this *entry) IsValid() bool {
+	return this.validUntil.After(time.Now())
+}
+
+func (this *entry) Extend() {
+	this.validUntil = time.Now().Add(time.Hour)
+}
+
+type DnsCache struct {
+	sync.RWMutex
+	cache map[string]*entry
+}
+
+func NewCache() *DnsCache {
+	cache := &DnsCache{
+		cache: make(map[string]*entry),
+	}
+	go cache.cleanup()
+	return cache
+}
+
+func (this *DnsCache) cleanup() {
+	for range time.Tick(10 * time.Second) {
+		entry2Remove := make([]*entry, 0, 128)
+		this.RLock()
+		for _, entry := range this.cache {
+			if !entry.IsValid() {
+				entry2Remove = append(entry2Remove, entry)
+			}
+		}
+		this.RUnlock()
+
+		for _, entry := range entry2Remove {
+			if !entry.IsValid() {
+				this.Lock()
+				delete(this.cache, entry.domain)
+				this.Unlock()
+			}
+		}
+	}
+}
+
+func (this *DnsCache) Add(domain string, ip net.IP) {
+	this.RLock()
+	entry, found := this.cache[domain]
+	this.RUnlock()
+	if found {
+		entry.ip = ip
+		entry.Extend()
+	} else {
+		this.Lock()
+		this.cache[domain] = newEntry(domain, ip)
+		this.Unlock()
+	}
+}
+
+func (this *DnsCache) Get(domain string) net.IP {
+	this.RLock()
+	entry, found := this.cache[domain]
+	this.RUnlock()
+	if found {
+		return entry.ip
+	}
+	return nil
+}

+ 23 - 0
app/dns/dns_test.go

@@ -0,0 +1,23 @@
+package dns_test
+
+import (
+	"net"
+	"testing"
+
+	"github.com/v2ray/v2ray-core/app/dns"
+	netassert "github.com/v2ray/v2ray-core/common/net/testing/assert"
+	v2testing "github.com/v2ray/v2ray-core/testing"
+)
+
+func TestDnsAdd(t *testing.T) {
+	v2testing.Current(t)
+
+	domain := "v2ray.com"
+	cache := dns.NewCache()
+	ip := cache.Get(domain)
+	netassert.IP(ip).IsNil()
+
+	cache.Add(domain, []byte{1, 2, 3, 4})
+	ip = cache.Get(domain)
+	netassert.IP(ip).Equals(net.IP([]byte{1, 2, 3, 4}))
+}

+ 17 - 4
app/space.go

@@ -2,12 +2,23 @@ package app
 
 type Space struct {
 	packetDispatcher PacketDispatcher
+	dnsCache         DnsCache
 }
 
 func NewSpace() *Space {
 	return new(Space)
 }
 
+func (this *Space) Bind(object interface{}) {
+	if packetDispatcher, ok := object.(PacketDispatcher); ok {
+		this.packetDispatcher = packetDispatcher
+	}
+
+	if dnsCache, ok := object.(DnsCache); ok {
+		this.dnsCache = dnsCache
+	}
+}
+
 func (this *Space) HasPacketDispatcher() bool {
 	return this.packetDispatcher != nil
 }
@@ -16,8 +27,10 @@ func (this *Space) PacketDispatcher() PacketDispatcher {
 	return this.packetDispatcher
 }
 
-func (this *Space) Bind(object interface{}) {
-	if packetDispatcher, ok := object.(PacketDispatcher); ok {
-		this.packetDispatcher = packetDispatcher
-	}
+func (this *Space) HasDnsCache() bool {
+	return this.dnsCache != nil
+}
+
+func (this *Space) DnsCache() DnsCache {
+	return this.dnsCache
 }

+ 39 - 0
common/net/testing/assert/ip.go

@@ -0,0 +1,39 @@
+package assert
+
+import (
+	"bytes"
+	"net"
+
+	"github.com/v2ray/v2ray-core/common/serial"
+	"github.com/v2ray/v2ray-core/testing/assert"
+)
+
+func IP(value net.IP) *IPSubject {
+	return &IPSubject{value: value}
+}
+
+type IPSubject struct {
+	assert.Subject
+	value net.IP
+}
+
+func (subject *IPSubject) Named(name string) *IPSubject {
+	subject.Subject.Named(name)
+	return subject
+}
+
+func (subject *IPSubject) DisplayString() string {
+	return subject.Subject.DisplayString(subject.value.String())
+}
+
+func (subject *IPSubject) IsNil() {
+	if subject.value != nil {
+		subject.Fail(subject.DisplayString(), "is", serial.StringLiteral("nil"))
+	}
+}
+
+func (subject *IPSubject) Equals(ip net.IP) {
+	if !bytes.Equal([]byte(subject.value), []byte(ip)) {
+		subject.Fail(subject.DisplayString(), "equals to", ip)
+	}
+}

+ 2 - 1
proxy/blackhole/blackhole.go

@@ -3,6 +3,7 @@ package blackhole
 import (
 	"io/ioutil"
 
+	"github.com/v2ray/v2ray-core/app"
 	v2net "github.com/v2ray/v2ray-core/common/net"
 	"github.com/v2ray/v2ray-core/proxy/common/connhandler"
 	"github.com/v2ray/v2ray-core/transport/ray"
@@ -31,7 +32,7 @@ func (this *BlackHole) Dispatch(firstPacket v2net.Packet, ray ray.OutboundRay) e
 type BlackHoleFactory struct {
 }
 
-func (this BlackHoleFactory) Create(config interface{}) (connhandler.OutboundConnectionHandler, error) {
+func (this BlackHoleFactory) Create(space *app.Space, config interface{}) (connhandler.OutboundConnectionHandler, error) {
 	return NewBlackHole(), nil
 }
 

+ 2 - 1
proxy/common/connhandler/outbound_connection.go

@@ -1,6 +1,7 @@
 package connhandler
 
 import (
+	"github.com/v2ray/v2ray-core/app"
 	v2net "github.com/v2ray/v2ray-core/common/net"
 	"github.com/v2ray/v2ray-core/transport/ray"
 )
@@ -8,7 +9,7 @@ import (
 // An OutboundConnectionHandlerFactory creates OutboundConnectionHandler on demand.
 type OutboundConnectionHandlerFactory interface {
 	// Create creates a new OutboundConnectionHandler with given config.
-	Create(config interface{}) (OutboundConnectionHandler, error)
+	Create(space *app.Space, config interface{}) (OutboundConnectionHandler, error)
 }
 
 // An OutboundConnectionHandler handles outbound network connection for V2Ray.

+ 15 - 4
proxy/freedom/freedom.go

@@ -4,16 +4,14 @@ import (
 	"net"
 	"sync"
 
+	"github.com/v2ray/v2ray-core/app"
 	"github.com/v2ray/v2ray-core/common/log"
 	v2net "github.com/v2ray/v2ray-core/common/net"
 	"github.com/v2ray/v2ray-core/transport/ray"
 )
 
 type FreedomConnection struct {
-}
-
-func NewFreedomConnection() *FreedomConnection {
-	return &FreedomConnection{}
+	space *app.Space
 }
 
 func (this *FreedomConnection) Dispatch(firstPacket v2net.Packet, ray ray.OutboundRay) error {
@@ -66,6 +64,19 @@ func (this *FreedomConnection) Dispatch(firstPacket v2net.Packet, ray ray.Outbou
 		v2net.ReaderToChan(output, conn)
 	}()
 
+	if this.space.HasDnsCache() {
+		if firstPacket.Destination().Address().IsDomain() {
+			domain := firstPacket.Destination().Address().Domain()
+			addr := conn.RemoteAddr()
+			switch typedAddr := addr.(type) {
+			case *net.TCPAddr:
+				this.space.DnsCache().Add(domain, typedAddr.IP)
+			case *net.UDPAddr:
+				this.space.DnsCache().Add(domain, typedAddr.IP)
+			}
+		}
+	}
+
 	writeMutex.Lock()
 	if tcpConn, ok := conn.(*net.TCPConn); ok {
 		tcpConn.CloseWrite()

+ 3 - 2
proxy/freedom/freedomfactory.go

@@ -1,14 +1,15 @@
 package freedom
 
 import (
+	"github.com/v2ray/v2ray-core/app"
 	"github.com/v2ray/v2ray-core/proxy/common/connhandler"
 )
 
 type FreedomFactory struct {
 }
 
-func (this FreedomFactory) Create(config interface{}) (connhandler.OutboundConnectionHandler, error) {
-	return NewFreedomConnection(), nil
+func (this FreedomFactory) Create(space *app.Space, config interface{}) (connhandler.OutboundConnectionHandler, error) {
+	return &FreedomConnection{space: space}, nil
 }
 
 func init() {

+ 2 - 1
proxy/testing/mocks/outboundhandler.go

@@ -4,6 +4,7 @@ import (
 	"io"
 	"sync"
 
+	"github.com/v2ray/v2ray-core/app"
 	v2net "github.com/v2ray/v2ray-core/common/net"
 	"github.com/v2ray/v2ray-core/proxy/common/connhandler"
 	"github.com/v2ray/v2ray-core/transport/ray"
@@ -44,6 +45,6 @@ func (this *OutboundConnectionHandler) Dispatch(packet v2net.Packet, ray ray.Out
 	return nil
 }
 
-func (this *OutboundConnectionHandler) Create(config interface{}) (connhandler.OutboundConnectionHandler, error) {
+func (this *OutboundConnectionHandler) Create(space *app.Space, config interface{}) (connhandler.OutboundConnectionHandler, error) {
 	return this, nil
 }

+ 4 - 1
proxy/vmess/outbound/outbound.go

@@ -6,6 +6,7 @@ import (
 	"net"
 	"sync"
 
+	"github.com/v2ray/v2ray-core/app"
 	"github.com/v2ray/v2ray-core/common/alloc"
 	v2crypto "github.com/v2ray/v2ray-core/common/crypto"
 	"github.com/v2ray/v2ray-core/common/log"
@@ -19,6 +20,7 @@ import (
 
 type VMessOutboundHandler struct {
 	receiverManager *ReceiverManager
+	space           *app.Space
 }
 
 func (this *VMessOutboundHandler) Dispatch(firstPacket v2net.Packet, ray ray.OutboundRay) error {
@@ -174,9 +176,10 @@ func handleResponse(conn net.Conn, request *protocol.VMessRequest, output chan<-
 type VMessOutboundHandlerFactory struct {
 }
 
-func (this *VMessOutboundHandlerFactory) Create(rawConfig interface{}) (connhandler.OutboundConnectionHandler, error) {
+func (this *VMessOutboundHandlerFactory) Create(space *app.Space, rawConfig interface{}) (connhandler.OutboundConnectionHandler, error) {
 	vOutConfig := rawConfig.(config.Outbound)
 	return &VMessOutboundHandler{
+		space:           space,
 		receiverManager: NewReceiverManager(vOutConfig.Receivers()),
 	}, nil
 }

+ 6 - 0
shell/point/config/config.go

@@ -1,6 +1,7 @@
 package config
 
 import (
+	"github.com/v2ray/v2ray-core/app/dns"
 	routerconfig "github.com/v2ray/v2ray-core/app/router/config"
 	"github.com/v2ray/v2ray-core/common/log"
 	v2net "github.com/v2ray/v2ray-core/common/net"
@@ -17,6 +18,11 @@ type LogConfig interface {
 	LogLevel() log.LogLevel
 }
 
+type DnsConfig interface {
+	Enabled() bool
+	Settings() dns.CacheConfig
+}
+
 type InboundDetourConfig interface {
 	Protocol() string
 	PortRange() v2net.PortRange

+ 2 - 2
shell/point/point.go

@@ -73,7 +73,7 @@ func NewPoint(pConfig config.PointConfig) (*Point, error) {
 		return nil, config.BadConfiguration
 	}
 	ochConfig := pConfig.OutboundConfig().Settings()
-	och, err := ochFactory.Create(ochConfig)
+	och, err := ochFactory.Create(vpoint.space, ochConfig)
 	if err != nil {
 		log.Error("Failed to create outbound connection handler: %v", err)
 		return nil, err
@@ -105,7 +105,7 @@ func NewPoint(pConfig config.PointConfig) (*Point, error) {
 				log.Error("Unknown detour outbound connection handler factory %s", detourConfig.Protocol())
 				return nil, config.BadConfiguration
 			}
-			detourHandler, err := detourFactory.Create(detourConfig.Settings())
+			detourHandler, err := detourFactory.Create(vpoint.space, detourConfig.Settings())
 			if err != nil {
 				log.Error("Failed to create detour outbound connection handler: %v", err)
 				return nil, err

+ 102 - 0
testing/scenarios/access.log

@@ -0,0 +1,102 @@
+2015/12/06 10:58:06 127.0.0.1:61726 accepted 127.0.0.1:50024 
+2015/12/06 10:58:06 127.0.0.1:61730 accepted 127.0.0.1:30001 
+2015/12/06 10:58:06 127.0.0.1:61733 accepted 127.0.0.1:30001 
+2015/12/06 10:58:06 127.0.0.1:61736 accepted 127.0.0.1:30001 
+2015/12/06 10:58:06 127.0.0.1:61739 accepted 127.0.0.1:30001 
+2015/12/06 10:58:06 127.0.0.1:61742 accepted 127.0.0.1:30001 
+2015/12/06 10:58:06 127.0.0.1:61745 accepted 127.0.0.1:30001 
+2015/12/06 10:58:06 127.0.0.1:61748 accepted 127.0.0.1:30001 
+2015/12/06 10:58:06 127.0.0.1:61751 accepted 127.0.0.1:30001 
+2015/12/06 10:58:06 127.0.0.1:61754 accepted 127.0.0.1:30001 
+2015/12/06 10:58:06 127.0.0.1:61757 accepted 127.0.0.1:30001 
+2015/12/06 10:58:06 127.0.0.1:61760 accepted 127.0.0.1:30001 
+2015/12/06 10:58:06 127.0.0.1:61763 accepted 127.0.0.1:30001 
+2015/12/06 10:58:06 127.0.0.1:61766 accepted 127.0.0.1:30001 
+2015/12/06 10:58:06 127.0.0.1:61769 accepted 127.0.0.1:30001 
+2015/12/06 10:58:06 127.0.0.1:61772 accepted 127.0.0.1:30001 
+2015/12/06 10:58:06 127.0.0.1:61775 accepted 127.0.0.1:30001 
+2015/12/06 10:58:06 127.0.0.1:61778 accepted 127.0.0.1:30001 
+2015/12/06 10:58:06 127.0.0.1:61781 accepted 127.0.0.1:30001 
+2015/12/06 10:58:06 127.0.0.1:61784 accepted 127.0.0.1:30001 
+2015/12/06 10:58:06 127.0.0.1:61787 accepted 127.0.0.1:30001 
+2015/12/06 10:58:06 127.0.0.1:61790 accepted 127.0.0.1:30001 
+2015/12/06 10:58:06 127.0.0.1:61793 accepted 127.0.0.1:30001 
+2015/12/06 10:58:06 127.0.0.1:61796 accepted 127.0.0.1:30001 
+2015/12/06 10:58:06 127.0.0.1:61799 accepted 127.0.0.1:30001 
+2015/12/06 10:58:06 127.0.0.1:61802 accepted 127.0.0.1:30001 
+2015/12/06 10:58:06 127.0.0.1:61805 accepted 127.0.0.1:30001 
+2015/12/06 10:58:06 127.0.0.1:61808 accepted 127.0.0.1:30001 
+2015/12/06 10:58:06 127.0.0.1:61811 accepted 127.0.0.1:30001 
+2015/12/06 10:58:06 127.0.0.1:61814 accepted 127.0.0.1:30001 
+2015/12/06 10:58:06 127.0.0.1:61817 accepted 127.0.0.1:30001 
+2015/12/06 10:58:06 127.0.0.1:61820 accepted 127.0.0.1:30001 
+2015/12/06 10:58:06 127.0.0.1:61823 accepted 127.0.0.1:30001 
+2015/12/06 10:58:06 127.0.0.1:61826 accepted 127.0.0.1:30001 
+2015/12/06 10:58:06 127.0.0.1:61829 accepted 127.0.0.1:30001 
+2015/12/06 10:58:07 127.0.0.1:61832 accepted 127.0.0.1:30001 
+2015/12/06 10:58:07 127.0.0.1:61835 accepted 127.0.0.1:30001 
+2015/12/06 10:58:07 127.0.0.1:61838 accepted 127.0.0.1:30001 
+2015/12/06 10:58:07 127.0.0.1:61841 accepted 127.0.0.1:30001 
+2015/12/06 10:58:07 127.0.0.1:61844 accepted 127.0.0.1:30001 
+2015/12/06 10:58:07 127.0.0.1:61849 accepted 127.0.0.1:30001 
+2015/12/06 10:58:07 127.0.0.1:61852 accepted 127.0.0.1:30001 
+2015/12/06 10:58:07 127.0.0.1:61855 accepted 127.0.0.1:30001 
+2015/12/06 10:58:07 127.0.0.1:61858 accepted 127.0.0.1:30001 
+2015/12/06 10:58:07 127.0.0.1:61861 accepted 127.0.0.1:30001 
+2015/12/06 10:58:07 127.0.0.1:61864 accepted 127.0.0.1:30001 
+2015/12/06 10:58:08 127.0.0.1:61867 accepted 127.0.0.1:30001 
+2015/12/06 10:58:08 127.0.0.1:61870 accepted 127.0.0.1:30001 
+2015/12/06 10:58:08 127.0.0.1:61873 accepted 127.0.0.1:30001 
+2015/12/06 10:58:08 127.0.0.1:61876 accepted 127.0.0.1:30001 
+2015/12/06 10:58:08 127.0.0.1:61879 accepted 127.0.0.1:30001 
+2015/12/06 10:58:08 127.0.0.1:61882 accepted 127.0.0.1:30001 
+2015/12/06 10:58:08 127.0.0.1:61885 accepted 127.0.0.1:30001 
+2015/12/06 10:58:08 127.0.0.1:61888 accepted 127.0.0.1:30001 
+2015/12/06 10:58:08 127.0.0.1:61891 accepted 127.0.0.1:30001 
+2015/12/06 10:58:08 127.0.0.1:61894 accepted 127.0.0.1:30001 
+2015/12/06 10:58:08 127.0.0.1:61897 accepted 127.0.0.1:30001 
+2015/12/06 10:58:08 127.0.0.1:61900 accepted 127.0.0.1:30001 
+2015/12/06 10:58:08 127.0.0.1:61903 accepted 127.0.0.1:30001 
+2015/12/06 10:58:08 127.0.0.1:61906 accepted 127.0.0.1:30001 
+2015/12/06 10:58:08 127.0.0.1:61909 accepted 127.0.0.1:30001 
+2015/12/06 10:58:08 127.0.0.1:61912 accepted 127.0.0.1:30001 
+2015/12/06 10:58:08 127.0.0.1:61915 accepted 127.0.0.1:30001 
+2015/12/06 10:58:08 127.0.0.1:61918 accepted 127.0.0.1:30001 
+2015/12/06 10:58:08 127.0.0.1:61921 accepted 127.0.0.1:30001 
+2015/12/06 10:58:08 127.0.0.1:61924 accepted 127.0.0.1:30001 
+2015/12/06 10:58:08 127.0.0.1:61927 accepted 127.0.0.1:30001 
+2015/12/06 10:58:08 127.0.0.1:61930 accepted 127.0.0.1:30001 
+2015/12/06 10:58:08 127.0.0.1:61933 accepted 127.0.0.1:30001 
+2015/12/06 10:58:09 127.0.0.1:61936 accepted 127.0.0.1:30001 
+2015/12/06 10:58:09 127.0.0.1:61939 accepted 127.0.0.1:30001 
+2015/12/06 10:58:09 127.0.0.1:61942 accepted 127.0.0.1:30001 
+2015/12/06 10:58:09 127.0.0.1:61945 accepted 127.0.0.1:30001 
+2015/12/06 10:58:09 127.0.0.1:61948 accepted 127.0.0.1:30001 
+2015/12/06 10:58:09 127.0.0.1:61951 accepted 127.0.0.1:30001 
+2015/12/06 10:58:09 127.0.0.1:61954 accepted 127.0.0.1:30001 
+2015/12/06 10:58:09 127.0.0.1:61957 accepted 127.0.0.1:30001 
+2015/12/06 10:58:09 127.0.0.1:61960 accepted 127.0.0.1:30001 
+2015/12/06 10:58:09 127.0.0.1:61963 accepted 127.0.0.1:30001 
+2015/12/06 10:58:09 127.0.0.1:61966 accepted 127.0.0.1:30001 
+2015/12/06 10:58:09 127.0.0.1:61969 accepted 127.0.0.1:30001 
+2015/12/06 10:58:09 127.0.0.1:61972 accepted 127.0.0.1:30001 
+2015/12/06 10:58:09 127.0.0.1:61975 accepted 127.0.0.1:30001 
+2015/12/06 10:58:09 127.0.0.1:61978 accepted 127.0.0.1:30001 
+2015/12/06 10:58:09 127.0.0.1:61981 accepted 127.0.0.1:30001 
+2015/12/06 10:58:09 127.0.0.1:61984 accepted 127.0.0.1:30001 
+2015/12/06 10:58:09 127.0.0.1:61987 accepted 127.0.0.1:30001 
+2015/12/06 10:58:09 127.0.0.1:61990 accepted 127.0.0.1:30001 
+2015/12/06 10:58:09 127.0.0.1:61993 accepted 127.0.0.1:30001 
+2015/12/06 10:58:09 127.0.0.1:61996 accepted 127.0.0.1:30001 
+2015/12/06 10:58:09 127.0.0.1:61999 accepted 127.0.0.1:30001 
+2015/12/06 10:58:09 127.0.0.1:62002 accepted 127.0.0.1:30001 
+2015/12/06 10:58:09 127.0.0.1:62005 accepted 127.0.0.1:30001 
+2015/12/06 10:58:09 127.0.0.1:62008 accepted 127.0.0.1:30001 
+2015/12/06 10:58:09 127.0.0.1:62011 accepted 127.0.0.1:30001 
+2015/12/06 10:58:09 127.0.0.1:62014 accepted 127.0.0.1:30001 
+2015/12/06 10:58:09 127.0.0.1:62017 accepted 127.0.0.1:30001 
+2015/12/06 10:58:09 127.0.0.1:62020 accepted 127.0.0.1:30001 
+2015/12/06 10:58:09 127.0.0.1:62023 accepted 127.0.0.1:30001 
+2015/12/06 10:58:09 127.0.0.1:62026 accepted 127.0.0.1:30001 
+2015/12/06 10:58:09 127.0.0.1:62029 accepted 127.0.0.1:30001 
+2015/12/06 10:58:09 127.0.0.1:62033 accepted 127.0.0.1:30003 

+ 0 - 0
testing/scenarios/error.log