Compare commits

..

1 Commits

Author SHA1 Message Date
fatedier
c064142501 client plugin: added plugin tls2raw 2024-07-16 16:23:49 +08:00
12 changed files with 63 additions and 73 deletions

View File

@ -9,6 +9,11 @@
<h3 align="center">Gold Sponsors</h3> <h3 align="center">Gold Sponsors</h3>
<!--gold sponsors start--> <!--gold sponsors start-->
<p align="center">
<a href="https://lokal.so/?utm_campaign=github_repo&utm_medium=referral&utm_content=frp&utm_source=github" target="_blank">
<img width="420px" src="https://raw.githubusercontent.com/fatedier/frp/dev/doc/pic/sponsor_lokal.png">
</a>
</p>
<p align="center"> <p align="center">
<a href="https://workos.com/?utm_campaign=github_repo&utm_medium=referral&utm_content=frp&utm_source=github" target="_blank"> <a href="https://workos.com/?utm_campaign=github_repo&utm_medium=referral&utm_content=frp&utm_source=github" target="_blank">
<img width="420px" src="https://raw.githubusercontent.com/fatedier/frp/dev/doc/pic/sponsor_workos.png"> <img width="420px" src="https://raw.githubusercontent.com/fatedier/frp/dev/doc/pic/sponsor_workos.png">

View File

@ -11,6 +11,11 @@ frp 是一个专注于内网穿透的高性能的反向代理应用,支持 TCP
<h3 align="center">Gold Sponsors</h3> <h3 align="center">Gold Sponsors</h3>
<!--gold sponsors start--> <!--gold sponsors start-->
<p align="center">
<a href="https://lokal.so/?utm_campaign=github_repo&utm_medium=referral&utm_content=frp&utm_source=github" target="_blank">
<img width="420px" src="https://raw.githubusercontent.com/fatedier/frp/dev/doc/pic/sponsor_lokal.png">
</a>
</p>
<p align="center"> <p align="center">
<a href="https://workos.com/?utm_campaign=github_repo&utm_medium=referral&utm_content=frp&utm_source=github" target="_blank"> <a href="https://workos.com/?utm_campaign=github_repo&utm_medium=referral&utm_content=frp&utm_source=github" target="_blank">
<img width="420px" src="https://raw.githubusercontent.com/fatedier/frp/dev/doc/pic/sponsor_workos.png"> <img width="420px" src="https://raw.githubusercontent.com/fatedier/frp/dev/doc/pic/sponsor_workos.png">

View File

@ -1,8 +1,3 @@
### Features ### Features
* Added a new plugin `tls2raw`: Enables TLS termination and forwarding of decrypted raw traffic to local service. * Added a new plugin `tls2raw`: Enables TLS termination and forwarding of decrypted raw traffic to local service.
* Added a default timeout of 30 seconds for the frpc subcommands to prevent commands from being stuck for a long time due to network issues.
### Fixes
* Fixed the issue that when `loginFailExit = false`, the frpc stop command cannot be stopped correctly if the server is not successfully connected after startup.

View File

