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 (
|
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
|
||||||
}
|
}
|
||||||
|
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{
|
Inbound: []*core.InboundHandlerConfig{
|
||||||
|
@ -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,
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user