1
0
mirror of https://github.com/v2fly/v2ray-core.git synced 2024-12-21 09:36:34 -05:00

bug fixes to dns server

This commit is contained in:
v2ray 2016-05-16 11:53:18 -07:00
parent 49c8c31e26
commit 18d75cb7b4
10 changed files with 46 additions and 28 deletions

View File

@ -104,6 +104,7 @@ func (this *UDPNameServer) HandleResponse(dest v2net.Destination, payload *alloc
} }
id := msg.Id id := msg.Id
ttl := DefaultTTL ttl := DefaultTTL
log.Debug("DNS: Handling response for id ", id, " content: ", msg.String())
this.Lock() this.Lock()
request, found := this.requests[id] request, found := this.requests[id]
@ -115,10 +116,16 @@ func (this *UDPNameServer) HandleResponse(dest v2net.Destination, payload *alloc
this.Unlock() this.Unlock()
for _, rr := range msg.Answer { for _, rr := range msg.Answer {
if a, ok := rr.(*dns.A); ok { switch rr := rr.(type) {
record.IPs = append(record.IPs, a.A) case *dns.A:
if a.Hdr.Ttl < ttl { record.IPs = append(record.IPs, rr.A)
ttl = a.Hdr.Ttl 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 { func (this *UDPNameServer) QueryA(domain string) <-chan *ARecord {
response := make(chan *ARecord) response := make(chan *ARecord, 1)
buffer := alloc.NewBuffer() buffer := alloc.NewBuffer()
msg := new(dns.Msg) msg := new(dns.Msg)
@ -140,13 +147,7 @@ func (this *UDPNameServer) QueryA(domain string) <-chan *ARecord {
Name: dns.Fqdn(domain), Name: dns.Fqdn(domain),
Qtype: dns.TypeA, Qtype: dns.TypeA,
Qclass: dns.ClassINET, Qclass: dns.ClassINET,
}, }}
dns.Question{
Name: dns.Fqdn(domain),
Qtype: dns.TypeAAAA,
Qclass: dns.ClassINET,
},
}
writtenBuffer, _ := msg.PackBuffer(buffer.Value) writtenBuffer, _ := msg.PackBuffer(buffer.Value)
buffer.Slice(0, len(writtenBuffer)) buffer.Slice(0, len(writtenBuffer))
@ -161,7 +162,7 @@ type LocalNameServer struct {
} }
func (this *LocalNameServer) QueryA(domain string) <-chan *ARecord { func (this *LocalNameServer) QueryA(domain string) <-chan *ARecord {
response := make(chan *ARecord) response := make(chan *ARecord, 1)
go func() { go func() {
defer close(response) defer close(response)

View File

@ -7,12 +7,13 @@ import (
"github.com/v2ray/v2ray-core/app" "github.com/v2ray/v2ray-core/app"
"github.com/v2ray/v2ray-core/app/dispatcher" "github.com/v2ray/v2ray-core/app/dispatcher"
"github.com/v2ray/v2ray-core/common/log"
"github.com/miekg/dns" "github.com/miekg/dns"
) )
const ( const (
QueryTimeout = time.Second * 2 QueryTimeout = time.Second * 8
) )
type DomainRecord struct { type DomainRecord struct {
@ -62,16 +63,21 @@ func (this *CacheServer) Get(context app.Context, domain string) []net.IP {
for _, server := range this.servers { for _, server := range this.servers {
response := server.QueryA(domain) response := server.QueryA(domain)
select { select {
case a := <-response: case a, open := <-response:
if !open || a == nil {
continue
}
this.Lock() this.Lock()
this.records[domain] = &DomainRecord{ this.records[domain] = &DomainRecord{
A: a, A: a,
} }
this.Unlock() this.Unlock()
log.Debug("DNS: Returning ", len(a.IPs), " IPs for domain ", domain)
return a.IPs return a.IPs
case <-time.Tick(QueryTimeout): case <-time.After(QueryTimeout):
} }
} }
log.Debug("DNS: Returning nil for domain ", domain)
return nil return nil
} }

View File

@ -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("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("115.239.210.36"))).IsTrue() // image.baidu.com
assert.Bool(rule.Apply(makeDestination("120.135.126.1"))).IsTrue() 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() assert.Bool(rule.Apply(makeDestination("8.8.8.8"))).IsFalse()
} }

View File

@ -8,6 +8,7 @@ import (
"github.com/v2ray/v2ray-core/app/dns" "github.com/v2ray/v2ray-core/app/dns"
"github.com/v2ray/v2ray-core/app/router" "github.com/v2ray/v2ray-core/app/router"
"github.com/v2ray/v2ray-core/common/collect" "github.com/v2ray/v2ray-core/common/collect"
"github.com/v2ray/v2ray-core/common/log"
v2net "github.com/v2ray/v2ray-core/common/net" 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() { if this.config.DomainStrategy == UseIPIfNonMatch && dest.Address().IsDomain() {
log.Info("Router: Looking up IP for ", dest)
ipDests := this.ResolveIP(dest) ipDests := this.ResolveIP(dest)
if ipDests != nil { if ipDests != nil {
for _, ipDest := range ipDests { for _, ipDest := range ipDests {
log.Info("Router: Trying IP ", ipDest)
for _, rule := range this.config.Rules { for _, rule := range this.config.Rules {
if rule.Apply(ipDest) { if rule.Apply(ipDest) {
return rule.Tag, nil return rule.Tag, nil

View File

@ -34,7 +34,7 @@ func TestSinglePacket(t *testing.T) {
data2Send := "Data to be sent to remote" data2Send := "Data to be sent to remote"
payload := alloc.NewSmallBuffer().Clear().Append([]byte(data2Send)) 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() traffic.InboundInput().Close()
respPayload, err := traffic.InboundOutput().Read() respPayload, err := traffic.InboundOutput().Read()

View File

@ -21,7 +21,7 @@ func TestNormalRequestParsing(t *testing.T) {
request, err := ReadRequest(buffer, nil, false) request, err := ReadRequest(buffer, nil, false)
assert.Error(err).IsNil() 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)) netassert.Port(request.Port).Equals(v2net.Port(80))
assert.Bool(request.OTA).IsFalse() assert.Bool(request.OTA).IsFalse()
} }
@ -110,7 +110,7 @@ func TestUDPRequestParsing(t *testing.T) {
request, err := ReadRequest(buffer, nil, true) request, err := ReadRequest(buffer, nil, true)
assert.Error(err).IsNil() 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)) netassert.Port(request.Port).Equals(v2net.Port(80))
assert.Bool(request.OTA).IsFalse() assert.Bool(request.OTA).IsFalse()
assert.Bytes(request.UDPPayload.Value).Equals([]byte{1, 2, 3, 4, 5, 6}) assert.Bytes(request.UDPPayload.Value).Equals([]byte{1, 2, 3, 4, 5, 6})

View File

@ -56,7 +56,7 @@ func init() {
if rawConfig.Host != nil { if rawConfig.Host != nil {
socksConfig.Address = rawConfig.Host.Address socksConfig.Address = rawConfig.Host.Address
} else { } else {
socksConfig.Address = v2net.IPAddress([]byte{127, 0, 0, 1}) socksConfig.Address = v2net.LocalHostIP
} }
return socksConfig, nil return socksConfig, nil
}) })

View File

@ -192,7 +192,7 @@ func TestUDPAssociate(t *testing.T) {
for i := 0; i < 100; i++ { for i := 0; i < 100; i++ {
udpPayload := "UDP request to udp server." 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) nBytes, err = udpConn.Write(udpRequest)
assert.Int(nBytes).Equals(len(udpRequest)) assert.Int(nBytes).Equals(len(udpRequest))
@ -202,7 +202,7 @@ func TestUDPAssociate(t *testing.T) {
nBytes, err = udpConn.Read(udpResponse) nBytes, err = udpConn.Read(udpResponse)
assert.Error(err).IsNil() assert.Error(err).IsNil()
assert.Bytes(udpResponse[:nBytes]).Equals( 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() udpConn.Close()

View File

@ -28,7 +28,7 @@ func (server *Server) ServeHTTP(resp http.ResponseWriter, req *http.Request) {
func (server *Server) Start() (v2net.Destination, error) { func (server *Server) Start() (v2net.Destination, error) {
go http.ListenAndServe(":"+server.Port.String(), server) 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() { func (this *Server) Close() {

View File

@ -21,11 +21,12 @@ type TimedInboundRay struct {
sync.RWMutex sync.RWMutex
} }
func NewTimedInboundRay(name string, inboundRay ray.InboundRay) *TimedInboundRay { func NewTimedInboundRay(name string, inboundRay ray.InboundRay, server *UDPServer) *TimedInboundRay {
r := &TimedInboundRay{ r := &TimedInboundRay{
name: name, name: name,
inboundRay: inboundRay, inboundRay: inboundRay,
accessed: make(chan bool), accessed: make(chan bool, 1),
server: server,
} }
go r.Monitor() go r.Monitor()
return r return r
@ -38,6 +39,13 @@ func (this *TimedInboundRay) Monitor() {
case <-this.accessed: case <-this.accessed:
default: default:
// Ray not accessed for a while, assuming communication is dead. // 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() this.Release()
return return
} }
@ -77,7 +85,6 @@ func (this *TimedInboundRay) Release() {
if this.server == nil { if this.server == nil {
return return
} }
this.server.RemoveRay(this.name)
this.server = nil this.server = nil
this.inboundRay.InboundInput().Close() this.inboundRay.InboundInput().Close()
this.inboundRay.InboundOutput().Release() this.inboundRay.InboundOutput().Release()
@ -114,7 +121,7 @@ func (this *UDPServer) locateExistingAndDispatch(name string, payload *alloc.Buf
} }
err := outputStream.Write(payload) err := outputStream.Write(payload)
if err != nil { if err != nil {
go this.RemoveRay(name) go entry.Release()
return false return false
} }
return true 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) log.Info("UDP Server: establishing new connection for ", destString)
inboundRay := this.packetDispatcher.DispatchToOutbound(destination) inboundRay := this.packetDispatcher.DispatchToOutbound(destination)
timedInboundRay := NewTimedInboundRay(destString, inboundRay) timedInboundRay := NewTimedInboundRay(destString, inboundRay, this)
outputStream := timedInboundRay.InboundInput() outputStream := timedInboundRay.InboundInput()
if outputStream != nil { if outputStream != nil {
outputStream.Write(payload) outputStream.Write(payload)