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

support dest override in dns outbound

This commit is contained in:
Darien Raymond 2019-02-12 22:34:43 +01:00
parent 6c31049295
commit 114ec4c74b
No known key found for this signature in database
GPG Key ID: 7251FFA14BB18169
7 changed files with 191 additions and 16 deletions

View File

@ -2,11 +2,25 @@ package conf
import ( import (
"github.com/golang/protobuf/proto" "github.com/golang/protobuf/proto"
"v2ray.com/core/common/net"
"v2ray.com/core/proxy/dns" "v2ray.com/core/proxy/dns"
) )
type DnsOutboundConfig struct{} type DnsOutboundConfig struct {
Network Network `json:network`
Address *Address `json:address`
Port uint16 `json:port`
}
func (c *DnsOutboundConfig) Build() (proto.Message, error) { func (c *DnsOutboundConfig) Build() (proto.Message, error) {
return new(dns.Config), nil config := &dns.Config{
Server: &net.Endpoint{
Network: c.Network.Build(),
Port: uint32(c.Port),
},
}
if c.Address != nil {
config.Server.Address = c.Address.Build()
}
return config, nil
} }

View File

@ -0,0 +1,33 @@
package conf_test
import (
"testing"
"v2ray.com/core/common/net"
. "v2ray.com/core/infra/conf"
"v2ray.com/core/proxy/dns"
)
func TestDnsProxyConfig(t *testing.T) {
creator := func() Buildable {
return new(DnsOutboundConfig)
}
runMultiTestCase(t, []TestCase{
{
Input: `{
"address": "8.8.8.8",
"port": 53,
"network": "tcp"
}`,
Parser: loadJSON(creator),
Output: &dns.Config{
Server: &net.Endpoint{
Network: net.Network_TCP,
Address: net.NewIPOrDomain(net.IPAddress([]byte{8, 8, 8, 8})),
Port: 53,
},
},
},
})
}

View File

