From 801b9490b84260890b9dfc9cd326809c0578bcb7 Mon Sep 17 00:00:00 2001 From: lucifer9 Date: Fri, 4 Sep 2020 15:35:54 +0800 Subject: [PATCH] fix abstract UDS & add PROXY protocol support to DS inbound --- infra/conf/transport_internet.go | 12 +++-- transport/internet/domainsocket/config.go | 13 ++++- transport/internet/domainsocket/config.pb.go | 57 ++++++++++++++------ transport/internet/domainsocket/config.proto | 16 ++++-- transport/internet/domainsocket/listener.go | 24 +++++++-- 5 files changed, 90 insertions(+), 32 deletions(-) diff --git a/infra/conf/transport_internet.go b/infra/conf/transport_internet.go index 34f9aac7..14655fe5 100644 --- a/infra/conf/transport_internet.go +++ b/infra/conf/transport_internet.go @@ -219,14 +219,18 @@ func (c *QUICConfig) Build() (proto.Message, error) { } type DomainSocketConfig struct { - Path string `json:"path"` - Abstract bool `json:"abstract"` + Path string `json:"path"` + Abstract bool `json:"abstract"` + Padding bool `json:"padding"` + AcceptProxyProtocol bool `json:"acceptProxyProtocol"` } func (c *DomainSocketConfig) Build() (proto.Message, error) { return &domainsocket.Config{ - Path: c.Path, - Abstract: c.Abstract, + Path: c.Path, + Abstract: c.Abstract, + Padding: c.Padding, + AcceptProxyProtocol: c.AcceptProxyProtocol, }, nil } diff --git a/transport/internet/domainsocket/config.go b/transport/internet/domainsocket/config.go index 09cfabb2..65216212 100644 --- a/transport/internet/domainsocket/config.go +++ b/transport/internet/domainsocket/config.go @@ -9,14 +9,23 @@ import ( ) const protocolName = "domainsocket" +const sizeofSunPath = 108 func (c *Config) GetUnixAddr() (*net.UnixAddr, error) { path := c.Path if path == "" { return nil, newError("empty domain socket path") } - if c.Abstract && path[0] != '\x00' { - path = "\x00" + path + if c.Abstract && path[0] != '@' { + path = "@" + path + } + if c.Abstract && c.Padding { + raw := []byte(path) + addr := make([]byte, sizeofSunPath) + for i, c := range raw { + addr[i] = c + } + path = string(addr) } return &net.UnixAddr{ Name: path, diff --git a/transport/internet/domainsocket/config.pb.go b/transport/internet/domainsocket/config.pb.go index 722ffe21..76c61b15 100644 --- a/transport/internet/domainsocket/config.pb.go +++ b/transport/internet/domainsocket/config.pb.go @@ -30,11 +30,17 @@ type Config struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - // Path of the domain socket. This overrides the IP/Port parameter from upstream caller. + // Path of the domain socket. This overrides the IP/Port parameter from + // upstream caller. Path string `protobuf:"bytes,1,opt,name=path,proto3" json:"path,omitempty"` // Abstract speicifies whether to use abstract namespace or not. - // Traditionally Unix domain socket is file system based. Abstract domain socket can be used without acquiring file lock. + // Traditionally Unix domain socket is file system based. Abstract domain + // socket can be used without acquiring file lock. Abstract bool `protobuf:"varint,2,opt,name=abstract,proto3" json:"abstract,omitempty"` + // Some apps, eg. haproxy, use the full length of sockaddr_un.sun_path to + // connect(2) or bind(2) when using abstract UDS. + Padding bool `protobuf:"varint,3,opt,name=padding,proto3" json:"padding,omitempty"` + AcceptProxyProtocol bool `protobuf:"varint,4,opt,name=acceptProxyProtocol,proto3" json:"acceptProxyProtocol,omitempty"` } func (x *Config) Reset() { @@ -83,6 +89,20 @@ func (x *Config) GetAbstract() bool { return false } +func (x *Config) GetPadding() bool { + if x != nil { + return x.Padding + } + return false +} + +func (x *Config) GetAcceptProxyProtocol() bool { + if x != nil { + return x.AcceptProxyProtocol + } + return false +} + var File_transport_internet_domainsocket_config_proto protoreflect.FileDescriptor var file_transport_internet_domainsocket_config_proto_rawDesc = []byte{ @@ -91,20 +111,25 @@ var file_transport_internet_domainsocket_config_proto_rawDesc = []byte{ 0x74, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x2a, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x64, 0x6f, - 0x6d, 0x61, 0x69, 0x6e, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x22, 0x38, 0x0a, 0x06, 0x43, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x1a, 0x0a, 0x08, 0x61, 0x62, 0x73, 0x74, - 0x72, 0x61, 0x63, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x61, 0x62, 0x73, 0x74, - 0x72, 0x61, 0x63, 0x74, 0x42, 0x8f, 0x01, 0x0a, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x76, 0x32, 0x72, - 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, - 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x64, 0x6f, 0x6d, 0x61, 0x69, - 0x6e, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x50, 0x01, 0x5a, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, - 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, - 0x6f, 0x72, 0x74, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2f, 0x64, 0x6f, 0x6d, - 0x61, 0x69, 0x6e, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0xaa, 0x02, 0x2a, 0x56, 0x32, 0x52, 0x61, - 0x79, 0x2e, 0x43, 0x6f, 0x72, 0x65, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, - 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, - 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x6d, 0x61, 0x69, 0x6e, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x22, 0x84, 0x01, 0x0a, 0x06, 0x43, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x1a, 0x0a, 0x08, 0x61, 0x62, 0x73, + 0x74, 0x72, 0x61, 0x63, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x61, 0x62, 0x73, + 0x74, 0x72, 0x61, 0x63, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x12, + 0x30, 0x0a, 0x13, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x50, 0x72, + 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x13, 0x61, 0x63, + 0x63, 0x65, 0x70, 0x74, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, + 0x6c, 0x42, 0x8f, 0x01, 0x0a, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, + 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, + 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x73, 0x6f, + 0x63, 0x6b, 0x65, 0x74, 0x50, 0x01, 0x5a, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, + 0x6d, 0x2f, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, + 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, + 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0xaa, 0x02, 0x2a, 0x56, 0x32, 0x52, 0x61, 0x79, 0x2e, 0x43, + 0x6f, 0x72, 0x65, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x49, 0x6e, + 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53, 0x6f, 0x63, + 0x6b, 0x65, 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/transport/internet/domainsocket/config.proto b/transport/internet/domainsocket/config.proto index b79565bd..5c1086d0 100644 --- a/transport/internet/domainsocket/config.proto +++ b/transport/internet/domainsocket/config.proto @@ -7,9 +7,15 @@ option java_package = "com.v2ray.core.transport.internet.domainsocket"; option java_multiple_files = true; message Config { - // Path of the domain socket. This overrides the IP/Port parameter from upstream caller. - string path = 1; - // Abstract speicifies whether to use abstract namespace or not. - // Traditionally Unix domain socket is file system based. Abstract domain socket can be used without acquiring file lock. - bool abstract = 2; + // Path of the domain socket. This overrides the IP/Port parameter from + // upstream caller. + string path = 1; + // Abstract speicifies whether to use abstract namespace or not. + // Traditionally Unix domain socket is file system based. Abstract domain + // socket can be used without acquiring file lock. + bool abstract = 2; + // Some apps, eg. haproxy, use the full length of sockaddr_un.sun_path to + // connect(2) or bind(2) when using abstract UDS. + bool padding = 3; + bool acceptProxyProtocol = 4; } diff --git a/transport/internet/domainsocket/listener.go b/transport/internet/domainsocket/listener.go index aba951d0..9a98971e 100644 --- a/transport/internet/domainsocket/listener.go +++ b/transport/internet/domainsocket/listener.go @@ -10,10 +10,12 @@ import ( "os" "strings" + "github.com/pires/go-proxyproto" "golang.org/x/sys/unix" "v2ray.com/core/common" "v2ray.com/core/common/net" + "v2ray.com/core/common/session" "v2ray.com/core/transport/internet" "v2ray.com/core/transport/internet/tls" ) @@ -39,11 +41,23 @@ func Listen(ctx context.Context, address net.Address, port net.Port, streamSetti return nil, newError("failed to listen domain socket").Base(err).AtWarning() } - ln := &Listener{ - addr: addr, - ln: unixListener, - config: settings, - addConn: handler, + var ln *Listener + if settings.AcceptProxyProtocol { + policyFunc := func(upstream net.Addr) (proxyproto.Policy, error) { return proxyproto.REQUIRE, nil } + ln = &Listener{ + addr: addr, + ln: &proxyproto.Listener{Listener: unixListener, Policy: policyFunc}, + config: settings, + addConn: handler, + } + newError("accepting PROXY protocol").AtWarning().WriteToLog(session.ExportIDToError(ctx)) + } else { + ln = &Listener{ + addr: addr, + ln: unixListener, + config: settings, + addConn: handler, + } } if !settings.Abstract {