diff --git a/cmd/frpc/sub/root.go b/cmd/frpc/sub/root.go index ee89c489..98b4ccde 100644 --- a/cmd/frpc/sub/root.go +++ b/cmd/frpc/sub/root.go @@ -33,6 +33,7 @@ import ( "github.com/fatedier/frp/pkg/config/v1/validation" "github.com/fatedier/frp/pkg/featuregate" "github.com/fatedier/frp/pkg/util/log" + pkgnet "github.com/fatedier/frp/pkg/util/net" "github.com/fatedier/frp/pkg/util/version" ) @@ -41,6 +42,7 @@ var ( cfgDir string showVersion bool strictConfigMode bool + prefixPath string ) func init() { @@ -48,6 +50,7 @@ func init() { rootCmd.PersistentFlags().StringVarP(&cfgDir, "config_dir", "", "", "config directory, run one frpc service for each file in config directory") rootCmd.PersistentFlags().BoolVarP(&showVersion, "version", "v", false, "version of frpc") rootCmd.PersistentFlags().BoolVarP(&strictConfigMode, "strict_config", "", true, "strict config parsing mode, unknown fields will cause an errors") + rootCmd.PersistentFlags().StringVarP(&prefixPath, "prefixPath", "", "", "ws/wss path of frpc") } var rootCmd = &cobra.Command{ @@ -149,6 +152,15 @@ func startService( log.Infof("start frpc service for config file [%s]", cfgFile) defer log.Infof("frpc service for config file [%s] stopped", cfgFile) } + + log.Infof("cfg.Transport.PrefixPath: %s", cfg.Transport.PrefixPath) + if cfg.Transport.PrefixPath != "" { + pkgnet.SetWsPrefixPath(cfg.Transport.PrefixPath) + } + if prefixPath != "" { + pkgnet.SetWsPrefixPath(prefixPath) + } + svr, err := client.NewService(client.ServiceOptions{ Common: cfg, ProxyCfgs: proxyCfgs, @@ -164,5 +176,6 @@ func startService( if shouldGracefulClose { go handleTermSignal(svr) } + log.Infof("frpc Websocket PrefixPath: \"%s\"", pkgnet.GetWsPrefixPath()) return svr.Run(context.Background()) } diff --git a/cmd/frps/root.go b/cmd/frps/root.go index fff487d1..115e869a 100644 --- a/cmd/frps/root.go +++ b/cmd/frps/root.go @@ -25,6 +25,7 @@ import ( v1 "github.com/fatedier/frp/pkg/config/v1" "github.com/fatedier/frp/pkg/config/v1/validation" "github.com/fatedier/frp/pkg/util/log" + pkgnet "github.com/fatedier/frp/pkg/util/net" "github.com/fatedier/frp/pkg/util/version" "github.com/fatedier/frp/server" ) @@ -33,6 +34,7 @@ var ( cfgFile string showVersion bool strictConfigMode bool + prefixPath string serverCfg v1.ServerConfig ) @@ -41,6 +43,7 @@ func init() { rootCmd.PersistentFlags().StringVarP(&cfgFile, "config", "c", "", "config file of frps") rootCmd.PersistentFlags().BoolVarP(&showVersion, "version", "v", false, "version of frps") rootCmd.PersistentFlags().BoolVarP(&strictConfigMode, "strict_config", "", true, "strict config parsing mode, unknown fields will cause errors") + rootCmd.PersistentFlags().StringVarP(&prefixPath, "prefixPath", "", "", "ws/wss path of frps") config.RegisterServerConfigFlags(rootCmd, &serverCfg) } @@ -54,6 +57,10 @@ var rootCmd = &cobra.Command{ return nil } + if prefixPath != "" { + pkgnet.SetWsPrefixPath(prefixPath) + } + var ( svrCfg *v1.ServerConfig isLegacyFormat bool @@ -112,6 +119,7 @@ func runServer(cfg *v1.ServerConfig) (err error) { return err } log.Infof("frps started successfully") + log.Infof("frps Websocket PrefixPath: \"%s\"", pkgnet.GetWsPrefixPath()) svr.Run(context.Background()) return } diff --git a/pkg/config/v1/client.go b/pkg/config/v1/client.go index d616fc0a..794284c6 100644 --- a/pkg/config/v1/client.go +++ b/pkg/config/v1/client.go @@ -17,9 +17,8 @@ package v1 import ( "os" - "github.com/samber/lo" - "github.com/fatedier/frp/pkg/util/util" + "github.com/samber/lo" ) type ClientConfig struct { @@ -96,6 +95,8 @@ type ClientTransportConfig struct { // Valid values are "tcp", "kcp", "quic", "websocket" and "wss". By default, this value // is "tcp". Protocol string `json:"protocol,omitempty"` + //When the protocol is ws or wss, use this parameter + PrefixPath string `json:"prefixpath,omitempty"` // The maximum amount of time a dial to server will wait for a connect to complete. DialServerTimeout int64 `json:"dialServerTimeout,omitempty"` // DialServerKeepAlive specifies the interval between keep-alive probes for an active network connection between frpc and frps. @@ -135,6 +136,7 @@ type ClientTransportConfig struct { func (c *ClientTransportConfig) Complete() { c.Protocol = util.EmptyOr(c.Protocol, "tcp") + c.PrefixPath = util.EmptyOr(c.PrefixPath, "/~!frp") c.DialServerTimeout = util.EmptyOr(c.DialServerTimeout, 10) c.DialServerKeepAlive = util.EmptyOr(c.DialServerKeepAlive, 7200) c.ProxyURL = util.EmptyOr(c.ProxyURL, os.Getenv("http_proxy")) diff --git a/pkg/util/net/websocket.go b/pkg/util/net/websocket.go index 263b3a1d..eb589dac 100644 --- a/pkg/util/net/websocket.go +++ b/pkg/util/net/websocket.go @@ -11,9 +11,7 @@ import ( var ErrWebsocketListenerClosed = errors.New("websocket listener closed") -const ( - FrpWebsocketPath = "/~!frp" -) +var FrpWebsocketPath = "/~!frp" type WebsocketListener struct { ln net.Listener @@ -66,3 +64,27 @@ func (p *WebsocketListener) Close() error { func (p *WebsocketListener) Addr() net.Addr { return p.ln.Addr() } + +func GetWsPrefixPath() string { + return FrpWebsocketPath +} + +func SetWsPrefixPath(path string) { + if path != "" { + if HasPrefix(path, "/") { + FrpWebsocketPath = path + } else { + FrpWebsocketPath = "/" + path + } + } else { + FrpWebsocketPath = "/~!frp" + } +} + +func HasPrefix(s, prefix string) bool { + return len(s) >= len(prefix) && s[0:len(prefix)] == prefix +} + +func HasSuffix(s, suffix string) bool { + return len(s) >= len(suffix) && s[len(s)-len(suffix):] == suffix +}