Browse Source

support dest override in dns outbound

pull/1550/head
Darien Raymond 6 years ago
parent
commit
114ec4c74b
No known key found for this signature in database
GPG Key ID: 7251FFA14BB18169
  1. 18
      infra/conf/dns_proxy.go
  2. 33
      infra/conf/dns_proxy_test.go
  3. 4
      infra/conf/v2ray_test.go
  4. 38
      proxy/dns/config.pb.go
  5. 4
      proxy/dns/config.proto
  6. 20
      proxy/dns/dns.go
  7. 90
      proxy/dns/dns_test.go

18
infra/conf/dns_proxy.go

@ -2,11 +2,25 @@ package conf
import (
"github.com/golang/protobuf/proto"
"v2ray.com/core/common/net"
"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) {
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
}

33
infra/conf/dns_proxy_test.go

@ -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,
},
},
},
})
}

4
infra/conf/v2ray_test.go

@ -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{

38
proxy/dns/config.pb.go

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

4
proxy/dns/config.proto

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

20
proxy/dns/dns.go

@ -41,6 +41,7 @@ type Handler struct {
ipv4Lookup dns.IPv4Lookup
ipv6Lookup dns.IPv6Lookup
ownLinkVerifier ownLinkVerifier
server net.Destination
}
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 {
h.ownLinkVerifier = v
}
if config.Server != nil {
h.server = config.Server.AsDestination()
}
return nil
}
@ -97,7 +102,20 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, d internet.
return newError("invalid outbound")
}
srcNetwork := outbound.Target.Network
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{
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 writer dns_proto.MessageWriter
if dest.Network == net.Network_TCP {
if srcNetwork == net.Network_TCP {
reader = dns_proto.NewTCPReader(link.Reader)
writer = &dns_proto.TCPWriter{
Writer: link.Writer,

90
proxy/dns/dns_test.go

@ -236,3 +236,93 @@ func TestTCPDNSTunnel(t *testing.T) {
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)
}
}

Loading…
Cancel
Save