@ -169,15 +169,6 @@ func (svr *Service) Run(ctx context.Context) error {
netpkg.SetDefaultDNSAddress(svr.common.DNSServer) netpkg.SetDefaultDNSAddress(svr.common.DNSServer)
} }
if svr.webServer != nil {
go func() {
log.Infof("admin server listen on %s", svr.webServer.Address())
if err := svr.webServer.Run(); err != nil {
log.Warnf("admin server exit with error: %v", err)
}
}()
}
// first login to frps // first login to frps
svr.loopLoginUntilSuccess(10*time.Second, lo.FromPtr(svr.common.LoginFailExit)) svr.loopLoginUntilSuccess(10*time.Second, lo.FromPtr(svr.common.LoginFailExit))
if svr.ctl == nil { if svr.ctl == nil {
@ -188,6 +179,14 @@ func (svr *Service) Run(ctx context.Context) error {
go svr.keepControllerWorking() go svr.keepControllerWorking()
if svr.webServer != nil {
go func() {
log.Infof("admin server listen on %s", svr.webServer.Address())
if err := svr.webServer.Run(); err != nil {
log.Warnf("admin server exit with error: %v", err)
}
}()
}
<-svr.ctx.Done() <-svr.ctx.Done()
svr.stop() svr.stop()
return nil return nil

View File

@ -15,11 +15,9 @@
package sub package sub
import ( import (
"context"
"fmt" "fmt"
"os" "os"
"strings" "strings"
"time"
"github.com/rodaine/table" "github.com/rodaine/table"
"github.com/spf13/cobra" "github.com/spf13/cobra"
@ -29,24 +27,24 @@ import (
clientsdk "github.com/fatedier/frp/pkg/sdk/client" clientsdk "github.com/fatedier/frp/pkg/sdk/client"
) )
var adminAPITimeout = 30 * time.Second
func init() { func init() {
commands := []struct { rootCmd.AddCommand(NewAdminCommand(
name string "reload",
description string "Hot-Reload frpc configuration",
handler func(*v1.ClientCommonConfig) error ReloadHandler,
}{ ))
{"reload", "Hot-Reload frpc configuration", ReloadHandler},
{"status", "Overview of all proxies status", StatusHandler},
{"stop", "Stop the running frpc", StopHandler},
}
for _, cmdConfig := range commands { rootCmd.AddCommand(NewAdminCommand(
cmd := NewAdminCommand(cmdConfig.name, cmdConfig.description, cmdConfig.handler) "status",
cmd.Flags().DurationVar(&adminAPITimeout, "api-timeout", adminAPITimeout, "Timeout for admin API calls") "Overview of all proxies status",
rootCmd.AddCommand(cmd) StatusHandler,
} ))
rootCmd.AddCommand(NewAdminCommand(
"stop",
"Stop the running frpc",
StopHandler,
))
} }
func NewAdminCommand(name, short string, handler func(*v1.ClientCommonConfig) error) *cobra.Command { func NewAdminCommand(name, short string, handler func(*v1.ClientCommonConfig) error) *cobra.Command {
@ -75,9 +73,7 @@ func NewAdminCommand(name, short string, handler func(*v1.ClientCommonConfig) er
func ReloadHandler(clientCfg *v1.ClientCommonConfig) error { func ReloadHandler(clientCfg *v1.ClientCommonConfig) error {
client := clientsdk.New(clientCfg.WebServer.Addr, clientCfg.WebServer.Port) client := clientsdk.New(clientCfg.WebServer.Addr, clientCfg.WebServer.Port)
client.SetAuth(clientCfg.WebServer.User, clientCfg.WebServer.Password) client.SetAuth(clientCfg.WebServer.User, clientCfg.WebServer.Password)
ctx, cancel := context.WithTimeout(context.Background(), adminAPITimeout) if err := client.Reload(strictConfigMode); err != nil {
defer cancel()
if err := client.Reload(ctx, strictConfigMode); err != nil {
return err return err
} }
fmt.Println("reload success") fmt.Println("reload success")
@ -87,9 +83,7 @@ func ReloadHandler(clientCfg *v1.ClientCommonConfig) error {
func StatusHandler(clientCfg *v1.ClientCommonConfig) error { func StatusHandler(clientCfg *v1.ClientCommonConfig) error {
client := clientsdk.New(clientCfg.WebServer.Addr, clientCfg.WebServer.Port) client := clientsdk.New(clientCfg.WebServer.Addr, clientCfg.WebServer.Port)
client.SetAuth(clientCfg.WebServer.User, clientCfg.WebServer.Password) client.SetAuth(clientCfg.WebServer.User, clientCfg.WebServer.Password)
ctx, cancel := context.WithTimeout(context.Background(), adminAPITimeout) res, err := client.GetAllProxyStatus()
defer cancel()
res, err := client.GetAllProxyStatus(ctx)
if err != nil { if err != nil {
return err return err
} }
@ -115,9 +109,7 @@ func StatusHandler(clientCfg *v1.ClientCommonConfig) error {
func StopHandler(clientCfg *v1.ClientCommonConfig) error { func StopHandler(clientCfg *v1.ClientCommonConfig) error {
client := clientsdk.New(clientCfg.WebServer.Addr, clientCfg.WebServer.Port) client := clientsdk.New(clientCfg.WebServer.Addr, clientCfg.WebServer.Port)
client.SetAuth(clientCfg.WebServer.User, clientCfg.WebServer.Password) client.SetAuth(clientCfg.WebServer.User, clientCfg.WebServer.Password)
ctx, cancel := context.WithTimeout(context.Background(), adminAPITimeout) if err := client.Stop(); err != nil {
defer cancel()
if err := client.Stop(ctx); err != nil {
return err return err
} }
fmt.Println("stop success") fmt.Println("stop success")

View File

@ -1,7 +1,6 @@
package client package client
import ( import (
"context"
"encoding/json" "encoding/json"
"fmt" "fmt"
"io" "io"
@ -32,8 +31,8 @@ func (c *Client) SetAuth(user, pwd string) {
c.authPwd = pwd c.authPwd = pwd
} }
func (c *Client) GetProxyStatus(ctx context.Context, name string) (*client.ProxyStatusResp, error) { func (c *Client) GetProxyStatus(name string) (*client.ProxyStatusResp, error) {
req, err := http.NewRequestWithContext(ctx, "GET", "http://"+c.address+"/api/status", nil) req, err := http.NewRequest("GET", "http://"+c.address+"/api/status", nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -55,8 +54,8 @@ func (c *Client) GetProxyStatus(ctx context.Context, name string) (*client.Proxy
return nil, fmt.Errorf("no proxy status found") return nil, fmt.Errorf("no proxy status found")
} }
func (c *Client) GetAllProxyStatus(ctx context.Context) (client.StatusResp, error) { func (c *Client) GetAllProxyStatus() (client.StatusResp, error) {
req, err := http.NewRequestWithContext(ctx, "GET", "http://"+c.address+"/api/status", nil) req, err := http.NewRequest("GET", "http://"+c.address+"/api/status", nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -71,7 +70,7 @@ func (c *Client) GetAllProxyStatus(ctx context.Context) (client.StatusResp, erro
return allStatus, nil return allStatus, nil
} }
func (c *Client) Reload(ctx context.Context, strictMode bool) error { func (c *Client) Reload(strictMode bool) error {
v := url.Values{} v := url.Values{}
if strictMode { if strictMode {
v.Set("strictConfig", "true") v.Set("strictConfig", "true")
@ -80,7 +79,7 @@ func (c *Client) Reload(ctx context.Context, strictMode bool) error {
if len(v) > 0 { if len(v) > 0 {
queryStr = "?" + v.Encode() queryStr = "?" + v.Encode()
} }
req, err := http.NewRequestWithContext(ctx, "GET", "http://"+c.address+"/api/reload"+queryStr, nil) req, err := http.NewRequest("GET", "http://"+c.address+"/api/reload"+queryStr, nil)
if err != nil { if err != nil {
return err return err
} }
@ -88,8 +87,8 @@ func (c *Client) Reload(ctx context.Context, strictMode bool) error {
return err return err
} }
func (c *Client) Stop(ctx context.Context) error { func (c *Client) Stop() error {
req, err := http.NewRequestWithContext(ctx, "POST", "http://"+c.address+"/api/stop", nil) req, err := http.NewRequest("POST", "http://"+c.address+"/api/stop", nil)
if err != nil { if err != nil {
return err return err
} }
@ -97,16 +96,16 @@ func (c *Client) Stop(ctx context.Context) error {
return err return err
} }
func (c *Client) GetConfig(ctx context.Context) (string, error) { func (c *Client) GetConfig() (string, error) {
req, err := http.NewRequestWithContext(ctx, "GET", "http://"+c.address+"/api/config", nil) req, err := http.NewRequest("GET", "http://"+c.address+"/api/config", nil)
if err != nil { if err != nil {
return "", err return "", err
} }
return c.do(req) return c.do(req)
} }
func (c *Client) UpdateConfig(ctx context.Context, content string) error { func (c *Client) UpdateConfig(content string) error {
req, err := http.NewRequestWithContext(ctx, "PUT", "http://"+c.address+"/api/config", strings.NewReader(content)) req, err := http.NewRequest("PUT", "http://"+c.address+"/api/config", strings.NewReader(content))
if err != nil { if err != nil {
return err return err
} }

View File

@ -14,7 +14,7 @@
package version package version
var version = "0.60.0" var version = "0.59.0"
func Full() string { func Full() string {
return version return version

View File

@ -1,7 +1,6 @@
package basic package basic
import ( import (
"context"
"fmt" "fmt"
"strconv" "strconv"
"strings" "strings"
@ -55,7 +54,7 @@ var _ = ginkgo.Describe("[Feature: ClientManage]", func() {
framework.NewRequestExpect(f).Port(p3Port).Ensure() framework.NewRequestExpect(f).Port(p3Port).Ensure()
client := f.APIClientForFrpc(adminPort) client := f.APIClientForFrpc(adminPort)
conf, err := client.GetConfig(context.Background()) conf, err := client.GetConfig()
framework.ExpectNoError(err) framework.ExpectNoError(err)
newP2Port := f.AllocPort() newP2Port := f.AllocPort()
@ -66,10 +65,10 @@ var _ = ginkgo.Describe("[Feature: ClientManage]", func() {
newClientConf = newClientConf[:p3Index] newClientConf = newClientConf[:p3Index]
} }
err = client.UpdateConfig(context.Background(), newClientConf) err = client.UpdateConfig(newClientConf)
framework.ExpectNoError(err) framework.ExpectNoError(err)
err = client.Reload(context.Background(), true) err = client.Reload(true)
framework.ExpectNoError(err) framework.ExpectNoError(err)
time.Sleep(time.Second) time.Sleep(time.Second)
@ -121,7 +120,7 @@ var _ = ginkgo.Describe("[Feature: ClientManage]", func() {
framework.NewRequestExpect(f).Port(testPort).Ensure() framework.NewRequestExpect(f).Port(testPort).Ensure()
client := f.APIClientForFrpc(adminPort) client := f.APIClientForFrpc(adminPort)
err := client.Stop(context.Background()) err := client.Stop()
framework.ExpectNoError(err) framework.ExpectNoError(err)
time.Sleep(3 * time.Second) time.Sleep(3 * time.Second)

View File

@ -1,7 +1,6 @@
package basic package basic
import ( import (
"context"
"fmt" "fmt"
"net" "net"
"strconv" "strconv"
@ -102,7 +101,7 @@ var _ = ginkgo.Describe("[Feature: Server Manager]", func() {
client := f.APIClientForFrpc(adminPort) client := f.APIClientForFrpc(adminPort)
// tcp random port // tcp random port
status, err := client.GetProxyStatus(context.Background(), "tcp") status, err := client.GetProxyStatus("tcp")
framework.ExpectNoError(err) framework.ExpectNoError(err)
_, portStr, err := net.SplitHostPort(status.RemoteAddr) _, portStr, err := net.SplitHostPort(status.RemoteAddr)
@ -113,7 +112,7 @@ var _ = ginkgo.Describe("[Feature: Server Manager]", func() {
framework.NewRequestExpect(f).Port(port).Ensure() framework.NewRequestExpect(f).Port(port).Ensure()
// udp random port // udp random port
status, err = client.GetProxyStatus(context.Background(), "udp") status, err = client.GetProxyStatus("udp")
framework.ExpectNoError(err) framework.ExpectNoError(err)
_, portStr, err = net.SplitHostPort(status.RemoteAddr) _, portStr, err = net.SplitHostPort(status.RemoteAddr)

View File

@ -1,7 +1,6 @@
package basic package basic
import ( import (
"context"
"fmt" "fmt"
"strconv" "strconv"
"strings" "strings"
@ -58,7 +57,7 @@ var _ = ginkgo.Describe("[Feature: ClientManage]", func() {
framework.NewRequestExpect(f).Port(p3Port).Ensure() framework.NewRequestExpect(f).Port(p3Port).Ensure()
client := f.APIClientForFrpc(adminPort) client := f.APIClientForFrpc(adminPort)
conf, err := client.GetConfig(context.Background()) conf, err := client.GetConfig()
framework.ExpectNoError(err) framework.ExpectNoError(err)
newP2Port := f.AllocPort() newP2Port := f.AllocPort()
@ -69,10 +68,10 @@ var _ = ginkgo.Describe("[Feature: ClientManage]", func() {
newClientConf = newClientConf[:p3Index] newClientConf = newClientConf[:p3Index]
} }
err = client.UpdateConfig(context.Background(), newClientConf) err = client.UpdateConfig(newClientConf)
framework.ExpectNoError(err) framework.ExpectNoError(err)
err = client.Reload(context.Background(), true) err = client.Reload(true)
framework.ExpectNoError(err) framework.ExpectNoError(err)
time.Sleep(time.Second) time.Sleep(time.Second)
@ -125,7 +124,7 @@ var _ = ginkgo.Describe("[Feature: ClientManage]", func() {
framework.NewRequestExpect(f).Port(testPort).Ensure() framework.NewRequestExpect(f).Port(testPort).Ensure()
client := f.APIClientForFrpc(adminPort) client := f.APIClientForFrpc(adminPort)
err := client.Stop(context.Background()) err := client.Stop()
framework.ExpectNoError(err) framework.ExpectNoError(err)
time.Sleep(3 * time.Second) time.Sleep(3 * time.Second)

View File

@ -1,7 +1,6 @@
package basic package basic
import ( import (
"context"
"fmt" "fmt"
"github.com/onsi/ginkgo/v2" "github.com/onsi/ginkgo/v2"
@ -73,7 +72,7 @@ var _ = ginkgo.Describe("[Feature: Config]", func() {
client := f.APIClientForFrpc(adminPort) client := f.APIClientForFrpc(adminPort)
checkProxyFn := func(name string, localPort, remotePort int) { checkProxyFn := func(name string, localPort, remotePort int) {
status, err := client.GetProxyStatus(context.Background(), name) status, err := client.GetProxyStatus(name)
framework.ExpectNoError(err) framework.ExpectNoError(err)
framework.ExpectContainSubstring(status.LocalAddr, fmt.Sprintf(":%d", localPort)) framework.ExpectContainSubstring(status.LocalAddr, fmt.Sprintf(":%d", localPort))

View File

@ -1,7 +1,6 @@
package basic package basic
import ( import (
"context"
"fmt" "fmt"
"net" "net"
"strconv" "strconv"
@ -113,7 +112,7 @@ var _ = ginkgo.Describe("[Feature: Server Manager]", func() {
client := f.APIClientForFrpc(adminPort) client := f.APIClientForFrpc(adminPort)
// tcp random port // tcp random port
status, err := client.GetProxyStatus(context.Background(), "tcp") status, err := client.GetProxyStatus("tcp")
framework.ExpectNoError(err) framework.ExpectNoError(err)
_, portStr, err := net.SplitHostPort(status.RemoteAddr) _, portStr, err := net.SplitHostPort(status.RemoteAddr)
@ -124,7 +123,7 @@ var _ = ginkgo.Describe("[Feature: Server Manager]", func() {
framework.NewRequestExpect(f).Port(port).Ensure() framework.NewRequestExpect(f).Port(port).Ensure()
// udp random port // udp random port
status, err = client.GetProxyStatus(context.Background(), "udp") status, err = client.GetProxyStatus("udp")
framework.ExpectNoError(err) framework.ExpectNoError(err)
_, portStr, err = net.SplitHostPort(status.RemoteAddr) _, portStr, err = net.SplitHostPort(status.RemoteAddr)