diff --git a/client/proxy/proxy.go b/client/proxy/proxy.go index 4bdd428..5ba63f9 100644 --- a/client/proxy/proxy.go +++ b/client/proxy/proxy.go @@ -15,7 +15,6 @@ package proxy import ( - "bytes" "context" "io" "net" @@ -149,7 +148,7 @@ func (pxy *BaseProxy) HandleTCPWorkConnection(workConn net.Conn, m *msg.StartWor } // check if we need to send proxy protocol info - var extraInfo []byte + var extraInfo plugin.ExtraInfo if baseCfg.Transport.ProxyProtocolVersion != "" { if m.SrcAddr != "" && m.SrcPort != 0 { if m.DstAddr == "" { @@ -175,16 +174,14 @@ func (pxy *BaseProxy) HandleTCPWorkConnection(workConn net.Conn, m *msg.StartWor h.Version = 2 } - buf := bytes.NewBuffer(nil) - _, _ = h.WriteTo(buf) - extraInfo = buf.Bytes() + extraInfo.ProxyProtocolHeader = h } } if pxy.proxyPlugin != nil { // if plugin is set, let plugin handle connection first xl.Debug("handle by plugin: %s", pxy.proxyPlugin.Name()) - pxy.proxyPlugin.Handle(remote, workConn, extraInfo) + pxy.proxyPlugin.Handle(remote, workConn, &extraInfo) xl.Debug("handle by plugin finished") return } @@ -202,10 +199,10 @@ func (pxy *BaseProxy) HandleTCPWorkConnection(workConn net.Conn, m *msg.StartWor xl.Debug("join connections, localConn(l[%s] r[%s]) workConn(l[%s] r[%s])", localConn.LocalAddr().String(), localConn.RemoteAddr().String(), workConn.LocalAddr().String(), workConn.RemoteAddr().String()) - if len(extraInfo) > 0 { - if _, err := localConn.Write(extraInfo); err != nil { + if extraInfo.ProxyProtocolHeader != nil { + if _, err := extraInfo.ProxyProtocolHeader.WriteTo(localConn); err != nil { workConn.Close() - xl.Error("write extraInfo to local conn error: %v", err) + xl.Error("write proxy protocol header to local conn error: %v", err) return } } diff --git a/cmd/frpc/sub/admin.go b/cmd/frpc/sub/admin.go index c5514bc..2a5f283 100644 --- a/cmd/frpc/sub/admin.go +++ b/cmd/frpc/sub/admin.go @@ -90,12 +90,12 @@ func StatusHandler(clientCfg *v1.ClientCommonConfig) error { fmt.Printf("Proxy Status...\n\n") for _, typ := range proxyTypes { - arrs := res[typ] + arrs := res[string(typ)] if len(arrs) == 0 { continue } - fmt.Println(strings.ToUpper(typ)) + fmt.Println(strings.ToUpper(string(typ))) tbl := table.New("Name", "Status", "LocalAddr", "Plugin", "RemoteAddr", "Error") for _, ps := range arrs { tbl.AddRow(ps.Name, ps.Status, ps.LocalAddr, ps.Plugin, ps.RemoteAddr, ps.Err) diff --git a/cmd/frpc/sub/proxy.go b/cmd/frpc/sub/proxy.go index d27d3fa..7ae8d35 100644 --- a/cmd/frpc/sub/proxy.go +++ b/cmd/frpc/sub/proxy.go @@ -23,24 +23,23 @@ import ( v1 "github.com/fatedier/frp/pkg/config/v1" "github.com/fatedier/frp/pkg/config/v1/validation" - "github.com/fatedier/frp/pkg/consts" ) -var proxyTypes = []string{ - consts.TCPProxy, - consts.UDPProxy, - consts.TCPMuxProxy, - consts.HTTPProxy, - consts.HTTPSProxy, - consts.STCPProxy, - consts.SUDPProxy, - consts.XTCPProxy, +var proxyTypes = []v1.ProxyType{ + v1.ProxyTypeTCP, + v1.ProxyTypeUDP, + v1.ProxyTypeTCPMUX, + v1.ProxyTypeHTTP, + v1.ProxyTypeHTTPS, + v1.ProxyTypeSTCP, + v1.ProxyTypeSUDP, + v1.ProxyTypeXTCP, } -var visitorTypes = []string{ - consts.STCPProxy, - consts.SUDPProxy, - consts.XTCPProxy, +var visitorTypes = []v1.VisitorType{ + v1.VisitorTypeSTCP, + v1.VisitorTypeSUDP, + v1.VisitorTypeXTCP, } func init() { @@ -50,17 +49,17 @@ func init() { panic("proxy type: " + typ + " not support") } clientCfg := v1.ClientCommonConfig{} - cmd := NewProxyCommand(typ, c, &clientCfg) + cmd := NewProxyCommand(string(typ), c, &clientCfg) RegisterClientCommonConfigFlags(cmd, &clientCfg) RegisterProxyFlags(cmd, c) // add sub command for visitor - if lo.Contains(visitorTypes, typ) { - vc := v1.NewVisitorConfigurerByType(typ) + if lo.Contains(visitorTypes, v1.VisitorType(typ)) { + vc := v1.NewVisitorConfigurerByType(v1.VisitorType(typ)) if vc == nil { panic("visitor type: " + typ + " not support") } - visitorCmd := NewVisitorCommand(typ, vc, &clientCfg) + visitorCmd := NewVisitorCommand(string(typ), vc, &clientCfg) RegisterVisitorFlags(visitorCmd, vc) cmd.AddCommand(visitorCmd) } diff --git a/pkg/auth/auth.go b/pkg/auth/auth.go index 4c65490..9d8db7b 100644 --- a/pkg/auth/auth.go +++ b/pkg/auth/auth.go @@ -18,7 +18,6 @@ import ( "fmt" v1 "github.com/fatedier/frp/pkg/config/v1" - "github.com/fatedier/frp/pkg/consts" "github.com/fatedier/frp/pkg/msg" ) @@ -30,9 +29,9 @@ type Setter interface { func NewAuthSetter(cfg v1.AuthClientConfig) (authProvider Setter) { switch cfg.Method { - case consts.TokenAuthMethod: + case v1.AuthMethodToken: authProvider = NewTokenAuth(cfg.AdditionalScopes, cfg.Token) - case consts.OidcAuthMethod: + case v1.AuthMethodOIDC: authProvider = NewOidcAuthSetter(cfg.AdditionalScopes, cfg.OIDC) default: panic(fmt.Sprintf("wrong method: '%s'", cfg.Method)) @@ -48,9 +47,9 @@ type Verifier interface { func NewAuthVerifier(cfg v1.AuthServerConfig) (authVerifier Verifier) { switch cfg.Method { - case consts.TokenAuthMethod: + case v1.AuthMethodToken: authVerifier = NewTokenAuth(cfg.AdditionalScopes, cfg.Token) - case consts.OidcAuthMethod: + case v1.AuthMethodOIDC: authVerifier = NewOidcAuthVerifier(cfg.AdditionalScopes, cfg.OIDC) } return authVerifier diff --git a/pkg/config/legacy/conversion.go b/pkg/config/legacy/conversion.go index 2540217..189cd73 100644 --- a/pkg/config/legacy/conversion.go +++ b/pkg/config/legacy/conversion.go @@ -26,7 +26,7 @@ import ( func Convert_ClientCommonConf_To_v1(conf *ClientCommonConf) *v1.ClientCommonConfig { out := &v1.ClientCommonConfig{} out.User = conf.User - out.Auth.Method = conf.ClientConfig.AuthenticationMethod + out.Auth.Method = v1.AuthMethod(conf.ClientConfig.AuthenticationMethod) out.Auth.Token = conf.ClientConfig.Token if conf.ClientConfig.AuthenticateHeartBeats { out.Auth.AdditionalScopes = append(out.Auth.AdditionalScopes, v1.AuthScopeHeartBeats) @@ -86,7 +86,7 @@ func Convert_ClientCommonConf_To_v1(conf *ClientCommonConf) *v1.ClientCommonConf func Convert_ServerCommonConf_To_v1(conf *ServerCommonConf) *v1.ServerConfig { out := &v1.ServerConfig{} - out.Auth.Method = conf.ServerConfig.AuthenticationMethod + out.Auth.Method = v1.AuthMethod(conf.ServerConfig.AuthenticationMethod) out.Auth.Token = conf.ServerConfig.Token if conf.ServerConfig.AuthenticateHeartBeats { out.Auth.AdditionalScopes = append(out.Auth.AdditionalScopes, v1.AuthScopeHeartBeats) diff --git a/pkg/config/legacy/proxy.go b/pkg/config/legacy/proxy.go index a6ce55a..e6653ee 100644 --- a/pkg/config/legacy/proxy.go +++ b/pkg/config/legacy/proxy.go @@ -21,20 +21,32 @@ import ( "gopkg.in/ini.v1" "github.com/fatedier/frp/pkg/config/types" - "github.com/fatedier/frp/pkg/consts" +) + +type ProxyType string + +const ( + ProxyTypeTCP ProxyType = "tcp" + ProxyTypeUDP ProxyType = "udp" + ProxyTypeTCPMUX ProxyType = "tcpmux" + ProxyTypeHTTP ProxyType = "http" + ProxyTypeHTTPS ProxyType = "https" + ProxyTypeSTCP ProxyType = "stcp" + ProxyTypeXTCP ProxyType = "xtcp" + ProxyTypeSUDP ProxyType = "sudp" ) // Proxy var ( - proxyConfTypeMap = map[string]reflect.Type{ - consts.TCPProxy: reflect.TypeOf(TCPProxyConf{}), - consts.TCPMuxProxy: reflect.TypeOf(TCPMuxProxyConf{}), - consts.UDPProxy: reflect.TypeOf(UDPProxyConf{}), - consts.HTTPProxy: reflect.TypeOf(HTTPProxyConf{}), - consts.HTTPSProxy: reflect.TypeOf(HTTPSProxyConf{}), - consts.STCPProxy: reflect.TypeOf(STCPProxyConf{}), - consts.XTCPProxy: reflect.TypeOf(XTCPProxyConf{}), - consts.SUDPProxy: reflect.TypeOf(SUDPProxyConf{}), + proxyConfTypeMap = map[ProxyType]reflect.Type{ + ProxyTypeTCP: reflect.TypeOf(TCPProxyConf{}), + ProxyTypeUDP: reflect.TypeOf(UDPProxyConf{}), + ProxyTypeTCPMUX: reflect.TypeOf(TCPMuxProxyConf{}), + ProxyTypeHTTP: reflect.TypeOf(HTTPProxyConf{}), + ProxyTypeHTTPS: reflect.TypeOf(HTTPSProxyConf{}), + ProxyTypeSTCP: reflect.TypeOf(STCPProxyConf{}), + ProxyTypeXTCP: reflect.TypeOf(XTCPProxyConf{}), + ProxyTypeSUDP: reflect.TypeOf(SUDPProxyConf{}), } ) @@ -46,7 +58,7 @@ type ProxyConf interface { UnmarshalFromIni(string, string, *ini.Section) error } -func NewConfByType(proxyType string) ProxyConf { +func NewConfByType(proxyType ProxyType) ProxyConf { v, ok := proxyConfTypeMap[proxyType] if !ok { return nil @@ -58,16 +70,16 @@ func NewConfByType(proxyType string) ProxyConf { // Proxy Conf Loader // DefaultProxyConf creates a empty ProxyConf object by proxyType. // If proxyType doesn't exist, return nil. -func DefaultProxyConf(proxyType string) ProxyConf { +func DefaultProxyConf(proxyType ProxyType) ProxyConf { return NewConfByType(proxyType) } // Proxy loaded from ini func NewProxyConfFromIni(prefix, name string, section *ini.Section) (ProxyConf, error) { // section.Key: if key not exists, section will set it with default value. - proxyType := section.Key("type").String() + proxyType := ProxyType(section.Key("type").String()) if proxyType == "" { - proxyType = consts.TCPProxy + proxyType = ProxyTypeTCP } conf := DefaultProxyConf(proxyType) diff --git a/pkg/config/legacy/visitor.go b/pkg/config/legacy/visitor.go index 5ee36a1..031c29b 100644 --- a/pkg/config/legacy/visitor.go +++ b/pkg/config/legacy/visitor.go @@ -19,16 +19,22 @@ import ( "reflect" "gopkg.in/ini.v1" +) - "github.com/fatedier/frp/pkg/consts" +type VisitorType string + +const ( + VisitorTypeSTCP VisitorType = "stcp" + VisitorTypeXTCP VisitorType = "xtcp" + VisitorTypeSUDP VisitorType = "sudp" ) // Visitor var ( - visitorConfTypeMap = map[string]reflect.Type{ - consts.STCPProxy: reflect.TypeOf(STCPVisitorConf{}), - consts.XTCPProxy: reflect.TypeOf(XTCPVisitorConf{}), - consts.SUDPProxy: reflect.TypeOf(SUDPVisitorConf{}), + visitorConfTypeMap = map[VisitorType]reflect.Type{ + VisitorTypeSTCP: reflect.TypeOf(STCPVisitorConf{}), + VisitorTypeXTCP: reflect.TypeOf(XTCPVisitorConf{}), + VisitorTypeSUDP: reflect.TypeOf(SUDPVisitorConf{}), } ) @@ -41,7 +47,7 @@ type VisitorConf interface { // DefaultVisitorConf creates a empty VisitorConf object by visitorType. // If visitorType doesn't exist, return nil. -func DefaultVisitorConf(visitorType string) VisitorConf { +func DefaultVisitorConf(visitorType VisitorType) VisitorConf { v, ok := visitorConfTypeMap[visitorType] if !ok { return nil @@ -161,7 +167,7 @@ func (cfg *XTCPVisitorConf) UnmarshalFromIni(prefix string, name string, section // Visitor loaded from ini func NewVisitorConfFromIni(prefix string, name string, section *ini.Section) (VisitorConf, error) { // section.Key: if key not exists, section will set it with default value. - visitorType := section.Key("type").String() + visitorType := VisitorType(section.Key("type").String()) if visitorType == "" { return nil, fmt.Errorf("type shouldn't be empty") diff --git a/pkg/config/load.go b/pkg/config/load.go index 739c4a8..af2c3e8 100644 --- a/pkg/config/load.go +++ b/pkg/config/load.go @@ -32,7 +32,6 @@ import ( "github.com/fatedier/frp/pkg/config/legacy" v1 "github.com/fatedier/frp/pkg/config/v1" "github.com/fatedier/frp/pkg/config/v1/validation" - "github.com/fatedier/frp/pkg/consts" "github.com/fatedier/frp/pkg/msg" "github.com/fatedier/frp/pkg/util/util" ) @@ -124,9 +123,9 @@ func LoadConfigure(b []byte, c any) error { } func NewProxyConfigurerFromMsg(m *msg.NewProxy, serverCfg *v1.ServerConfig) (v1.ProxyConfigurer, error) { - m.ProxyType = util.EmptyOr(m.ProxyType, consts.TCPProxy) + m.ProxyType = util.EmptyOr(m.ProxyType, string(v1.ProxyTypeTCP)) - configurer := v1.NewProxyConfigurerByType(m.ProxyType) + configurer := v1.NewProxyConfigurerByType(v1.ProxyType(m.ProxyType)) if configurer == nil { return nil, fmt.Errorf("unknown proxy type: %s", m.ProxyType) } diff --git a/pkg/config/v1/client.go b/pkg/config/v1/client.go index 6c68738..76e3171 100644 --- a/pkg/config/v1/client.go +++ b/pkg/config/v1/client.go @@ -165,7 +165,7 @@ type AuthClientConfig struct { // authenticate frpc with frps. If "token" is specified - token will be // read into login message. If "oidc" is specified - OIDC (Open ID Connect) // token will be issued using OIDC settings. By default, this value is "token". - Method string `json:"method,omitempty"` + Method AuthMethod `json:"method,omitempty"` // Specify whether to include auth info in additional scope. // Current supported scopes are: "HeartBeats", "NewWorkConns". AdditionalScopes []AuthScope `json:"additionalScopes,omitempty"` diff --git a/pkg/config/v1/client_test.go b/pkg/config/v1/client_test.go index 01acbf0..9a3662c 100644 --- a/pkg/config/v1/client_test.go +++ b/pkg/config/v1/client_test.go @@ -26,7 +26,7 @@ func TestClientConfigComplete(t *testing.T) { c := &ClientConfig{} c.Complete() - require.Equal("token", c.Auth.Method) + require.EqualValues("token", c.Auth.Method) require.Equal(true, lo.FromPtr(c.Transport.TCPMux)) require.Equal(true, lo.FromPtr(c.LoginFailExit)) require.Equal(true, lo.FromPtr(c.Transport.TLS.Enable)) diff --git a/pkg/config/v1/common.go b/pkg/config/v1/common.go index dcb7b5e..be4e39a 100644 --- a/pkg/config/v1/common.go +++ b/pkg/config/v1/common.go @@ -25,6 +25,13 @@ const ( AuthScopeNewWorkConns AuthScope = "NewWorkConns" ) +type AuthMethod string + +const ( + AuthMethodToken AuthMethod = "token" + AuthMethodOIDC AuthMethod = "oidc" +) + // QUIC protocol options type QUICOptions struct { KeepalivePeriod int `json:"quicKeepalivePeriod,omitempty" validate:"gte=0"` diff --git a/pkg/config/v1/proxy.go b/pkg/config/v1/proxy.go index 60107ed..dc09c6b 100644 --- a/pkg/config/v1/proxy.go +++ b/pkg/config/v1/proxy.go @@ -23,7 +23,6 @@ import ( "github.com/samber/lo" "github.com/fatedier/frp/pkg/config/types" - "github.com/fatedier/frp/pkg/consts" "github.com/fatedier/frp/pkg/msg" "github.com/fatedier/frp/pkg/util/util" ) @@ -174,7 +173,7 @@ func (c *TypedProxyConfig) UnmarshalJSON(b []byte) error { } c.Type = typeStruct.Type - configurer := NewProxyConfigurerByType(typeStruct.Type) + configurer := NewProxyConfigurerByType(ProxyType(typeStruct.Type)) if configurer == nil { return fmt.Errorf("unknown proxy type: %s", typeStruct.Type) } @@ -196,18 +195,31 @@ type ProxyConfigurer interface { UnmarshalFromMsg(*msg.NewProxy) } -var proxyConfigTypeMap = map[string]reflect.Type{ - consts.TCPProxy: reflect.TypeOf(TCPProxyConfig{}), - consts.UDPProxy: reflect.TypeOf(UDPProxyConfig{}), - consts.HTTPProxy: reflect.TypeOf(HTTPProxyConfig{}), - consts.HTTPSProxy: reflect.TypeOf(HTTPSProxyConfig{}), - consts.TCPMuxProxy: reflect.TypeOf(TCPMuxProxyConfig{}), - consts.STCPProxy: reflect.TypeOf(STCPProxyConfig{}), - consts.XTCPProxy: reflect.TypeOf(XTCPProxyConfig{}), - consts.SUDPProxy: reflect.TypeOf(SUDPProxyConfig{}), +type ProxyType string + +const ( + ProxyTypeTCP ProxyType = "tcp" + ProxyTypeUDP ProxyType = "udp" + ProxyTypeTCPMUX ProxyType = "tcpmux" + ProxyTypeHTTP ProxyType = "http" + ProxyTypeHTTPS ProxyType = "https" + ProxyTypeSTCP ProxyType = "stcp" + ProxyTypeXTCP ProxyType = "xtcp" + ProxyTypeSUDP ProxyType = "sudp" +) + +var proxyConfigTypeMap = map[ProxyType]reflect.Type{ + ProxyTypeTCP: reflect.TypeOf(TCPProxyConfig{}), + ProxyTypeUDP: reflect.TypeOf(UDPProxyConfig{}), + ProxyTypeHTTP: reflect.TypeOf(HTTPProxyConfig{}), + ProxyTypeHTTPS: reflect.TypeOf(HTTPSProxyConfig{}), + ProxyTypeTCPMUX: reflect.TypeOf(TCPMuxProxyConfig{}), + ProxyTypeSTCP: reflect.TypeOf(STCPProxyConfig{}), + ProxyTypeXTCP: reflect.TypeOf(XTCPProxyConfig{}), + ProxyTypeSUDP: reflect.TypeOf(SUDPProxyConfig{}), } -func NewProxyConfigurerByType(proxyType string) ProxyConfigurer { +func NewProxyConfigurerByType(proxyType ProxyType) ProxyConfigurer { v, ok := proxyConfigTypeMap[proxyType] if !ok { return nil @@ -316,6 +328,12 @@ func (c *HTTPSProxyConfig) UnmarshalFromMsg(m *msg.NewProxy) { c.SubDomain = m.SubDomain } +type TCPMultiplexerType string + +const ( + TCPMultiplexerHTTPConnect TCPMultiplexerType = "httpconnect" +) + var _ ProxyConfigurer = &TCPMuxProxyConfig{} type TCPMuxProxyConfig struct { diff --git a/pkg/config/v1/server.go b/pkg/config/v1/server.go index 53d758d..380bd2d 100644 --- a/pkg/config/v1/server.go +++ b/pkg/config/v1/server.go @@ -120,7 +120,7 @@ func (c *ServerConfig) Complete() { } type AuthServerConfig struct { - Method string `json:"method,omitempty"` + Method AuthMethod `json:"method,omitempty"` AdditionalScopes []AuthScope `json:"additionalScopes,omitempty"` Token string `json:"token,omitempty"` OIDC AuthOIDCServerConfig `json:"oidc,omitempty"` diff --git a/pkg/config/v1/server_test.go b/pkg/config/v1/server_test.go index 8ce5b2c..3100fc4 100644 --- a/pkg/config/v1/server_test.go +++ b/pkg/config/v1/server_test.go @@ -26,7 +26,7 @@ func TestServerConfigComplete(t *testing.T) { c := &ServerConfig{} c.Complete() - require.Equal("token", c.Auth.Method) + require.EqualValues("token", c.Auth.Method) require.Equal(true, lo.FromPtr(c.Transport.TCPMux)) require.Equal(true, lo.FromPtr(c.DetailedErrorsToClient)) } diff --git a/pkg/config/v1/validation/proxy.go b/pkg/config/v1/validation/proxy.go index c53cf7f..65970e9 100644 --- a/pkg/config/v1/validation/proxy.go +++ b/pkg/config/v1/validation/proxy.go @@ -22,7 +22,6 @@ import ( "github.com/samber/lo" v1 "github.com/fatedier/frp/pkg/config/v1" - "github.com/fatedier/frp/pkg/consts" ) func validateProxyBaseConfigForClient(c *v1.ProxyBaseConfig) error { @@ -134,7 +133,7 @@ func validateTCPMuxProxyConfigForClient(c *v1.TCPMuxProxyConfig) error { return err } - if !lo.Contains([]string{consts.HTTPConnectTCPMultiplexer}, c.Multiplexer) { + if !lo.Contains([]string{string(v1.TCPMultiplexerHTTPConnect)}, c.Multiplexer) { return fmt.Errorf("not support multiplexer: %s", c.Multiplexer) } return nil @@ -197,7 +196,7 @@ func validateUDPProxyConfigForServer(c *v1.UDPProxyConfig, s *v1.ServerConfig) e } func validateTCPMuxProxyConfigForServer(c *v1.TCPMuxProxyConfig, s *v1.ServerConfig) error { - if c.Multiplexer == consts.HTTPConnectTCPMultiplexer && + if c.Multiplexer == string(v1.TCPMultiplexerHTTPConnect) && s.TCPMuxHTTPConnectPort == 0 { return fmt.Errorf("tcpmux with multiplexer httpconnect not supported because this feature is not enabled in server") } diff --git a/pkg/config/v1/validation/validation.go b/pkg/config/v1/validation/validation.go index dcce5f7..4ca6b67 100644 --- a/pkg/config/v1/validation/validation.go +++ b/pkg/config/v1/validation/validation.go @@ -30,7 +30,7 @@ var ( "wss", } - SupportedAuthMethods = []string{ + SupportedAuthMethods = []v1.AuthMethod{ "token", "oidc", } diff --git a/pkg/config/v1/visitor.go b/pkg/config/v1/visitor.go index 6e22988..90ecd86 100644 --- a/pkg/config/v1/visitor.go +++ b/pkg/config/v1/visitor.go @@ -22,7 +22,6 @@ import ( "github.com/samber/lo" - "github.com/fatedier/frp/pkg/consts" "github.com/fatedier/frp/pkg/util/util" ) @@ -73,10 +72,18 @@ type VisitorConfigurer interface { GetBaseConfig() *VisitorBaseConfig } -var visitorConfigTypeMap = map[string]reflect.Type{ - consts.STCPProxy: reflect.TypeOf(STCPVisitorConfig{}), - consts.XTCPProxy: reflect.TypeOf(XTCPVisitorConfig{}), - consts.SUDPProxy: reflect.TypeOf(SUDPVisitorConfig{}), +type VisitorType string + +const ( + VisitorTypeSTCP VisitorType = "stcp" + VisitorTypeXTCP VisitorType = "xtcp" + VisitorTypeSUDP VisitorType = "sudp" +) + +var visitorConfigTypeMap = map[VisitorType]reflect.Type{ + VisitorTypeSTCP: reflect.TypeOf(STCPVisitorConfig{}), + VisitorTypeXTCP: reflect.TypeOf(XTCPVisitorConfig{}), + VisitorTypeSUDP: reflect.TypeOf(SUDPVisitorConfig{}), } type TypedVisitorConfig struct { @@ -97,7 +104,7 @@ func (c *TypedVisitorConfig) UnmarshalJSON(b []byte) error { } c.Type = typeStruct.Type - configurer := NewVisitorConfigurerByType(typeStruct.Type) + configurer := NewVisitorConfigurerByType(VisitorType(typeStruct.Type)) if configurer == nil { return fmt.Errorf("unknown visitor type: %s", typeStruct.Type) } @@ -108,7 +115,7 @@ func (c *TypedVisitorConfig) UnmarshalJSON(b []byte) error { return nil } -func NewVisitorConfigurerByType(t string) VisitorConfigurer { +func NewVisitorConfigurerByType(t VisitorType) VisitorConfigurer { v, ok := visitorConfigTypeMap[t] if !ok { return nil diff --git a/pkg/consts/consts.go b/pkg/consts/consts.go deleted file mode 100644 index 9e44383..0000000 --- a/pkg/consts/consts.go +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright 2016 fatedier, fatedier@gmail.com -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package consts - -var ( - // proxy status - Idle = "idle" - Working = "working" - Closed = "closed" - Online = "online" - Offline = "offline" - - // proxy type - TCPProxy = "tcp" - UDPProxy = "udp" - TCPMuxProxy = "tcpmux" - HTTPProxy = "http" - HTTPSProxy = "https" - STCPProxy = "stcp" - XTCPProxy = "xtcp" - SUDPProxy = "sudp" - - // authentication method - TokenAuthMethod = "token" - OidcAuthMethod = "oidc" - - // TCP multiplexer - HTTPConnectTCPMultiplexer = "httpconnect" -) diff --git a/pkg/plugin/client/http2https.go b/pkg/plugin/client/http2https.go index 712a24b..7f093af 100644 --- a/pkg/plugin/client/http2https.go +++ b/pkg/plugin/client/http2https.go @@ -76,7 +76,7 @@ func NewHTTP2HTTPSPlugin(options v1.ClientPluginOptions) (Plugin, error) { return p, nil } -func (p *HTTP2HTTPSPlugin) Handle(conn io.ReadWriteCloser, realConn net.Conn, _ []byte) { +func (p *HTTP2HTTPSPlugin) Handle(conn io.ReadWriteCloser, realConn net.Conn, _ *ExtraInfo) { wrapConn := utilnet.WrapReadWriteCloserToConn(conn, realConn) _ = p.l.PutConn(wrapConn) } diff --git a/pkg/plugin/client/http_proxy.go b/pkg/plugin/client/http_proxy.go index 6af7c10..06c6296 100644 --- a/pkg/plugin/client/http_proxy.go +++ b/pkg/plugin/client/http_proxy.go @@ -65,7 +65,7 @@ func (hp *HTTPProxy) Name() string { return v1.PluginHTTPProxy } -func (hp *HTTPProxy) Handle(conn io.ReadWriteCloser, realConn net.Conn, _ []byte) { +func (hp *HTTPProxy) Handle(conn io.ReadWriteCloser, realConn net.Conn, _ *ExtraInfo) { wrapConn := utilnet.WrapReadWriteCloserToConn(conn, realConn) sc, rd := libnet.NewSharedConn(wrapConn) diff --git a/pkg/plugin/client/https2http.go b/pkg/plugin/client/https2http.go index 0adfabf..aa498f3 100644 --- a/pkg/plugin/client/https2http.go +++ b/pkg/plugin/client/https2http.go @@ -95,7 +95,7 @@ func (p *HTTPS2HTTPPlugin) genTLSConfig() (*tls.Config, error) { return config, nil } -func (p *HTTPS2HTTPPlugin) Handle(conn io.ReadWriteCloser, realConn net.Conn, _ []byte) { +func (p *HTTPS2HTTPPlugin) Handle(conn io.ReadWriteCloser, realConn net.Conn, _ *ExtraInfo) { wrapConn := utilnet.WrapReadWriteCloserToConn(conn, realConn) _ = p.l.PutConn(wrapConn) } diff --git a/pkg/plugin/client/https2https.go b/pkg/plugin/client/https2https.go index 374755e..fc38f62 100644 --- a/pkg/plugin/client/https2https.go +++ b/pkg/plugin/client/https2https.go @@ -101,7 +101,7 @@ func (p *HTTPS2HTTPSPlugin) genTLSConfig() (*tls.Config, error) { return config, nil } -func (p *HTTPS2HTTPSPlugin) Handle(conn io.ReadWriteCloser, realConn net.Conn, _ []byte) { +func (p *HTTPS2HTTPSPlugin) Handle(conn io.ReadWriteCloser, realConn net.Conn, _ *ExtraInfo) { wrapConn := utilnet.WrapReadWriteCloserToConn(conn, realConn) _ = p.l.PutConn(wrapConn) } diff --git a/pkg/plugin/client/plugin.go b/pkg/plugin/client/plugin.go index da0ceb5..520e379 100644 --- a/pkg/plugin/client/plugin.go +++ b/pkg/plugin/client/plugin.go @@ -21,6 +21,7 @@ import ( "sync" "github.com/fatedier/golib/errors" + pp "github.com/pires/go-proxyproto" v1 "github.com/fatedier/frp/pkg/config/v1" ) @@ -47,11 +48,14 @@ func Create(name string, options v1.ClientPluginOptions) (p Plugin, err error) { return } +type ExtraInfo struct { + ProxyProtocolHeader *pp.Header +} + type Plugin interface { Name() string - // extraBufToLocal will send to local connection first, then join conn with local connection - Handle(conn io.ReadWriteCloser, realConn net.Conn, extraBufToLocal []byte) + Handle(conn io.ReadWriteCloser, realConn net.Conn, extra *ExtraInfo) Close() error } diff --git a/pkg/plugin/client/socks5.go b/pkg/plugin/client/socks5.go index f71d579..c2e253d 100644 --- a/pkg/plugin/client/socks5.go +++ b/pkg/plugin/client/socks5.go @@ -48,7 +48,7 @@ func NewSocks5Plugin(options v1.ClientPluginOptions) (p Plugin, err error) { return } -func (sp *Socks5Plugin) Handle(conn io.ReadWriteCloser, realConn net.Conn, _ []byte) { +func (sp *Socks5Plugin) Handle(conn io.ReadWriteCloser, realConn net.Conn, _ *ExtraInfo) { defer conn.Close() wrapConn := utilnet.WrapReadWriteCloserToConn(conn, realConn) _ = sp.Server.ServeConn(wrapConn) diff --git a/pkg/plugin/client/static_file.go b/pkg/plugin/client/static_file.go index 9140ffd..20b79a0 100644 --- a/pkg/plugin/client/static_file.go +++ b/pkg/plugin/client/static_file.go @@ -66,7 +66,7 @@ func NewStaticFilePlugin(options v1.ClientPluginOptions) (Plugin, error) { return sp, nil } -func (sp *StaticFilePlugin) Handle(conn io.ReadWriteCloser, realConn net.Conn, _ []byte) { +func (sp *StaticFilePlugin) Handle(conn io.ReadWriteCloser, realConn net.Conn, _ *ExtraInfo) { wrapConn := utilnet.WrapReadWriteCloserToConn(conn, realConn) _ = sp.l.PutConn(wrapConn) } diff --git a/pkg/plugin/client/unix_domain_socket.go b/pkg/plugin/client/unix_domain_socket.go index 266a529..f186ec9 100644 --- a/pkg/plugin/client/unix_domain_socket.go +++ b/pkg/plugin/client/unix_domain_socket.go @@ -46,13 +46,13 @@ func NewUnixDomainSocketPlugin(options v1.ClientPluginOptions) (p Plugin, err er return } -func (uds *UnixDomainSocketPlugin) Handle(conn io.ReadWriteCloser, _ net.Conn, extraBufToLocal []byte) { +func (uds *UnixDomainSocketPlugin) Handle(conn io.ReadWriteCloser, _ net.Conn, extra *ExtraInfo) { localConn, err := net.DialUnix("unix", nil, uds.UnixAddr) if err != nil { return } - if len(extraBufToLocal) > 0 { - if _, err := localConn.Write(extraBufToLocal); err != nil { + if extra.ProxyProtocolHeader != nil { + if _, err := extra.ProxyProtocolHeader.WriteTo(localConn); err != nil { return } } diff --git a/pkg/util/version/version.go b/pkg/util/version/version.go index 9a91359..32a9458 100644 --- a/pkg/util/version/version.go +++ b/pkg/util/version/version.go @@ -45,38 +45,3 @@ func Major(v string) int64 { func Minor(v string) int64 { return getSubVersion(v, 2) } - -// add every case there if server will not accept client's protocol and return false -func Compat(client string) (ok bool, msg string) { - if LessThan(client, "0.18.0") { - return false, "Please upgrade your frpc version to at least 0.18.0" - } - return true, "" -} - -func LessThan(client string, server string) bool { - vc := Proto(client) - vs := Proto(server) - if vc > vs { - return false - } else if vc < vs { - return true - } - - vc = Major(client) - vs = Major(server) - if vc > vs { - return false - } else if vc < vs { - return true - } - - vc = Minor(client) - vs = Minor(server) - if vc > vs { - return false - } else if vc < vs { - return true - } - return false -} diff --git a/pkg/util/version/version_test.go b/pkg/util/version/version_test.go index a77bf42..73b96a8 100644 --- a/pkg/util/version/version_test.go +++ b/pkg/util/version/version_test.go @@ -51,15 +51,3 @@ func TestVersion(t *testing.T) { version := Full() assert.Equal(parseVerion, version) } - -func TestCompact(t *testing.T) { - assert := assert.New(t) - ok, _ := Compat("0.9.0") - assert.False(ok) - - ok, _ = Compat("10.0.0") - assert.True(ok) - - ok, _ = Compat("0.10.0") - assert.False(ok) -} diff --git a/server/control.go b/server/control.go index 5f6eb9f..f2eaaa5 100644 --- a/server/control.go +++ b/server/control.go @@ -568,7 +568,15 @@ func (ctl *Control) RegisterProxy(pxyMsg *msg.NewProxy) (remoteAddr string, err // NewProxy will return an interface Proxy. // In fact, it creates different proxies based on the proxy type. We just call run() here. - pxy, err := proxy.NewProxy(ctl.ctx, userInfo, ctl.rc, ctl.poolCount, ctl.GetWorkConn, pxyConf, ctl.serverCfg, ctl.loginMsg) + pxy, err := proxy.NewProxy(ctl.ctx, &proxy.Options{ + UserInfo: userInfo, + LoginMsg: ctl.loginMsg, + PoolCount: ctl.poolCount, + ResourceController: ctl.rc, + GetWorkConnFn: ctl.GetWorkConn, + Configurer: pxyConf, + ServerCfg: ctl.serverCfg, + }) if err != nil { return remoteAddr, err } diff --git a/server/dashboard_api.go b/server/dashboard_api.go index 7a4fdff..56faac3 100644 --- a/server/dashboard_api.go +++ b/server/dashboard_api.go @@ -22,7 +22,6 @@ import ( "github.com/fatedier/frp/pkg/config/types" v1 "github.com/fatedier/frp/pkg/config/v1" - "github.com/fatedier/frp/pkg/consts" "github.com/fatedier/frp/pkg/metrics/mem" "github.com/fatedier/frp/pkg/util/log" "github.com/fatedier/frp/pkg/util/version" @@ -139,21 +138,21 @@ type XTCPOutConf struct { BaseOutConf } -func getConfByType(proxyType string) interface{} { - switch proxyType { - case consts.TCPProxy: +func getConfByType(proxyType string) any { + switch v1.ProxyType(proxyType) { + case v1.ProxyTypeTCP: return &TCPOutConf{} - case consts.TCPMuxProxy: + case v1.ProxyTypeTCPMUX: return &TCPMuxOutConf{} - case consts.UDPProxy: + case v1.ProxyTypeUDP: return &UDPOutConf{} - case consts.HTTPProxy: + case v1.ProxyTypeHTTP: return &HTTPOutConf{} - case consts.HTTPSProxy: + case v1.ProxyTypeHTTPS: return &HTTPSOutConf{} - case consts.STCPProxy: + case v1.ProxyTypeSTCP: return &STCPOutConf{} - case consts.XTCPProxy: + case v1.ProxyTypeXTCP: return &XTCPOutConf{} default: return nil @@ -215,12 +214,12 @@ func (svr *Service) getProxyStatsByType(proxyType string) (proxyInfos []*ProxySt log.Warn("unmarshal proxy [%s] conf info error: %v", ps.Name, err) continue } - proxyInfo.Status = consts.Online + proxyInfo.Status = "online" if pxy.GetLoginMsg() != nil { proxyInfo.ClientVersion = pxy.GetLoginMsg().Version } } else { - proxyInfo.Status = consts.Offline + proxyInfo.Status = "offline" } proxyInfo.Name = ps.Name proxyInfo.TodayTrafficIn = ps.TodayTrafficIn @@ -293,9 +292,9 @@ func (svr *Service) getProxyStatsByTypeAndName(proxyType string, proxyName strin msg = "parse conf error" return } - proxyInfo.Status = consts.Online + proxyInfo.Status = "online" } else { - proxyInfo.Status = consts.Offline + proxyInfo.Status = "offline" } proxyInfo.TodayTrafficIn = ps.TodayTrafficIn proxyInfo.TodayTrafficOut = ps.TodayTrafficOut diff --git a/server/group/tcpmux.go b/server/group/tcpmux.go index 0d9790e..1712bc7 100644 --- a/server/group/tcpmux.go +++ b/server/group/tcpmux.go @@ -22,7 +22,7 @@ import ( gerr "github.com/fatedier/golib/errors" - "github.com/fatedier/frp/pkg/consts" + v1 "github.com/fatedier/frp/pkg/config/v1" "github.com/fatedier/frp/pkg/util/tcpmux" "github.com/fatedier/frp/pkg/util/vhost" ) @@ -59,8 +59,8 @@ func (tmgc *TCPMuxGroupCtl) Listen( } tmgc.mu.Unlock() - switch multiplexer { - case consts.HTTPConnectTCPMultiplexer: + switch v1.TCPMultiplexerType(multiplexer) { + case v1.TCPMultiplexerHTTPConnect: return tcpMuxGroup.HTTPConnectListen(ctx, group, groupKey, routeConfig) default: err = fmt.Errorf("unknown multiplexer [%s]", multiplexer) diff --git a/server/proxy/proxy.go b/server/proxy/proxy.go index 0cd7a6e..fe6f781 100644 --- a/server/proxy/proxy.go +++ b/server/proxy/proxy.go @@ -271,9 +271,18 @@ func (pxy *BaseProxy) handleUserTCPConnection(userConn net.Conn) { xl.Debug("join connections closed") } -func NewProxy(ctx context.Context, userInfo plugin.UserInfo, rc *controller.ResourceController, poolCount int, - getWorkConnFn GetWorkConnFn, configurer v1.ProxyConfigurer, serverCfg *v1.ServerConfig, loginMsg *msg.Login, -) (pxy Proxy, err error) { +type Options struct { + UserInfo plugin.UserInfo + LoginMsg *msg.Login + PoolCount int + ResourceController *controller.ResourceController + GetWorkConnFn GetWorkConnFn + Configurer v1.ProxyConfigurer + ServerCfg *v1.ServerConfig +} + +func NewProxy(ctx context.Context, options *Options) (pxy Proxy, err error) { + configurer := options.Configurer xl := xlog.FromContextSafe(ctx).Spawn().AppendPrefix(configurer.GetBaseConfig().Name) var limiter *rate.Limiter @@ -284,16 +293,16 @@ func NewProxy(ctx context.Context, userInfo plugin.UserInfo, rc *controller.Reso basePxy := BaseProxy{ name: configurer.GetBaseConfig().Name, - rc: rc, + rc: options.ResourceController, listeners: make([]net.Listener, 0), - poolCount: poolCount, - getWorkConnFn: getWorkConnFn, - serverCfg: serverCfg, + poolCount: options.PoolCount, + getWorkConnFn: options.GetWorkConnFn, + serverCfg: options.ServerCfg, limiter: limiter, xl: xl, ctx: xlog.NewContext(ctx, xl), - userInfo: userInfo, - loginMsg: loginMsg, + userInfo: options.UserInfo, + loginMsg: options.LoginMsg, configurer: configurer, } diff --git a/server/proxy/tcpmux.go b/server/proxy/tcpmux.go index 1582422..5b914c3 100644 --- a/server/proxy/tcpmux.go +++ b/server/proxy/tcpmux.go @@ -21,7 +21,6 @@ import ( "strings" v1 "github.com/fatedier/frp/pkg/config/v1" - "github.com/fatedier/frp/pkg/consts" "github.com/fatedier/frp/pkg/util/util" "github.com/fatedier/frp/pkg/util/vhost" ) @@ -99,8 +98,8 @@ func (pxy *TCPMuxProxy) httpConnectRun() (remoteAddr string, err error) { } func (pxy *TCPMuxProxy) Run() (remoteAddr string, err error) { - switch pxy.cfg.Multiplexer { - case consts.HTTPConnectTCPMultiplexer: + switch v1.TCPMultiplexerType(pxy.cfg.Multiplexer) { + case v1.TCPMultiplexerHTTPConnect: remoteAddr, err = pxy.httpConnectRun() default: err = fmt.Errorf("unknown multiplexer [%s]", pxy.cfg.Multiplexer) diff --git a/server/service.go b/server/service.go index a5e84ea..9deffa0 100644 --- a/server/service.go +++ b/server/service.go @@ -533,12 +533,6 @@ func (svr *Service) RegisterControl(ctlConn net.Conn, loginMsg *msg.Login) (err xl.Info("client login info: ip [%s] version [%s] hostname [%s] os [%s] arch [%s]", ctlConn.RemoteAddr().String(), loginMsg.Version, loginMsg.Hostname, loginMsg.Os, loginMsg.Arch) - // Check client version. - if ok, msg := version.Compat(loginMsg.Version); !ok { - err = fmt.Errorf("%s", msg) - return - } - // Check auth. if err = svr.authVerifier.VerifyLogin(loginMsg); err != nil { return