diff --git a/Release.md b/Release.md index 7f01beef..a25902cb 100644 --- a/Release.md +++ b/Release.md @@ -1,3 +1,8 @@ ### Features * Configuration: We now support TOML, YAML, and JSON for configuration. Please note that INI is deprecated and will be removed in future releases. New features will only be available in TOML, YAML, or JSON. Users wanting these new features should switch their configuration format accordingly. #2521 + +### Breaking Changes + +* Change the way to start the visitor through the command line from `frpc stcp --role=visitor xxx` to `frpc stcp visitor xxx`. +* Modified the semantics of the `server_addr` in the command line, no longer including the port. Added the `server_port` parameter to configure the port. diff --git a/cmd/frpc/sub/admin.go b/cmd/frpc/sub/admin.go new file mode 100644 index 00000000..c5514bc1 --- /dev/null +++ b/cmd/frpc/sub/admin.go @@ -0,0 +1,117 @@ +// Copyright 2023 The frp Authors +// +// 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 sub + +import ( + "fmt" + "os" + "strings" + + "github.com/rodaine/table" + "github.com/spf13/cobra" + + "github.com/fatedier/frp/pkg/config" + v1 "github.com/fatedier/frp/pkg/config/v1" + clientsdk "github.com/fatedier/frp/pkg/sdk/client" +) + +func init() { + rootCmd.AddCommand(NewAdminCommand( + "reload", + "Hot-Reload frpc configuration", + ReloadHandler, + )) + + rootCmd.AddCommand(NewAdminCommand( + "status", + "Overview of all proxies status", + StatusHandler, + )) + + rootCmd.AddCommand(NewAdminCommand( + "stop", + "Stop the running frpc", + StopHandler, + )) +} + +func NewAdminCommand(name, short string, handler func(*v1.ClientCommonConfig) error) *cobra.Command { + return &cobra.Command{ + Use: name, + Short: short, + Run: func(cmd *cobra.Command, args []string) { + cfg, _, _, _, err := config.LoadClientConfig(cfgFile) + if err != nil { + fmt.Println(err) + os.Exit(1) + } + if cfg.WebServer.Port <= 0 { + fmt.Println("web server port should be set if you want to use this feature") + os.Exit(1) + } + + if err := handler(cfg); err != nil { + fmt.Println(err) + os.Exit(1) + } + }, + } +} + +func ReloadHandler(clientCfg *v1.ClientCommonConfig) error { + client := clientsdk.New(clientCfg.WebServer.Addr, clientCfg.WebServer.Port) + client.SetAuth(clientCfg.WebServer.User, clientCfg.WebServer.Password) + if err := client.Reload(); err != nil { + return err + } + fmt.Println("reload success") + return nil +} + +func StatusHandler(clientCfg *v1.ClientCommonConfig) error { + client := clientsdk.New(clientCfg.WebServer.Addr, clientCfg.WebServer.Port) + client.SetAuth(clientCfg.WebServer.User, clientCfg.WebServer.Password) + res, err := client.GetAllProxyStatus() + if err != nil { + return err + } + + fmt.Printf("Proxy Status...\n\n") + for _, typ := range proxyTypes { + arrs := res[typ] + if len(arrs) == 0 { + continue + } + + fmt.Println(strings.ToUpper(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) + } + tbl.Print() + fmt.Println("") + } + return nil +} + +func StopHandler(clientCfg *v1.ClientCommonConfig) error { + client := clientsdk.New(clientCfg.WebServer.Addr, clientCfg.WebServer.Port) + client.SetAuth(clientCfg.WebServer.User, clientCfg.WebServer.Password) + if err := client.Stop(); err != nil { + return err + } + fmt.Println("stop success") + return nil +} diff --git a/cmd/frpc/sub/flags.go b/cmd/frpc/sub/flags.go new file mode 100644 index 00000000..eb3cc010 --- /dev/null +++ b/cmd/frpc/sub/flags.go @@ -0,0 +1,125 @@ +// Copyright 2023 The frp Authors +// +// 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 sub + +import ( + "fmt" + + "github.com/spf13/cobra" + + "github.com/fatedier/frp/pkg/config/types" + v1 "github.com/fatedier/frp/pkg/config/v1" + "github.com/fatedier/frp/pkg/config/v1/validation" +) + +type BandwidthQuantityFlag struct { + V *types.BandwidthQuantity +} + +func (f *BandwidthQuantityFlag) Set(s string) error { + return f.V.UnmarshalString(s) +} + +func (f *BandwidthQuantityFlag) String() string { + return f.V.String() +} + +func (f *BandwidthQuantityFlag) Type() string { + return "string" +} + +func RegisterProxyFlags(cmd *cobra.Command, c v1.ProxyConfigurer) { + registerProxyBaseConfigFlags(cmd, c.GetBaseConfig()) + switch cc := c.(type) { + case *v1.TCPProxyConfig: + cmd.Flags().IntVarP(&cc.RemotePort, "remote_port", "r", 0, "remote port") + case *v1.UDPProxyConfig: + cmd.Flags().IntVarP(&cc.RemotePort, "remote_port", "r", 0, "remote port") + case *v1.HTTPProxyConfig: + registerProxyDomainConfigFlags(cmd, &cc.DomainConfig) + cmd.Flags().StringSliceVarP(&cc.Locations, "locations", "", []string{}, "locations") + cmd.Flags().StringVarP(&cc.HTTPUser, "http_user", "", "", "http auth user") + cmd.Flags().StringVarP(&cc.HTTPPassword, "http_pwd", "", "", "http auth password") + cmd.Flags().StringVarP(&cc.HostHeaderRewrite, "host_header_rewrite", "", "", "host header rewrite") + case *v1.HTTPSProxyConfig: + registerProxyDomainConfigFlags(cmd, &cc.DomainConfig) + case *v1.TCPMuxProxyConfig: + registerProxyDomainConfigFlags(cmd, &cc.DomainConfig) + cmd.Flags().StringVarP(&cc.Multiplexer, "mux", "", "", "multiplexer") + case *v1.STCPProxyConfig: + cmd.Flags().StringVarP(&cc.Secretkey, "sk", "", "", "secret key") + case *v1.SUDPProxyConfig: + cmd.Flags().StringVarP(&cc.Secretkey, "sk", "", "", "secret key") + case *v1.XTCPProxyConfig: + cmd.Flags().StringVarP(&cc.Secretkey, "sk", "", "", "secret key") + } +} + +func registerProxyBaseConfigFlags(cmd *cobra.Command, c *v1.ProxyBaseConfig) { + if c == nil { + return + } + cmd.Flags().StringVarP(&c.Name, "proxy_name", "n", "", "proxy name") + cmd.Flags().StringVarP(&c.LocalIP, "local_ip", "i", "127.0.0.1", "local ip") + cmd.Flags().IntVarP(&c.LocalPort, "local_port", "l", 0, "local port") + cmd.Flags().BoolVarP(&c.Transport.UseEncryption, "ue", "", false, "use encryption") + cmd.Flags().BoolVarP(&c.Transport.UseCompression, "uc", "", false, "use compression") + cmd.Flags().StringVarP(&c.Transport.BandwidthLimitMode, "bandwidth_limit_mode", "", types.BandwidthLimitModeClient, "bandwidth limit mode") + cmd.Flags().VarP(&BandwidthQuantityFlag{V: &c.Transport.BandwidthLimit}, "bandwidth_limit", "", "bandwidth limit (e.g. 100KB or 1MB)") +} + +func registerProxyDomainConfigFlags(cmd *cobra.Command, c *v1.DomainConfig) { + if c == nil { + return + } + cmd.Flags().StringSliceVarP(&c.CustomDomains, "custom_domain", "d", []string{}, "custom domains") + cmd.Flags().StringVarP(&c.SubDomain, "sd", "", "", "sub domain") +} + +func RegisterVisitorFlags(cmd *cobra.Command, c v1.VisitorConfigurer) { + registerVisitorBaseConfigFlags(cmd, c.GetBaseConfig()) + + // add visitor flags if exist +} + +func registerVisitorBaseConfigFlags(cmd *cobra.Command, c *v1.VisitorBaseConfig) { + if c == nil { + return + } + cmd.Flags().StringVarP(&c.Name, "visitor_name", "n", "", "visitor name") + cmd.Flags().BoolVarP(&c.Transport.UseEncryption, "ue", "", false, "use encryption") + cmd.Flags().BoolVarP(&c.Transport.UseCompression, "uc", "", false, "use compression") + cmd.Flags().StringVarP(&c.SecretKey, "sk", "", "", "secret key") + cmd.Flags().StringVarP(&c.ServerName, "server_name", "", "", "server name") + cmd.Flags().StringVarP(&c.BindAddr, "bind_addr", "", "", "bind addr") + cmd.Flags().IntVarP(&c.BindPort, "bind_port", "", 0, "bind port") +} + +func RegisterClientCommonConfigFlags(cmd *cobra.Command, c *v1.ClientCommonConfig) { + cmd.PersistentFlags().StringVarP(&c.ServerAddr, "server_addr", "s", "127.0.0.1", "frp server's address") + cmd.PersistentFlags().IntVarP(&c.ServerPort, "server_port", "P", 7000, "frp server's port") + cmd.PersistentFlags().StringVarP(&c.User, "user", "u", "", "user") + cmd.PersistentFlags().StringVarP(&c.Transport.Protocol, "protocol", "p", "tcp", + fmt.Sprintf("optional values are %v", validation.SupportedTransportProtocols)) + cmd.PersistentFlags().StringVarP(&c.Auth.Token, "token", "t", "", "auth token") + cmd.PersistentFlags().StringVarP(&c.Log.Level, "log_level", "", "info", "log level") + cmd.PersistentFlags().StringVarP(&c.Log.To, "log_file", "", "console", "console or file path") + cmd.PersistentFlags().Int64VarP(&c.Log.MaxDays, "log_max_days", "", 3, "log file reversed days") + cmd.PersistentFlags().BoolVarP(&c.Log.DisablePrintColor, "disable_log_color", "", false, "disable log color in console") + cmd.PersistentFlags().StringVarP(&c.Transport.TLS.ServerName, "tls_server_name", "", "", "specify the custom server name of tls certificate") + cmd.PersistentFlags().StringVarP(&c.DNSServer, "dns_server", "", "", "specify dns server instead of using system default one") + + c.Transport.TLS.Enable = cmd.PersistentFlags().BoolP("tls_enable", "", true, "enable frpc tls") +} diff --git a/cmd/frpc/sub/http.go b/cmd/frpc/sub/http.go deleted file mode 100644 index 55c45b70..00000000 --- a/cmd/frpc/sub/http.go +++ /dev/null @@ -1,96 +0,0 @@ -// Copyright 2018 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 sub - -import ( - "fmt" - "os" - "strings" - - "github.com/spf13/cobra" - - "github.com/fatedier/frp/pkg/config/types" - v1 "github.com/fatedier/frp/pkg/config/v1" - "github.com/fatedier/frp/pkg/config/v1/validation" - "github.com/fatedier/frp/pkg/consts" -) - -func init() { - RegisterCommonFlags(httpCmd) - - httpCmd.PersistentFlags().StringVarP(&proxyName, "proxy_name", "n", "", "proxy name") - httpCmd.PersistentFlags().StringVarP(&localIP, "local_ip", "i", "127.0.0.1", "local ip") - httpCmd.PersistentFlags().IntVarP(&localPort, "local_port", "l", 0, "local port") - httpCmd.PersistentFlags().StringVarP(&customDomains, "custom_domain", "d", "", "custom domain") - httpCmd.PersistentFlags().StringVarP(&subDomain, "sd", "", "", "sub domain") - httpCmd.PersistentFlags().StringVarP(&locations, "locations", "", "", "locations") - httpCmd.PersistentFlags().StringVarP(&httpUser, "http_user", "", "", "http auth user") - httpCmd.PersistentFlags().StringVarP(&httpPwd, "http_pwd", "", "", "http auth password") - httpCmd.PersistentFlags().StringVarP(&hostHeaderRewrite, "host_header_rewrite", "", "", "host header rewrite") - httpCmd.PersistentFlags().BoolVarP(&useEncryption, "ue", "", false, "use encryption") - httpCmd.PersistentFlags().BoolVarP(&useCompression, "uc", "", false, "use compression") - httpCmd.PersistentFlags().StringVarP(&bandwidthLimit, "bandwidth_limit", "", "", "bandwidth limit") - httpCmd.PersistentFlags().StringVarP(&bandwidthLimitMode, "bandwidth_limit_mode", "", types.BandwidthLimitModeClient, "bandwidth limit mode") - - rootCmd.AddCommand(httpCmd) -} - -var httpCmd = &cobra.Command{ - Use: "http", - Short: "Run frpc with a single http proxy", - RunE: func(cmd *cobra.Command, args []string) error { - clientCfg, err := parseClientCommonCfgFromCmd() - if err != nil { - fmt.Println(err) - os.Exit(1) - } - - cfg := &v1.HTTPProxyConfig{} - var prefix string - if user != "" { - prefix = user + "." - } - cfg.Name = prefix + proxyName - cfg.Type = consts.HTTPProxy - cfg.LocalIP = localIP - cfg.LocalPort = localPort - cfg.CustomDomains = strings.Split(customDomains, ",") - cfg.SubDomain = subDomain - cfg.Locations = strings.Split(locations, ",") - cfg.HTTPUser = httpUser - cfg.HTTPPassword = httpPwd - cfg.HostHeaderRewrite = hostHeaderRewrite - cfg.Transport.UseEncryption = useEncryption - cfg.Transport.UseCompression = useCompression - cfg.Transport.BandwidthLimit, err = types.NewBandwidthQuantity(bandwidthLimit) - if err != nil { - fmt.Println(err) - os.Exit(1) - } - cfg.Transport.BandwidthLimitMode = bandwidthLimitMode - - if err := validation.ValidateProxyConfigurerForClient(cfg); err != nil { - fmt.Println(err) - os.Exit(1) - } - - err = startService(clientCfg, []v1.ProxyConfigurer{cfg}, nil, "") - if err != nil { - fmt.Println(err) - os.Exit(1) - } - return nil - }, -} diff --git a/cmd/frpc/sub/https.go b/cmd/frpc/sub/https.go deleted file mode 100644 index d6bf4a6e..00000000 --- a/cmd/frpc/sub/https.go +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright 2018 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 sub - -import ( - "fmt" - "os" - "strings" - - "github.com/spf13/cobra" - - "github.com/fatedier/frp/pkg/config/types" - v1 "github.com/fatedier/frp/pkg/config/v1" - "github.com/fatedier/frp/pkg/config/v1/validation" - "github.com/fatedier/frp/pkg/consts" -) - -func init() { - RegisterCommonFlags(httpsCmd) - - httpsCmd.PersistentFlags().StringVarP(&proxyName, "proxy_name", "n", "", "proxy name") - httpsCmd.PersistentFlags().StringVarP(&localIP, "local_ip", "i", "127.0.0.1", "local ip") - httpsCmd.PersistentFlags().IntVarP(&localPort, "local_port", "l", 0, "local port") - httpsCmd.PersistentFlags().StringVarP(&customDomains, "custom_domain", "d", "", "custom domain") - httpsCmd.PersistentFlags().StringVarP(&subDomain, "sd", "", "", "sub domain") - httpsCmd.PersistentFlags().BoolVarP(&useEncryption, "ue", "", false, "use encryption") - httpsCmd.PersistentFlags().BoolVarP(&useCompression, "uc", "", false, "use compression") - httpsCmd.PersistentFlags().StringVarP(&bandwidthLimit, "bandwidth_limit", "", "", "bandwidth limit") - httpsCmd.PersistentFlags().StringVarP(&bandwidthLimitMode, "bandwidth_limit_mode", "", types.BandwidthLimitModeClient, "bandwidth limit mode") - - rootCmd.AddCommand(httpsCmd) -} - -var httpsCmd = &cobra.Command{ - Use: "https", - Short: "Run frpc with a single https proxy", - RunE: func(cmd *cobra.Command, args []string) error { - clientCfg, err := parseClientCommonCfgFromCmd() - if err != nil { - fmt.Println(err) - os.Exit(1) - } - - cfg := &v1.HTTPSProxyConfig{} - var prefix string - if user != "" { - prefix = user + "." - } - cfg.Name = prefix + proxyName - cfg.Type = consts.HTTPSProxy - cfg.LocalIP = localIP - cfg.LocalPort = localPort - cfg.CustomDomains = strings.Split(customDomains, ",") - cfg.SubDomain = subDomain - cfg.Transport.UseEncryption = useEncryption - cfg.Transport.UseCompression = useCompression - cfg.Transport.BandwidthLimit, err = types.NewBandwidthQuantity(bandwidthLimit) - if err != nil { - fmt.Println(err) - os.Exit(1) - } - cfg.Transport.BandwidthLimitMode = bandwidthLimitMode - - if err := validation.ValidateProxyConfigurerForClient(cfg); err != nil { - fmt.Println(err) - os.Exit(1) - } - - err = startService(clientCfg, []v1.ProxyConfigurer{cfg}, nil, "") - if err != nil { - fmt.Println(err) - os.Exit(1) - } - return nil - }, -} diff --git a/cmd/frpc/sub/nathole.go b/cmd/frpc/sub/nathole.go index 92977cd2..72b635f1 100644 --- a/cmd/frpc/sub/nathole.go +++ b/cmd/frpc/sub/nathole.go @@ -31,8 +31,6 @@ var ( ) func init() { - RegisterCommonFlags(natholeCmd) - rootCmd.AddCommand(natholeCmd) natholeCmd.AddCommand(natholeDiscoveryCmd) diff --git a/cmd/frpc/sub/proxy.go b/cmd/frpc/sub/proxy.go new file mode 100644 index 00000000..d27d3fad --- /dev/null +++ b/cmd/frpc/sub/proxy.go @@ -0,0 +1,121 @@ +// Copyright 2023 The frp Authors +// +// 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 sub + +import ( + "fmt" + "os" + + "github.com/samber/lo" + "github.com/spf13/cobra" + + 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 visitorTypes = []string{ + consts.STCPProxy, + consts.SUDPProxy, + consts.XTCPProxy, +} + +func init() { + for _, typ := range proxyTypes { + c := v1.NewProxyConfigurerByType(typ) + if c == nil { + panic("proxy type: " + typ + " not support") + } + clientCfg := v1.ClientCommonConfig{} + cmd := NewProxyCommand(typ, c, &clientCfg) + RegisterClientCommonConfigFlags(cmd, &clientCfg) + RegisterProxyFlags(cmd, c) + + // add sub command for visitor + if lo.Contains(visitorTypes, typ) { + vc := v1.NewVisitorConfigurerByType(typ) + if vc == nil { + panic("visitor type: " + typ + " not support") + } + visitorCmd := NewVisitorCommand(typ, vc, &clientCfg) + RegisterVisitorFlags(visitorCmd, vc) + cmd.AddCommand(visitorCmd) + } + rootCmd.AddCommand(cmd) + } +} + +func NewProxyCommand(name string, c v1.ProxyConfigurer, clientCfg *v1.ClientCommonConfig) *cobra.Command { + return &cobra.Command{ + Use: name, + Short: fmt.Sprintf("Run frpc with a single %s proxy", name), + Run: func(cmd *cobra.Command, args []string) { + clientCfg.Complete() + if _, err := validation.ValidateClientCommonConfig(clientCfg); err != nil { + fmt.Println(err) + os.Exit(1) + } + + c.Complete(clientCfg.User) + c.GetBaseConfig().Type = name + if err := validation.ValidateProxyConfigurerForClient(c); err != nil { + fmt.Println(err) + os.Exit(1) + } + err := startService(clientCfg, []v1.ProxyConfigurer{c}, nil, "") + if err != nil { + fmt.Println(err) + os.Exit(1) + } + }, + } +} + +func NewVisitorCommand(name string, c v1.VisitorConfigurer, clientCfg *v1.ClientCommonConfig) *cobra.Command { + return &cobra.Command{ + Use: "visitor", + Short: fmt.Sprintf("Run frpc with a single %s visitor", name), + Run: func(cmd *cobra.Command, args []string) { + clientCfg.Complete() + if _, err := validation.ValidateClientCommonConfig(clientCfg); err != nil { + fmt.Println(err) + os.Exit(1) + } + + c.Complete(clientCfg) + c.GetBaseConfig().Type = name + if err := validation.ValidateVisitorConfigurer(c); err != nil { + fmt.Println(err) + os.Exit(1) + } + err := startService(clientCfg, nil, []v1.VisitorConfigurer{c}, "") + if err != nil { + fmt.Println(err) + os.Exit(1) + } + }, + } +} diff --git a/cmd/frpc/sub/reload.go b/cmd/frpc/sub/reload.go deleted file mode 100644 index a01a34f3..00000000 --- a/cmd/frpc/sub/reload.go +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright 2018 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 sub - -import ( - "encoding/base64" - "fmt" - "io" - "net/http" - "os" - "strings" - - "github.com/spf13/cobra" - - "github.com/fatedier/frp/pkg/config" - v1 "github.com/fatedier/frp/pkg/config/v1" -) - -func init() { - rootCmd.AddCommand(reloadCmd) -} - -var reloadCmd = &cobra.Command{ - Use: "reload", - Short: "Hot-Reload frpc configuration", - RunE: func(cmd *cobra.Command, args []string) error { - cfg, _, _, _, err := config.LoadClientConfig(cfgFile) - if err != nil { - fmt.Println(err) - os.Exit(1) - } - - err = reload(cfg) - if err != nil { - fmt.Printf("frpc reload error: %v\n", err) - os.Exit(1) - } - fmt.Printf("reload success\n") - return nil - }, -} - -func reload(clientCfg *v1.ClientCommonConfig) error { - if clientCfg.WebServer.Port == 0 { - return fmt.Errorf("the port of web server shoud be set if you want to use reload feature") - } - - req, err := http.NewRequest("GET", "http://"+ - clientCfg.WebServer.Addr+":"+ - fmt.Sprintf("%d", clientCfg.WebServer.Port)+"/api/reload", nil) - if err != nil { - return err - } - - authStr := "Basic " + base64.StdEncoding.EncodeToString( - []byte(clientCfg.WebServer.User+":"+clientCfg.WebServer.Password)) - - req.Header.Add("Authorization", authStr) - resp, err := http.DefaultClient.Do(req) - if err != nil { - return err - } - defer resp.Body.Close() - - if resp.StatusCode == 200 { - return nil - } - - body, err := io.ReadAll(resp.Body) - if err != nil { - return err - } - return fmt.Errorf("code [%d], %s", resp.StatusCode, strings.TrimSpace(string(body))) -} diff --git a/cmd/frpc/sub/root.go b/cmd/frpc/sub/root.go index 878114b1..915e6b35 100644 --- a/cmd/frpc/sub/root.go +++ b/cmd/frpc/sub/root.go @@ -18,16 +18,13 @@ import ( "context" "fmt" "io/fs" - "net" "os" "os/signal" "path/filepath" - "strconv" "sync" "syscall" "time" - "github.com/samber/lo" "github.com/spf13/cobra" "github.com/fatedier/frp/client" @@ -42,40 +39,6 @@ var ( cfgFile string cfgDir string showVersion bool - - serverAddr string - user string - protocol string - token string - logLevel string - logFile string - logMaxDays int - disableLogColor bool - dnsServer string - - proxyName string - localIP string - localPort int - remotePort int - useEncryption bool - useCompression bool - bandwidthLimit string - bandwidthLimitMode string - customDomains string - subDomain string - httpUser string - httpPwd string - locations string - hostHeaderRewrite string - role string - sk string - multiplexer string - serverName string - bindAddr string - bindPort int - - tlsEnable bool - tlsServerName string ) func init() { @@ -84,20 +47,6 @@ func init() { rootCmd.PersistentFlags().BoolVarP(&showVersion, "version", "v", false, "version of frpc") } -func RegisterCommonFlags(cmd *cobra.Command) { - cmd.PersistentFlags().StringVarP(&serverAddr, "server_addr", "s", "127.0.0.1:7000", "frp server's address") - cmd.PersistentFlags().StringVarP(&user, "user", "u", "", "user") - cmd.PersistentFlags().StringVarP(&protocol, "protocol", "p", "tcp", "tcp, kcp, quic, websocket, wss") - cmd.PersistentFlags().StringVarP(&token, "token", "t", "", "auth token") - cmd.PersistentFlags().StringVarP(&logLevel, "log_level", "", "info", "log level") - cmd.PersistentFlags().StringVarP(&logFile, "log_file", "", "console", "console or file path") - cmd.PersistentFlags().IntVarP(&logMaxDays, "log_max_days", "", 3, "log file reversed days") - cmd.PersistentFlags().BoolVarP(&disableLogColor, "disable_log_color", "", false, "disable log color in console") - cmd.PersistentFlags().BoolVarP(&tlsEnable, "tls_enable", "", true, "enable frpc tls") - cmd.PersistentFlags().StringVarP(&tlsServerName, "tls_server_name", "", "", "specify the custom server name of tls certificate") - cmd.PersistentFlags().StringVarP(&dnsServer, "dns_server", "", "", "specify dns server instead of using system default one") -} - var rootCmd = &cobra.Command{ Use: "frpc", Short: "frpc is the client of frp (https://github.com/fatedier/frp)", @@ -158,45 +107,6 @@ func handleTermSignal(svr *client.Service) { svr.GracefulClose(500 * time.Millisecond) } -func parseClientCommonCfgFromCmd() (*v1.ClientCommonConfig, error) { - cfg := &v1.ClientCommonConfig{} - - ipStr, portStr, err := net.SplitHostPort(serverAddr) - if err != nil { - return nil, fmt.Errorf("invalid server_addr: %v", err) - } - - cfg.ServerAddr = ipStr - cfg.ServerPort, err = strconv.Atoi(portStr) - if err != nil { - return nil, fmt.Errorf("invalid server_addr: %v", err) - } - - cfg.User = user - cfg.Transport.Protocol = protocol - cfg.Log.Level = logLevel - cfg.Log.To = logFile - cfg.Log.MaxDays = int64(logMaxDays) - cfg.Log.DisablePrintColor = disableLogColor - cfg.DNSServer = dnsServer - - // Only token authentication is supported in cmd mode - cfg.Auth.Token = token - cfg.Transport.TLS.Enable = lo.ToPtr(tlsEnable) - cfg.Transport.TLS.ServerName = tlsServerName - - cfg.Complete() - - warning, err := validation.ValidateClientCommonConfig(cfg) - if warning != nil { - fmt.Printf("WARNING: %v\n", warning) - } - if err != nil { - return nil, fmt.Errorf("parse config error: %v", err) - } - return cfg, nil -} - func runClient(cfgFilePath string) error { cfg, pxyCfgs, visitorCfgs, isLegacyFormat, err := config.LoadClientConfig(cfgFilePath) if err != nil { diff --git a/cmd/frpc/sub/status.go b/cmd/frpc/sub/status.go deleted file mode 100644 index 1db4a956..00000000 --- a/cmd/frpc/sub/status.go +++ /dev/null @@ -1,108 +0,0 @@ -// Copyright 2018 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 sub - -import ( - "encoding/base64" - "encoding/json" - "fmt" - "io" - "net/http" - "os" - "strings" - - "github.com/rodaine/table" - "github.com/spf13/cobra" - - "github.com/fatedier/frp/client" - "github.com/fatedier/frp/pkg/config" - v1 "github.com/fatedier/frp/pkg/config/v1" -) - -func init() { - rootCmd.AddCommand(statusCmd) -} - -var statusCmd = &cobra.Command{ - Use: "status", - Short: "Overview of all proxies status", - RunE: func(cmd *cobra.Command, args []string) error { - cfg, _, _, _, err := config.LoadClientConfig(cfgFile) - if err != nil { - fmt.Println(err) - os.Exit(1) - } - - if err = status(cfg); err != nil { - fmt.Printf("frpc get status error: %v\n", err) - os.Exit(1) - } - return nil - }, -} - -func status(clientCfg *v1.ClientCommonConfig) error { - if clientCfg.WebServer.Port == 0 { - return fmt.Errorf("the port of web server shoud be set if you want to get proxy status") - } - - req, err := http.NewRequest("GET", "http://"+ - clientCfg.WebServer.Addr+":"+fmt.Sprintf("%d", clientCfg.WebServer.Port)+"/api/status", nil) - if err != nil { - return err - } - - authStr := "Basic " + base64.StdEncoding.EncodeToString( - []byte(clientCfg.WebServer.User+":"+clientCfg.WebServer.Password)) - - req.Header.Add("Authorization", authStr) - resp, err := http.DefaultClient.Do(req) - if err != nil { - return err - } - defer resp.Body.Close() - - if resp.StatusCode != 200 { - return fmt.Errorf("admin api status code [%d]", resp.StatusCode) - } - - body, err := io.ReadAll(resp.Body) - if err != nil { - return err - } - res := make(client.StatusResp) - err = json.Unmarshal(body, &res) - if err != nil { - return fmt.Errorf("unmarshal http response error: %s", strings.TrimSpace(string(body))) - } - - fmt.Println("Proxy Status...") - types := []string{"tcp", "udp", "tcpmux", "http", "https", "stcp", "sudp", "xtcp"} - for _, pxyType := range types { - arrs := res[pxyType] - if len(arrs) == 0 { - continue - } - - fmt.Println(strings.ToUpper(pxyType)) - 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) - } - tbl.Print() - fmt.Println("") - } - return nil -} diff --git a/cmd/frpc/sub/stcp.go b/cmd/frpc/sub/stcp.go deleted file mode 100644 index 47ad3628..00000000 --- a/cmd/frpc/sub/stcp.go +++ /dev/null @@ -1,114 +0,0 @@ -// Copyright 2018 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 sub - -import ( - "fmt" - "os" - - "github.com/spf13/cobra" - - "github.com/fatedier/frp/pkg/config/types" - v1 "github.com/fatedier/frp/pkg/config/v1" - "github.com/fatedier/frp/pkg/config/v1/validation" - "github.com/fatedier/frp/pkg/consts" -) - -func init() { - RegisterCommonFlags(stcpCmd) - - stcpCmd.PersistentFlags().StringVarP(&proxyName, "proxy_name", "n", "", "proxy name") - stcpCmd.PersistentFlags().StringVarP(&role, "role", "", "server", "role") - stcpCmd.PersistentFlags().StringVarP(&sk, "sk", "", "", "secret key") - stcpCmd.PersistentFlags().StringVarP(&serverName, "server_name", "", "", "server name") - stcpCmd.PersistentFlags().StringVarP(&localIP, "local_ip", "i", "127.0.0.1", "local ip") - stcpCmd.PersistentFlags().IntVarP(&localPort, "local_port", "l", 0, "local port") - stcpCmd.PersistentFlags().StringVarP(&bindAddr, "bind_addr", "", "", "bind addr") - stcpCmd.PersistentFlags().IntVarP(&bindPort, "bind_port", "", 0, "bind port") - stcpCmd.PersistentFlags().BoolVarP(&useEncryption, "ue", "", false, "use encryption") - stcpCmd.PersistentFlags().BoolVarP(&useCompression, "uc", "", false, "use compression") - stcpCmd.PersistentFlags().StringVarP(&bandwidthLimit, "bandwidth_limit", "", "", "bandwidth limit") - stcpCmd.PersistentFlags().StringVarP(&bandwidthLimitMode, "bandwidth_limit_mode", "", types.BandwidthLimitModeClient, "bandwidth limit mode") - - rootCmd.AddCommand(stcpCmd) -} - -var stcpCmd = &cobra.Command{ - Use: "stcp", - Short: "Run frpc with a single stcp proxy", - RunE: func(cmd *cobra.Command, args []string) error { - clientCfg, err := parseClientCommonCfgFromCmd() - if err != nil { - fmt.Println(err) - os.Exit(1) - } - - pxyCfgs := make([]v1.ProxyConfigurer, 0) - visitorCfgs := make([]v1.VisitorConfigurer, 0) - - var prefix string - if user != "" { - prefix = user + "." - } - - switch role { - case "server": - cfg := &v1.STCPProxyConfig{} - cfg.Name = prefix + proxyName - cfg.Type = consts.STCPProxy - cfg.Transport.UseEncryption = useEncryption - cfg.Transport.UseCompression = useCompression - cfg.Secretkey = sk - cfg.LocalIP = localIP - cfg.LocalPort = localPort - cfg.Transport.BandwidthLimit, err = types.NewBandwidthQuantity(bandwidthLimit) - if err != nil { - fmt.Println(err) - os.Exit(1) - } - cfg.Transport.BandwidthLimitMode = bandwidthLimitMode - if err := validation.ValidateProxyConfigurerForClient(cfg); err != nil { - fmt.Println(err) - os.Exit(1) - } - pxyCfgs = append(pxyCfgs, cfg) - case "visitor": - cfg := &v1.STCPVisitorConfig{} - cfg.Name = prefix + proxyName - cfg.Type = consts.STCPProxy - cfg.Transport.UseEncryption = useEncryption - cfg.Transport.UseCompression = useCompression - cfg.SecretKey = sk - cfg.ServerName = serverName - cfg.BindAddr = bindAddr - cfg.BindPort = bindPort - if err := validation.ValidateVisitorConfigurer(cfg); err != nil { - fmt.Println(err) - os.Exit(1) - } - visitorCfgs = append(visitorCfgs, cfg) - default: - fmt.Println("invalid role") - os.Exit(1) - } - - err = startService(clientCfg, pxyCfgs, visitorCfgs, "") - if err != nil { - fmt.Println(err) - os.Exit(1) - } - return nil - }, -} diff --git a/cmd/frpc/sub/stop.go b/cmd/frpc/sub/stop.go deleted file mode 100644 index c0ec5da5..00000000 --- a/cmd/frpc/sub/stop.go +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright 2023 The frp Authors -// -// 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 sub - -import ( - "encoding/base64" - "fmt" - "io" - "net/http" - "os" - "strings" - - "github.com/spf13/cobra" - - "github.com/fatedier/frp/pkg/config" - v1 "github.com/fatedier/frp/pkg/config/v1" -) - -func init() { - rootCmd.AddCommand(stopCmd) -} - -var stopCmd = &cobra.Command{ - Use: "stop", - Short: "Stop the running frpc", - RunE: func(cmd *cobra.Command, args []string) error { - cfg, _, _, _, err := config.LoadClientConfig(cfgFile) - if err != nil { - fmt.Println(err) - os.Exit(1) - } - - err = stopClient(cfg) - if err != nil { - fmt.Printf("frpc stop error: %v\n", err) - os.Exit(1) - } - fmt.Printf("stop success\n") - return nil - }, -} - -func stopClient(clientCfg *v1.ClientCommonConfig) error { - if clientCfg.WebServer.Port == 0 { - return fmt.Errorf("the port of web server shoud be set if you want to use stop feature") - } - - req, err := http.NewRequest("POST", "http://"+ - clientCfg.WebServer.Addr+":"+ - fmt.Sprintf("%d", clientCfg.WebServer.Port)+"/api/stop", nil) - if err != nil { - return err - } - - authStr := "Basic " + base64.StdEncoding.EncodeToString( - []byte(clientCfg.WebServer.User+":"+clientCfg.WebServer.Password)) - - req.Header.Add("Authorization", authStr) - resp, err := http.DefaultClient.Do(req) - if err != nil { - return err - } - defer resp.Body.Close() - - if resp.StatusCode == 200 { - return nil - } - - body, err := io.ReadAll(resp.Body) - if err != nil { - return err - } - return fmt.Errorf("code [%d], %s", resp.StatusCode, strings.TrimSpace(string(body))) -} diff --git a/cmd/frpc/sub/sudp.go b/cmd/frpc/sub/sudp.go deleted file mode 100644 index 28f17ee6..00000000 --- a/cmd/frpc/sub/sudp.go +++ /dev/null @@ -1,113 +0,0 @@ -// Copyright 2018 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 sub - -import ( - "fmt" - "os" - - "github.com/spf13/cobra" - - "github.com/fatedier/frp/pkg/config/types" - v1 "github.com/fatedier/frp/pkg/config/v1" - "github.com/fatedier/frp/pkg/config/v1/validation" - "github.com/fatedier/frp/pkg/consts" -) - -func init() { - RegisterCommonFlags(sudpCmd) - - sudpCmd.PersistentFlags().StringVarP(&proxyName, "proxy_name", "n", "", "proxy name") - sudpCmd.PersistentFlags().StringVarP(&role, "role", "", "server", "role") - sudpCmd.PersistentFlags().StringVarP(&sk, "sk", "", "", "secret key") - sudpCmd.PersistentFlags().StringVarP(&serverName, "server_name", "", "", "server name") - sudpCmd.PersistentFlags().StringVarP(&localIP, "local_ip", "i", "127.0.0.1", "local ip") - sudpCmd.PersistentFlags().IntVarP(&localPort, "local_port", "l", 0, "local port") - sudpCmd.PersistentFlags().StringVarP(&bindAddr, "bind_addr", "", "", "bind addr") - sudpCmd.PersistentFlags().IntVarP(&bindPort, "bind_port", "", 0, "bind port") - sudpCmd.PersistentFlags().BoolVarP(&useEncryption, "ue", "", false, "use encryption") - sudpCmd.PersistentFlags().BoolVarP(&useCompression, "uc", "", false, "use compression") - sudpCmd.PersistentFlags().StringVarP(&bandwidthLimit, "bandwidth_limit", "", "", "bandwidth limit") - sudpCmd.PersistentFlags().StringVarP(&bandwidthLimitMode, "bandwidth_limit_mode", "", types.BandwidthLimitModeClient, "bandwidth limit mode") - - rootCmd.AddCommand(sudpCmd) -} - -var sudpCmd = &cobra.Command{ - Use: "sudp", - Short: "Run frpc with a single sudp proxy", - RunE: func(cmd *cobra.Command, args []string) error { - clientCfg, err := parseClientCommonCfgFromCmd() - if err != nil { - fmt.Println(err) - os.Exit(1) - } - - pxyCfgs := make([]v1.ProxyConfigurer, 0) - visitorCfgs := make([]v1.VisitorConfigurer, 0) - - var prefix string - if user != "" { - prefix = user + "." - } - - switch role { - case "server": - cfg := &v1.SUDPProxyConfig{} - cfg.Name = prefix + proxyName - cfg.Type = consts.SUDPProxy - cfg.Transport.UseEncryption = useEncryption - cfg.Transport.UseCompression = useCompression - cfg.Secretkey = sk - cfg.LocalIP = localIP - cfg.LocalPort = localPort - cfg.Transport.BandwidthLimit, err = types.NewBandwidthQuantity(bandwidthLimit) - if err != nil { - fmt.Println(err) - os.Exit(1) - } - cfg.Transport.BandwidthLimitMode = bandwidthLimitMode - if err := validation.ValidateProxyConfigurerForClient(cfg); err != nil { - fmt.Println(err) - os.Exit(1) - } - pxyCfgs = append(pxyCfgs, cfg) - case "visitor": - cfg := &v1.SUDPVisitorConfig{} - cfg.Name = prefix + proxyName - cfg.Type = consts.SUDPProxy - cfg.Transport.UseEncryption = useEncryption - cfg.Transport.UseCompression = useCompression - cfg.SecretKey = sk - cfg.ServerName = serverName - cfg.BindAddr = bindAddr - cfg.BindPort = bindPort - if err := validation.ValidateVisitorConfigurer(cfg); err != nil { - fmt.Println(err) - os.Exit(1) - } - visitorCfgs = append(visitorCfgs, cfg) - default: - fmt.Println("invalid role") - os.Exit(1) - } - - err = startService(clientCfg, pxyCfgs, visitorCfgs, "") - if err != nil { - os.Exit(1) - } - return nil - }, -} diff --git a/cmd/frpc/sub/tcp.go b/cmd/frpc/sub/tcp.go deleted file mode 100644 index 1a65a2a9..00000000 --- a/cmd/frpc/sub/tcp.go +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright 2018 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 sub - -import ( - "fmt" - "os" - - "github.com/spf13/cobra" - - "github.com/fatedier/frp/pkg/config/types" - v1 "github.com/fatedier/frp/pkg/config/v1" - "github.com/fatedier/frp/pkg/config/v1/validation" - "github.com/fatedier/frp/pkg/consts" -) - -func init() { - RegisterCommonFlags(tcpCmd) - - tcpCmd.PersistentFlags().StringVarP(&proxyName, "proxy_name", "n", "", "proxy name") - tcpCmd.PersistentFlags().StringVarP(&localIP, "local_ip", "i", "127.0.0.1", "local ip") - tcpCmd.PersistentFlags().IntVarP(&localPort, "local_port", "l", 0, "local port") - tcpCmd.PersistentFlags().IntVarP(&remotePort, "remote_port", "r", 0, "remote port") - tcpCmd.PersistentFlags().BoolVarP(&useEncryption, "ue", "", false, "use encryption") - tcpCmd.PersistentFlags().BoolVarP(&useCompression, "uc", "", false, "use compression") - tcpCmd.PersistentFlags().StringVarP(&bandwidthLimit, "bandwidth_limit", "", "", "bandwidth limit") - tcpCmd.PersistentFlags().StringVarP(&bandwidthLimitMode, "bandwidth_limit_mode", "", types.BandwidthLimitModeClient, "bandwidth limit mode") - - rootCmd.AddCommand(tcpCmd) -} - -var tcpCmd = &cobra.Command{ - Use: "tcp", - Short: "Run frpc with a single tcp proxy", - RunE: func(cmd *cobra.Command, args []string) error { - clientCfg, err := parseClientCommonCfgFromCmd() - if err != nil { - fmt.Println(err) - os.Exit(1) - } - - cfg := &v1.TCPProxyConfig{} - var prefix string - if user != "" { - prefix = user + "." - } - cfg.Name = prefix + proxyName - cfg.Type = consts.TCPProxy - cfg.LocalIP = localIP - cfg.LocalPort = localPort - cfg.RemotePort = remotePort - cfg.Transport.UseEncryption = useEncryption - cfg.Transport.UseCompression = useCompression - cfg.Transport.BandwidthLimit, err = types.NewBandwidthQuantity(bandwidthLimit) - if err != nil { - fmt.Println(err) - os.Exit(1) - } - cfg.Transport.BandwidthLimitMode = bandwidthLimitMode - - if err := validation.ValidateProxyConfigurerForClient(cfg); err != nil { - fmt.Println(err) - os.Exit(1) - } - err = startService(clientCfg, []v1.ProxyConfigurer{cfg}, nil, "") - if err != nil { - fmt.Println(err) - os.Exit(1) - } - return nil - }, -} diff --git a/cmd/frpc/sub/tcpmux.go b/cmd/frpc/sub/tcpmux.go deleted file mode 100644 index a217591b..00000000 --- a/cmd/frpc/sub/tcpmux.go +++ /dev/null @@ -1,90 +0,0 @@ -// Copyright 2020 guylewin, guy@lewin.co.il -// -// 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 sub - -import ( - "fmt" - "os" - "strings" - - "github.com/spf13/cobra" - - "github.com/fatedier/frp/pkg/config/types" - v1 "github.com/fatedier/frp/pkg/config/v1" - "github.com/fatedier/frp/pkg/config/v1/validation" - "github.com/fatedier/frp/pkg/consts" -) - -func init() { - RegisterCommonFlags(tcpMuxCmd) - - tcpMuxCmd.PersistentFlags().StringVarP(&proxyName, "proxy_name", "n", "", "proxy name") - tcpMuxCmd.PersistentFlags().StringVarP(&localIP, "local_ip", "i", "127.0.0.1", "local ip") - tcpMuxCmd.PersistentFlags().IntVarP(&localPort, "local_port", "l", 0, "local port") - tcpMuxCmd.PersistentFlags().StringVarP(&customDomains, "custom_domain", "d", "", "custom domain") - tcpMuxCmd.PersistentFlags().StringVarP(&subDomain, "sd", "", "", "sub domain") - tcpMuxCmd.PersistentFlags().StringVarP(&multiplexer, "mux", "", "", "multiplexer") - tcpMuxCmd.PersistentFlags().BoolVarP(&useEncryption, "ue", "", false, "use encryption") - tcpMuxCmd.PersistentFlags().BoolVarP(&useCompression, "uc", "", false, "use compression") - tcpMuxCmd.PersistentFlags().StringVarP(&bandwidthLimit, "bandwidth_limit", "", "", "bandwidth limit") - tcpMuxCmd.PersistentFlags().StringVarP(&bandwidthLimitMode, "bandwidth_limit_mode", "", types.BandwidthLimitModeClient, "bandwidth limit mode") - - rootCmd.AddCommand(tcpMuxCmd) -} - -var tcpMuxCmd = &cobra.Command{ - Use: "tcpmux", - Short: "Run frpc with a single tcpmux proxy", - RunE: func(cmd *cobra.Command, args []string) error { - clientCfg, err := parseClientCommonCfgFromCmd() - if err != nil { - fmt.Println(err) - os.Exit(1) - } - - cfg := &v1.TCPMuxProxyConfig{} - var prefix string - if user != "" { - prefix = user + "." - } - cfg.Name = prefix + proxyName - cfg.Type = consts.TCPMuxProxy - cfg.LocalIP = localIP - cfg.LocalPort = localPort - cfg.CustomDomains = strings.Split(customDomains, ",") - cfg.SubDomain = subDomain - cfg.Multiplexer = multiplexer - cfg.Transport.UseEncryption = useEncryption - cfg.Transport.UseCompression = useCompression - cfg.Transport.BandwidthLimit, err = types.NewBandwidthQuantity(bandwidthLimit) - if err != nil { - fmt.Println(err) - os.Exit(1) - } - cfg.Transport.BandwidthLimitMode = bandwidthLimitMode - - if err := validation.ValidateProxyConfigurerForClient(cfg); err != nil { - fmt.Println(err) - os.Exit(1) - } - - err = startService(clientCfg, []v1.ProxyConfigurer{cfg}, nil, "") - if err != nil { - fmt.Println(err) - os.Exit(1) - } - return nil - }, -} diff --git a/cmd/frpc/sub/udp.go b/cmd/frpc/sub/udp.go deleted file mode 100644 index e617070a..00000000 --- a/cmd/frpc/sub/udp.go +++ /dev/null @@ -1,85 +0,0 @@ -// Copyright 2018 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 sub - -import ( - "fmt" - "os" - - "github.com/spf13/cobra" - - "github.com/fatedier/frp/pkg/config/types" - v1 "github.com/fatedier/frp/pkg/config/v1" - "github.com/fatedier/frp/pkg/config/v1/validation" - "github.com/fatedier/frp/pkg/consts" -) - -func init() { - RegisterCommonFlags(udpCmd) - - udpCmd.PersistentFlags().StringVarP(&proxyName, "proxy_name", "n", "", "proxy name") - udpCmd.PersistentFlags().StringVarP(&localIP, "local_ip", "i", "127.0.0.1", "local ip") - udpCmd.PersistentFlags().IntVarP(&localPort, "local_port", "l", 0, "local port") - udpCmd.PersistentFlags().IntVarP(&remotePort, "remote_port", "r", 0, "remote port") - udpCmd.PersistentFlags().BoolVarP(&useEncryption, "ue", "", false, "use encryption") - udpCmd.PersistentFlags().BoolVarP(&useCompression, "uc", "", false, "use compression") - udpCmd.PersistentFlags().StringVarP(&bandwidthLimit, "bandwidth_limit", "", "", "bandwidth limit") - udpCmd.PersistentFlags().StringVarP(&bandwidthLimitMode, "bandwidth_limit_mode", "", types.BandwidthLimitModeClient, "bandwidth limit mode") - - rootCmd.AddCommand(udpCmd) -} - -var udpCmd = &cobra.Command{ - Use: "udp", - Short: "Run frpc with a single udp proxy", - RunE: func(cmd *cobra.Command, args []string) error { - clientCfg, err := parseClientCommonCfgFromCmd() - if err != nil { - fmt.Println(err) - os.Exit(1) - } - - cfg := &v1.UDPProxyConfig{} - var prefix string - if user != "" { - prefix = user + "." - } - cfg.Name = prefix + proxyName - cfg.Type = consts.UDPProxy - cfg.LocalIP = localIP - cfg.LocalPort = localPort - cfg.RemotePort = remotePort - cfg.Transport.UseEncryption = useEncryption - cfg.Transport.UseCompression = useCompression - cfg.Transport.BandwidthLimit, err = types.NewBandwidthQuantity(bandwidthLimit) - if err != nil { - fmt.Println(err) - os.Exit(1) - } - cfg.Transport.BandwidthLimitMode = bandwidthLimitMode - - if err := validation.ValidateProxyConfigurerForClient(cfg); err != nil { - fmt.Println(err) - os.Exit(1) - } - - err = startService(clientCfg, []v1.ProxyConfigurer{cfg}, nil, "") - if err != nil { - fmt.Println(err) - os.Exit(1) - } - return nil - }, -} diff --git a/cmd/frpc/sub/xtcp.go b/cmd/frpc/sub/xtcp.go deleted file mode 100644 index a4bdd803..00000000 --- a/cmd/frpc/sub/xtcp.go +++ /dev/null @@ -1,116 +0,0 @@ -// Copyright 2018 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 sub - -import ( - "fmt" - "os" - - "github.com/spf13/cobra" - - "github.com/fatedier/frp/pkg/config/types" - v1 "github.com/fatedier/frp/pkg/config/v1" - "github.com/fatedier/frp/pkg/config/v1/validation" - "github.com/fatedier/frp/pkg/consts" -) - -func init() { - RegisterCommonFlags(xtcpCmd) - - xtcpCmd.PersistentFlags().StringVarP(&proxyName, "proxy_name", "n", "", "proxy name") - xtcpCmd.PersistentFlags().StringVarP(&role, "role", "", "server", "role") - xtcpCmd.PersistentFlags().StringVarP(&sk, "sk", "", "", "secret key") - xtcpCmd.PersistentFlags().StringVarP(&serverName, "server_name", "", "", "server name") - xtcpCmd.PersistentFlags().StringVarP(&localIP, "local_ip", "i", "127.0.0.1", "local ip") - xtcpCmd.PersistentFlags().IntVarP(&localPort, "local_port", "l", 0, "local port") - xtcpCmd.PersistentFlags().StringVarP(&bindAddr, "bind_addr", "", "", "bind addr") - xtcpCmd.PersistentFlags().IntVarP(&bindPort, "bind_port", "", 0, "bind port") - xtcpCmd.PersistentFlags().BoolVarP(&useEncryption, "ue", "", false, "use encryption") - xtcpCmd.PersistentFlags().BoolVarP(&useCompression, "uc", "", false, "use compression") - xtcpCmd.PersistentFlags().StringVarP(&bandwidthLimit, "bandwidth_limit", "", "", "bandwidth limit") - xtcpCmd.PersistentFlags().StringVarP(&bandwidthLimitMode, "bandwidth_limit_mode", "", types.BandwidthLimitModeClient, "bandwidth limit mode") - - rootCmd.AddCommand(xtcpCmd) -} - -var xtcpCmd = &cobra.Command{ - Use: "xtcp", - Short: "Run frpc with a single xtcp proxy", - RunE: func(cmd *cobra.Command, args []string) error { - clientCfg, err := parseClientCommonCfgFromCmd() - if err != nil { - fmt.Println(err) - os.Exit(1) - } - - pxyCfgs := make([]v1.ProxyConfigurer, 0) - visitorCfgs := make([]v1.VisitorConfigurer, 0) - - var prefix string - if user != "" { - prefix = user + "." - } - - switch role { - case "server": - cfg := &v1.XTCPProxyConfig{} - cfg.Name = prefix + proxyName - cfg.Type = consts.XTCPProxy - cfg.Transport.UseEncryption = useEncryption - cfg.Transport.UseCompression = useCompression - cfg.Secretkey = sk - cfg.LocalIP = localIP - cfg.LocalPort = localPort - cfg.Transport.BandwidthLimit, err = types.NewBandwidthQuantity(bandwidthLimit) - if err != nil { - fmt.Println(err) - os.Exit(1) - } - cfg.Transport.BandwidthLimitMode = bandwidthLimitMode - - if err := validation.ValidateProxyConfigurerForClient(cfg); err != nil { - fmt.Println(err) - os.Exit(1) - } - pxyCfgs = append(pxyCfgs, cfg) - case "visitor": - cfg := &v1.XTCPVisitorConfig{} - cfg.Name = prefix + proxyName - cfg.Type = consts.XTCPProxy - cfg.Transport.UseEncryption = useEncryption - cfg.Transport.UseCompression = useCompression - cfg.SecretKey = sk - cfg.ServerName = serverName - cfg.BindAddr = bindAddr - cfg.BindPort = bindPort - - if err := validation.ValidateVisitorConfigurer(cfg); err != nil { - fmt.Println(err) - os.Exit(1) - } - visitorCfgs = append(visitorCfgs, cfg) - default: - fmt.Println("invalid role") - os.Exit(1) - } - - err = startService(clientCfg, pxyCfgs, visitorCfgs, "") - if err != nil { - fmt.Println(err) - os.Exit(1) - } - return nil - }, -} diff --git a/cmd/frps/flags.go b/cmd/frps/flags.go new file mode 100644 index 00000000..50170684 --- /dev/null +++ b/cmd/frps/flags.go @@ -0,0 +1,110 @@ +// Copyright 2023 The frp Authors +// +// 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 main + +import ( + "strconv" + + "github.com/spf13/cobra" + + "github.com/fatedier/frp/pkg/config/types" + v1 "github.com/fatedier/frp/pkg/config/v1" +) + +type PortsRangeSliceFlag struct { + V *[]types.PortsRange +} + +func (f *PortsRangeSliceFlag) String() string { + if f.V == nil { + return "" + } + return types.PortsRangeSlice(*f.V).String() +} + +func (f *PortsRangeSliceFlag) Set(s string) error { + slice, err := types.NewPortsRangeSliceFromString(s) + if err != nil { + return err + } + *f.V = slice + return nil +} + +func (f *PortsRangeSliceFlag) Type() string { + return "string" +} + +type BoolFuncFlag struct { + TrueFunc func() + FalseFunc func() + + v bool +} + +func (f *BoolFuncFlag) String() string { + return strconv.FormatBool(f.v) +} + +func (f *BoolFuncFlag) Set(s string) error { + f.v = strconv.FormatBool(f.v) == "true" + + if !f.v { + if f.FalseFunc != nil { + f.FalseFunc() + } + return nil + } + + if f.TrueFunc != nil { + f.TrueFunc() + } + return nil +} + +func (f *BoolFuncFlag) Type() string { + return "bool" +} + +func RegisterServerConfigFlags(cmd *cobra.Command, c *v1.ServerConfig) { + cmd.PersistentFlags().StringVarP(&c.BindAddr, "bind_addr", "", "0.0.0.0", "bind address") + cmd.PersistentFlags().IntVarP(&c.BindPort, "bind_port", "p", 7000, "bind port") + cmd.PersistentFlags().IntVarP(&c.KCPBindPort, "kcp_bind_port", "", 0, "kcp bind udp port") + cmd.PersistentFlags().StringVarP(&c.ProxyBindAddr, "proxy_bind_addr", "", "0.0.0.0", "proxy bind address") + cmd.PersistentFlags().IntVarP(&c.VhostHTTPPort, "vhost_http_port", "", 0, "vhost http port") + cmd.PersistentFlags().IntVarP(&c.VhostHTTPSPort, "vhost_https_port", "", 0, "vhost https port") + cmd.PersistentFlags().Int64VarP(&c.VhostHTTPTimeout, "vhost_http_timeout", "", 60, "vhost http response header timeout") + cmd.PersistentFlags().StringVarP(&c.WebServer.Addr, "dashboard_addr", "", "0.0.0.0", "dashboard address") + cmd.PersistentFlags().IntVarP(&c.WebServer.Port, "dashboard_port", "", 0, "dashboard port") + cmd.PersistentFlags().StringVarP(&c.WebServer.User, "dashboard_user", "", "admin", "dashboard user") + cmd.PersistentFlags().StringVarP(&c.WebServer.Password, "dashboard_pwd", "", "admin", "dashboard password") + cmd.PersistentFlags().BoolVarP(&c.EnablePrometheus, "enable_prometheus", "", false, "enable prometheus dashboard") + cmd.PersistentFlags().StringVarP(&c.Log.To, "log_file", "", "console", "log file") + cmd.PersistentFlags().StringVarP(&c.Log.Level, "log_level", "", "info", "log level") + cmd.PersistentFlags().Int64VarP(&c.Log.MaxDays, "log_max_days", "", 3, "log max days") + cmd.PersistentFlags().BoolVarP(&c.Log.DisablePrintColor, "disable_log_color", "", false, "disable log color in console") + cmd.PersistentFlags().StringVarP(&c.Auth.Token, "token", "t", "", "auth token") + cmd.PersistentFlags().StringVarP(&c.SubDomainHost, "subdomain_host", "", "", "subdomain host") + cmd.PersistentFlags().VarP(&PortsRangeSliceFlag{V: &c.AllowPorts}, "allow_ports", "", "allow ports") + cmd.PersistentFlags().Int64VarP(&c.MaxPortsPerClient, "max_ports_per_client", "", 0, "max ports per client") + cmd.PersistentFlags().BoolVarP(&c.Transport.TLS.Force, "tls_only", "", false, "frps tls only") + + webServerTLS := v1.TLSConfig{} + cmd.PersistentFlags().StringVarP(&webServerTLS.CertFile, "dashboard_tls_cert_file", "", "", "dashboard tls cert file") + cmd.PersistentFlags().StringVarP(&webServerTLS.KeyFile, "dashboard_tls_key_file", "", "", "dashboard tls key file") + cmd.PersistentFlags().VarP(&BoolFuncFlag{ + TrueFunc: func() { c.WebServer.TLS = &webServerTLS }, + }, "dashboard_tls_mode", "", "if enable dashboard tls mode") +} diff --git a/cmd/frps/root.go b/cmd/frps/root.go index 601e068e..4a6f0117 100644 --- a/cmd/frps/root.go +++ b/cmd/frps/root.go @@ -22,7 +22,6 @@ import ( "github.com/spf13/cobra" "github.com/fatedier/frp/pkg/config" - "github.com/fatedier/frp/pkg/config/types" v1 "github.com/fatedier/frp/pkg/config/v1" "github.com/fatedier/frp/pkg/config/v1/validation" "github.com/fatedier/frp/pkg/util/log" @@ -34,61 +33,14 @@ var ( cfgFile string showVersion bool - bindAddr string - bindPort int - kcpBindPort int - proxyBindAddr string - vhostHTTPPort int - vhostHTTPSPort int - vhostHTTPTimeout int64 - dashboardAddr string - dashboardPort int - dashboardUser string - dashboardPwd string - enablePrometheus bool - logFile string - logLevel string - logMaxDays int64 - disableLogColor bool - token string - subDomainHost string - allowPorts string - maxPortsPerClient int64 - tlsOnly bool - dashboardTLSMode bool - dashboardTLSCertFile string - dashboardTLSKeyFile string + serverCfg v1.ServerConfig ) func init() { rootCmd.PersistentFlags().StringVarP(&cfgFile, "config", "c", "", "config file of frps") rootCmd.PersistentFlags().BoolVarP(&showVersion, "version", "v", false, "version of frps") - rootCmd.PersistentFlags().StringVarP(&bindAddr, "bind_addr", "", "0.0.0.0", "bind address") - rootCmd.PersistentFlags().IntVarP(&bindPort, "bind_port", "p", 7000, "bind port") - rootCmd.PersistentFlags().IntVarP(&kcpBindPort, "kcp_bind_port", "", 0, "kcp bind udp port") - rootCmd.PersistentFlags().StringVarP(&proxyBindAddr, "proxy_bind_addr", "", "0.0.0.0", "proxy bind address") - rootCmd.PersistentFlags().IntVarP(&vhostHTTPPort, "vhost_http_port", "", 0, "vhost http port") - rootCmd.PersistentFlags().IntVarP(&vhostHTTPSPort, "vhost_https_port", "", 0, "vhost https port") - rootCmd.PersistentFlags().Int64VarP(&vhostHTTPTimeout, "vhost_http_timeout", "", 60, "vhost http response header timeout") - rootCmd.PersistentFlags().StringVarP(&dashboardAddr, "dashboard_addr", "", "0.0.0.0", "dashboard address") - rootCmd.PersistentFlags().IntVarP(&dashboardPort, "dashboard_port", "", 0, "dashboard port") - rootCmd.PersistentFlags().StringVarP(&dashboardUser, "dashboard_user", "", "admin", "dashboard user") - rootCmd.PersistentFlags().StringVarP(&dashboardPwd, "dashboard_pwd", "", "admin", "dashboard password") - rootCmd.PersistentFlags().BoolVarP(&enablePrometheus, "enable_prometheus", "", false, "enable prometheus dashboard") - rootCmd.PersistentFlags().StringVarP(&logFile, "log_file", "", "console", "log file") - rootCmd.PersistentFlags().StringVarP(&logLevel, "log_level", "", "info", "log level") - rootCmd.PersistentFlags().Int64VarP(&logMaxDays, "log_max_days", "", 3, "log max days") - rootCmd.PersistentFlags().BoolVarP(&disableLogColor, "disable_log_color", "", false, "disable log color in console") - - rootCmd.PersistentFlags().StringVarP(&token, "token", "t", "", "auth token") - rootCmd.PersistentFlags().StringVarP(&subDomainHost, "subdomain_host", "", "", "subdomain host") - rootCmd.PersistentFlags().StringVarP(&allowPorts, "allow_ports", "", "", "allow ports") - rootCmd.PersistentFlags().Int64VarP(&maxPortsPerClient, "max_ports_per_client", "", 0, "max ports per client") - rootCmd.PersistentFlags().BoolVarP(&tlsOnly, "tls_only", "", false, "frps tls only") - rootCmd.PersistentFlags().BoolVarP(&dashboardTLSMode, "dashboard_tls_mode", "", false, "dashboard tls mode") - rootCmd.PersistentFlags().StringVarP(&dashboardTLSCertFile, "dashboard_tls_cert_file", "", "", "dashboard tls cert file") - rootCmd.PersistentFlags().StringVarP(&dashboardTLSKeyFile, "dashboard_tls_key_file", "", "", "dashboard tls key file") + RegisterServerConfigFlags(rootCmd, &serverCfg) } var rootCmd = &cobra.Command{ @@ -116,10 +68,8 @@ var rootCmd = &cobra.Command{ "please use yaml/json/toml format instead!\n") } } else { - if svrCfg, err = parseServerConfigFromCmd(); err != nil { - fmt.Println(err) - os.Exit(1) - } + serverCfg.Complete() + svrCfg = &serverCfg } warning, err := validation.ValidateServerConfig(svrCfg) @@ -145,50 +95,6 @@ func Execute() { } } -func parseServerConfigFromCmd() (*v1.ServerConfig, error) { - cfg := &v1.ServerConfig{} - - cfg.BindAddr = bindAddr - cfg.BindPort = bindPort - cfg.KCPBindPort = kcpBindPort - cfg.ProxyBindAddr = proxyBindAddr - cfg.VhostHTTPPort = vhostHTTPPort - cfg.VhostHTTPSPort = vhostHTTPSPort - cfg.VhostHTTPTimeout = vhostHTTPTimeout - cfg.WebServer.Addr = dashboardAddr - cfg.WebServer.Port = dashboardPort - cfg.WebServer.User = dashboardUser - cfg.WebServer.Password = dashboardPwd - cfg.EnablePrometheus = enablePrometheus - if dashboardTLSMode { - cfg.WebServer.TLS = &v1.TLSConfig{ - CertFile: dashboardTLSCertFile, - KeyFile: dashboardTLSKeyFile, - } - } - cfg.Log.To = logFile - cfg.Log.Level = logLevel - cfg.Log.MaxDays = logMaxDays - cfg.Log.DisablePrintColor = disableLogColor - cfg.SubDomainHost = subDomainHost - cfg.Transport.TLS.Force = tlsOnly - cfg.MaxPortsPerClient = maxPortsPerClient - - // Only token authentication is supported in cmd mode - cfg.Auth.Token = token - - if len(allowPorts) > 0 { - portsRanges, err := types.NewPortsRangeSliceFromString(allowPorts) - if err != nil { - return cfg, fmt.Errorf("allow_ports format error: %v", err) - } - cfg.AllowPorts = portsRanges - } - - cfg.Complete() - return cfg, nil -} - func runServer(cfg *v1.ServerConfig) (err error) { log.InitLog(cfg.Log.To, cfg.Log.Level, cfg.Log.MaxDays, cfg.Log.DisablePrintColor) diff --git a/pkg/config/types/types.go b/pkg/config/types/types.go index b6fb7a85..fac29d74 100644 --- a/pkg/config/types/types.go +++ b/pkg/config/types/types.go @@ -134,6 +134,9 @@ type PortsRange struct { type PortsRangeSlice []PortsRange func (p PortsRangeSlice) String() string { + if len(p) == 0 { + return "" + } strs := []string{} for _, v := range p { if v.Single > 0 { diff --git a/pkg/config/v1/validation/client.go b/pkg/config/v1/validation/client.go index 00214dde..38123946 100644 --- a/pkg/config/v1/validation/client.go +++ b/pkg/config/v1/validation/client.go @@ -29,11 +29,11 @@ func ValidateClientCommonConfig(c *v1.ClientCommonConfig) (Warning, error) { warnings Warning errs error ) - if !lo.Contains(supportedAuthMethods, c.Auth.Method) { - errs = AppendError(errs, fmt.Errorf("invalid auth method, optional values are %v", supportedAuthMethods)) + if !lo.Contains(SupportedAuthMethods, c.Auth.Method) { + errs = AppendError(errs, fmt.Errorf("invalid auth method, optional values are %v", SupportedAuthMethods)) } - if !lo.Every(supportedAuthAdditionalScopes, c.Auth.AdditionalScopes) { - errs = AppendError(errs, fmt.Errorf("invalid auth additional scopes, optional values are %v", supportedAuthAdditionalScopes)) + if !lo.Every(SupportedAuthAdditionalScopes, c.Auth.AdditionalScopes) { + errs = AppendError(errs, fmt.Errorf("invalid auth additional scopes, optional values are %v", SupportedAuthAdditionalScopes)) } if err := validateLogConfig(&c.Log); err != nil { @@ -63,8 +63,8 @@ func ValidateClientCommonConfig(c *v1.ClientCommonConfig) (Warning, error) { warnings = AppendError(warnings, checkTLSConfig("transport.tls.trustedCaFile", c.Transport.TLS.TrustedCaFile)) } - if !lo.Contains(supportedTransportProtocols, c.Transport.Protocol) { - errs = AppendError(errs, fmt.Errorf("invalid transport.protocol, optional values are %v", supportedTransportProtocols)) + if !lo.Contains(SupportedTransportProtocols, c.Transport.Protocol) { + errs = AppendError(errs, fmt.Errorf("invalid transport.protocol, optional values are %v", SupportedTransportProtocols)) } for _, f := range c.IncludeConfigFiles { diff --git a/pkg/config/v1/validation/common.go b/pkg/config/v1/validation/common.go index 3409a9d6..c159e270 100644 --- a/pkg/config/v1/validation/common.go +++ b/pkg/config/v1/validation/common.go @@ -44,8 +44,8 @@ func ValidatePort(port int, fieldPath string) error { } func validateLogConfig(c *v1.LogConfig) error { - if !lo.Contains(supportedLogLevels, c.Level) { - return fmt.Errorf("invalid log level, optional values are %v", supportedLogLevels) + if !lo.Contains(SupportedLogLevels, c.Level) { + return fmt.Errorf("invalid log level, optional values are %v", SupportedLogLevels) } return nil } diff --git a/pkg/config/v1/validation/server.go b/pkg/config/v1/validation/server.go index d8b222f8..5f17d6c7 100644 --- a/pkg/config/v1/validation/server.go +++ b/pkg/config/v1/validation/server.go @@ -27,11 +27,11 @@ func ValidateServerConfig(c *v1.ServerConfig) (Warning, error) { warnings Warning errs error ) - if !lo.Contains(supportedAuthMethods, c.Auth.Method) { - errs = AppendError(errs, fmt.Errorf("invalid auth method, optional values are %v", supportedAuthMethods)) + if !lo.Contains(SupportedAuthMethods, c.Auth.Method) { + errs = AppendError(errs, fmt.Errorf("invalid auth method, optional values are %v", SupportedAuthMethods)) } - if !lo.Every(supportedAuthAdditionalScopes, c.Auth.AdditionalScopes) { - errs = AppendError(errs, fmt.Errorf("invalid auth additional scopes, optional values are %v", supportedAuthAdditionalScopes)) + if !lo.Every(SupportedAuthAdditionalScopes, c.Auth.AdditionalScopes) { + errs = AppendError(errs, fmt.Errorf("invalid auth additional scopes, optional values are %v", SupportedAuthAdditionalScopes)) } if err := validateLogConfig(&c.Log); err != nil { @@ -50,8 +50,8 @@ func ValidateServerConfig(c *v1.ServerConfig) (Warning, error) { errs = AppendError(errs, ValidatePort(c.TCPMuxHTTPConnectPort, "tcpMuxHTTPConnectPort")) for _, p := range c.HTTPPlugins { - if !lo.Every(supportedHTTPPluginOps, p.Ops) { - errs = AppendError(errs, fmt.Errorf("invalid http plugin ops, optional values are %v", supportedHTTPPluginOps)) + if !lo.Every(SupportedHTTPPluginOps, p.Ops) { + errs = AppendError(errs, fmt.Errorf("invalid http plugin ops, optional values are %v", SupportedHTTPPluginOps)) } } return warnings, errs diff --git a/pkg/config/v1/validation/validation.go b/pkg/config/v1/validation/validation.go index bc25272a..dcce5f71 100644 --- a/pkg/config/v1/validation/validation.go +++ b/pkg/config/v1/validation/validation.go @@ -22,7 +22,7 @@ import ( ) var ( - supportedTransportProtocols = []string{ + SupportedTransportProtocols = []string{ "tcp", "kcp", "quic", @@ -30,17 +30,17 @@ var ( "wss", } - supportedAuthMethods = []string{ + SupportedAuthMethods = []string{ "token", "oidc", } - supportedAuthAdditionalScopes = []v1.AuthScope{ + SupportedAuthAdditionalScopes = []v1.AuthScope{ "HeartBeats", "NewWorkConns", } - supportedLogLevels = []string{ + SupportedLogLevels = []string{ "trace", "debug", "info", @@ -48,7 +48,7 @@ var ( "error", } - supportedHTTPPluginOps = []string{ + SupportedHTTPPluginOps = []string{ splugin.OpLogin, splugin.OpNewProxy, splugin.OpCloseProxy, diff --git a/pkg/config/v1/validation/visitor.go b/pkg/config/v1/validation/visitor.go index c478b490..5307dc90 100644 --- a/pkg/config/v1/validation/visitor.go +++ b/pkg/config/v1/validation/visitor.go @@ -42,7 +42,11 @@ func ValidateVisitorConfigurer(c v1.VisitorConfigurer) error { func validateVisitorBaseConfig(c *v1.VisitorBaseConfig) error { if c.Name == "" { - return errors.New("name should not be empty") + return errors.New("name is required") + } + + if c.ServerName == "" { + return errors.New("server name is required") } if c.BindPort == 0 { diff --git a/test/e2e/pkg/sdk/client/client.go b/pkg/sdk/client/client.go similarity index 79% rename from test/e2e/pkg/sdk/client/client.go rename to pkg/sdk/client/client.go index 3d157073..c9657905 100644 --- a/test/e2e/pkg/sdk/client/client.go +++ b/pkg/sdk/client/client.go @@ -10,7 +10,7 @@ import ( "strings" "github.com/fatedier/frp/client" - "github.com/fatedier/frp/test/e2e/pkg/utils" + "github.com/fatedier/frp/pkg/util/util" ) type Client struct { @@ -53,6 +53,22 @@ func (c *Client) GetProxyStatus(name string) (*client.ProxyStatusResp, error) { return nil, fmt.Errorf("no proxy status found") } +func (c *Client) GetAllProxyStatus() (client.StatusResp, error) { + req, err := http.NewRequest("GET", "http://"+c.address+"/api/status", nil) + if err != nil { + return nil, err + } + content, err := c.do(req) + if err != nil { + return nil, err + } + allStatus := make(client.StatusResp) + if err = json.Unmarshal([]byte(content), &allStatus); err != nil { + return nil, fmt.Errorf("unmarshal http response error: %s", strings.TrimSpace(content)) + } + return allStatus, nil +} + func (c *Client) Reload() error { req, err := http.NewRequest("GET", "http://"+c.address+"/api/reload", nil) if err != nil { @@ -90,7 +106,7 @@ func (c *Client) UpdateConfig(content string) error { func (c *Client) setAuthHeader(req *http.Request) { if c.authUser != "" || c.authPwd != "" { - req.Header.Set("Authorization", utils.BasicAuth(c.authUser, c.authPwd)) + req.Header.Set("Authorization", util.BasicAuth(c.authUser, c.authPwd)) } } diff --git a/pkg/util/util/http.go b/pkg/util/util/http.go index 7d6200a2..a6a25a4c 100644 --- a/pkg/util/util/http.go +++ b/pkg/util/util/http.go @@ -95,3 +95,8 @@ func ParseBasicAuth(auth string) (username, password string, ok bool) { } return cs[:s], cs[s+1:], true } + +func BasicAuth(username, passwd string) string { + auth := username + ":" + passwd + return "Basic " + base64.StdEncoding.EncodeToString([]byte(auth)) +} diff --git a/test/e2e/legacy/basic/client.go b/test/e2e/legacy/basic/client.go index b2e462bb..da23db9c 100644 --- a/test/e2e/legacy/basic/client.go +++ b/test/e2e/legacy/basic/client.go @@ -8,10 +8,10 @@ import ( "github.com/onsi/ginkgo/v2" + clientsdk "github.com/fatedier/frp/pkg/sdk/client" "github.com/fatedier/frp/test/e2e/framework" "github.com/fatedier/frp/test/e2e/framework/consts" "github.com/fatedier/frp/test/e2e/pkg/request" - clientsdk "github.com/fatedier/frp/test/e2e/pkg/sdk/client" ) var _ = ginkgo.Describe("[Feature: ClientManage]", func() { diff --git a/test/e2e/legacy/basic/cmd.go b/test/e2e/legacy/basic/cmd.go index 89f2435d..7d86233a 100644 --- a/test/e2e/legacy/basic/cmd.go +++ b/test/e2e/legacy/basic/cmd.go @@ -1,7 +1,6 @@ package basic import ( - "fmt" "strconv" "strings" @@ -70,7 +69,7 @@ var _ = ginkgo.Describe("[Feature: Cmd]", func() { localPort := f.PortByName(framework.TCPEchoServerPort) remotePort := f.AllocPort() - _, _, err = f.RunFrpc("tcp", "-s", fmt.Sprintf("127.0.0.1:%d", serverPort), "-t", "123", "-u", "test", + _, _, err = f.RunFrpc("tcp", "-s", "127.0.0.1", "-P", strconv.Itoa(serverPort), "-t", "123", "-u", "test", "-l", strconv.Itoa(localPort), "-r", strconv.Itoa(remotePort), "-n", "tcp_test") framework.ExpectNoError(err) @@ -84,7 +83,7 @@ var _ = ginkgo.Describe("[Feature: Cmd]", func() { localPort := f.PortByName(framework.UDPEchoServerPort) remotePort := f.AllocPort() - _, _, err = f.RunFrpc("udp", "-s", fmt.Sprintf("127.0.0.1:%d", serverPort), "-t", "123", "-u", "test", + _, _, err = f.RunFrpc("udp", "-s", "127.0.0.1", "-P", strconv.Itoa(serverPort), "-t", "123", "-u", "test", "-l", strconv.Itoa(localPort), "-r", strconv.Itoa(remotePort), "-n", "udp_test") framework.ExpectNoError(err) @@ -98,7 +97,7 @@ var _ = ginkgo.Describe("[Feature: Cmd]", func() { _, _, err := f.RunFrps("-t", "123", "-p", strconv.Itoa(serverPort), "--vhost_http_port", strconv.Itoa(vhostHTTPPort)) framework.ExpectNoError(err) - _, _, err = f.RunFrpc("http", "-s", "127.0.0.1:"+strconv.Itoa(serverPort), "-t", "123", "-u", "test", + _, _, err = f.RunFrpc("http", "-s", "127.0.0.1", "-P", strconv.Itoa(serverPort), "-t", "123", "-u", "test", "-n", "udp_test", "-l", strconv.Itoa(f.PortByName(framework.HTTPSimpleServerPort)), "--custom_domain", "test.example.com") framework.ExpectNoError(err) diff --git a/test/e2e/legacy/basic/server.go b/test/e2e/legacy/basic/server.go index 08bc6b22..f3c2a228 100644 --- a/test/e2e/legacy/basic/server.go +++ b/test/e2e/legacy/basic/server.go @@ -7,11 +7,11 @@ import ( "github.com/onsi/ginkgo/v2" + clientsdk "github.com/fatedier/frp/pkg/sdk/client" "github.com/fatedier/frp/test/e2e/framework" "github.com/fatedier/frp/test/e2e/framework/consts" "github.com/fatedier/frp/test/e2e/pkg/port" "github.com/fatedier/frp/test/e2e/pkg/request" - clientsdk "github.com/fatedier/frp/test/e2e/pkg/sdk/client" ) var _ = ginkgo.Describe("[Feature: Server Manager]", func() { diff --git a/test/e2e/legacy/features/bandwidth_limit.go b/test/e2e/legacy/features/bandwidth_limit.go index cbc6e928..c94e473f 100644 --- a/test/e2e/legacy/features/bandwidth_limit.go +++ b/test/e2e/legacy/features/bandwidth_limit.go @@ -10,8 +10,8 @@ import ( plugin "github.com/fatedier/frp/pkg/plugin/server" "github.com/fatedier/frp/test/e2e/framework" "github.com/fatedier/frp/test/e2e/framework/consts" - plugintest "github.com/fatedier/frp/test/e2e/legacy/plugin" "github.com/fatedier/frp/test/e2e/mock/server/streamserver" + pluginpkg "github.com/fatedier/frp/test/e2e/pkg/plugin" "github.com/fatedier/frp/test/e2e/pkg/request" ) @@ -65,7 +65,7 @@ var _ = ginkgo.Describe("[Feature: Bandwidth Limit]", func() { ret.Content = content return &ret } - pluginServer := plugintest.NewHTTPPluginServer(pluginPort, newFunc, handler, nil) + pluginServer := pluginpkg.NewHTTPPluginServer(pluginPort, newFunc, handler, nil) f.RunServer("", pluginServer) diff --git a/test/e2e/legacy/plugin/server.go b/test/e2e/legacy/plugin/server.go index 0011b1b9..3f14a42d 100644 --- a/test/e2e/legacy/plugin/server.go +++ b/test/e2e/legacy/plugin/server.go @@ -10,6 +10,7 @@ import ( "github.com/fatedier/frp/pkg/transport" "github.com/fatedier/frp/test/e2e/framework" "github.com/fatedier/frp/test/e2e/framework/consts" + pluginpkg "github.com/fatedier/frp/test/e2e/pkg/plugin" ) var _ = ginkgo.Describe("[Feature: Server-Plugins]", func() { @@ -40,7 +41,7 @@ var _ = ginkgo.Describe("[Feature: Server-Plugins]", func() { } return &ret } - pluginServer := NewHTTPPluginServer(localPort, newFunc, handler, nil) + pluginServer := pluginpkg.NewHTTPPluginServer(localPort, newFunc, handler, nil) f.RunServer("", pluginServer) @@ -98,7 +99,7 @@ var _ = ginkgo.Describe("[Feature: Server-Plugins]", func() { } return &ret } - pluginServer := NewHTTPPluginServer(localPort, newFunc, handler, nil) + pluginServer := pluginpkg.NewHTTPPluginServer(localPort, newFunc, handler, nil) f.RunServer("", pluginServer) @@ -133,7 +134,7 @@ var _ = ginkgo.Describe("[Feature: Server-Plugins]", func() { ret.Content = content return &ret } - pluginServer := NewHTTPPluginServer(localPort, newFunc, handler, nil) + pluginServer := pluginpkg.NewHTTPPluginServer(localPort, newFunc, handler, nil) f.RunServer("", pluginServer) @@ -174,7 +175,7 @@ var _ = ginkgo.Describe("[Feature: Server-Plugins]", func() { recordProxyName = content.ProxyName return &ret } - pluginServer := NewHTTPPluginServer(localPort, newFunc, handler, nil) + pluginServer := pluginpkg.NewHTTPPluginServer(localPort, newFunc, handler, nil) f.RunServer("", pluginServer) @@ -226,7 +227,7 @@ var _ = ginkgo.Describe("[Feature: Server-Plugins]", func() { ret.Unchange = true return &ret } - pluginServer := NewHTTPPluginServer(localPort, newFunc, handler, nil) + pluginServer := pluginpkg.NewHTTPPluginServer(localPort, newFunc, handler, nil) f.RunServer("", pluginServer) @@ -276,7 +277,7 @@ var _ = ginkgo.Describe("[Feature: Server-Plugins]", func() { ret.Unchange = true return &ret } - pluginServer := NewHTTPPluginServer(localPort, newFunc, handler, nil) + pluginServer := pluginpkg.NewHTTPPluginServer(localPort, newFunc, handler, nil) f.RunServer("", pluginServer) @@ -321,7 +322,7 @@ var _ = ginkgo.Describe("[Feature: Server-Plugins]", func() { ret.Unchange = true return &ret } - pluginServer := NewHTTPPluginServer(localPort, newFunc, handler, nil) + pluginServer := pluginpkg.NewHTTPPluginServer(localPort, newFunc, handler, nil) f.RunServer("", pluginServer) @@ -368,7 +369,7 @@ var _ = ginkgo.Describe("[Feature: Server-Plugins]", func() { } tlsConfig, err := transport.NewServerTLSConfig("", "", "") framework.ExpectNoError(err) - pluginServer := NewHTTPPluginServer(localPort, newFunc, handler, tlsConfig) + pluginServer := pluginpkg.NewHTTPPluginServer(localPort, newFunc, handler, tlsConfig) f.RunServer("", pluginServer) diff --git a/test/e2e/legacy/plugin/utils.go b/test/e2e/pkg/plugin/plugin.go similarity index 100% rename from test/e2e/legacy/plugin/utils.go rename to test/e2e/pkg/plugin/plugin.go diff --git a/test/e2e/pkg/request/request.go b/test/e2e/pkg/request/request.go index 44bc0d0c..50deb3bf 100644 --- a/test/e2e/pkg/request/request.go +++ b/test/e2e/pkg/request/request.go @@ -14,8 +14,8 @@ import ( libdial "github.com/fatedier/golib/net/dial" + "github.com/fatedier/frp/pkg/util/util" "github.com/fatedier/frp/test/e2e/pkg/rpc" - "github.com/fatedier/frp/test/e2e/pkg/utils" ) type Request struct { @@ -115,7 +115,7 @@ func (r *Request) HTTPHeaders(headers map[string]string) *Request { } func (r *Request) HTTPAuth(user, password string) *Request { - r.authValue = utils.BasicAuth(user, password) + r.authValue = util.BasicAuth(user, password) return r } diff --git a/test/e2e/pkg/utils/utils.go b/test/e2e/pkg/utils/utils.go deleted file mode 100644 index 7b177e14..00000000 --- a/test/e2e/pkg/utils/utils.go +++ /dev/null @@ -1,10 +0,0 @@ -package utils - -import ( - "encoding/base64" -) - -func BasicAuth(username, passwd string) string { - auth := username + ":" + passwd - return "Basic " + base64.StdEncoding.EncodeToString([]byte(auth)) -} diff --git a/test/e2e/v1/basic/client.go b/test/e2e/v1/basic/client.go index 111a238a..25b99424 100644 --- a/test/e2e/v1/basic/client.go +++ b/test/e2e/v1/basic/client.go @@ -8,10 +8,10 @@ import ( "github.com/onsi/ginkgo/v2" + clientsdk "github.com/fatedier/frp/pkg/sdk/client" "github.com/fatedier/frp/test/e2e/framework" "github.com/fatedier/frp/test/e2e/framework/consts" "github.com/fatedier/frp/test/e2e/pkg/request" - clientsdk "github.com/fatedier/frp/test/e2e/pkg/sdk/client" ) var _ = ginkgo.Describe("[Feature: ClientManage]", func() { diff --git a/test/e2e/v1/basic/cmd.go b/test/e2e/v1/basic/cmd.go index 9d3120fa..08a9ea94 100644 --- a/test/e2e/v1/basic/cmd.go +++ b/test/e2e/v1/basic/cmd.go @@ -1,7 +1,6 @@ package basic import ( - "fmt" "strconv" "strings" @@ -66,7 +65,7 @@ var _ = ginkgo.Describe("[Feature: Cmd]", func() { localPort := f.PortByName(framework.TCPEchoServerPort) remotePort := f.AllocPort() - _, _, err = f.RunFrpc("tcp", "-s", fmt.Sprintf("127.0.0.1:%d", serverPort), "-t", "123", "-u", "test", + _, _, err = f.RunFrpc("tcp", "-s", "127.0.0.1", "-P", strconv.Itoa(serverPort), "-t", "123", "-u", "test", "-l", strconv.Itoa(localPort), "-r", strconv.Itoa(remotePort), "-n", "tcp_test") framework.ExpectNoError(err) @@ -80,7 +79,7 @@ var _ = ginkgo.Describe("[Feature: Cmd]", func() { localPort := f.PortByName(framework.UDPEchoServerPort) remotePort := f.AllocPort() - _, _, err = f.RunFrpc("udp", "-s", fmt.Sprintf("127.0.0.1:%d", serverPort), "-t", "123", "-u", "test", + _, _, err = f.RunFrpc("udp", "-s", "127.0.0.1", "-P", strconv.Itoa(serverPort), "-t", "123", "-u", "test", "-l", strconv.Itoa(localPort), "-r", strconv.Itoa(remotePort), "-n", "udp_test") framework.ExpectNoError(err) @@ -94,7 +93,7 @@ var _ = ginkgo.Describe("[Feature: Cmd]", func() { _, _, err := f.RunFrps("-t", "123", "-p", strconv.Itoa(serverPort), "--vhost_http_port", strconv.Itoa(vhostHTTPPort)) framework.ExpectNoError(err) - _, _, err = f.RunFrpc("http", "-s", "127.0.0.1:"+strconv.Itoa(serverPort), "-t", "123", "-u", "test", + _, _, err = f.RunFrpc("http", "-s", "127.0.0.1", "-P", strconv.Itoa(serverPort), "-t", "123", "-u", "test", "-n", "udp_test", "-l", strconv.Itoa(f.PortByName(framework.HTTPSimpleServerPort)), "--custom_domain", "test.example.com") framework.ExpectNoError(err) diff --git a/test/e2e/v1/basic/server.go b/test/e2e/v1/basic/server.go index ff1225b8..eed1ddaa 100644 --- a/test/e2e/v1/basic/server.go +++ b/test/e2e/v1/basic/server.go @@ -7,11 +7,11 @@ import ( "github.com/onsi/ginkgo/v2" + clientsdk "github.com/fatedier/frp/pkg/sdk/client" "github.com/fatedier/frp/test/e2e/framework" "github.com/fatedier/frp/test/e2e/framework/consts" "github.com/fatedier/frp/test/e2e/pkg/port" "github.com/fatedier/frp/test/e2e/pkg/request" - clientsdk "github.com/fatedier/frp/test/e2e/pkg/sdk/client" ) var _ = ginkgo.Describe("[Feature: Server Manager]", func() { diff --git a/test/e2e/v1/features/bandwidth_limit.go b/test/e2e/v1/features/bandwidth_limit.go index 5bf1c796..efcf38ed 100644 --- a/test/e2e/v1/features/bandwidth_limit.go +++ b/test/e2e/v1/features/bandwidth_limit.go @@ -10,8 +10,8 @@ import ( plugin "github.com/fatedier/frp/pkg/plugin/server" "github.com/fatedier/frp/test/e2e/framework" "github.com/fatedier/frp/test/e2e/framework/consts" - plugintest "github.com/fatedier/frp/test/e2e/legacy/plugin" "github.com/fatedier/frp/test/e2e/mock/server/streamserver" + pluginpkg "github.com/fatedier/frp/test/e2e/pkg/plugin" "github.com/fatedier/frp/test/e2e/pkg/request" ) @@ -66,7 +66,7 @@ var _ = ginkgo.Describe("[Feature: Bandwidth Limit]", func() { ret.Content = content return &ret } - pluginServer := plugintest.NewHTTPPluginServer(pluginPort, newFunc, handler, nil) + pluginServer := pluginpkg.NewHTTPPluginServer(pluginPort, newFunc, handler, nil) f.RunServer("", pluginServer) diff --git a/test/e2e/v1/plugin/server.go b/test/e2e/v1/plugin/server.go index 02e8469d..66456f57 100644 --- a/test/e2e/v1/plugin/server.go +++ b/test/e2e/v1/plugin/server.go @@ -10,6 +10,7 @@ import ( "github.com/fatedier/frp/pkg/transport" "github.com/fatedier/frp/test/e2e/framework" "github.com/fatedier/frp/test/e2e/framework/consts" + pluginpkg "github.com/fatedier/frp/test/e2e/pkg/plugin" ) var _ = ginkgo.Describe("[Feature: Server-Plugins]", func() { @@ -40,7 +41,7 @@ var _ = ginkgo.Describe("[Feature: Server-Plugins]", func() { } return &ret } - pluginServer := NewHTTPPluginServer(localPort, newFunc, handler, nil) + pluginServer := pluginpkg.NewHTTPPluginServer(localPort, newFunc, handler, nil) f.RunServer("", pluginServer) @@ -101,7 +102,7 @@ var _ = ginkgo.Describe("[Feature: Server-Plugins]", func() { } return &ret } - pluginServer := NewHTTPPluginServer(localPort, newFunc, handler, nil) + pluginServer := pluginpkg.NewHTTPPluginServer(localPort, newFunc, handler, nil) f.RunServer("", pluginServer) @@ -138,7 +139,7 @@ var _ = ginkgo.Describe("[Feature: Server-Plugins]", func() { ret.Content = content return &ret } - pluginServer := NewHTTPPluginServer(localPort, newFunc, handler, nil) + pluginServer := pluginpkg.NewHTTPPluginServer(localPort, newFunc, handler, nil) f.RunServer("", pluginServer) @@ -181,7 +182,7 @@ var _ = ginkgo.Describe("[Feature: Server-Plugins]", func() { recordProxyName = content.ProxyName return &ret } - pluginServer := NewHTTPPluginServer(localPort, newFunc, handler, nil) + pluginServer := pluginpkg.NewHTTPPluginServer(localPort, newFunc, handler, nil) f.RunServer("", pluginServer) @@ -235,7 +236,7 @@ var _ = ginkgo.Describe("[Feature: Server-Plugins]", func() { ret.Unchange = true return &ret } - pluginServer := NewHTTPPluginServer(localPort, newFunc, handler, nil) + pluginServer := pluginpkg.NewHTTPPluginServer(localPort, newFunc, handler, nil) f.RunServer("", pluginServer) @@ -287,7 +288,7 @@ var _ = ginkgo.Describe("[Feature: Server-Plugins]", func() { ret.Unchange = true return &ret } - pluginServer := NewHTTPPluginServer(localPort, newFunc, handler, nil) + pluginServer := pluginpkg.NewHTTPPluginServer(localPort, newFunc, handler, nil) f.RunServer("", pluginServer) @@ -334,7 +335,7 @@ var _ = ginkgo.Describe("[Feature: Server-Plugins]", func() { ret.Unchange = true return &ret } - pluginServer := NewHTTPPluginServer(localPort, newFunc, handler, nil) + pluginServer := pluginpkg.NewHTTPPluginServer(localPort, newFunc, handler, nil) f.RunServer("", pluginServer) @@ -383,7 +384,7 @@ var _ = ginkgo.Describe("[Feature: Server-Plugins]", func() { } tlsConfig, err := transport.NewServerTLSConfig("", "", "") framework.ExpectNoError(err) - pluginServer := NewHTTPPluginServer(localPort, newFunc, handler, tlsConfig) + pluginServer := pluginpkg.NewHTTPPluginServer(localPort, newFunc, handler, tlsConfig) f.RunServer("", pluginServer) diff --git a/test/e2e/v1/plugin/utils.go b/test/e2e/v1/plugin/utils.go deleted file mode 100644 index 51de01d9..00000000 --- a/test/e2e/v1/plugin/utils.go +++ /dev/null @@ -1,41 +0,0 @@ -package plugin - -import ( - "crypto/tls" - "encoding/json" - "io" - "net/http" - - plugin "github.com/fatedier/frp/pkg/plugin/server" - "github.com/fatedier/frp/pkg/util/log" - "github.com/fatedier/frp/test/e2e/mock/server/httpserver" -) - -type Handler func(req *plugin.Request) *plugin.Response - -type NewPluginRequest func() *plugin.Request - -func NewHTTPPluginServer(port int, newFunc NewPluginRequest, handler Handler, tlsConfig *tls.Config) *httpserver.Server { - return httpserver.New( - httpserver.WithBindPort(port), - httpserver.WithTLSConfig(tlsConfig), - httpserver.WithHandler(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { - r := newFunc() - buf, err := io.ReadAll(req.Body) - if err != nil { - w.WriteHeader(500) - return - } - log.Trace("plugin request: %s", string(buf)) - err = json.Unmarshal(buf, &r) - if err != nil { - w.WriteHeader(500) - return - } - resp := handler(r) - buf, _ = json.Marshal(resp) - log.Trace("plugin response: %s", string(buf)) - _, _ = w.Write(buf) - })), - ) -}