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:
parent
6c31049295
commit
114ec4c74b
@ -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
Normal file
33
infra/conf/dns_proxy_test.go
Normal 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,
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
@ -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{
|
||||
|
@ -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,
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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…
Reference in New Issue
Block a user