diff --git a/go.mod b/go.mod index 242c9a71..962edda3 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/fatedier/frp -go 1.25.0 +go 1.25.5 require ( github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 @@ -10,13 +10,13 @@ require ( github.com/gorilla/mux v1.8.1 github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 github.com/hashicorp/yamux v0.1.2 - github.com/onsi/ginkgo/v2 v2.27.3 - github.com/onsi/gomega v1.38.3 + github.com/onsi/ginkgo/v2 v2.27.4 + github.com/onsi/gomega v1.39.0 github.com/pelletier/go-toml/v2 v2.2.4 github.com/pion/stun/v2 v2.0.0 github.com/pires/go-proxyproto v0.8.1 github.com/prometheus/client_golang v1.23.2 - github.com/quic-go/quic-go v0.58.0 + github.com/quic-go/quic-go v0.59.0 github.com/rodaine/table v1.3.0 github.com/samber/lo v1.52.0 github.com/songgao/water v0.0.0-20200317203138-2b4b6d7c09d8 @@ -33,7 +33,7 @@ require ( golang.org/x/sync v0.19.0 golang.org/x/time v0.14.0 golang.zx2c4.com/wireguard v0.0.0-20250521234502-f333402bd9cb - gopkg.in/ini.v1 v1.67.0 + gopkg.in/ini.v1 v1.67.1 k8s.io/apimachinery v0.35.0 k8s.io/client-go v0.35.0 ) @@ -49,7 +49,7 @@ require ( github.com/go-task/slim-sprig/v3 v3.0.0 // indirect github.com/golang/snappy v1.0.0 // indirect github.com/google/go-cmp v0.7.0 // indirect - github.com/google/pprof v0.0.0-20251213031049-b05bdaca462f // indirect + github.com/google/pprof v0.0.0-20260111202518-71be6bfdd440 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/klauspost/cpuid/v2 v2.3.0 // indirect github.com/klauspost/reedsolomon v1.12.6 // indirect @@ -61,7 +61,7 @@ require ( github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/client_model v0.6.2 // indirect - github.com/prometheus/common v0.67.4 // indirect + github.com/prometheus/common v0.67.5 // indirect github.com/prometheus/procfs v0.19.2 // indirect github.com/tidwall/match v1.2.0 // indirect github.com/tidwall/pretty v1.2.1 // indirect @@ -71,15 +71,15 @@ require ( go.uber.org/mock v0.6.0 // indirect go.yaml.in/yaml/v2 v2.4.3 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect - golang.org/x/mod v0.31.0 // indirect - golang.org/x/sys v0.39.0 // indirect - golang.org/x/text v0.32.0 // indirect + golang.org/x/mod v0.32.0 // indirect + golang.org/x/sys v0.40.0 // indirect + golang.org/x/text v0.33.0 // indirect golang.org/x/tools v0.40.0 // indirect golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect - google.golang.org/protobuf v1.36.10 // indirect + google.golang.org/protobuf v1.36.11 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/klog/v2 v2.130.1 // indirect - k8s.io/utils v0.0.0-20251002143259-bc988d571ff4 // indirect + k8s.io/utils v0.0.0-20260108192941-914a6e750570 // indirect sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 // indirect sigs.k8s.io/yaml v1.6.0 // indirect ) diff --git a/go.sum b/go.sum index 1d07b5fe..1e71101e 100644 --- a/go.sum +++ b/go.sum @@ -64,6 +64,8 @@ github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/pprof v0.0.0-20251213031049-b05bdaca462f h1:HU1RgM6NALf/KW9HEY6zry3ADbDKcmpQ+hJedoNGQYQ= github.com/google/pprof v0.0.0-20251213031049-b05bdaca462f/go.mod h1:67FPmZWbr+KDT/VlpWtw6sO9XSjpJmLuHpoLmWiTGgY= +github.com/google/pprof v0.0.0-20260111202518-71be6bfdd440 h1:oKBqR+eQXiIM7X8K1JEg9aoTEePLq/c6Awe484abOuA= +github.com/google/pprof v0.0.0-20260111202518-71be6bfdd440/go.mod h1:MxpfABSjhmINe3F1It9d+8exIHFvUqtLIRCdOGNXqiI= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= @@ -96,8 +98,12 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/onsi/ginkgo/v2 v2.27.3 h1:ICsZJ8JoYafeXFFlFAG75a7CxMsJHwgKwtO+82SE9L8= github.com/onsi/ginkgo/v2 v2.27.3/go.mod h1:ArE1D/XhNXBXCBkKOLkbsb2c81dQHCRcF5zwn/ykDRo= +github.com/onsi/ginkgo/v2 v2.27.4 h1:fcEcQW/A++6aZAZQNUmNjvA9PSOzefMJBerHJ4t8v8Y= +github.com/onsi/ginkgo/v2 v2.27.4/go.mod h1:ArE1D/XhNXBXCBkKOLkbsb2c81dQHCRcF5zwn/ykDRo= github.com/onsi/gomega v1.38.3 h1:eTX+W6dobAYfFeGC2PV6RwXRu/MyT+cQguijutvkpSM= github.com/onsi/gomega v1.38.3/go.mod h1:ZCU1pkQcXDO5Sl9/VVEGlDyp+zm0m1cmeG5TOzLgdh4= +github.com/onsi/gomega v1.39.0 h1:y2ROC3hKFmQZJNFeGAMeHZKkjBL65mIZcvrLQBF9k6Q= +github.com/onsi/gomega v1.39.0/go.mod h1:ZCU1pkQcXDO5Sl9/VVEGlDyp+zm0m1cmeG5TOzLgdh4= github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4= github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= github.com/pion/dtls/v2 v2.2.7/go.mod h1:8WiMkebSHFD0T+dIU+UeBaoV7kDhOW5oDCzZ7WZ/F9s= @@ -128,10 +134,14 @@ github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNw github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE= github.com/prometheus/common v0.67.4 h1:yR3NqWO1/UyO1w2PhUvXlGQs/PtFmoveVO0KZ4+Lvsc= github.com/prometheus/common v0.67.4/go.mod h1:gP0fq6YjjNCLssJCQp0yk4M8W6ikLURwkdd/YKtTbyI= +github.com/prometheus/common v0.67.5 h1:pIgK94WWlQt1WLwAC5j2ynLaBRDiinoAb86HZHTUGI4= +github.com/prometheus/common v0.67.5/go.mod h1:SjE/0MzDEEAyrdr5Gqc6G+sXI67maCxzaT3A2+HqjUw= github.com/prometheus/procfs v0.19.2 h1:zUMhqEW66Ex7OXIiDkll3tl9a1ZdilUOd/F6ZXw4Vws= github.com/prometheus/procfs v0.19.2/go.mod h1:M0aotyiemPhBCM0z5w87kL22CxfcH05ZpYlu+b4J7mw= github.com/quic-go/quic-go v0.58.0 h1:ggY2pvZaVdB9EyojxL1p+5mptkuHyX5MOSv4dgWF4Ug= github.com/quic-go/quic-go v0.58.0/go.mod h1:upnsH4Ju1YkqpLXC305eW3yDZ4NfnNbmQRCMWS58IKU= +github.com/quic-go/quic-go v0.59.0 h1:OLJkp1Mlm/aS7dpKgTc6cnpynnD2Xg7C1pwL6vy/SAw= +github.com/quic-go/quic-go v0.59.0/go.mod h1:upnsH4Ju1YkqpLXC305eW3yDZ4NfnNbmQRCMWS58IKU= github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rodaine/table v1.3.0 h1:4/3S3SVkHnVZX91EHFvAMV7K42AnJ0XuymRR2C5HlGE= @@ -210,6 +220,8 @@ golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91 golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.31.0 h1:HaW9xtz0+kOcWKwli0ZXy79Ix+UW/vOfmWI5QVd2tgI= golang.org/x/mod v0.31.0/go.mod h1:43JraMp9cGx1Rx3AqioxrbrhNsLl2l/iNAvuBkrezpg= +golang.org/x/mod v0.32.0 h1:9F4d3PHLljb6x//jOyokMv3eX+YDeepZSEo3mFJy93c= +golang.org/x/mod v0.32.0/go.mod h1:SgipZ/3h2Ci89DlEtEXWUk/HteuRin+HHhN+WbNhguU= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -253,6 +265,8 @@ golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk= golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ= +golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= @@ -271,6 +285,8 @@ golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU= golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY= +golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE= +golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8= golang.org/x/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI= golang.org/x/time v0.14.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -305,11 +321,15 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE= google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= +google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= +google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/ini.v1 v1.67.1 h1:tVBILHy0R6e4wkYOn3XmiITt/hEVH4TFMYvAX2Ytz6k= +gopkg.in/ini.v1 v1.67.1/go.mod h1:x/cyOwCgZqOkJoDIJ3c1KNHMo10+nLGAhh+kn3Zizss= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= @@ -325,6 +345,8 @@ k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= k8s.io/utils v0.0.0-20251002143259-bc988d571ff4 h1:SjGebBtkBqHFOli+05xYbK8YF1Dzkbzn+gDM4X9T4Ck= k8s.io/utils v0.0.0-20251002143259-bc988d571ff4/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +k8s.io/utils v0.0.0-20260108192941-914a6e750570 h1:JT4W8lsdrGENg9W+YwwdLJxklIuKWdRm+BC+xt33FOY= +k8s.io/utils v0.0.0-20260108192941-914a6e750570/go.mod h1:xDxuJ0whA3d0I4mf/C4ppKHxXynQ+fxnkmQH0vTHnuk= sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 h1:IpInykpT6ceI+QxKBbEflcR5EXP7sU1kvOlxwZh5txg= sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg= sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs= diff --git a/pkg/api/client/tunnel/config.go b/pkg/api/client/tunnel/config.go index 4d201fbe..3d4502b6 100644 --- a/pkg/api/client/tunnel/config.go +++ b/pkg/api/client/tunnel/config.go @@ -3,10 +3,12 @@ package tunnel import ( "context" "encoding/json" - _api "github.com/fatedier/frp/pkg/api/exec" + "io" "net/http" "time" + + _api "github.com/fatedier/frp/pkg/api/exec" ) type GetConfigParams struct { @@ -26,7 +28,7 @@ func (s Service) GetConfig(params GetConfigParams) (response *GetConfigResponse, ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) // 设置超时 defer cancel() - rs, err := _api.Execute(ctx, "/client/tunnel/config", http.MethodGet, "", params, nil) + rs, err := _api.ClientExecute(ctx, "/client/tunnel/config", http.MethodGet, params, nil) if err != nil { return nil, err } diff --git a/pkg/api/const/const.go b/pkg/api/const/const.go new file mode 100644 index 00000000..e17e6969 --- /dev/null +++ b/pkg/api/const/const.go @@ -0,0 +1,19 @@ +package api + +import ( + "fmt" + + "github.com/fatedier/frp/pkg/util/version" +) + +var Endpoints = []string{ + "https://frp.api.locyanfrp.cn/v1/", +} + +var UserAgents = struct { + Client string + Server string +}{ + Client: fmt.Sprintf("LoCyanFrp/%s (Frp Client; %s)", version.ApiService(), version.Full()), + Server: fmt.Sprintf("LoCyanFrp/%s (Frp Server; %s)", version.ApiService(), version.Full()), +} diff --git a/pkg/api/exec/client.go b/pkg/api/exec/client.go index bb9163b5..f5fe8dfd 100644 --- a/pkg/api/exec/client.go +++ b/pkg/api/exec/client.go @@ -6,20 +6,21 @@ import ( "encoding/json" "errors" "fmt" - "github.com/fatedier/frp/pkg/util/log" - "github.com/fatedier/frp/pkg/util/version" "io" "net/http" "net/url" + + "github.com/fatedier/frp/pkg/api/const" + "github.com/fatedier/frp/pkg/util/log" ) -func Execute(ctx context.Context, path string, method string, apiKey string, query interface{}, body *url.Values) (*http.Response, error) { +func ClientExecute(ctx context.Context, path string, method string, query interface{}, body *url.Values) (*http.Response, error) { var ( fullURL string resp *http.Response err error ) - for _, baseURL := range V3ApiEndpoints { + for _, baseURL := range api.Endpoints { fullURL, err = url.JoinPath(baseURL, path) if err != nil { continue @@ -30,10 +31,7 @@ func Execute(ctx context.Context, path string, method string, apiKey string, que return nil, err } - req.Header.Set("User-Agent", fmt.Sprintf("LoCyanFrp/2.0 (Frp; %s)", version.Full())) - if apiKey != "" { - req.Header.Set("X-Node-API-Key", apiKey) - } + req.Header.Set("User-Agent", api.UserAgents.Client) switch method { case http.MethodGet, http.MethodDelete: diff --git a/pkg/api/exec/const.go b/pkg/api/exec/const.go deleted file mode 100644 index f9cdd048..00000000 --- a/pkg/api/exec/const.go +++ /dev/null @@ -1,6 +0,0 @@ -package exec - -var V3ApiEndpoints = []string{ - "https://api.locyanfrp.cn/v3/frp", - "https://backup.api.locyanfrp.cn/v3/frp", -} diff --git a/pkg/api/exec/server.go b/pkg/api/exec/server.go new file mode 100644 index 00000000..618db525 --- /dev/null +++ b/pkg/api/exec/server.go @@ -0,0 +1,81 @@ +package exec + +import ( + "bytes" + "context" + "encoding/json" + "errors" + "fmt" + "io" + "net/http" + "net/url" + "strconv" + + _const "github.com/fatedier/frp/pkg/api/const" + "github.com/fatedier/frp/pkg/api/type" + "github.com/fatedier/frp/pkg/util/log" +) + +func ServerExecute(ctx context.Context, path string, method string, cfg api.ServerConfig, query interface{}, body *url.Values) (*http.Response, error) { + var ( + fullURL string + resp *http.Response + err error + ) + for _, baseURL := range _const.Endpoints { + fullURL, err = url.JoinPath(baseURL, path) + if err != nil { + continue + } + + req, err := http.NewRequestWithContext(ctx, method, fullURL, nil) + if err != nil { + return nil, err + } + + req.Header.Set("User-Agent", _const.UserAgents.Server) + req.Header.Set("X-Node-Id", strconv.FormatInt(cfg.NodeId, 10)) + req.Header.Set("X-Api-Key", cfg.ApiKey) + + switch method { + case http.MethodGet, http.MethodDelete: + if query != nil { + reqQuery := req.URL.Query() + + paramBytes, err := json.Marshal(query) + if err != nil { + return nil, err + } + + var paramMap map[string]interface{} + err = json.Unmarshal(paramBytes, ¶mMap) + if err != nil { + return nil, err + } + + for key, value := range paramMap { + reqQuery.Add(key, fmt.Sprintf("%v", value)) + } + + req.URL.RawQuery = reqQuery.Encode() + } + case http.MethodPost, http.MethodPut, http.MethodPatch: + if body != nil { + req.Header.Set("Content-Type", "application/x-www-form-urlencoded") + req.Body = io.NopCloser(bytes.NewBufferString(body.Encode())) + } + } + + resp, err = http.DefaultClient.Do(req) + if err == nil { + // 请求成功 + return resp, nil + } + + log.Warnf("API Error: request failed (endpoint: %s)", baseURL) + if resp != nil { + resp.Body.Close() + } + } + return nil, errors.New("API Error: request failed, all endpoints failed") +} diff --git a/pkg/api/server/tunnel/run_id.go b/pkg/api/server/tunnel/run_id.go index 4d8a05df..d5319ba8 100644 --- a/pkg/api/server/tunnel/run_id.go +++ b/pkg/api/server/tunnel/run_id.go @@ -3,16 +3,18 @@ package tunnel import ( "context" "encoding/json" - _api "github.com/fatedier/frp/pkg/api/exec" + "io" "net/http" "net/url" "strconv" "time" + + _api "github.com/fatedier/frp/pkg/api/exec" + "github.com/fatedier/frp/pkg/api/type" ) type PostRunIdParams struct { - NodeId int64 `json:"node_id"` TunnelId int64 `json:"tunnel_id"` RunId string `json:"run_id"` } @@ -23,15 +25,14 @@ type PostRunIdResponse struct { Data struct{} `json:"data"` } -func (s Service) PutRunId(apiKey string, params PostRunIdParams) (response *PostRunIdResponse, err error) { +func (s Service) PutRunId(serverConfig api.ServerConfig, params PostRunIdParams) (response *PostRunIdResponse, err error) { ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) // 设置超时 defer cancel() body := &url.Values{} - body.Set("node_id", strconv.FormatInt(params.NodeId, 10)) body.Set("tunnel_id", strconv.FormatInt(params.TunnelId, 10)) body.Set("run_id", params.RunId) - rs, err := _api.Execute(ctx, "/server/tunnel/run-id", http.MethodPut, apiKey, nil, body) + rs, err := _api.ServerExecute(ctx, "/server/tunnel/run-id", http.MethodPut, serverConfig, nil, body) if err != nil { return nil, err } diff --git a/pkg/api/server/tunnel/tunnel.go b/pkg/api/server/tunnel/tunnel.go index b93442b6..ed60d2a1 100644 --- a/pkg/api/server/tunnel/tunnel.go +++ b/pkg/api/server/tunnel/tunnel.go @@ -3,16 +3,18 @@ package tunnel import ( "context" "encoding/json" - _api "github.com/fatedier/frp/pkg/api/exec" + "io" "net/http" "net/url" "strconv" "time" + + _api "github.com/fatedier/frp/pkg/api/exec" + "github.com/fatedier/frp/pkg/api/type" ) type PostTunnelParams struct { - NodeId int64 `json:"node_id"` FrpToken string `json:"frp_token"` TunnelName string `json:"tunnel_name"` TunnelType string `json:"tunnel_type"` @@ -32,12 +34,11 @@ type PostTunnelResponse struct { } `json:"data"` } -func (s Service) PostTunnel(apiKey string, params PostTunnelParams) (response *PostTunnelResponse, err error) { +func (s Service) PostTunnel(serverConfig api.ServerConfig, params PostTunnelParams) (response *PostTunnelResponse, err error) { ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) // 设置超时 defer cancel() body := &url.Values{} - body.Set("node_id", strconv.FormatInt(params.NodeId, 10)) body.Set("frp_token", params.FrpToken) body.Set("tunnel_name", params.TunnelName) body.Set("tunnel_type", params.TunnelType) @@ -55,7 +56,7 @@ func (s Service) PostTunnel(apiKey string, params PostTunnelParams) (response *P if params.SecretKey != nil { body.Set("secret_key", *params.SecretKey) } - rs, err := _api.Execute(ctx, "/server/tunnel", http.MethodPost, apiKey, nil, body) + rs, err := _api.ServerExecute(ctx, "/server/tunnel", http.MethodPost, serverConfig, nil, body) if err != nil { return nil, err } diff --git a/pkg/api/server/user/speed_limit.go b/pkg/api/server/user/speed_limit.go index 260e8fc3..b9cc3d56 100644 --- a/pkg/api/server/user/speed_limit.go +++ b/pkg/api/server/user/speed_limit.go @@ -3,10 +3,13 @@ package user import ( "context" "encoding/json" - _api "github.com/fatedier/frp/pkg/api/exec" + "io" "net/http" "time" + + _api "github.com/fatedier/frp/pkg/api/exec" + "github.com/fatedier/frp/pkg/api/type" ) type GetSpeedLimitParams struct { @@ -23,11 +26,11 @@ type GetSpeedLimitResponse struct { } `json:"data"` } -func (s Service) GetSpeedLimit(apiKey string, params GetSpeedLimitParams) (response *GetSpeedLimitResponse, err error) { +func (s Service) GetSpeedLimit(serverConfig api.ServerConfig, params GetSpeedLimitParams) (response *GetSpeedLimitResponse, err error) { ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) // 设置超时 defer cancel() - rs, err := _api.Execute(ctx, "/server/user/speed-limit", http.MethodGet, apiKey, params, nil) + rs, err := _api.ServerExecute(ctx, "/server/user/speed-limit", http.MethodGet, serverConfig, params, nil) if err != nil { return nil, err } diff --git a/pkg/api/server/user/token.go b/pkg/api/server/user/token.go index aac53ce8..b3a72cf8 100644 --- a/pkg/api/server/user/token.go +++ b/pkg/api/server/user/token.go @@ -3,12 +3,14 @@ package user import ( "context" "encoding/json" - _api "github.com/fatedier/frp/pkg/api/exec" "io" "net/http" "net/url" "strconv" "time" + + _api "github.com/fatedier/frp/pkg/api/exec" + "github.com/fatedier/frp/pkg/api/type" ) type PostTokenParams struct { @@ -22,14 +24,14 @@ type PostTokenResponse struct { Data struct{} `json:"data"` } -func (s Service) PostToken(apiKey string, params PostTokenParams) (response *PostTokenResponse, err error) { +func (s Service) PostToken(serverConfig api.ServerConfig, params PostTokenParams) (response *PostTokenResponse, err error) { ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) // 设置超时 defer cancel() body := &url.Values{} body.Set("node_id", strconv.FormatInt(params.NodeId, 10)) body.Set("frp_token", params.FrpToken) - rs, err := _api.Execute(ctx, "/server/user/token", http.MethodPost, apiKey, nil, body) + rs, err := _api.ServerExecute(ctx, "/server/user/token", http.MethodPost, serverConfig, nil, body) if err != nil { return nil, err } diff --git a/pkg/api/type/type.go b/pkg/api/type/type.go new file mode 100644 index 00000000..59286ecd --- /dev/null +++ b/pkg/api/type/type.go @@ -0,0 +1,6 @@ +package api + +type ServerConfig struct { + NodeId int64 + ApiKey string +} diff --git a/pkg/config/legacy/conversion.go b/pkg/config/legacy/conversion.go index 12795762..da381da1 100644 --- a/pkg/config/legacy/conversion.go +++ b/pkg/config/legacy/conversion.go @@ -167,8 +167,8 @@ func Convert_ServerCommonConf_To_v1(conf *ServerCommonConf) *v1.ServerConfig { out.AllowPorts, _ = types.NewPortsRangeSliceFromString(conf.AllowPortsStr) out.EnableApi = conf.EnableApi - out.NodeApiKey = conf.NodeApiKey - out.NodeId = conf.NodeId + out.Node.ApiKey = conf.NodeApiKey + out.Node.Id = conf.NodeId return out } diff --git a/pkg/config/v1/server.go b/pkg/config/v1/server.go index c5b374e5..e794303b 100644 --- a/pkg/config/v1/server.go +++ b/pkg/config/v1/server.go @@ -97,9 +97,8 @@ type ServerConfig struct { HTTPPlugins []HTTPPluginOptions `json:"httpPlugins,omitempty"` - EnableApi bool `json:"enableApi,omitempty"` - NodeId int64 `json:"nodeId,omitempty"` - NodeApiKey string `json:"nodeApiKey,omitempty"` + EnableApi bool `json:"enableApi,omitempty"` + Node NodeConfig `json:"node,omitempty"` } func (c *ServerConfig) Complete() error { @@ -218,3 +217,8 @@ type SSHTunnelGateway struct { func (c *SSHTunnelGateway) Complete() { c.AutoGenPrivateKeyPath = util.EmptyOr(c.AutoGenPrivateKeyPath, "./.autogen_ssh_key") } + +type NodeConfig struct { + Id int64 `json:"id,omitempty"` + ApiKey string `json:"apiKey,omitempty"` +} diff --git a/pkg/util/version/version.go b/pkg/util/version/version.go index 91009141..58d1762c 100644 --- a/pkg/util/version/version.go +++ b/pkg/util/version/version.go @@ -21,8 +21,9 @@ type Custom struct { } var version = "LoCyanFrp-0.66.0" +var apiServiceVersion = "3" var custom = Custom{ - Build: "2", + Build: "3", } func Full() string { @@ -36,3 +37,7 @@ func Version() string { func Build() string { return custom.Build } + +func ApiService() string { + return apiServiceVersion +} diff --git a/server/control.go b/server/control.go index f750b054..45dfdc98 100644 --- a/server/control.go +++ b/server/control.go @@ -27,7 +27,9 @@ import ( "github.com/fatedier/frp/pkg/api" "github.com/fatedier/frp/pkg/api/server/tunnel" + apitype "github.com/fatedier/frp/pkg/api/type" "github.com/fatedier/frp/pkg/database" + "github.com/fatedier/frp/pkg/util/util" "github.com/samber/lo" "golang.org/x/time/rate" @@ -40,7 +42,6 @@ import ( plugin "github.com/fatedier/frp/pkg/plugin/server" "github.com/fatedier/frp/pkg/transport" netpkg "github.com/fatedier/frp/pkg/util/net" - "github.com/fatedier/frp/pkg/util/util" "github.com/fatedier/frp/pkg/util/version" "github.com/fatedier/frp/pkg/util/wait" "github.com/fatedier/frp/pkg/util/xlog" @@ -479,7 +480,6 @@ func (ctl *Control) handleCloseProxy(m msg.Message) { } func (ctl *Control) RegisterProxy(pxyMsg *msg.NewProxy) (remoteAddr string, err error) { - xl := ctl.xl var pxyConf v1.ProxyConfigurer // Load configures from NewProxy message and validate. pxyConf, err = config.NewProxyConfigurerFromMsg(pxyMsg, ctl.serverCfg) @@ -500,8 +500,7 @@ func (ctl *Control) RegisterProxy(pxyMsg *msg.NewProxy) (remoteAddr string, err var as *api.V3Service as, err = api.NewApiService() if err != nil { - xl.Errorf("init API service falied: %v", err) - return + return "", errors.New(fmt.Sprintf("create api service error: %v", err)) } var tunnelName string @@ -512,7 +511,6 @@ func (ctl *Control) RegisterProxy(pxyMsg *msg.NewProxy) (remoteAddr string, err } verifyTunnelParams := tunnel.PostTunnelParams{ - NodeId: ctl.serverCfg.NodeId, FrpToken: ctl.loginMsg.User, TunnelName: tunnelName, TunnelType: pxyMsg.ProxyType, @@ -531,10 +529,12 @@ func (ctl *Control) RegisterProxy(pxyMsg *msg.NewProxy) (remoteAddr string, err } var rsVerifyTunnel *tunnel.PostTunnelResponse - rsVerifyTunnel, err = as.Server.Tunnel.PostTunnel(ctl.serverCfg.NodeApiKey, verifyTunnelParams) + rsVerifyTunnel, err = as.Server.Tunnel.PostTunnel(apitype.ServerConfig{ + NodeId: ctl.serverCfg.Node.Id, + ApiKey: ctl.serverCfg.Node.ApiKey, + }, verifyTunnelParams) if err != nil { - xl.Errorf("verify tunnel failed: %v", err) - return + return "", errors.New(fmt.Sprintf("post tunnel error: %v", err)) } if rsVerifyTunnel.Status != 200 { return "", errors.New(fmt.Sprintf( @@ -546,11 +546,16 @@ func (ctl *Control) RegisterProxy(pxyMsg *msg.NewProxy) (remoteAddr string, err } var rsSubmitRunId *tunnel.PostRunIdResponse - rsSubmitRunId, err = as.Server.Tunnel.PutRunId(ctl.serverCfg.NodeApiKey, tunnel.PostRunIdParams{ - NodeId: ctl.serverCfg.NodeId, - TunnelId: rsVerifyTunnel.Data.TunnelId, - RunId: ctl.runID, - }) + rsSubmitRunId, err = as.Server.Tunnel.PutRunId( + apitype.ServerConfig{ + NodeId: ctl.serverCfg.Node.Id, + ApiKey: ctl.serverCfg.Node.ApiKey, + }, + tunnel.PostRunIdParams{ + TunnelId: rsVerifyTunnel.Data.TunnelId, + RunId: ctl.runID, + }, + ) if err != nil { return } diff --git a/server/service.go b/server/service.go index 057c5d6d..13319305 100644 --- a/server/service.go +++ b/server/service.go @@ -28,7 +28,9 @@ import ( "github.com/fatedier/frp/pkg/api" "github.com/fatedier/frp/pkg/api/server/user" + apitype "github.com/fatedier/frp/pkg/api/type" "github.com/fatedier/frp/pkg/database" + "github.com/fatedier/frp/pkg/util/util" "github.com/quic-go/quic-go" "github.com/fatedier/golib/crypto" @@ -48,7 +50,6 @@ import ( "github.com/fatedier/frp/pkg/util/log" netpkg "github.com/fatedier/frp/pkg/util/net" "github.com/fatedier/frp/pkg/util/tcpmux" - "github.com/fatedier/frp/pkg/util/util" "github.com/fatedier/frp/pkg/util/version" "github.com/fatedier/frp/pkg/util/vhost" "github.com/fatedier/frp/pkg/util/xlog" @@ -595,7 +596,7 @@ func (svr *Service) RegisterControl(ctlConn net.Conn, loginMsg *msg.Login, inter if err != nil { return err } - loginMsg.RunID = fmt.Sprintf("%d.%s", svr.cfg.NodeId, generated) + loginMsg.RunID = fmt.Sprintf("%d.%s", svr.cfg.Node.Id, generated) } else { isClosed, err := svr.closedProxyManager.IsClosed(loginMsg.RunID) if err != nil { @@ -631,10 +632,15 @@ func (svr *Service) RegisterControl(ctlConn net.Conn, loginMsg *msg.Login, inter } var rsVerifyToken *user.PostTokenResponse - rsVerifyToken, err = as.Server.User.PostToken(svr.cfg.NodeApiKey, user.PostTokenParams{ - NodeId: svr.cfg.NodeId, - FrpToken: loginMsg.User, - }) + rsVerifyToken, err = as.Server.User.PostToken( + apitype.ServerConfig{ + NodeId: svr.cfg.Node.Id, + ApiKey: svr.cfg.Node.ApiKey, + }, + user.PostTokenParams{ + FrpToken: loginMsg.User, + }, + ) if err != nil { return err } @@ -646,10 +652,15 @@ func (svr *Service) RegisterControl(ctlConn net.Conn, loginMsg *msg.Login, inter )) } - rsGetLimit, err = as.Server.User.GetSpeedLimit(svr.cfg.NodeApiKey, user.GetSpeedLimitParams{ - NodeId: svr.cfg.NodeId, - FrpToken: loginMsg.User, - }) + rsGetLimit, err = as.Server.User.GetSpeedLimit( + apitype.ServerConfig{ + NodeId: svr.cfg.Node.Id, + ApiKey: svr.cfg.Node.ApiKey, + }, + user.GetSpeedLimitParams{ + FrpToken: loginMsg.User, + }, + ) if err != nil { return err }