@ -221,7 +221,9 @@ func TestV2RayConfig(t *testing.T) {
}, },
}, },
}), }),
ProxySettings: serial.ToTypedMessage(&dns_proxy.Config{}), ProxySettings: serial.ToTypedMessage(&dns_proxy.Config{
Server: &net.Endpoint{},
}),
}, },
}, },
Inbound: []*core.InboundHandlerConfig{ Inbound: []*core.InboundHandlerConfig{

View File

@ -4,6 +4,7 @@ import (
fmt "fmt" fmt "fmt"
proto "github.com/golang/protobuf/proto" proto "github.com/golang/protobuf/proto"
math "math" math "math"
net "v2ray.com/core/common/net"
) )
// Reference imports to suppress errors if they are not otherwise used. // Reference imports to suppress errors if they are not otherwise used.
@ -18,9 +19,11 @@ var _ = math.Inf
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
type Config struct { type Config struct {
XXX_NoUnkeyedLiteral struct{} `json:"-"` // Server is the DNS server address. If specified, this address overrides the original one.
XXX_unrecognized []byte `json:"-"` Server *net.Endpoint `protobuf:"bytes,1,opt,name=server,proto3" json:"server,omitempty"`
XXX_sizecache int32 `json:"-"` XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
} }
func (m *Config) Reset() { *m = Config{} } func (m *Config) Reset() { *m = Config{} }
@ -48,6 +51,13 @@ func (m *Config) XXX_DiscardUnknown() {
var xxx_messageInfo_Config proto.InternalMessageInfo var xxx_messageInfo_Config proto.InternalMessageInfo
func (m *Config) GetServer() *net.Endpoint {
if m != nil {
return m.Server
}
return nil
}
func init() { func init() {
proto.RegisterType((*Config)(nil), "v2ray.core.proxy.dns.Config") proto.RegisterType((*Config)(nil), "v2ray.core.proxy.dns.Config")
} }
@ -57,13 +67,17 @@ func init() {
} }
var fileDescriptor_c49bb2d51e576d57 = []byte{ var fileDescriptor_c49bb2d51e576d57 = []byte{
// 123 bytes of a gzipped FileDescriptorProto // 190 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x52, 0x2d, 0x33, 0x2a, 0x4a, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x8e, 0x31, 0xab, 0xc2, 0x30,
0xac, 0xd4, 0x4b, 0xce, 0xcf, 0xd5, 0x4f, 0xce, 0x2f, 0x4a, 0xd5, 0x2f, 0x28, 0xca, 0xaf, 0xa8, 0x14, 0x46, 0xe9, 0x7b, 0xd0, 0x21, 0x6f, 0x2b, 0x1d, 0xca, 0x5b, 0xde, 0x43, 0x10, 0x04, 0xe1,
0xd4, 0x4f, 0xc9, 0x2b, 0xd6, 0x4f, 0xce, 0xcf, 0x4b, 0xcb, 0x4c, 0xd7, 0x2b, 0x28, 0xca, 0x2f, 0x06, 0xea, 0xa0, 0xab, 0x56, 0xf7, 0xd2, 0xc1, 0xc1, 0xad, 0x26, 0x51, 0x32, 0xe4, 0xde, 0x72,
0xc9, 0x17, 0x12, 0x81, 0x29, 0x2b, 0x4a, 0xd5, 0x03, 0x2b, 0xd1, 0x4b, 0xc9, 0x2b, 0x56, 0xe2, 0x13, 0x8a, 0xfd, 0x4b, 0xfe, 0x4a, 0x31, 0x55, 0x10, 0x71, 0xfe, 0xce, 0x77, 0x38, 0x62, 0xda,
0xe0, 0x62, 0x73, 0x06, 0xab, 0x72, 0xb2, 0xe0, 0x92, 0x48, 0xce, 0xcf, 0xd5, 0xc3, 0xa6, 0x2a, 0x97, 0xdc, 0x0e, 0xa0, 0xc8, 0x49, 0x45, 0x6c, 0x64, 0xc7, 0x74, 0x19, 0xa4, 0x46, 0x2f, 0x15,
0x80, 0x31, 0x8a, 0x39, 0x25, 0xaf, 0x78, 0x15, 0x93, 0x48, 0x98, 0x51, 0x50, 0x62, 0xa5, 0x9e, 0xe1, 0xc9, 0x9e, 0xa1, 0x63, 0x0a, 0x94, 0xe5, 0x4f, 0x8c, 0x0d, 0x44, 0x04, 0x34, 0xfa, 0xdf,
0x33, 0x48, 0x36, 0x00, 0x2c, 0xeb, 0x92, 0x57, 0x9c, 0xc4, 0x06, 0xb6, 0xc0, 0x18, 0x10, 0x00, 0xf9, 0xdb, 0x59, 0x91, 0x73, 0x84, 0x12, 0x4d, 0x90, 0xda, 0xf8, 0x60, 0xb1, 0x0d, 0x96, 0x70,
0x00, 0xff, 0xff, 0xee, 0x22, 0xde, 0xc9, 0x89, 0x00, 0x00, 0x00, 0x54, 0x4c, 0xd6, 0x22, 0xad, 0xa2, 0x32, 0x5b, 0x8a, 0xd4, 0x1b, 0xee, 0x0d, 0x17, 0xc9, 0x7f,
0x32, 0xfb, 0x29, 0xff, 0xe0, 0xc5, 0x3e, 0x3a, 0x00, 0x4d, 0x80, 0x1d, 0xea, 0x8e, 0x2c, 0x86,
0xe6, 0x81, 0x6f, 0x56, 0xa2, 0x50, 0xe4, 0xe0, 0x53, 0x4b, 0x9d, 0x1c, 0xbe, 0x35, 0xfa, 0xeb,
0x57, 0xbe, 0x2f, 0x9b, 0x76, 0x80, 0xea, 0xbe, 0xd6, 0x71, 0xdd, 0xa2, 0x3f, 0xa6, 0xb1, 0x61,
0x71, 0x0b, 0x00, 0x00, 0xff, 0xff, 0x1c, 0x84, 0x9c, 0x79, 0xef, 0x00, 0x00, 0x00,
} }

View File

@ -6,5 +6,9 @@ option go_package = "dns";
option java_package = "com.v2ray.core.proxy.dns"; option java_package = "com.v2ray.core.proxy.dns";
option java_multiple_files = true; option java_multiple_files = true;
import "v2ray.com/core/common/net/destination.proto";
message Config { message Config {
// Server is the DNS server address. If specified, this address overrides the original one.
v2ray.core.common.net.Endpoint server = 1;
} }

View File

@ -41,6 +41,7 @@ type Handler struct {
ipv4Lookup dns.IPv4Lookup ipv4Lookup dns.IPv4Lookup
ipv6Lookup dns.IPv6Lookup ipv6Lookup dns.IPv6Lookup
ownLinkVerifier ownLinkVerifier ownLinkVerifier ownLinkVerifier
server net.Destination
} }
func (h *Handler) Init(config *Config, dnsClient dns.Client) error { func (h *Handler) Init(config *Config, dnsClient dns.Client) error {
@ -59,6 +60,10 @@ func (h *Handler) Init(config *Config, dnsClient dns.Client) error {
if v, ok := dnsClient.(ownLinkVerifier); ok { if v, ok := dnsClient.(ownLinkVerifier); ok {
h.ownLinkVerifier = v h.ownLinkVerifier = v
} }
if config.Server != nil {
h.server = config.Server.AsDestination()
}
return nil return nil
} }
@ -97,7 +102,20 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, d internet.
return newError("invalid outbound") return newError("invalid outbound")
} }
srcNetwork := outbound.Target.Network
dest := outbound.Target dest := outbound.Target
if h.server.Network != net.Network_Unknown {
dest.Network = h.server.Network
}
if h.server.Address != nil {
dest.Address = h.server.Address
}
if h.server.Port != 0 {
dest.Port = h.server.Port
}
newError("handling DNS traffic to ", dest).WriteToLog(session.ExportIDToError(ctx))
conn := &outboundConn{ conn := &outboundConn{
dialer: func() (internet.Connection, error) { dialer: func() (internet.Connection, error) {
@ -108,7 +126,7 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, d internet.
var reader dns_proto.MessageReader var reader dns_proto.MessageReader
var writer dns_proto.MessageWriter var writer dns_proto.MessageWriter
if dest.Network == net.Network_TCP { if srcNetwork == net.Network_TCP {
reader = dns_proto.NewTCPReader(link.Reader) reader = dns_proto.NewTCPReader(link.Reader)
writer = &dns_proto.TCPWriter{ writer = &dns_proto.TCPWriter{
Writer: link.Writer, Writer: link.Writer,

View File

@ -236,3 +236,93 @@ func TestTCPDNSTunnel(t *testing.T) {
t.Error(r) t.Error(r)
} }
} }
func TestUDP2TCPDNSTunnel(t *testing.T) {
port := tcp.PickPort()
dnsServer := dns.Server{
Addr: "127.0.0.1:" + port.String(),
Net: "tcp",
Handler: &staticHandler{},
}
defer dnsServer.Shutdown()
go dnsServer.ListenAndServe()
time.Sleep(time.Second)
serverPort := tcp.PickPort()
config := &core.Config{
App: []*serial.TypedMessage{
serial.ToTypedMessage(&dnsapp.Config{
NameServer: []*dnsapp.NameServer{
{
Address: &net.Endpoint{
Network: net.Network_UDP,
Address: &net.IPOrDomain{
Address: &net.IPOrDomain_Ip{
Ip: []byte{127, 0, 0, 1},
},
},
Port: uint32(port),
},
},
},
}),
serial.ToTypedMessage(&dispatcher.Config{}),
serial.ToTypedMessage(&proxyman.OutboundConfig{}),
serial.ToTypedMessage(&proxyman.InboundConfig{}),
serial.ToTypedMessage(&policy.Config{}),
},
Inbound: []*core.InboundHandlerConfig{
{
ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
Address: net.NewIPOrDomain(net.LocalHostIP),
Port: uint32(port),
Networks: []net.Network{net.Network_TCP},
}),
ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{
PortRange: net.SinglePortRange(serverPort),
Listen: net.NewIPOrDomain(net.LocalHostIP),
}),
},
},
Outbound: []*core.OutboundHandlerConfig{
{
ProxySettings: serial.ToTypedMessage(&dns_proxy.Config{
Server: &net.Endpoint{
Network: net.Network_TCP,
},
}),
},
},
}
v, err := core.New(config)
common.Must(err)
common.Must(v.Start())
defer v.Close()
m1 := new(dns.Msg)
m1.Id = dns.Id()
m1.RecursionDesired = true
m1.Question = make([]dns.Question, 1)
m1.Question[0] = dns.Question{"google.com.", dns.TypeA, dns.ClassINET}
c := &dns.Client{
Net: "tcp",
}
in, _, err := c.Exchange(m1, "127.0.0.1:"+serverPort.String())
common.Must(err)
if len(in.Answer) != 1 {
t.Fatal("len(answer): ", len(in.Answer))
}
rr, ok := in.Answer[0].(*dns.A)
if !ok {
t.Fatal("not A record")
}
if r := cmp.Diff(rr.A[:], net.IP{8, 8, 8, 8}); r != "" {
t.Error(r)
}
}