From 18d75cb7b4beb762a1f6959e51f363a1a8742713 Mon Sep 17 00:00:00 2001 From: v2ray Date: Mon, 16 May 2016 11:53:18 -0700 Subject: [PATCH] bug fixes to dns server --- app/dns/nameserver.go | 27 ++++++++++++++------------- app/dns/server.go | 12 +++++++++--- app/router/rules/chinaip_test.go | 1 + app/router/rules/router.go | 3 +++ proxy/freedom/freedom_test.go | 2 +- proxy/shadowsocks/protocol_test.go | 4 ++-- proxy/socks/config_json.go | 2 +- testing/scenarios/socks_end_test.go | 4 ++-- testing/servers/http/http.go | 2 +- transport/hub/udp_server.go | 17 ++++++++++++----- 10 files changed, 46 insertions(+), 28 deletions(-) diff --git a/app/dns/nameserver.go b/app/dns/nameserver.go index a0d889ff2..5401ab2d3 100644 --- a/app/dns/nameserver.go +++ b/app/dns/nameserver.go @@ -104,6 +104,7 @@ func (this *UDPNameServer) HandleResponse(dest v2net.Destination, payload *alloc } id := msg.Id ttl := DefaultTTL + log.Debug("DNS: Handling response for id ", id, " content: ", msg.String()) this.Lock() request, found := this.requests[id] @@ -115,10 +116,16 @@ func (this *UDPNameServer) HandleResponse(dest v2net.Destination, payload *alloc this.Unlock() for _, rr := range msg.Answer { - if a, ok := rr.(*dns.A); ok { - record.IPs = append(record.IPs, a.A) - if a.Hdr.Ttl < ttl { - ttl = a.Hdr.Ttl + switch rr := rr.(type) { + case *dns.A: + record.IPs = append(record.IPs, rr.A) + if rr.Hdr.Ttl < ttl { + ttl = rr.Hdr.Ttl + } + case *dns.AAAA: + record.IPs = append(record.IPs, rr.AAAA) + if rr.Hdr.Ttl < ttl { + ttl = rr.Hdr.Ttl } } } @@ -129,7 +136,7 @@ func (this *UDPNameServer) HandleResponse(dest v2net.Destination, payload *alloc } func (this *UDPNameServer) QueryA(domain string) <-chan *ARecord { - response := make(chan *ARecord) + response := make(chan *ARecord, 1) buffer := alloc.NewBuffer() msg := new(dns.Msg) @@ -140,13 +147,7 @@ func (this *UDPNameServer) QueryA(domain string) <-chan *ARecord { Name: dns.Fqdn(domain), Qtype: dns.TypeA, Qclass: dns.ClassINET, - }, - dns.Question{ - Name: dns.Fqdn(domain), - Qtype: dns.TypeAAAA, - Qclass: dns.ClassINET, - }, - } + }} writtenBuffer, _ := msg.PackBuffer(buffer.Value) buffer.Slice(0, len(writtenBuffer)) @@ -161,7 +162,7 @@ type LocalNameServer struct { } func (this *LocalNameServer) QueryA(domain string) <-chan *ARecord { - response := make(chan *ARecord) + response := make(chan *ARecord, 1) go func() { defer close(response) diff --git a/app/dns/server.go b/app/dns/server.go index 4f6834a73..686383afb 100644 --- a/app/dns/server.go +++ b/app/dns/server.go @@ -7,12 +7,13 @@ import ( "github.com/v2ray/v2ray-core/app" "github.com/v2ray/v2ray-core/app/dispatcher" + "github.com/v2ray/v2ray-core/common/log" "github.com/miekg/dns" ) const ( - QueryTimeout = time.Second * 2 + QueryTimeout = time.Second * 8 ) type DomainRecord struct { @@ -62,16 +63,21 @@ func (this *CacheServer) Get(context app.Context, domain string) []net.IP { for _, server := range this.servers { response := server.QueryA(domain) select { - case a := <-response: + case a, open := <-response: + if !open || a == nil { + continue + } this.Lock() this.records[domain] = &DomainRecord{ A: a, } this.Unlock() + log.Debug("DNS: Returning ", len(a.IPs), " IPs for domain ", domain) return a.IPs - case <-time.Tick(QueryTimeout): + case <-time.After(QueryTimeout): } } + log.Debug("DNS: Returning nil for domain ", domain) return nil } diff --git a/app/router/rules/chinaip_test.go b/app/router/rules/chinaip_test.go index 044be4ec2..86d76277b 100644 --- a/app/router/rules/chinaip_test.go +++ b/app/router/rules/chinaip_test.go @@ -22,6 +22,7 @@ func TestChinaIP(t *testing.T) { assert.Bool(rule.Apply(makeDestination("101.226.103.106"))).IsTrue() // qq.com assert.Bool(rule.Apply(makeDestination("115.239.210.36"))).IsTrue() // image.baidu.com assert.Bool(rule.Apply(makeDestination("120.135.126.1"))).IsTrue() + assert.Bool(rule.Apply(makeDestination("101.201.173.126"))).IsTrue() assert.Bool(rule.Apply(makeDestination("8.8.8.8"))).IsFalse() } diff --git a/app/router/rules/router.go b/app/router/rules/router.go index 8e755cb19..60e3a5fe0 100644 --- a/app/router/rules/router.go +++ b/app/router/rules/router.go @@ -8,6 +8,7 @@ import ( "github.com/v2ray/v2ray-core/app/dns" "github.com/v2ray/v2ray-core/app/router" "github.com/v2ray/v2ray-core/common/collect" + "github.com/v2ray/v2ray-core/common/log" v2net "github.com/v2ray/v2ray-core/common/net" ) @@ -78,9 +79,11 @@ func (this *Router) takeDetourWithoutCache(dest v2net.Destination) (string, erro } } if this.config.DomainStrategy == UseIPIfNonMatch && dest.Address().IsDomain() { + log.Info("Router: Looking up IP for ", dest) ipDests := this.ResolveIP(dest) if ipDests != nil { for _, ipDest := range ipDests { + log.Info("Router: Trying IP ", ipDest) for _, rule := range this.config.Rules { if rule.Apply(ipDest) { return rule.Tag, nil diff --git a/proxy/freedom/freedom_test.go b/proxy/freedom/freedom_test.go index 1838ca56b..a6fecee67 100644 --- a/proxy/freedom/freedom_test.go +++ b/proxy/freedom/freedom_test.go @@ -34,7 +34,7 @@ func TestSinglePacket(t *testing.T) { data2Send := "Data to be sent to remote" payload := alloc.NewSmallBuffer().Clear().Append([]byte(data2Send)) - go freedom.Dispatch(v2net.TCPDestination(v2net.IPAddress([]byte{127, 0, 0, 1}), port), payload, traffic) + go freedom.Dispatch(v2net.TCPDestination(v2net.LocalHostIP, port), payload, traffic) traffic.InboundInput().Close() respPayload, err := traffic.InboundOutput().Read() diff --git a/proxy/shadowsocks/protocol_test.go b/proxy/shadowsocks/protocol_test.go index f0fee6e38..92d25d7ef 100644 --- a/proxy/shadowsocks/protocol_test.go +++ b/proxy/shadowsocks/protocol_test.go @@ -21,7 +21,7 @@ func TestNormalRequestParsing(t *testing.T) { request, err := ReadRequest(buffer, nil, false) assert.Error(err).IsNil() - netassert.Address(request.Address).Equals(v2net.IPAddress([]byte{127, 0, 0, 1})) + netassert.Address(request.Address).Equals(v2net.LocalHostIP) netassert.Port(request.Port).Equals(v2net.Port(80)) assert.Bool(request.OTA).IsFalse() } @@ -110,7 +110,7 @@ func TestUDPRequestParsing(t *testing.T) { request, err := ReadRequest(buffer, nil, true) assert.Error(err).IsNil() - netassert.Address(request.Address).Equals(v2net.IPAddress([]byte{127, 0, 0, 1})) + netassert.Address(request.Address).Equals(v2net.LocalHostIP) netassert.Port(request.Port).Equals(v2net.Port(80)) assert.Bool(request.OTA).IsFalse() assert.Bytes(request.UDPPayload.Value).Equals([]byte{1, 2, 3, 4, 5, 6}) diff --git a/proxy/socks/config_json.go b/proxy/socks/config_json.go index ee513dc46..bcbcf5ed7 100644 --- a/proxy/socks/config_json.go +++ b/proxy/socks/config_json.go @@ -56,7 +56,7 @@ func init() { if rawConfig.Host != nil { socksConfig.Address = rawConfig.Host.Address } else { - socksConfig.Address = v2net.IPAddress([]byte{127, 0, 0, 1}) + socksConfig.Address = v2net.LocalHostIP } return socksConfig, nil }) diff --git a/testing/scenarios/socks_end_test.go b/testing/scenarios/socks_end_test.go index 56f33ea33..3831e15f2 100644 --- a/testing/scenarios/socks_end_test.go +++ b/testing/scenarios/socks_end_test.go @@ -192,7 +192,7 @@ func TestUDPAssociate(t *testing.T) { for i := 0; i < 100; i++ { udpPayload := "UDP request to udp server." - udpRequest := socks5UDPRequest(v2net.UDPDestination(v2net.IPAddress([]byte{127, 0, 0, 1}), targetPort), []byte(udpPayload)) + udpRequest := socks5UDPRequest(v2net.UDPDestination(v2net.LocalHostIP, targetPort), []byte(udpPayload)) nBytes, err = udpConn.Write(udpRequest) assert.Int(nBytes).Equals(len(udpRequest)) @@ -202,7 +202,7 @@ func TestUDPAssociate(t *testing.T) { nBytes, err = udpConn.Read(udpResponse) assert.Error(err).IsNil() assert.Bytes(udpResponse[:nBytes]).Equals( - socks5UDPRequest(v2net.UDPDestination(v2net.IPAddress([]byte{127, 0, 0, 1}), targetPort), []byte("Processed: UDP request to udp server."))) + socks5UDPRequest(v2net.UDPDestination(v2net.LocalHostIP, targetPort), []byte("Processed: UDP request to udp server."))) } udpConn.Close() diff --git a/testing/servers/http/http.go b/testing/servers/http/http.go index 112783bf9..a019d12d6 100644 --- a/testing/servers/http/http.go +++ b/testing/servers/http/http.go @@ -28,7 +28,7 @@ func (server *Server) ServeHTTP(resp http.ResponseWriter, req *http.Request) { func (server *Server) Start() (v2net.Destination, error) { go http.ListenAndServe(":"+server.Port.String(), server) - return v2net.TCPDestination(v2net.IPAddress([]byte{127, 0, 0, 1}), v2net.Port(server.Port)), nil + return v2net.TCPDestination(v2net.LocalHostIP, v2net.Port(server.Port)), nil } func (this *Server) Close() { diff --git a/transport/hub/udp_server.go b/transport/hub/udp_server.go index 8f7fdf002..06b1a93ed 100644 --- a/transport/hub/udp_server.go +++ b/transport/hub/udp_server.go @@ -21,11 +21,12 @@ type TimedInboundRay struct { sync.RWMutex } -func NewTimedInboundRay(name string, inboundRay ray.InboundRay) *TimedInboundRay { +func NewTimedInboundRay(name string, inboundRay ray.InboundRay, server *UDPServer) *TimedInboundRay { r := &TimedInboundRay{ name: name, inboundRay: inboundRay, - accessed: make(chan bool), + accessed: make(chan bool, 1), + server: server, } go r.Monitor() return r @@ -38,6 +39,13 @@ func (this *TimedInboundRay) Monitor() { case <-this.accessed: default: // Ray not accessed for a while, assuming communication is dead. + this.RLock() + if this.server == nil { + this.RUnlock() + return + } + this.server.RemoveRay(this.name) + this.RUnlock() this.Release() return } @@ -77,7 +85,6 @@ func (this *TimedInboundRay) Release() { if this.server == nil { return } - this.server.RemoveRay(this.name) this.server = nil this.inboundRay.InboundInput().Close() this.inboundRay.InboundOutput().Release() @@ -114,7 +121,7 @@ func (this *UDPServer) locateExistingAndDispatch(name string, payload *alloc.Buf } err := outputStream.Write(payload) if err != nil { - go this.RemoveRay(name) + go entry.Release() return false } return true @@ -131,7 +138,7 @@ func (this *UDPServer) Dispatch(source v2net.Destination, destination v2net.Dest log.Info("UDP Server: establishing new connection for ", destString) inboundRay := this.packetDispatcher.DispatchToOutbound(destination) - timedInboundRay := NewTimedInboundRay(destString, inboundRay) + timedInboundRay := NewTimedInboundRay(destString, inboundRay, this) outputStream := timedInboundRay.InboundInput() if outputStream != nil { outputStream.Write(payload)