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:
parent
49c8c31e26
commit
18d75cb7b4
@ -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)
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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()
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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()
|
||||||
|
@ -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})
|
||||||
|
@ -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
|
||||||
})
|
})
|
||||||
|
@ -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()
|
||||||
|
@ -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() {
|
||||||
|
@ -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)
|
||||||
|
Loading…
Reference in New Issue
Block a user