mirror of
https://github.com/fatedier/frp.git
synced 2025-06-17 09:08:21 +00:00
Compare commits
No commits in common. "d689f0fc531604b78b510c2f5f182831a2b5bee5" and "d505ecb473751e24cdfd2df7676beb5e54eff676" have entirely different histories.
d689f0fc53
...
d505ecb473
11
.github/workflows/stale.yml
vendored
11
.github/workflows/stale.yml
vendored
@ -16,20 +16,19 @@ jobs:
|
|||||||
permissions:
|
permissions:
|
||||||
issues: write # for actions/stale to close stale issues
|
issues: write # for actions/stale to close stale issues
|
||||||
pull-requests: write # for actions/stale to close stale PRs
|
pull-requests: write # for actions/stale to close stale PRs
|
||||||
actions: write
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/stale@v9
|
- uses: actions/stale@v8
|
||||||
with:
|
with:
|
||||||
stale-issue-message: 'Issues go stale after 21d of inactivity. Stale issues rot after an additional 7d of inactivity and eventually close.'
|
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
stale-pr-message: "PRs go stale after 21d of inactivity. Stale PRs rot after an additional 7d of inactivity and eventually close."
|
stale-issue-message: 'Issues go stale after 30d of inactivity. Stale issues rot after an additional 7d of inactivity and eventually close.'
|
||||||
|
stale-pr-message: "PRs go stale after 30d of inactivity. Stale PRs rot after an additional 7d of inactivity and eventually close."
|
||||||
stale-issue-label: 'lifecycle/stale'
|
stale-issue-label: 'lifecycle/stale'
|
||||||
exempt-issue-labels: 'bug,doc,enhancement,future,proposal,question,testing,todo,easy,help wanted,assigned'
|
exempt-issue-labels: 'bug,doc,enhancement,future,proposal,question,testing,todo,easy,help wanted,assigned'
|
||||||
stale-pr-label: 'lifecycle/stale'
|
stale-pr-label: 'lifecycle/stale'
|
||||||
exempt-pr-labels: 'bug,doc,enhancement,future,proposal,question,testing,todo,easy,help wanted,assigned'
|
exempt-pr-labels: 'bug,doc,enhancement,future,proposal,question,testing,todo,easy,help wanted,assigned'
|
||||||
days-before-stale: 21
|
days-before-stale: 30
|
||||||
days-before-close: 7
|
days-before-close: 7
|
||||||
debug-only: ${{ github.event.inputs.debug-only }}
|
debug-only: ${{ github.event.inputs.debug-only }}
|
||||||
exempt-all-pr-milestones: true
|
exempt-all-pr-milestones: true
|
||||||
exempt-all-pr-assignees: true
|
exempt-all-pr-assignees: true
|
||||||
operations-per-run: 200
|
|
||||||
|
2
.gitignore
vendored
2
.gitignore
vendored
@ -34,8 +34,6 @@ dist/
|
|||||||
.idea/
|
.idea/
|
||||||
.vscode/
|
.vscode/
|
||||||
.autogen_ssh_key
|
.autogen_ssh_key
|
||||||
client.crt
|
|
||||||
client.key
|
|
||||||
|
|
||||||
# Cache
|
# Cache
|
||||||
*.swp
|
*.swp
|
||||||
|
10
Release.md
10
Release.md
@ -1,11 +1,3 @@
|
|||||||
### Deprecation Notices
|
|
||||||
|
|
||||||
* Using an underscore in a flag name is deprecated and has been replaced by a hyphen. The underscore format will remain compatible for some time, until it is completely removed in a future version. For example, `--remote_port` is replaced with `--remote-port`.
|
|
||||||
|
|
||||||
### Features
|
|
||||||
|
|
||||||
* The `Refresh` and `ClearOfflineProxies` buttons have been added to the Dashboard of frps.
|
|
||||||
|
|
||||||
### Fixes
|
### Fixes
|
||||||
|
|
||||||
* The host/domain matching in the routing rules has been changed to be case-insensitive.
|
* frpc has a certain chance to panic when login: close of closed channel.
|
||||||
|
32
assets/frpc/static/index-1c7ed8b0.js
Normal file
32
assets/frpc/static/index-1c7ed8b0.js
Normal file
File diff suppressed because one or more lines are too long
1
assets/frpc/static/index-1e2a7ce0.css
Normal file
1
assets/frpc/static/index-1e2a7ce0.css
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -4,12 +4,13 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<title>frp client admin UI</title>
|
<title>frp client admin UI</title>
|
||||||
<script type="module" crossorigin src="./index-bLBhaJo8.js"></script>
|
<script type="module" crossorigin src="./index-1c7ed8b0.js"></script>
|
||||||
<link rel="stylesheet" crossorigin href="./index-iuf46MlF.css">
|
<link rel="stylesheet" href="./index-1e2a7ce0.css">
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<div id="app"></div>
|
<div id="app"></div>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
1
assets/frps/static/index-1e0c7400.css
Normal file
1
assets/frps/static/index-1e0c7400.css
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
74
assets/frps/static/index-c322b7dd.js
Normal file
74
assets/frps/static/index-c322b7dd.js
Normal file
File diff suppressed because one or more lines are too long
@ -4,12 +4,13 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<title>frps dashboard</title>
|
<title>frps dashboard</title>
|
||||||
<script type="module" crossorigin src="./index-1gecbKzv.js"></script>
|
<script type="module" crossorigin src="./index-c322b7dd.js"></script>
|
||||||
<link rel="stylesheet" crossorigin href="./index-Lf6B06jY.css">
|
<link rel="stylesheet" href="./index-1e0c7400.css">
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<div id="app"></div>
|
<div id="app"></div>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
@ -35,7 +35,7 @@ import (
|
|||||||
"github.com/fatedier/frp/pkg/util/xlog"
|
"github.com/fatedier/frp/pkg/util/xlog"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Connector is an interface for establishing connections to the server.
|
// Connector is a interface for establishing connections to the server.
|
||||||
type Connector interface {
|
type Connector interface {
|
||||||
Open() error
|
Open() error
|
||||||
Connect() (net.Conn, error)
|
Connect() (net.Conn, error)
|
||||||
@ -59,7 +59,7 @@ func NewConnector(ctx context.Context, cfg *v1.ClientCommonConfig) Connector {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Open opens an underlying connection to the server.
|
// Open opens a underlying connection to the server.
|
||||||
// The underlying connection is either a TCP connection or a QUIC connection.
|
// The underlying connection is either a TCP connection or a QUIC connection.
|
||||||
// After the underlying connection is established, you can call Connect() to get a stream.
|
// After the underlying connection is established, you can call Connect() to get a stream.
|
||||||
// If TCPMux isn't enabled, the underlying connection is nil, you will get a new real TCP connection every time you call Connect().
|
// If TCPMux isn't enabled, the underlying connection is nil, you will get a new real TCP connection every time you call Connect().
|
||||||
|
@ -133,7 +133,6 @@ func (ctl *Control) handleReqWorkConn(_ msg.Message) {
|
|||||||
}
|
}
|
||||||
if err = ctl.sessionCtx.AuthSetter.SetNewWorkConn(m); err != nil {
|
if err = ctl.sessionCtx.AuthSetter.SetNewWorkConn(m); err != nil {
|
||||||
xl.Warn("error during NewWorkConn authentication: %v", err)
|
xl.Warn("error during NewWorkConn authentication: %v", err)
|
||||||
workConn.Close()
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if err = msg.WriteMsg(workConn, m); err != nil {
|
if err = msg.WriteMsg(workConn, m); err != nil {
|
||||||
|
@ -97,7 +97,6 @@ func runMultipleClients(cfgDir string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func Execute() {
|
func Execute() {
|
||||||
rootCmd.SetGlobalNormalizationFunc(config.WordSepNormalizeFunc)
|
|
||||||
if err := rootCmd.Execute(); err != nil {
|
if err := rootCmd.Execute(); err != nil {
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
@ -92,7 +92,6 @@ var rootCmd = &cobra.Command{
|
|||||||
}
|
}
|
||||||
|
|
||||||
func Execute() {
|
func Execute() {
|
||||||
rootCmd.SetGlobalNormalizationFunc(config.WordSepNormalizeFunc)
|
|
||||||
if err := rootCmd.Execute(); err != nil {
|
if err := rootCmd.Execute(); err != nil {
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
@ -41,7 +41,7 @@ transport.maxPoolCount = 5
|
|||||||
# transport.tcpKeepalive = 7200
|
# transport.tcpKeepalive = 7200
|
||||||
|
|
||||||
# transport.tls.force specifies whether to only accept TLS-encrypted connections. By default, the value is false.
|
# transport.tls.force specifies whether to only accept TLS-encrypted connections. By default, the value is false.
|
||||||
transport.tls.force = false
|
tls.force = false
|
||||||
|
|
||||||
# transport.tls.certFile = "server.crt"
|
# transport.tls.certFile = "server.crt"
|
||||||
# transport.tls.keyFile = "server.key"
|
# transport.tls.keyFile = "server.key"
|
||||||
@ -129,7 +129,7 @@ allowPorts = [
|
|||||||
maxPortsPerClient = 0
|
maxPortsPerClient = 0
|
||||||
|
|
||||||
# If subDomainHost is not empty, you can set subdomain when type is http or https in frpc's configure file
|
# If subDomainHost is not empty, you can set subdomain when type is http or https in frpc's configure file
|
||||||
# When subdomain is test, the host used by routing is test.frps.com
|
# When subdomain is est, the host used by routing is test.frps.com
|
||||||
subDomainHost = "frps.com"
|
subDomainHost = "frps.com"
|
||||||
|
|
||||||
# custom 404 page for HTTP requests
|
# custom 404 page for HTTP requests
|
||||||
|
8
go.mod
8
go.mod
@ -18,13 +18,13 @@ require (
|
|||||||
github.com/pion/stun v0.6.1
|
github.com/pion/stun v0.6.1
|
||||||
github.com/pires/go-proxyproto v0.7.0
|
github.com/pires/go-proxyproto v0.7.0
|
||||||
github.com/prometheus/client_golang v1.16.0
|
github.com/prometheus/client_golang v1.16.0
|
||||||
github.com/quic-go/quic-go v0.37.7
|
github.com/quic-go/quic-go v0.37.4
|
||||||
github.com/rodaine/table v1.1.0
|
github.com/rodaine/table v1.1.0
|
||||||
github.com/samber/lo v1.38.1
|
github.com/samber/lo v1.38.1
|
||||||
github.com/spf13/cobra v1.8.0
|
github.com/spf13/cobra v1.8.0
|
||||||
github.com/spf13/pflag v1.0.5
|
github.com/spf13/pflag v1.0.5
|
||||||
github.com/stretchr/testify v1.8.4
|
github.com/stretchr/testify v1.8.4
|
||||||
golang.org/x/crypto v0.17.0
|
golang.org/x/crypto v0.15.0
|
||||||
golang.org/x/net v0.17.0
|
golang.org/x/net v0.17.0
|
||||||
golang.org/x/oauth2 v0.10.0
|
golang.org/x/oauth2 v0.10.0
|
||||||
golang.org/x/sync v0.3.0
|
golang.org/x/sync v0.3.0
|
||||||
@ -39,7 +39,7 @@ require (
|
|||||||
github.com/beorn7/perks v1.0.1 // indirect
|
github.com/beorn7/perks v1.0.1 // indirect
|
||||||
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
||||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
github.com/go-jose/go-jose/v3 v3.0.1 // indirect
|
github.com/go-jose/go-jose/v3 v3.0.0 // indirect
|
||||||
github.com/go-logr/logr v1.2.4 // indirect
|
github.com/go-logr/logr v1.2.4 // indirect
|
||||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
|
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
|
||||||
github.com/golang/mock v1.6.0 // indirect
|
github.com/golang/mock v1.6.0 // indirect
|
||||||
@ -67,7 +67,7 @@ require (
|
|||||||
github.com/tjfoc/gmsm v1.4.1 // indirect
|
github.com/tjfoc/gmsm v1.4.1 // indirect
|
||||||
golang.org/x/exp v0.0.0-20221205204356-47842c84f3db // indirect
|
golang.org/x/exp v0.0.0-20221205204356-47842c84f3db // indirect
|
||||||
golang.org/x/mod v0.10.0 // indirect
|
golang.org/x/mod v0.10.0 // indirect
|
||||||
golang.org/x/sys v0.15.0 // indirect
|
golang.org/x/sys v0.14.0 // indirect
|
||||||
golang.org/x/text v0.14.0 // indirect
|
golang.org/x/text v0.14.0 // indirect
|
||||||
golang.org/x/tools v0.9.3 // indirect
|
golang.org/x/tools v0.9.3 // indirect
|
||||||
google.golang.org/appengine v1.6.7 // indirect
|
google.golang.org/appengine v1.6.7 // indirect
|
||||||
|
18
go.sum
18
go.sum
@ -32,8 +32,8 @@ github.com/fatedier/kcp-go v2.0.4-0.20190803094908-fe8645b0a904+incompatible h1:
|
|||||||
github.com/fatedier/kcp-go v2.0.4-0.20190803094908-fe8645b0a904+incompatible/go.mod h1:YpCOaxj7vvMThhIQ9AfTOPW2sfztQR5WDfs7AflSy4s=
|
github.com/fatedier/kcp-go v2.0.4-0.20190803094908-fe8645b0a904+incompatible/go.mod h1:YpCOaxj7vvMThhIQ9AfTOPW2sfztQR5WDfs7AflSy4s=
|
||||||
github.com/fatedier/yamux v0.0.0-20230628132301-7aca4898904d h1:ynk1ra0RUqDWQfvFi5KtMiSobkVQ3cNc0ODb8CfIETo=
|
github.com/fatedier/yamux v0.0.0-20230628132301-7aca4898904d h1:ynk1ra0RUqDWQfvFi5KtMiSobkVQ3cNc0ODb8CfIETo=
|
||||||
github.com/fatedier/yamux v0.0.0-20230628132301-7aca4898904d/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ=
|
github.com/fatedier/yamux v0.0.0-20230628132301-7aca4898904d/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ=
|
||||||
github.com/go-jose/go-jose/v3 v3.0.1 h1:pWmKFVtt+Jl0vBZTIpz/eAKwsm6LkIxDVVbFHKkchhA=
|
github.com/go-jose/go-jose/v3 v3.0.0 h1:s6rrhirfEP/CGIoc6p+PZAeogN2SxKav6Wp7+dyMWVo=
|
||||||
github.com/go-jose/go-jose/v3 v3.0.1/go.mod h1:RNkWWRld676jZEYoV3+XK8L2ZnNSvIsxFMht0mSX+u8=
|
github.com/go-jose/go-jose/v3 v3.0.0/go.mod h1:RNkWWRld676jZEYoV3+XK8L2ZnNSvIsxFMht0mSX+u8=
|
||||||
github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=
|
github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=
|
||||||
github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
|
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
|
||||||
@ -119,8 +119,8 @@ github.com/prometheus/procfs v0.10.1 h1:kYK1Va/YMlutzCGazswoHKo//tZVlFpKYh+Pymzi
|
|||||||
github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM=
|
github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM=
|
||||||
github.com/quic-go/qtls-go1-20 v0.3.1 h1:O4BLOM3hwfVF3AcktIylQXyl7Yi2iBNVy5QsV+ySxbg=
|
github.com/quic-go/qtls-go1-20 v0.3.1 h1:O4BLOM3hwfVF3AcktIylQXyl7Yi2iBNVy5QsV+ySxbg=
|
||||||
github.com/quic-go/qtls-go1-20 v0.3.1/go.mod h1:X9Nh97ZL80Z+bX/gUXMbipO6OxdiDi58b/fMC9mAL+k=
|
github.com/quic-go/qtls-go1-20 v0.3.1/go.mod h1:X9Nh97ZL80Z+bX/gUXMbipO6OxdiDi58b/fMC9mAL+k=
|
||||||
github.com/quic-go/quic-go v0.37.7 h1:AgKsQLZ1+YCwZd2GYhBUsJDYZwEkA5gENtAjb+MxONU=
|
github.com/quic-go/quic-go v0.37.4 h1:ke8B73yMCWGq9MfrCCAw0Uzdm7GaViC3i39dsIdDlH4=
|
||||||
github.com/quic-go/quic-go v0.37.7/go.mod h1:YsbH1r4mSHPJcLF4k4zruUkLBqctEMBDR6VPvcYjIsU=
|
github.com/quic-go/quic-go v0.37.4/go.mod h1:YsbH1r4mSHPJcLF4k4zruUkLBqctEMBDR6VPvcYjIsU=
|
||||||
github.com/rodaine/table v1.1.0 h1:/fUlCSdjamMY8VifdQRIu3VWZXYLY7QHFkVorS8NTr4=
|
github.com/rodaine/table v1.1.0 h1:/fUlCSdjamMY8VifdQRIu3VWZXYLY7QHFkVorS8NTr4=
|
||||||
github.com/rodaine/table v1.1.0/go.mod h1:Qu3q5wi1jTQD6B6HsP6szie/S4w1QUQ8pq22pz9iL8g=
|
github.com/rodaine/table v1.1.0/go.mod h1:Qu3q5wi1jTQD6B6HsP6szie/S4w1QUQ8pq22pz9iL8g=
|
||||||
github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
|
github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
|
||||||
@ -157,8 +157,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh
|
|||||||
golang.org/x/crypto v0.0.0-20201012173705-84dcc777aaee/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20201012173705-84dcc777aaee/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE=
|
golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE=
|
||||||
golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k=
|
golang.org/x/crypto v0.15.0 h1:frVn1TEaCEaZcn3Tmd7Y2b5KKPaZ+I32Q2OA3kYp5TA=
|
||||||
golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
|
golang.org/x/crypto v0.15.0/go.mod h1:4ChreQoLWfG3xLDer1WdlH5NdlQ3+mwnQq1YTKY+72g=
|
||||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
golang.org/x/exp v0.0.0-20221205204356-47842c84f3db h1:D/cFflL63o2KSLJIwjlcIt8PR064j/xsmdEJL/YvY/o=
|
golang.org/x/exp v0.0.0-20221205204356-47842c84f3db h1:D/cFflL63o2KSLJIwjlcIt8PR064j/xsmdEJL/YvY/o=
|
||||||
golang.org/x/exp v0.0.0-20221205204356-47842c84f3db/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
|
golang.org/x/exp v0.0.0-20221205204356-47842c84f3db/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
|
||||||
@ -210,13 +210,13 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
|
golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q=
|
||||||
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
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.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||||
golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
|
golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
|
||||||
golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4=
|
golang.org/x/term v0.14.0 h1:LGK9IlZ8T9jvdy6cTdfKUCltatMFOehAQo9SRC46UQ8=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
|
@ -26,9 +26,5 @@ frpsPath=${ROOT}/bin/frps
|
|||||||
if [ "${FRPS_PATH}" ]; then
|
if [ "${FRPS_PATH}" ]; then
|
||||||
frpsPath="${FRPS_PATH}"
|
frpsPath="${FRPS_PATH}"
|
||||||
fi
|
fi
|
||||||
concurrency="16"
|
|
||||||
if [ "${CONCURRENCY}" ]; then
|
|
||||||
concurrency="${CONCURRENCY}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
ginkgo -nodes=${concurrency} --poll-progress-after=60s ${ROOT}/test/e2e -- -frpc-path=${frpcPath} -frps-path=${frpsPath} -log-level=${logLevel} -debug=${debug}
|
ginkgo -nodes=8 --poll-progress-after=60s ${ROOT}/test/e2e -- -frpc-path=${frpcPath} -frps-path=${frpsPath} -log-level=${logLevel} -debug=${debug}
|
||||||
|
@ -17,24 +17,14 @@ package config
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/spf13/pflag"
|
|
||||||
|
|
||||||
"github.com/fatedier/frp/pkg/config/types"
|
"github.com/fatedier/frp/pkg/config/types"
|
||||||
v1 "github.com/fatedier/frp/pkg/config/v1"
|
v1 "github.com/fatedier/frp/pkg/config/v1"
|
||||||
"github.com/fatedier/frp/pkg/config/v1/validation"
|
"github.com/fatedier/frp/pkg/config/v1/validation"
|
||||||
)
|
)
|
||||||
|
|
||||||
// WordSepNormalizeFunc changes all flags that contain "_" separators
|
|
||||||
func WordSepNormalizeFunc(f *pflag.FlagSet, name string) pflag.NormalizedName {
|
|
||||||
if strings.Contains(name, "_") {
|
|
||||||
return pflag.NormalizedName(strings.ReplaceAll(name, "_", "-"))
|
|
||||||
}
|
|
||||||
return pflag.NormalizedName(name)
|
|
||||||
}
|
|
||||||
|
|
||||||
type RegisterFlagOption func(*registerFlagOptions)
|
type RegisterFlagOption func(*registerFlagOptions)
|
||||||
|
|
||||||
type registerFlagOptions struct {
|
type registerFlagOptions struct {
|
||||||
|
@ -195,7 +195,7 @@ type ProxyConfigurer interface {
|
|||||||
// MarshalToMsg marshals this config into a msg.NewProxy message. This
|
// MarshalToMsg marshals this config into a msg.NewProxy message. This
|
||||||
// function will be called on the frpc side.
|
// function will be called on the frpc side.
|
||||||
MarshalToMsg(*msg.NewProxy)
|
MarshalToMsg(*msg.NewProxy)
|
||||||
// UnmarshalFromMsg unmarshal a msg.NewProxy message into this config.
|
// UnmarshalFromMsg unmarshals a msg.NewProxy message into this config.
|
||||||
// This function will be called on the frps side.
|
// This function will be called on the frps side.
|
||||||
UnmarshalFromMsg(*msg.NewProxy)
|
UnmarshalFromMsg(*msg.NewProxy)
|
||||||
}
|
}
|
||||||
|
@ -61,23 +61,23 @@ func (m *serverMetrics) run() {
|
|||||||
for {
|
for {
|
||||||
time.Sleep(12 * time.Hour)
|
time.Sleep(12 * time.Hour)
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
count, total := m.clearUselessInfo(time.Duration(7*24) * time.Hour)
|
count, total := m.clearUselessInfo()
|
||||||
log.Debug("clear useless proxy statistics data count %d/%d, cost %v", count, total, time.Since(start))
|
log.Debug("clear useless proxy statistics data count %d/%d, cost %v", count, total, time.Since(start))
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *serverMetrics) clearUselessInfo(continuousOfflineDuration time.Duration) (int, int) {
|
func (m *serverMetrics) clearUselessInfo() (int, int) {
|
||||||
count := 0
|
count := 0
|
||||||
total := 0
|
total := 0
|
||||||
// To check if there are any proxies that have been closed for more than continuousOfflineDuration and remove them.
|
// To check if there are proxies that closed than 7 days and drop them.
|
||||||
m.mu.Lock()
|
m.mu.Lock()
|
||||||
defer m.mu.Unlock()
|
defer m.mu.Unlock()
|
||||||
total = len(m.info.ProxyStatistics)
|
total = len(m.info.ProxyStatistics)
|
||||||
for name, data := range m.info.ProxyStatistics {
|
for name, data := range m.info.ProxyStatistics {
|
||||||
if !data.LastCloseTime.IsZero() &&
|
if !data.LastCloseTime.IsZero() &&
|
||||||
data.LastStartTime.Before(data.LastCloseTime) &&
|
data.LastStartTime.Before(data.LastCloseTime) &&
|
||||||
time.Since(data.LastCloseTime) > continuousOfflineDuration {
|
time.Since(data.LastCloseTime) > time.Duration(7*24)*time.Hour {
|
||||||
delete(m.info.ProxyStatistics, name)
|
delete(m.info.ProxyStatistics, name)
|
||||||
count++
|
count++
|
||||||
log.Trace("clear proxy [%s]'s statistics data, lastCloseTime: [%s]", name, data.LastCloseTime.String())
|
log.Trace("clear proxy [%s]'s statistics data, lastCloseTime: [%s]", name, data.LastCloseTime.String())
|
||||||
@ -86,10 +86,6 @@ func (m *serverMetrics) clearUselessInfo(continuousOfflineDuration time.Duration
|
|||||||
return count, total
|
return count, total
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *serverMetrics) ClearOfflineProxies() (int, int) {
|
|
||||||
return m.clearUselessInfo(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *serverMetrics) NewClient() {
|
func (m *serverMetrics) NewClient() {
|
||||||
m.info.ClientCounts.Inc(1)
|
m.info.ClientCounts.Inc(1)
|
||||||
}
|
}
|
||||||
|
@ -79,5 +79,4 @@ type Collector interface {
|
|||||||
GetProxiesByType(proxyType string) []*ProxyStats
|
GetProxiesByType(proxyType string) []*ProxyStats
|
||||||
GetProxiesByTypeAndName(proxyType string, proxyName string) *ProxyStats
|
GetProxiesByTypeAndName(proxyType string, proxyName string) *ProxyStats
|
||||||
GetProxyTraffic(name string) *ProxyTrafficInfo
|
GetProxyTraffic(name string) *ProxyTrafficInfo
|
||||||
ClearOfflineProxies() (int, int)
|
|
||||||
}
|
}
|
||||||
|
@ -254,8 +254,6 @@ func (s *TunnelServer) parseClientAndProxyConfigurer(_ *tcpipForward, extraPaylo
|
|||||||
Short: "ssh v0@{address} [command]",
|
Short: "ssh v0@{address} [command]",
|
||||||
Run: func(*cobra.Command, []string) {},
|
Run: func(*cobra.Command, []string) {},
|
||||||
}
|
}
|
||||||
cmd.SetGlobalNormalizationFunc(config.WordSepNormalizeFunc)
|
|
||||||
|
|
||||||
args := strings.Split(extraPayload, " ")
|
args := strings.Split(extraPayload, " ")
|
||||||
if len(args) < 1 {
|
if len(args) < 1 {
|
||||||
return nil, nil, helpMessage, fmt.Errorf("invalid extra payload")
|
return nil, nil, helpMessage, fmt.Errorf("invalid extra payload")
|
||||||
|
@ -19,7 +19,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
var version = "0.54.0"
|
var version = "0.53.2"
|
||||||
|
|
||||||
func Full() string {
|
func Full() string {
|
||||||
return version
|
return version
|
||||||
|
@ -33,8 +33,6 @@ func NewRouters() *Routers {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *Routers) Add(domain, location, httpUser string, payload interface{}) error {
|
func (r *Routers) Add(domain, location, httpUser string, payload interface{}) error {
|
||||||
domain = strings.ToLower(domain)
|
|
||||||
|
|
||||||
r.mutex.Lock()
|
r.mutex.Lock()
|
||||||
defer r.mutex.Unlock()
|
defer r.mutex.Unlock()
|
||||||
|
|
||||||
@ -66,8 +64,6 @@ func (r *Routers) Add(domain, location, httpUser string, payload interface{}) er
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *Routers) Del(domain, location, httpUser string) {
|
func (r *Routers) Del(domain, location, httpUser string) {
|
||||||
domain = strings.ToLower(domain)
|
|
||||||
|
|
||||||
r.mutex.Lock()
|
r.mutex.Lock()
|
||||||
defer r.mutex.Unlock()
|
defer r.mutex.Unlock()
|
||||||
|
|
||||||
@ -90,8 +86,6 @@ func (r *Routers) Del(domain, location, httpUser string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *Routers) Get(host, path, httpUser string) (vr *Router, exist bool) {
|
func (r *Routers) Get(host, path, httpUser string) (vr *Router, exist bool) {
|
||||||
host = strings.ToLower(host)
|
|
||||||
|
|
||||||
r.mutex.RLock()
|
r.mutex.RLock()
|
||||||
defer r.mutex.RUnlock()
|
defer r.mutex.RUnlock()
|
||||||
|
|
||||||
|
@ -17,7 +17,6 @@ package server
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"net/http"
|
"net/http"
|
||||||
"sort"
|
|
||||||
|
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||||
@ -54,7 +53,6 @@ func (svr *Service) registerRouteHandlers(helper *httppkg.RouterRegisterHelper)
|
|||||||
subRouter.HandleFunc("/api/proxy/{type}", svr.apiProxyByType).Methods("GET")
|
subRouter.HandleFunc("/api/proxy/{type}", svr.apiProxyByType).Methods("GET")
|
||||||
subRouter.HandleFunc("/api/proxy/{type}/{name}", svr.apiProxyByTypeAndName).Methods("GET")
|
subRouter.HandleFunc("/api/proxy/{type}/{name}", svr.apiProxyByTypeAndName).Methods("GET")
|
||||||
subRouter.HandleFunc("/api/traffic/{name}", svr.apiProxyTraffic).Methods("GET")
|
subRouter.HandleFunc("/api/traffic/{name}", svr.apiProxyTraffic).Methods("GET")
|
||||||
subRouter.HandleFunc("/api/proxies", svr.deleteProxies).Methods("DELETE")
|
|
||||||
|
|
||||||
// view
|
// view
|
||||||
subRouter.Handle("/favicon.ico", http.FileServer(helper.AssetsFS)).Methods("GET")
|
subRouter.Handle("/favicon.ico", http.FileServer(helper.AssetsFS)).Methods("GET")
|
||||||
@ -228,9 +226,6 @@ func (svr *Service) apiProxyByType(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
proxyInfoResp := GetProxyInfoResp{}
|
proxyInfoResp := GetProxyInfoResp{}
|
||||||
proxyInfoResp.Proxies = svr.getProxyStatsByType(proxyType)
|
proxyInfoResp.Proxies = svr.getProxyStatsByType(proxyType)
|
||||||
sort.Slice(proxyInfoResp.Proxies, func(i, j int) bool {
|
|
||||||
return proxyInfoResp.Proxies[i].Name < proxyInfoResp.Proxies[j].Name
|
|
||||||
})
|
|
||||||
|
|
||||||
buf, _ := json.Marshal(&proxyInfoResp)
|
buf, _ := json.Marshal(&proxyInfoResp)
|
||||||
res.Msg = string(buf)
|
res.Msg = string(buf)
|
||||||
@ -381,26 +376,3 @@ func (svr *Service) apiProxyTraffic(w http.ResponseWriter, r *http.Request) {
|
|||||||
buf, _ := json.Marshal(&trafficResp)
|
buf, _ := json.Marshal(&trafficResp)
|
||||||
res.Msg = string(buf)
|
res.Msg = string(buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DELETE /api/proxies?status=offline
|
|
||||||
func (svr *Service) deleteProxies(w http.ResponseWriter, r *http.Request) {
|
|
||||||
res := GeneralResponse{Code: 200}
|
|
||||||
|
|
||||||
log.Info("Http request: [%s]", r.URL.Path)
|
|
||||||
defer func() {
|
|
||||||
log.Info("Http response [%s]: code [%d]", r.URL.Path, res.Code)
|
|
||||||
w.WriteHeader(res.Code)
|
|
||||||
if len(res.Msg) > 0 {
|
|
||||||
_, _ = w.Write([]byte(res.Msg))
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
status := r.URL.Query().Get("status")
|
|
||||||
if status != "offline" {
|
|
||||||
res.Code = 400
|
|
||||||
res.Msg = "status only support offline"
|
|
||||||
return
|
|
||||||
}
|
|
||||||
cleared, total := mem.StatsCollector.ClearOfflineProxies()
|
|
||||||
log.Info("cleared [%d] offline proxies, total [%d] proxies", cleared, total)
|
|
||||||
}
|
|
||||||
|
@ -67,7 +67,7 @@ func NewDefaultFramework() *Framework {
|
|||||||
TotalParallelNode: suiteConfig.ParallelTotal,
|
TotalParallelNode: suiteConfig.ParallelTotal,
|
||||||
CurrentNodeIndex: suiteConfig.ParallelProcess,
|
CurrentNodeIndex: suiteConfig.ParallelProcess,
|
||||||
FromPortIndex: 10000,
|
FromPortIndex: 10000,
|
||||||
ToPortIndex: 30000,
|
ToPortIndex: 60000,
|
||||||
}
|
}
|
||||||
return NewFramework(options)
|
return NewFramework(options)
|
||||||
}
|
}
|
||||||
|
@ -42,7 +42,7 @@ func (f *Framework) RunProcesses(serverTemplates []string, clientTemplates []str
|
|||||||
ExpectNoError(err)
|
ExpectNoError(err)
|
||||||
time.Sleep(500 * time.Millisecond)
|
time.Sleep(500 * time.Millisecond)
|
||||||
}
|
}
|
||||||
time.Sleep(2 * time.Second)
|
time.Sleep(1 * time.Second)
|
||||||
|
|
||||||
currentClientProcesses := make([]*process.Process, 0, len(clientTemplates))
|
currentClientProcesses := make([]*process.Process, 0, len(clientTemplates))
|
||||||
for i := range clientTemplates {
|
for i := range clientTemplates {
|
||||||
@ -76,7 +76,7 @@ func (f *Framework) RunFrps(args ...string) (*process.Process, string, error) {
|
|||||||
return p, p.StdOutput(), err
|
return p, p.StdOutput(), err
|
||||||
}
|
}
|
||||||
// sleep for a while to get std output
|
// sleep for a while to get std output
|
||||||
time.Sleep(2 * time.Second)
|
time.Sleep(time.Second)
|
||||||
return p, p.StdOutput(), nil
|
return p, p.StdOutput(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -87,7 +87,7 @@ func (f *Framework) RunFrpc(args ...string) (*process.Process, string, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return p, p.StdOutput(), err
|
return p, p.StdOutput(), err
|
||||||
}
|
}
|
||||||
time.Sleep(2 * time.Second)
|
time.Sleep(time.Second)
|
||||||
return p, p.StdOutput(), nil
|
return p, p.StdOutput(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,11 +22,11 @@ var _ = ginkgo.Describe("[Feature: Server Manager]", func() {
|
|||||||
clientConf := consts.LegacyDefaultClientConfig
|
clientConf := consts.LegacyDefaultClientConfig
|
||||||
|
|
||||||
serverConf += `
|
serverConf += `
|
||||||
allow_ports = 10000-11000,11002,12000-13000
|
allow_ports = 20000-25000,25002,30000-50000
|
||||||
`
|
`
|
||||||
|
|
||||||
tcpPortName := port.GenName("TCP", port.WithRangePorts(10000, 11000))
|
tcpPortName := port.GenName("TCP", port.WithRangePorts(20000, 25000))
|
||||||
udpPortName := port.GenName("UDP", port.WithRangePorts(12000, 13000))
|
udpPortName := port.GenName("UDP", port.WithRangePorts(30000, 50000))
|
||||||
clientConf += fmt.Sprintf(`
|
clientConf += fmt.Sprintf(`
|
||||||
[tcp-allowded-in-range]
|
[tcp-allowded-in-range]
|
||||||
type = tcp
|
type = tcp
|
||||||
@ -37,7 +37,7 @@ var _ = ginkgo.Describe("[Feature: Server Manager]", func() {
|
|||||||
[tcp-port-not-allowed]
|
[tcp-port-not-allowed]
|
||||||
type = tcp
|
type = tcp
|
||||||
local_port = {{ .%s }}
|
local_port = {{ .%s }}
|
||||||
remote_port = 11001
|
remote_port = 25001
|
||||||
`, framework.TCPEchoServerPort)
|
`, framework.TCPEchoServerPort)
|
||||||
clientConf += fmt.Sprintf(`
|
clientConf += fmt.Sprintf(`
|
||||||
[tcp-port-unavailable]
|
[tcp-port-unavailable]
|
||||||
@ -55,7 +55,7 @@ var _ = ginkgo.Describe("[Feature: Server Manager]", func() {
|
|||||||
[udp-port-not-allowed]
|
[udp-port-not-allowed]
|
||||||
type = udp
|
type = udp
|
||||||
local_port = {{ .%s }}
|
local_port = {{ .%s }}
|
||||||
remote_port = 11003
|
remote_port = 25003
|
||||||
`, framework.UDPEchoServerPort)
|
`, framework.UDPEchoServerPort)
|
||||||
|
|
||||||
f.RunProcesses([]string{serverConf}, []string{clientConf})
|
f.RunProcesses([]string{serverConf}, []string{clientConf})
|
||||||
@ -65,7 +65,7 @@ var _ = ginkgo.Describe("[Feature: Server Manager]", func() {
|
|||||||
framework.NewRequestExpect(f).PortName(tcpPortName).Ensure()
|
framework.NewRequestExpect(f).PortName(tcpPortName).Ensure()
|
||||||
|
|
||||||
// Not Allowed
|
// Not Allowed
|
||||||
framework.NewRequestExpect(f).Port(11001).ExpectError(true).Ensure()
|
framework.NewRequestExpect(f).Port(25001).ExpectError(true).Ensure()
|
||||||
|
|
||||||
// Unavailable, already bind by frps
|
// Unavailable, already bind by frps
|
||||||
framework.NewRequestExpect(f).PortName(consts.PortServerName).ExpectError(true).Ensure()
|
framework.NewRequestExpect(f).PortName(consts.PortServerName).ExpectError(true).Ensure()
|
||||||
@ -76,7 +76,7 @@ var _ = ginkgo.Describe("[Feature: Server Manager]", func() {
|
|||||||
|
|
||||||
// Not Allowed
|
// Not Allowed
|
||||||
framework.NewRequestExpect(f).RequestModify(func(r *request.Request) {
|
framework.NewRequestExpect(f).RequestModify(func(r *request.Request) {
|
||||||
r.UDP().Port(11003)
|
r.UDP().Port(25003)
|
||||||
}).ExpectError(true).Ensure()
|
}).ExpectError(true).Ensure()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -79,7 +79,6 @@ func (pa *Allocator) GetByName(portName string) int {
|
|||||||
udpConn.Close()
|
udpConn.Close()
|
||||||
|
|
||||||
pa.used.Insert(port)
|
pa.used.Insert(port)
|
||||||
pa.reserved.Delete(port)
|
|
||||||
return port
|
return port
|
||||||
}
|
}
|
||||||
return 0
|
return 0
|
||||||
|
@ -90,12 +90,12 @@ var _ = ginkgo.Describe("[Feature: Cmd]", func() {
|
|||||||
ginkgo.It("HTTP", func() {
|
ginkgo.It("HTTP", func() {
|
||||||
serverPort := f.AllocPort()
|
serverPort := f.AllocPort()
|
||||||
vhostHTTPPort := f.AllocPort()
|
vhostHTTPPort := f.AllocPort()
|
||||||
_, _, err := f.RunFrps("-t", "123", "-p", strconv.Itoa(serverPort), "--vhost-http-port", strconv.Itoa(vhostHTTPPort))
|
_, _, err := f.RunFrps("-t", "123", "-p", strconv.Itoa(serverPort), "--vhost_http_port", strconv.Itoa(vhostHTTPPort))
|
||||||
framework.ExpectNoError(err)
|
framework.ExpectNoError(err)
|
||||||
|
|
||||||
_, _, err = f.RunFrpc("http", "-s", "127.0.0.1", "-P", 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)),
|
"-n", "udp_test", "-l", strconv.Itoa(f.PortByName(framework.HTTPSimpleServerPort)),
|
||||||
"--custom-domain", "test.example.com")
|
"--custom_domain", "test.example.com")
|
||||||
framework.ExpectNoError(err)
|
framework.ExpectNoError(err)
|
||||||
|
|
||||||
framework.NewRequestExpect(f).Port(vhostHTTPPort).
|
framework.NewRequestExpect(f).Port(vhostHTTPPort).
|
||||||
|
@ -23,14 +23,14 @@ var _ = ginkgo.Describe("[Feature: Server Manager]", func() {
|
|||||||
|
|
||||||
serverConf += `
|
serverConf += `
|
||||||
allowPorts = [
|
allowPorts = [
|
||||||
{ start = 10000, end = 11000 },
|
{ start = 20000, end = 25000 },
|
||||||
{ single = 11002 },
|
{ single = 25002 },
|
||||||
{ start = 12000, end = 13000 },
|
{ start = 30000, end = 50000 },
|
||||||
]
|
]
|
||||||
`
|
`
|
||||||
|
|
||||||
tcpPortName := port.GenName("TCP", port.WithRangePorts(10000, 11000))
|
tcpPortName := port.GenName("TCP", port.WithRangePorts(20000, 25000))
|
||||||
udpPortName := port.GenName("UDP", port.WithRangePorts(12000, 13000))
|
udpPortName := port.GenName("UDP", port.WithRangePorts(30000, 50000))
|
||||||
clientConf += fmt.Sprintf(`
|
clientConf += fmt.Sprintf(`
|
||||||
[[proxies]]
|
[[proxies]]
|
||||||
name = "tcp-allowded-in-range"
|
name = "tcp-allowded-in-range"
|
||||||
@ -43,7 +43,7 @@ var _ = ginkgo.Describe("[Feature: Server Manager]", func() {
|
|||||||
name = "tcp-port-not-allowed"
|
name = "tcp-port-not-allowed"
|
||||||
type = "tcp"
|
type = "tcp"
|
||||||
localPort = {{ .%s }}
|
localPort = {{ .%s }}
|
||||||
remotePort = 11001
|
remotePort = 25001
|
||||||
`, framework.TCPEchoServerPort)
|
`, framework.TCPEchoServerPort)
|
||||||
clientConf += fmt.Sprintf(`
|
clientConf += fmt.Sprintf(`
|
||||||
[[proxies]]
|
[[proxies]]
|
||||||
@ -64,7 +64,7 @@ var _ = ginkgo.Describe("[Feature: Server Manager]", func() {
|
|||||||
name = "udp-port-not-allowed"
|
name = "udp-port-not-allowed"
|
||||||
type = "udp"
|
type = "udp"
|
||||||
localPort = {{ .%s }}
|
localPort = {{ .%s }}
|
||||||
remotePort = 11003
|
remotePort = 25003
|
||||||
`, framework.UDPEchoServerPort)
|
`, framework.UDPEchoServerPort)
|
||||||
|
|
||||||
f.RunProcesses([]string{serverConf}, []string{clientConf})
|
f.RunProcesses([]string{serverConf}, []string{clientConf})
|
||||||
@ -74,7 +74,7 @@ var _ = ginkgo.Describe("[Feature: Server Manager]", func() {
|
|||||||
framework.NewRequestExpect(f).PortName(tcpPortName).Ensure()
|
framework.NewRequestExpect(f).PortName(tcpPortName).Ensure()
|
||||||
|
|
||||||
// Not Allowed
|
// Not Allowed
|
||||||
framework.NewRequestExpect(f).Port(11001).ExpectError(true).Ensure()
|
framework.NewRequestExpect(f).Port(25001).ExpectError(true).Ensure()
|
||||||
|
|
||||||
// Unavailable, already bind by frps
|
// Unavailable, already bind by frps
|
||||||
framework.NewRequestExpect(f).PortName(consts.PortServerName).ExpectError(true).Ensure()
|
framework.NewRequestExpect(f).PortName(consts.PortServerName).ExpectError(true).Ensure()
|
||||||
@ -85,7 +85,7 @@ var _ = ginkgo.Describe("[Feature: Server Manager]", func() {
|
|||||||
|
|
||||||
// Not Allowed
|
// Not Allowed
|
||||||
framework.NewRequestExpect(f).RequestModify(func(r *request.Request) {
|
framework.NewRequestExpect(f).RequestModify(func(r *request.Request) {
|
||||||
r.UDP().Port(11003)
|
r.UDP().Port(25003)
|
||||||
}).ExpectError(true).Ensure()
|
}).ExpectError(true).Ensure()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ var _ = ginkgo.Describe("[Feature: SSH Tunnel]", func() {
|
|||||||
tc := ssh.NewTunnelClient(
|
tc := ssh.NewTunnelClient(
|
||||||
fmt.Sprintf("127.0.0.1:%d", localPort),
|
fmt.Sprintf("127.0.0.1:%d", localPort),
|
||||||
fmt.Sprintf("127.0.0.1:%d", sshPort),
|
fmt.Sprintf("127.0.0.1:%d", sshPort),
|
||||||
fmt.Sprintf("tcp --remote-port %d", remotePort),
|
fmt.Sprintf("tcp --remote_port %d", remotePort),
|
||||||
)
|
)
|
||||||
framework.ExpectNoError(tc.Start())
|
framework.ExpectNoError(tc.Start())
|
||||||
defer tc.Close()
|
defer tc.Close()
|
||||||
@ -55,7 +55,7 @@ var _ = ginkgo.Describe("[Feature: SSH Tunnel]", func() {
|
|||||||
tc := ssh.NewTunnelClient(
|
tc := ssh.NewTunnelClient(
|
||||||
fmt.Sprintf("127.0.0.1:%d", localPort),
|
fmt.Sprintf("127.0.0.1:%d", localPort),
|
||||||
fmt.Sprintf("127.0.0.1:%d", sshPort),
|
fmt.Sprintf("127.0.0.1:%d", sshPort),
|
||||||
"http --custom-domain test.example.com",
|
"http --custom_domain test.example.com",
|
||||||
)
|
)
|
||||||
framework.ExpectNoError(tc.Start())
|
framework.ExpectNoError(tc.Start())
|
||||||
defer tc.Close()
|
defer tc.Close()
|
||||||
@ -83,7 +83,7 @@ var _ = ginkgo.Describe("[Feature: SSH Tunnel]", func() {
|
|||||||
tc := ssh.NewTunnelClient(
|
tc := ssh.NewTunnelClient(
|
||||||
fmt.Sprintf("127.0.0.1:%d", localPort),
|
fmt.Sprintf("127.0.0.1:%d", localPort),
|
||||||
fmt.Sprintf("127.0.0.1:%d", sshPort),
|
fmt.Sprintf("127.0.0.1:%d", sshPort),
|
||||||
fmt.Sprintf("https --custom-domain %s", testDomain),
|
fmt.Sprintf("https --custom_domain %s", testDomain),
|
||||||
)
|
)
|
||||||
framework.ExpectNoError(tc.Start())
|
framework.ExpectNoError(tc.Start())
|
||||||
defer tc.Close()
|
defer tc.Close()
|
||||||
@ -125,7 +125,7 @@ var _ = ginkgo.Describe("[Feature: SSH Tunnel]", func() {
|
|||||||
tc := ssh.NewTunnelClient(
|
tc := ssh.NewTunnelClient(
|
||||||
fmt.Sprintf("127.0.0.1:%d", localPort),
|
fmt.Sprintf("127.0.0.1:%d", localPort),
|
||||||
fmt.Sprintf("127.0.0.1:%d", sshPort),
|
fmt.Sprintf("127.0.0.1:%d", sshPort),
|
||||||
fmt.Sprintf("tcpmux --mux=httpconnect --custom-domain %s", testDomain),
|
fmt.Sprintf("tcpmux --mux=httpconnect --custom_domain %s", testDomain),
|
||||||
)
|
)
|
||||||
framework.ExpectNoError(tc.Start())
|
framework.ExpectNoError(tc.Start())
|
||||||
defer tc.Close()
|
defer tc.Close()
|
||||||
@ -179,7 +179,7 @@ var _ = ginkgo.Describe("[Feature: SSH Tunnel]", func() {
|
|||||||
tc := ssh.NewTunnelClient(
|
tc := ssh.NewTunnelClient(
|
||||||
fmt.Sprintf("127.0.0.1:%d", localPort),
|
fmt.Sprintf("127.0.0.1:%d", localPort),
|
||||||
fmt.Sprintf("127.0.0.1:%d", sshPort),
|
fmt.Sprintf("127.0.0.1:%d", sshPort),
|
||||||
"stcp -n stcp-test --sk=abcdefg --allow-users=\"*\"",
|
"stcp -n stcp-test --sk=abcdefg --allow_users=\"*\"",
|
||||||
)
|
)
|
||||||
framework.ExpectNoError(tc.Start())
|
framework.ExpectNoError(tc.Start())
|
||||||
defer tc.Close()
|
defer tc.Close()
|
||||||
|
1
web/frpc/auto-imports.d.ts
vendored
1
web/frpc/auto-imports.d.ts
vendored
@ -1,7 +1,6 @@
|
|||||||
/* eslint-disable */
|
/* eslint-disable */
|
||||||
/* prettier-ignore */
|
/* prettier-ignore */
|
||||||
// @ts-nocheck
|
// @ts-nocheck
|
||||||
// noinspection JSUnusedGlobalSymbols
|
|
||||||
// Generated by unplugin-auto-import
|
// Generated by unplugin-auto-import
|
||||||
export {}
|
export {}
|
||||||
declare global {
|
declare global {
|
||||||
|
4
web/frpc/components.d.ts
vendored
4
web/frpc/components.d.ts
vendored
@ -3,9 +3,11 @@
|
|||||||
// @ts-nocheck
|
// @ts-nocheck
|
||||||
// Generated by unplugin-vue-components
|
// Generated by unplugin-vue-components
|
||||||
// Read more: https://github.com/vuejs/core/pull/3399
|
// Read more: https://github.com/vuejs/core/pull/3399
|
||||||
|
import '@vue/runtime-core'
|
||||||
|
|
||||||
export {}
|
export {}
|
||||||
|
|
||||||
declare module 'vue' {
|
declare module '@vue/runtime-core' {
|
||||||
export interface GlobalComponents {
|
export interface GlobalComponents {
|
||||||
ClientConfigure: typeof import('./src/components/ClientConfigure.vue')['default']
|
ClientConfigure: typeof import('./src/components/ClientConfigure.vue')['default']
|
||||||
ElButton: typeof import('element-plus/es')['ElButton']
|
ElButton: typeof import('element-plus/es')['ElButton']
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "frpc-dashboard",
|
"name": "-frpc-dashboard",
|
||||||
"version": "0.0.1",
|
"version": "0.0.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
@ -11,25 +11,25 @@
|
|||||||
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore"
|
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"element-plus": "^2.5.3",
|
"element-plus": "^2.3.3",
|
||||||
"vue": "^3.4.15",
|
"vue": "^3.2.47",
|
||||||
"vue-router": "^4.2.5"
|
"vue-router": "^4.1.6"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@rushstack/eslint-patch": "^1.7.2",
|
"@rushstack/eslint-patch": "^1.1.4",
|
||||||
"@types/node": "^18.11.12",
|
"@types/node": "^18.11.12",
|
||||||
"@vitejs/plugin-vue": "^5.0.3",
|
"@vitejs/plugin-vue": "^4.0.0",
|
||||||
"@vue/eslint-config-prettier": "^9.0.0",
|
"@vue/eslint-config-prettier": "^7.0.0",
|
||||||
"@vue/eslint-config-typescript": "^12.0.0",
|
"@vue/eslint-config-typescript": "^11.0.0",
|
||||||
"@vue/tsconfig": "^0.5.1",
|
"@vue/tsconfig": "^0.1.3",
|
||||||
"eslint": "^8.56.0",
|
"eslint": "^8.22.0",
|
||||||
"eslint-plugin-vue": "^9.21.0",
|
"eslint-plugin-vue": "^9.3.0",
|
||||||
"npm-run-all": "^4.1.5",
|
"npm-run-all": "^4.1.5",
|
||||||
"prettier": "^3.2.4",
|
"prettier": "^2.7.1",
|
||||||
"typescript": "~5.3.3",
|
"typescript": "~4.7.4",
|
||||||
"unplugin-auto-import": "^0.17.5",
|
"unplugin-auto-import": "^0.14.3",
|
||||||
"unplugin-vue-components": "^0.26.0",
|
"unplugin-vue-components": "^0.24.0",
|
||||||
"vite": "^5.0.12",
|
"vite": "^4.0.0",
|
||||||
"vue-tsc": "^1.8.27"
|
"vue-tsc": "^1.0.12"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
8
web/frpc/tsconfig.config.json
Normal file
8
web/frpc/tsconfig.config.json
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"extends": "@vue/tsconfig/tsconfig.node.json",
|
||||||
|
"include": ["vite.config.*", "vitest.config.*", "cypress.config.*", "playwright.config.*"],
|
||||||
|
"compilerOptions": {
|
||||||
|
"composite": true,
|
||||||
|
"types": ["node"]
|
||||||
|
}
|
||||||
|
}
|
@ -1,25 +1,16 @@
|
|||||||
{
|
{
|
||||||
|
"extends": "@vue/tsconfig/tsconfig.web.json",
|
||||||
|
"include": ["env.d.ts", "src/**/*", "src/**/*.vue"],
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"target": "ES2020",
|
"baseUrl": ".",
|
||||||
"useDefineForClassFields": true,
|
"paths": {
|
||||||
"module": "ESNext",
|
"@/*": ["./src/*"]
|
||||||
"lib": ["ES2020", "DOM", "DOM.Iterable"],
|
}
|
||||||
"skipLibCheck": true,
|
|
||||||
|
|
||||||
/* Bundler mode */
|
|
||||||
"moduleResolution": "bundler",
|
|
||||||
"allowImportingTsExtensions": true,
|
|
||||||
"resolveJsonModule": true,
|
|
||||||
"isolatedModules": true,
|
|
||||||
"noEmit": true,
|
|
||||||
"jsx": "preserve",
|
|
||||||
|
|
||||||
/* Linting */
|
|
||||||
"strict": true,
|
|
||||||
"noUnusedLocals": true,
|
|
||||||
"noUnusedParameters": true,
|
|
||||||
"noFallthroughCasesInSwitch": true
|
|
||||||
},
|
},
|
||||||
"include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue"],
|
|
||||||
"references": [{ "path": "./tsconfig.node.json" }]
|
"references": [
|
||||||
|
{
|
||||||
|
"path": "./tsconfig.config.json"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
@ -1,10 +0,0 @@
|
|||||||
{
|
|
||||||
"compilerOptions": {
|
|
||||||
"composite": true,
|
|
||||||
"skipLibCheck": true,
|
|
||||||
"module": "ESNext",
|
|
||||||
"moduleResolution": "bundler",
|
|
||||||
"allowSyntheticDefaultImports": true
|
|
||||||
},
|
|
||||||
"include": ["vite.config.ts"]
|
|
||||||
}
|
|
2126
web/frpc/yarn.lock
2126
web/frpc/yarn.lock
File diff suppressed because it is too large
Load Diff
6
web/frps/auto-imports.d.ts
vendored
6
web/frps/auto-imports.d.ts
vendored
@ -1,8 +1,4 @@
|
|||||||
/* eslint-disable */
|
// Generated by 'unplugin-auto-import'
|
||||||
/* prettier-ignore */
|
|
||||||
// @ts-nocheck
|
|
||||||
// noinspection JSUnusedGlobalSymbols
|
|
||||||
// Generated by unplugin-auto-import
|
|
||||||
export {}
|
export {}
|
||||||
declare global {
|
declare global {
|
||||||
|
|
||||||
|
12
web/frps/components.d.ts
vendored
12
web/frps/components.d.ts
vendored
@ -1,11 +1,11 @@
|
|||||||
/* eslint-disable */
|
// generated by unplugin-vue-components
|
||||||
/* prettier-ignore */
|
// We suggest you to commit this file into source control
|
||||||
// @ts-nocheck
|
|
||||||
// Generated by unplugin-vue-components
|
|
||||||
// Read more: https://github.com/vuejs/core/pull/3399
|
// Read more: https://github.com/vuejs/core/pull/3399
|
||||||
|
import '@vue/runtime-core'
|
||||||
|
|
||||||
export {}
|
export {}
|
||||||
|
|
||||||
declare module 'vue' {
|
declare module '@vue/runtime-core' {
|
||||||
export interface GlobalComponents {
|
export interface GlobalComponents {
|
||||||
ElButton: typeof import('element-plus/es')['ElButton']
|
ElButton: typeof import('element-plus/es')['ElButton']
|
||||||
ElCol: typeof import('element-plus/es')['ElCol']
|
ElCol: typeof import('element-plus/es')['ElCol']
|
||||||
@ -13,8 +13,6 @@ declare module 'vue' {
|
|||||||
ElFormItem: typeof import('element-plus/es')['ElFormItem']
|
ElFormItem: typeof import('element-plus/es')['ElFormItem']
|
||||||
ElMenu: typeof import('element-plus/es')['ElMenu']
|
ElMenu: typeof import('element-plus/es')['ElMenu']
|
||||||
ElMenuItem: typeof import('element-plus/es')['ElMenuItem']
|
ElMenuItem: typeof import('element-plus/es')['ElMenuItem']
|
||||||
ElPageHeader: typeof import('element-plus/es')['ElPageHeader']
|
|
||||||
ElPopconfirm: typeof import('element-plus/es')['ElPopconfirm']
|
|
||||||
ElPopover: typeof import('element-plus/es')['ElPopover']
|
ElPopover: typeof import('element-plus/es')['ElPopover']
|
||||||
ElRow: typeof import('element-plus/es')['ElRow']
|
ElRow: typeof import('element-plus/es')['ElRow']
|
||||||
ElSubMenu: typeof import('element-plus/es')['ElSubMenu']
|
ElSubMenu: typeof import('element-plus/es')['ElSubMenu']
|
||||||
|
@ -12,27 +12,27 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/humanize-plus": "^1.8.0",
|
"@types/humanize-plus": "^1.8.0",
|
||||||
"echarts": "^5.4.3",
|
"echarts": "^5.4.1",
|
||||||
"element-plus": "^2.5.3",
|
"element-plus": "^2.3.3",
|
||||||
"humanize-plus": "^1.8.2",
|
"humanize-plus": "^1.8.2",
|
||||||
"vue": "^3.4.15",
|
"vue": "^3.2.47",
|
||||||
"vue-router": "^4.2.5"
|
"vue-router": "^4.1.6"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@rushstack/eslint-patch": "^1.7.2",
|
"@rushstack/eslint-patch": "^1.1.4",
|
||||||
"@types/node": "^18.11.12",
|
"@types/node": "^18.11.12",
|
||||||
"@vitejs/plugin-vue": "^5.0.3",
|
"@vitejs/plugin-vue": "^4.0.0",
|
||||||
"@vue/eslint-config-prettier": "^9.0.0",
|
"@vue/eslint-config-prettier": "^7.0.0",
|
||||||
"@vue/eslint-config-typescript": "^12.0.0",
|
"@vue/eslint-config-typescript": "^11.0.0",
|
||||||
"@vue/tsconfig": "^0.5.1",
|
"@vue/tsconfig": "^0.1.3",
|
||||||
"eslint": "^8.56.0",
|
"eslint": "^8.22.0",
|
||||||
"eslint-plugin-vue": "^9.21.0",
|
"eslint-plugin-vue": "^9.3.0",
|
||||||
"npm-run-all": "^4.1.5",
|
"npm-run-all": "^4.1.5",
|
||||||
"prettier": "^3.2.4",
|
"prettier": "^2.7.1",
|
||||||
"typescript": "~5.3.3",
|
"typescript": "~4.7.4",
|
||||||
"unplugin-auto-import": "^0.17.5",
|
"unplugin-auto-import": "^0.13.0",
|
||||||
"unplugin-vue-components": "^0.26.0",
|
"unplugin-vue-components": "^0.23.0",
|
||||||
"vite": "^5.0.12",
|
"vite": "^4.0.4",
|
||||||
"vue-tsc": "^1.8.27"
|
"vue-tsc": "^1.0.12"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<ProxyView :proxies="proxies" proxyType="http" @refresh="fetchData"/>
|
<ProxyView :proxies="proxies" proxyType="http" />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
@ -27,7 +27,6 @@ const fetchData = () => {
|
|||||||
return res.json()
|
return res.json()
|
||||||
})
|
})
|
||||||
.then((json) => {
|
.then((json) => {
|
||||||
proxies.value = []
|
|
||||||
for (let proxyStats of json.proxies) {
|
for (let proxyStats of json.proxies) {
|
||||||
proxies.value.push(
|
proxies.value.push(
|
||||||
new HTTPProxy(proxyStats, vhostHTTPPort, subdomainHost)
|
new HTTPProxy(proxyStats, vhostHTTPPort, subdomainHost)
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<ProxyView :proxies="proxies" proxyType="https" @refresh="fetchData"/>
|
<ProxyView :proxies="proxies" proxyType="https" />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
@ -27,7 +27,6 @@ const fetchData = () => {
|
|||||||
return res.json()
|
return res.json()
|
||||||
})
|
})
|
||||||
.then((json) => {
|
.then((json) => {
|
||||||
proxies.value = []
|
|
||||||
for (let proxyStats of json.proxies) {
|
for (let proxyStats of json.proxies) {
|
||||||
proxies.value.push(
|
proxies.value.push(
|
||||||
new HTTPSProxy(proxyStats, vhostHTTPSPort, subdomainHost)
|
new HTTPSProxy(proxyStats, vhostHTTPSPort, subdomainHost)
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<ProxyView :proxies="proxies" proxyType="stcp" @refresh="fetchData"/>
|
<ProxyView :proxies="proxies" proxyType="stcp" />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
@ -15,7 +15,6 @@ const fetchData = () => {
|
|||||||
return res.json()
|
return res.json()
|
||||||
})
|
})
|
||||||
.then((json) => {
|
.then((json) => {
|
||||||
proxies.value = []
|
|
||||||
for (let proxyStats of json.proxies) {
|
for (let proxyStats of json.proxies) {
|
||||||
proxies.value.push(new STCPProxy(proxyStats))
|
proxies.value.push(new STCPProxy(proxyStats))
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<ProxyView :proxies="proxies" proxyType="sudp" @refresh="fetchData"/>
|
<ProxyView :proxies="proxies" proxyType="sudp" />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
@ -15,7 +15,6 @@ const fetchData = () => {
|
|||||||
return res.json()
|
return res.json()
|
||||||
})
|
})
|
||||||
.then((json) => {
|
.then((json) => {
|
||||||
proxies.value = []
|
|
||||||
for (let proxyStats of json.proxies) {
|
for (let proxyStats of json.proxies) {
|
||||||
proxies.value.push(new SUDPProxy(proxyStats))
|
proxies.value.push(new SUDPProxy(proxyStats))
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<ProxyView :proxies="proxies" proxyType="tcp" @refresh="fetchData" />
|
<ProxyView :proxies="proxies" proxyType="tcp" />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
@ -15,7 +15,6 @@ const fetchData = () => {
|
|||||||
return res.json()
|
return res.json()
|
||||||
})
|
})
|
||||||
.then((json) => {
|
.then((json) => {
|
||||||
proxies.value = []
|
|
||||||
for (let proxyStats of json.proxies) {
|
for (let proxyStats of json.proxies) {
|
||||||
proxies.value.push(new TCPProxy(proxyStats))
|
proxies.value.push(new TCPProxy(proxyStats))
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<ProxyView :proxies="proxies" proxyType="udp" @refresh="fetchData"/>
|
<ProxyView :proxies="proxies" proxyType="udp" />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
@ -15,12 +15,12 @@ const fetchData = () => {
|
|||||||
return res.json()
|
return res.json()
|
||||||
})
|
})
|
||||||
.then((json) => {
|
.then((json) => {
|
||||||
proxies.value = []
|
|
||||||
for (let proxyStats of json.proxies) {
|
for (let proxyStats of json.proxies) {
|
||||||
proxies.value.push(new UDPProxy(proxyStats))
|
proxies.value.push(new UDPProxy(proxyStats))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fetchData()
|
fetchData()
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -1,28 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<el-page-header
|
|
||||||
:icon="null"
|
|
||||||
style="width: 100%; margin-left: 30px; margin-bottom: 20px"
|
|
||||||
>
|
|
||||||
<template #title>
|
|
||||||
<span>{{ proxyType }}</span>
|
|
||||||
</template>
|
|
||||||
<template #content> </template>
|
|
||||||
<template #extra>
|
|
||||||
<div class="flex items-center" style="margin-right: 30px">
|
|
||||||
<el-popconfirm
|
|
||||||
title="Are you sure to clear all data of offline proxies?"
|
|
||||||
@confirm="clearOfflineProxies"
|
|
||||||
>
|
|
||||||
<template #reference>
|
|
||||||
<el-button>ClearOfflineProxies</el-button>
|
|
||||||
</template>
|
|
||||||
</el-popconfirm>
|
|
||||||
<el-button @click="$emit('refresh')">Refresh</el-button>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</el-page-header>
|
|
||||||
|
|
||||||
<el-table
|
<el-table
|
||||||
:data="proxies"
|
:data="proxies"
|
||||||
:default-sort="{ prop: 'name', order: 'ascending' }"
|
:default-sort="{ prop: 'name', order: 'ascending' }"
|
||||||
@ -90,7 +67,6 @@
|
|||||||
import * as Humanize from 'humanize-plus'
|
import * as Humanize from 'humanize-plus'
|
||||||
import type { TableColumnCtx } from 'element-plus'
|
import type { TableColumnCtx } from 'element-plus'
|
||||||
import type { BaseProxy } from '../utils/proxy.js'
|
import type { BaseProxy } from '../utils/proxy.js'
|
||||||
import { ElMessage } from 'element-plus'
|
|
||||||
import ProxyViewExpand from './ProxyViewExpand.vue'
|
import ProxyViewExpand from './ProxyViewExpand.vue'
|
||||||
|
|
||||||
defineProps<{
|
defineProps<{
|
||||||
@ -98,8 +74,6 @@ defineProps<{
|
|||||||
proxyType: string
|
proxyType: string
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const emit = defineEmits(['refresh'])
|
|
||||||
|
|
||||||
const formatTrafficIn = (row: BaseProxy, _: TableColumnCtx<BaseProxy>) => {
|
const formatTrafficIn = (row: BaseProxy, _: TableColumnCtx<BaseProxy>) => {
|
||||||
return Humanize.fileSize(row.trafficIn)
|
return Humanize.fileSize(row.trafficIn)
|
||||||
}
|
}
|
||||||
@ -107,37 +81,4 @@ const formatTrafficIn = (row: BaseProxy, _: TableColumnCtx<BaseProxy>) => {
|
|||||||
const formatTrafficOut = (row: BaseProxy, _: TableColumnCtx<BaseProxy>) => {
|
const formatTrafficOut = (row: BaseProxy, _: TableColumnCtx<BaseProxy>) => {
|
||||||
return Humanize.fileSize(row.trafficOut)
|
return Humanize.fileSize(row.trafficOut)
|
||||||
}
|
}
|
||||||
|
|
||||||
const clearOfflineProxies = () => {
|
|
||||||
fetch('/api/proxies?status=offline', {
|
|
||||||
method: 'DELETE',
|
|
||||||
credentials: 'include',
|
|
||||||
})
|
|
||||||
.then((res) => {
|
|
||||||
if (res.ok) {
|
|
||||||
ElMessage({
|
|
||||||
message: 'Successfully cleared offline proxies',
|
|
||||||
type: 'success',
|
|
||||||
})
|
|
||||||
emit('refresh')
|
|
||||||
} else {
|
|
||||||
ElMessage({
|
|
||||||
message: 'Failed to clear offline proxies: ' + res.status + ' ' + res.statusText,
|
|
||||||
type: 'warning',
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
ElMessage({
|
|
||||||
message: 'Failed to clear offline proxies: ' + err.message,
|
|
||||||
type: 'warning',
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
|
||||||
.el-page-header__title {
|
|
||||||
font-size: 20px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
@ -17,7 +17,10 @@
|
|||||||
<el-form-item label="KCP Bind Port" v-if="data.kcpBindPort != 0">
|
<el-form-item label="KCP Bind Port" v-if="data.kcpBindPort != 0">
|
||||||
<span>{{ data.kcpBindPort }}</span>
|
<span>{{ data.kcpBindPort }}</span>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="QUIC Bind Port" v-if="data.quicBindPort != 0">
|
<el-form-item
|
||||||
|
label="QUIC Bind Port"
|
||||||
|
v-if="data.quicBindPort != 0"
|
||||||
|
>
|
||||||
<span>{{ data.quicBindPort }}</span>
|
<span>{{ data.quicBindPort }}</span>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="Http Port" v-if="data.vhostHTTPPort != 0">
|
<el-form-item label="Http Port" v-if="data.vhostHTTPPort != 0">
|
||||||
|
@ -23,10 +23,8 @@ class BaseProxy {
|
|||||||
this.type = ''
|
this.type = ''
|
||||||
this.encryption = false
|
this.encryption = false
|
||||||
this.compression = false
|
this.compression = false
|
||||||
this.encryption =
|
this.encryption = (proxyStats.conf?.transport?.useEncryption) || this.encryption;
|
||||||
proxyStats.conf?.transport?.useEncryption || this.encryption
|
this.compression = (proxyStats.conf?.transport?.useCompression) || this.compression;
|
||||||
this.compression =
|
|
||||||
proxyStats.conf?.transport?.useCompression || this.compression
|
|
||||||
this.conns = proxyStats.curConns
|
this.conns = proxyStats.curConns
|
||||||
this.trafficIn = proxyStats.todayTrafficIn
|
this.trafficIn = proxyStats.todayTrafficIn
|
||||||
this.trafficOut = proxyStats.todayTrafficOut
|
this.trafficOut = proxyStats.todayTrafficOut
|
||||||
@ -78,7 +76,7 @@ class HTTPProxy extends BaseProxy {
|
|||||||
this.type = 'http'
|
this.type = 'http'
|
||||||
this.port = port
|
this.port = port
|
||||||
if (proxyStats.conf) {
|
if (proxyStats.conf) {
|
||||||
this.customDomains = proxyStats.conf.customDomains || this.customDomains
|
this.customDomains = proxyStats.conf.customDomains || this.customDomains;
|
||||||
this.hostHeaderRewrite = proxyStats.conf.hostHeaderRewrite
|
this.hostHeaderRewrite = proxyStats.conf.hostHeaderRewrite
|
||||||
this.locations = proxyStats.conf.locations
|
this.locations = proxyStats.conf.locations
|
||||||
if (proxyStats.conf.subdomain) {
|
if (proxyStats.conf.subdomain) {
|
||||||
@ -94,7 +92,7 @@ class HTTPSProxy extends BaseProxy {
|
|||||||
this.type = 'https'
|
this.type = 'https'
|
||||||
this.port = port
|
this.port = port
|
||||||
if (proxyStats.conf != null) {
|
if (proxyStats.conf != null) {
|
||||||
this.customDomains = proxyStats.conf.customDomains || this.customDomains
|
this.customDomains = proxyStats.conf.customDomains || this.customDomains;
|
||||||
if (proxyStats.conf.subdomain) {
|
if (proxyStats.conf.subdomain) {
|
||||||
this.subdomain = `${proxyStats.conf.subdomain}.${subdomainHost}`
|
this.subdomain = `${proxyStats.conf.subdomain}.${subdomainHost}`
|
||||||
}
|
}
|
||||||
|
8
web/frps/tsconfig.config.json
Normal file
8
web/frps/tsconfig.config.json
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"extends": "@vue/tsconfig/tsconfig.node.json",
|
||||||
|
"include": ["vite.config.*", "vitest.config.*", "cypress.config.*", "playwright.config.*"],
|
||||||
|
"compilerOptions": {
|
||||||
|
"composite": true,
|
||||||
|
"types": ["node"]
|
||||||
|
}
|
||||||
|
}
|
@ -1,25 +1,16 @@
|
|||||||
{
|
{
|
||||||
|
"extends": "@vue/tsconfig/tsconfig.web.json",
|
||||||
|
"include": ["env.d.ts", "src/**/*", "src/**/*.vue"],
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"target": "ES2020",
|
"baseUrl": ".",
|
||||||
"useDefineForClassFields": true,
|
"paths": {
|
||||||
"module": "ESNext",
|
"@/*": ["./src/*"]
|
||||||
"lib": ["ES2020", "DOM", "DOM.Iterable"],
|
}
|
||||||
"skipLibCheck": true,
|
|
||||||
|
|
||||||
/* Bundler mode */
|
|
||||||
"moduleResolution": "bundler",
|
|
||||||
"allowImportingTsExtensions": true,
|
|
||||||
"resolveJsonModule": true,
|
|
||||||
"isolatedModules": true,
|
|
||||||
"noEmit": true,
|
|
||||||
"jsx": "preserve",
|
|
||||||
|
|
||||||
/* Linting */
|
|
||||||
"strict": true,
|
|
||||||
"noUnusedLocals": true,
|
|
||||||
"noUnusedParameters": true,
|
|
||||||
"noFallthroughCasesInSwitch": true
|
|
||||||
},
|
},
|
||||||
"include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue"],
|
|
||||||
"references": [{ "path": "./tsconfig.node.json" }]
|
"references": [
|
||||||
|
{
|
||||||
|
"path": "./tsconfig.config.json"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
@ -1,10 +0,0 @@
|
|||||||
{
|
|
||||||
"compilerOptions": {
|
|
||||||
"composite": true,
|
|
||||||
"skipLibCheck": true,
|
|
||||||
"module": "ESNext",
|
|
||||||
"moduleResolution": "bundler",
|
|
||||||
"allowSyntheticDefaultImports": true
|
|
||||||
},
|
|
||||||
"include": ["vite.config.ts"]
|
|
||||||
}
|
|
2225
web/frps/yarn.lock
2225
web/frps/yarn.lock
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user