diff --git a/README.md b/README.md index 0b335b2..4cf18b6 100644 --- a/README.md +++ b/README.md @@ -343,20 +343,15 @@ Configure `frps` same as above. Note that it may not work with all types of NAT devices. You might want to fallback to stcp if xtcp doesn't work. -1. In `frps.ini` configure a UDP port for xtcp: - - ```ini - # frps.ini - bind_udp_port = 7001 - ``` - -2. Start `frpc` on machine B, and expose the SSH port. Note that the `remote_port` field is removed: +1. Start `frpc` on machine B, and expose the SSH port. Note that the `remote_port` field is removed: ```ini # frpc.ini [common] server_addr = x.x.x.x server_port = 7000 + # set up a new stun server if the default one is not available. + # nat_hole_stun_server = xxx [p2p_ssh] type = xtcp @@ -365,13 +360,15 @@ Note that it may not work with all types of NAT devices. You might want to fallb local_port = 22 ``` -3. Start another `frpc` (typically on another machine C) with the configuration to connect to SSH using P2P mode: +2. Start another `frpc` (typically on another machine C) with the configuration to connect to SSH using P2P mode: ```ini # frpc.ini [common] server_addr = x.x.x.x server_port = 7000 + # set up a new stun server if the default one is not available. + # nat_hole_stun_server = xxx [p2p_ssh_visitor] type = xtcp @@ -380,9 +377,11 @@ Note that it may not work with all types of NAT devices. You might want to fallb sk = abcdefg bind_addr = 127.0.0.1 bind_port = 6000 + # when automatic tunnel persistence is required, set it to true + keep_tunnel_open = false ``` -4. On machine C, connect to SSH on machine B, using this command: +3. On machine C, connect to SSH on machine B, using this command: `ssh -oPort=6000 127.0.0.1` diff --git a/Release.md b/Release.md index 1d3a27c..2b2fbab 100644 --- a/Release.md +++ b/Release.md @@ -1,8 +1,19 @@ +## Notes + +We have thoroughly refactored xtcp in this version to improve its penetration rate and stability. + +In this version, different penetration strategies can be attempted by retrying connections multiple times. Once a hole is successfully punched, the strategy will be recorded in the server cache for future reuse. When new users connect, the successfully penetrated tunnel can be reused instead of punching a new hole. + +**Due to a significant refactor of xtcp, this version is not compatible with previous versions of xtcp.** + +**To use features related to xtcp, both frpc and frps need to be updated to the latest version.** + ### New -* The `httpconnect` type in `tcpmux` now supports authentication through the parameters `http_user` and `http_pwd`. +* The frpc has added the `nathole discover` command for testing the NAT type of the current network. +* `XTCP` has been refactored, resulting in a significant improvement in the success rate of penetration. +* When verifying passwords, use `subtle.ConstantTimeCompare` and introduce a certain delay when the password is incorrect. -### Improved +### Fix -* The web framework has been upgraded to vue3 + element-plus, and the dashboard has added some information display and supports dark mode. -* The e2e testing has been switched to ginkgo v2. +* Fix the problem of lagging when opening multiple table entries in the frps dashboard. diff --git a/cmd/frps/root.go b/cmd/frps/root.go index 4086eac..1ba1352 100644 --- a/cmd/frps/root.go +++ b/cmd/frps/root.go @@ -39,7 +39,6 @@ var ( bindAddr string bindPort int - bindUDPPort int kcpBindPort int proxyBindAddr string vhostHTTPPort int @@ -70,7 +69,6 @@ func init() { 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(&bindUDPPort, "bind_udp_port", "", 0, "bind udp 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") @@ -159,7 +157,6 @@ func parseServerCommonCfgFromCmd() (cfg config.ServerCommonConf, err error) { cfg.BindAddr = bindAddr cfg.BindPort = bindPort - cfg.BindUDPPort = bindUDPPort cfg.KCPBindPort = kcpBindPort cfg.ProxyBindAddr = proxyBindAddr cfg.VhostHTTPPort = vhostHTTPPort diff --git a/conf/frpc_full.ini b/conf/frpc_full.ini index f614c37..e18d2a0 100644 --- a/conf/frpc_full.ini +++ b/conf/frpc_full.ini @@ -6,14 +6,6 @@ server_addr = 0.0.0.0 server_port = 7000 -# Specify another address of the server to connect for nat hole. By default, it's same with -# server_addr. -# nat_hole_server_addr = 0.0.0.0 - -# ServerUDPPort specifies the server port to help penetrate NAT hole. By default, this value is 0. -# This parameter is only used when executing "nathole discover" in the command line. -# server_udp_port = 0 - # STUN server to help penetrate NAT hole. # nat_hole_stun_server = stun.easyvoip.com:3478 @@ -366,6 +358,11 @@ bind_addr = 127.0.0.1 bind_port = 9001 use_encryption = false use_compression = false +# when automatic tunnel persistence is required, set it to true +keep_tunnel_open = false +# effective when keep_tunnel_open is set to true, the number of attempts to punch through per hour +max_retries_an_hour = 8 +min_retry_interval = 90 [tcpmuxhttpconnect] type = tcpmux diff --git a/conf/frps_full.ini b/conf/frps_full.ini index 2d5e08e..525072d 100644 --- a/conf/frps_full.ini +++ b/conf/frps_full.ini @@ -6,9 +6,6 @@ bind_addr = 0.0.0.0 bind_port = 7000 -# udp port to help make udp hole to penetrate nat -bind_udp_port = 7001 - # udp port used for kcp protocol, it can be same with 'bind_port'. # if not set, kcp is disabled in frps. kcp_bind_port = 7000 @@ -157,6 +154,9 @@ udp_packet_size = 1500 # Dashboard port must be set first pprof_enable = false +# Retention time for NAT hole punching strategy data. +nat_hole_analysis_data_reserve_hours = 168 + [plugin.user-manager] addr = 127.0.0.1:9000 path = /handler diff --git a/pkg/config/client.go b/pkg/config/client.go index 3ee3910..50a46d5 100644 --- a/pkg/config/client.go +++ b/pkg/config/client.go @@ -35,15 +35,9 @@ type ClientCommonConf struct { // ServerAddr specifies the address of the server to connect to. By // default, this value is "0.0.0.0". ServerAddr string `ini:"server_addr" json:"server_addr"` - // Specify another address of the server to connect for nat hole. By default, it's same with - // ServerAddr. - NatHoleServerAddr string `ini:"nat_hole_server_addr" json:"nat_hole_server_addr"` // ServerPort specifies the port to connect to the server on. By default, // this value is 7000. ServerPort int `ini:"server_port" json:"server_port"` - // ServerUDPPort specifies the server port to help penetrate NAT hole. By default, this value is 0. - // This parameter is only used when executing "nathole discover" in the command line. - ServerUDPPort int `ini:"server_udp_port" json:"server_udp_port"` // STUN server to help penetrate NAT hole. NatHoleSTUNServer string `ini:"nat_hole_stun_server" json:"nat_hole_stun_server"` // The maximum amount of time a dial to server will wait for a connect to complete. diff --git a/pkg/config/server.go b/pkg/config/server.go index f54a32f..7d3310f 100644 --- a/pkg/config/server.go +++ b/pkg/config/server.go @@ -38,10 +38,6 @@ type ServerCommonConf struct { // BindPort specifies the port that the server listens on. By default, this // value is 7000. BindPort int `ini:"bind_port" json:"bind_port" validate:"gte=0,lte=65535"` - // BindUDPPort specifies the UDP port that the server listens on. If this - // value is 0, the server will not listen for UDP connections. By default, - // this value is 0 - BindUDPPort int `ini:"bind_udp_port" json:"bind_udp_port" validate:"gte=0,lte=65535"` // KCPBindPort specifies the KCP port that the server listens on. If this // value is 0, the server will not listen for KCP connections. By default, // this value is 0. diff --git a/pkg/config/server_test.go b/pkg/config/server_test.go index e93ba3d..85a63f5 100644 --- a/pkg/config/server_test.go +++ b/pkg/config/server_test.go @@ -104,7 +104,6 @@ func Test_LoadServerCommonConf(t *testing.T) { }, BindAddr: "0.0.0.9", BindPort: 7009, - BindUDPPort: 7008, KCPBindPort: 7007, QUICKeepalivePeriod: 10, QUICMaxIdleTimeout: 30, @@ -183,7 +182,6 @@ func Test_LoadServerCommonConf(t *testing.T) { }, BindAddr: "0.0.0.9", BindPort: 7009, - BindUDPPort: 7008, QUICKeepalivePeriod: 10, QUICMaxIdleTimeout: 30, QUICMaxIncomingStreams: 100000, diff --git a/pkg/msg/msg.go b/pkg/msg/msg.go index b6a209d..c6fec4d 100644 --- a/pkg/msg/msg.go +++ b/pkg/msg/msg.go @@ -80,10 +80,9 @@ type Login struct { } type LoginResp struct { - Version string `json:"version,omitempty"` - RunID string `json:"run_id,omitempty"` - ServerUDPPort int `json:"server_udp_port,omitempty"` - Error string `json:"error,omitempty"` + Version string `json:"version,omitempty"` + RunID string `json:"run_id,omitempty"` + Error string `json:"error,omitempty"` } // When frpc login success, send this message to frps for running a new proxy. diff --git a/pkg/util/version/version.go b/pkg/util/version/version.go index 920cb56..1623bd8 100644 --- a/pkg/util/version/version.go +++ b/pkg/util/version/version.go @@ -19,7 +19,7 @@ import ( "strings" ) -var version = "0.48.0" +var version = "0.49.0" func Full() string { return version diff --git a/server/control.go b/server/control.go index f905e74..d7ed327 100644 --- a/server/control.go +++ b/server/control.go @@ -203,10 +203,9 @@ func NewControl( // Start send a login success message to client and start working. func (ctl *Control) Start() { loginRespMsg := &msg.LoginResp{ - Version: version.Full(), - RunID: ctl.runID, - ServerUDPPort: ctl.serverCfg.BindUDPPort, - Error: "", + Version: version.Full(), + RunID: ctl.runID, + Error: "", } _ = msg.WriteMsg(ctl.conn, loginRespMsg) diff --git a/server/dashboard_api.go b/server/dashboard_api.go index a7f078f..aaf2b32 100644 --- a/server/dashboard_api.go +++ b/server/dashboard_api.go @@ -35,7 +35,6 @@ type GeneralResponse struct { type serverInfoResp struct { Version string `json:"version"` BindPort int `json:"bind_port"` - BindUDPPort int `json:"bind_udp_port"` VhostHTTPPort int `json:"vhost_http_port"` VhostHTTPSPort int `json:"vhost_https_port"` TCPMuxHTTPConnectPort int `json:"tcpmux_httpconnect_port"` @@ -76,7 +75,6 @@ func (svr *Service) APIServerInfo(w http.ResponseWriter, r *http.Request) { svrResp := serverInfoResp{ Version: version.Full(), BindPort: svr.cfg.BindPort, - BindUDPPort: svr.cfg.BindUDPPort, VhostHTTPPort: svr.cfg.VhostHTTPPort, VhostHTTPSPort: svr.cfg.VhostHTTPSPort, TCPMuxHTTPConnectPort: svr.cfg.TCPMuxHTTPConnectPort,