From a3bc930075eaebac8554d585e2249551b2325eff Mon Sep 17 00:00:00 2001 From: RPRX <63339210+rprx@users.noreply.github.com> Date: Wed, 26 Aug 2020 04:29:12 +0000 Subject: [PATCH] Add PROXY protocol support to WS inbound https://github.com/v2fly/v2ray-core/pull/103 --- infra/conf/transport_internet.go | 11 +++-- transport/internet/websocket/config.pb.go | 49 ++++++++++++++--------- transport/internet/websocket/config.proto | 2 + transport/internet/websocket/hub.go | 41 +++++++++---------- 4 files changed, 58 insertions(+), 45 deletions(-) diff --git a/infra/conf/transport_internet.go b/infra/conf/transport_internet.go index de1700cf9..34f9aac7d 100644 --- a/infra/conf/transport_internet.go +++ b/infra/conf/transport_internet.go @@ -134,9 +134,10 @@ func (c *TCPConfig) Build() (proto.Message, error) { } type WebSocketConfig struct { - Path string `json:"path"` - Path2 string `json:"Path"` // The key was misspelled. For backward compatibility, we have to keep track the old key. - Headers map[string]string `json:"headers"` + Path string `json:"path"` + Path2 string `json:"Path"` // The key was misspelled. For backward compatibility, we have to keep track the old key. + Headers map[string]string `json:"headers"` + AcceptProxyProtocol bool `json:"acceptProxyProtocol"` } // Build implements Buildable. @@ -152,11 +153,13 @@ func (c *WebSocketConfig) Build() (proto.Message, error) { Value: value, }) } - config := &websocket.Config{ Path: path, Header: header, } + if c.AcceptProxyProtocol { + config.AcceptProxyProtocol = c.AcceptProxyProtocol + } return config, nil } diff --git a/transport/internet/websocket/config.pb.go b/transport/internet/websocket/config.pb.go index dffcfae60..07fa6ed52 100644 --- a/transport/internet/websocket/config.pb.go +++ b/transport/internet/websocket/config.pb.go @@ -86,8 +86,9 @@ type Config struct { unknownFields protoimpl.UnknownFields // URL path to the WebSocket service. Empty value means root(/). - Path string `protobuf:"bytes,2,opt,name=path,proto3" json:"path,omitempty"` - Header []*Header `protobuf:"bytes,3,rep,name=header,proto3" json:"header,omitempty"` + Path string `protobuf:"bytes,2,opt,name=path,proto3" json:"path,omitempty"` + Header []*Header `protobuf:"bytes,3,rep,name=header,proto3" json:"header,omitempty"` + AcceptProxyProtocol bool `protobuf:"varint,4,opt,name=accept_proxy_protocol,json=acceptProxyProtocol,proto3" json:"accept_proxy_protocol,omitempty"` } func (x *Config) Reset() { @@ -136,6 +137,13 @@ func (x *Config) GetHeader() []*Header { return nil } +func (x *Config) GetAcceptProxyProtocol() bool { + if x != nil { + return x.AcceptProxyProtocol + } + return false +} + var File_transport_internet_websocket_config_proto protoreflect.FileDescriptor var file_transport_internet_websocket_config_proto_rawDesc = []byte{ @@ -147,23 +155,26 @@ var file_transport_internet_websocket_config_proto_rawDesc = []byte{ 0x63, 0x6b, 0x65, 0x74, 0x22, 0x30, 0x0a, 0x06, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x6b, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, - 0x70, 0x61, 0x74, 0x68, 0x12, 0x47, 0x0a, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x03, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2f, 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, 0x77, 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x2e, 0x48, - 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4a, 0x04, 0x08, - 0x01, 0x10, 0x02, 0x42, 0x86, 0x01, 0x0a, 0x2b, 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, 0x77, 0x65, 0x62, 0x73, 0x6f, 0x63, - 0x6b, 0x65, 0x74, 0x50, 0x01, 0x5a, 0x2b, 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, 0x77, 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, - 0x65, 0x74, 0xaa, 0x02, 0x27, 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, 0x57, 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x62, 0x06, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x33, + 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x9f, 0x01, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x47, 0x0a, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, + 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2f, 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, 0x77, 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x2e, + 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x32, + 0x0a, 0x15, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x5f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x5f, 0x70, + 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, 0x4a, 0x04, 0x08, 0x01, 0x10, 0x02, 0x42, 0x86, 0x01, 0x0a, 0x2b, 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, 0x77, + 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x50, 0x01, 0x5a, 0x2b, 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, 0x77, 0x65, + 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0xaa, 0x02, 0x27, 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, 0x57, 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, + 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/transport/internet/websocket/config.proto b/transport/internet/websocket/config.proto index 7dd5484bd..7d53f9d13 100644 --- a/transport/internet/websocket/config.proto +++ b/transport/internet/websocket/config.proto @@ -18,4 +18,6 @@ message Config { string path = 2; repeated Header header = 3; + + bool accept_proxy_protocol = 4; } diff --git a/transport/internet/websocket/hub.go b/transport/internet/websocket/hub.go index fc9d08c1d..52908d4b0 100644 --- a/transport/internet/websocket/hub.go +++ b/transport/internet/websocket/hub.go @@ -10,6 +10,8 @@ import ( "time" "github.com/gorilla/websocket" + "github.com/pires/go-proxyproto" + "v2ray.com/core/common" "v2ray.com/core/common/net" http_proto "v2ray.com/core/common/protocol/http" @@ -61,16 +63,27 @@ type Listener struct { } func ListenWS(ctx context.Context, address net.Address, port net.Port, streamSettings *internet.MemoryStreamConfig, addConn internet.ConnHandler) (internet.Listener, error) { + listener, err := internet.ListenSystem(ctx, &net.TCPAddr{ + IP: address.IP(), + Port: int(port), + }, streamSettings.SocketSettings) + if err != nil { + return nil, newError("failed to listen TCP(for WS) on", address, ":", port).Base(err) + } + newError("Listening TCP(for WS) on ", address, ":", port).WriteToLog(session.ExportIDToError(ctx)) + wsSettings := streamSettings.ProtocolSettings.(*Config) - var tlsConfig *tls.Config - if config := v2tls.ConfigFromStreamSettings(streamSettings); config != nil { - tlsConfig = config.GetTLSConfig() + if wsSettings.AcceptProxyProtocol { + policyFunc := func(upstream net.Addr) (proxyproto.Policy, error) { return proxyproto.REQUIRE, nil } + listener = &proxyproto.Listener{Listener: listener, Policy: policyFunc} + newError("Accepting PROXY protocol").AtWarning().WriteToLog(session.ExportIDToError(ctx)) } - listener, err := listenTCP(ctx, address, port, tlsConfig, streamSettings.SocketSettings) - if err != nil { - return nil, err + if config := v2tls.ConfigFromStreamSettings(streamSettings); config != nil { + if tlsConfig := config.GetTLSConfig(); tlsConfig != nil { + listener = tls.NewListener(listener, tlsConfig) + } } l := &Listener{ @@ -97,22 +110,6 @@ func ListenWS(ctx context.Context, address net.Address, port net.Port, streamSet return l, err } -func listenTCP(ctx context.Context, address net.Address, port net.Port, tlsConfig *tls.Config, sockopt *internet.SocketConfig) (net.Listener, error) { - listener, err := internet.ListenSystem(ctx, &net.TCPAddr{ - IP: address.IP(), - Port: int(port), - }, sockopt) - if err != nil { - return nil, newError("failed to listen TCP on", address, ":", port).Base(err) - } - - if tlsConfig != nil { - return tls.NewListener(listener, tlsConfig), nil - } - - return listener, nil -} - // Addr implements net.Listener.Addr(). func (ln *Listener) Addr() net.Addr { return ln.listener.Addr()