Skip to content

Commit

Permalink
support dest override in dns outbound
Browse files Browse the repository at this point in the history
  • Loading branch information
DarienRaymond committed Feb 12, 2019
1 parent 6c31049 commit 114ec4c
Show file tree
Hide file tree
Showing 7 changed files with 191 additions and 16 deletions.
18 changes: 16 additions & 2 deletions infra/conf/dns_proxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 changes: 33 additions & 0 deletions infra/conf/dns_proxy_test.go
Original file line number Diff line number Diff line change
@@ -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 changes: 3 additions & 1 deletion infra/conf/v2ray_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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{
Expand Down
38 changes: 26 additions & 12 deletions proxy/dns/config.pb.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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{} }
Expand Down Expand Up @@ -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")
}
Expand All @@ -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 changes: 4 additions & 0 deletions proxy/dns/config.proto
Original file line number Diff line number Diff line change
Expand Up @@ -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 changes: 19 additions & 1 deletion proxy/dns/dns.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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
}

Expand Down Expand Up @@ -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) {
Expand All @@ -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,
Expand Down
90 changes: 90 additions & 0 deletions proxy/dns/dns_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}

0 comments on commit 114ec4c

Please sign in to comment.