mirror of
https://github.com/fatedier/frp.git
synced 2025-08-02 12:07:20 +00:00
Compare commits
26 Commits
v0.55.1
...
65f74199de
Author | SHA1 | Date | |
---|---|---|---|
|
65f74199de | ||
|
d0d396becb | ||
|
ee3892798d | ||
|
405969085f | ||
|
c1893ee1b4 | ||
|
eaae212d2d | ||
|
885278c045 | ||
|
2626d6ed92 | ||
|
f3a71bc08f | ||
|
dd7e2e8473 | ||
|
07946e9752 | ||
|
e52727e01c | ||
|
ba937e9fbf | ||
|
d2d03a8fd9 | ||
|
590ccda677 | ||
|
86f90f4d27 | ||
|
f16ef00975 | ||
|
b36f3834eb | ||
|
c08be0fd92 | ||
|
bc5fb91c05 | ||
|
002831ea82 | ||
|
acf33db4e4 | ||
|
3585f5c0c0 | ||
|
8383d528d9 | ||
|
fa977c839f | ||
|
86c2ad78c8 |
2
.github/workflows/golangci-lint.yml
vendored
2
.github/workflows/golangci-lint.yml
vendored
@@ -23,7 +23,7 @@ jobs:
|
|||||||
uses: golangci/golangci-lint-action@v4
|
uses: golangci/golangci-lint-action@v4
|
||||||
with:
|
with:
|
||||||
# Optional: version of golangci-lint to use in form of v1.2 or v1.2.3 or `latest` to use the latest version
|
# Optional: version of golangci-lint to use in form of v1.2 or v1.2.3 or `latest` to use the latest version
|
||||||
version: v1.56
|
version: v1.57
|
||||||
|
|
||||||
# Optional: golangci-lint command line arguments.
|
# Optional: golangci-lint command line arguments.
|
||||||
# args: --issues-exit-code=0
|
# args: --issues-exit-code=0
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
service:
|
service:
|
||||||
golangci-lint-version: 1.56.x # use the fixed version to not introduce new linters unexpectedly
|
golangci-lint-version: 1.57.x # use the fixed version to not introduce new linters unexpectedly
|
||||||
|
|
||||||
run:
|
run:
|
||||||
concurrency: 4
|
concurrency: 4
|
||||||
# timeout for analysis, e.g. 30s, 5m, default is 1m
|
# timeout for analysis, e.g. 30s, 5m, default is 1m
|
||||||
@@ -8,23 +8,6 @@ run:
|
|||||||
build-tags:
|
build-tags:
|
||||||
- integ
|
- integ
|
||||||
- integfuzz
|
- integfuzz
|
||||||
# which dirs to skip: they won't be analyzed;
|
|
||||||
# can use regexp here: generated.*, regexp is applied on full path;
|
|
||||||
# default value is empty list, but next dirs are always skipped independently
|
|
||||||
# from this option's value:
|
|
||||||
# vendor$, third_party$, testdata$, examples$, Godeps$, builtin$
|
|
||||||
skip-dirs:
|
|
||||||
- genfiles$
|
|
||||||
- vendor$
|
|
||||||
- bin$
|
|
||||||
|
|
||||||
# which files to skip: they will be analyzed, but issues from them
|
|
||||||
# won't be reported. Default value is empty list, but there is
|
|
||||||
# no need to include all autogenerated files, we confidently recognize
|
|
||||||
# autogenerated files. If it's not please let us know.
|
|
||||||
skip-files:
|
|
||||||
- ".*\\.pb\\.go"
|
|
||||||
- ".*\\.gen\\.go"
|
|
||||||
|
|
||||||
linters:
|
linters:
|
||||||
disable-all: true
|
disable-all: true
|
||||||
@@ -103,12 +86,8 @@ linters-settings:
|
|||||||
severity: "low"
|
severity: "low"
|
||||||
confidence: "low"
|
confidence: "low"
|
||||||
excludes:
|
excludes:
|
||||||
- G102
|
|
||||||
- G112
|
|
||||||
- G306
|
|
||||||
- G401
|
- G401
|
||||||
- G402
|
- G402
|
||||||
- G404
|
|
||||||
- G501
|
- G501
|
||||||
|
|
||||||
issues:
|
issues:
|
||||||
@@ -136,6 +115,14 @@ issues:
|
|||||||
- unparam
|
- unparam
|
||||||
text: "is always false"
|
text: "is always false"
|
||||||
|
|
||||||
|
exclude-dirs:
|
||||||
|
- genfiles$
|
||||||
|
- vendor$
|
||||||
|
- bin$
|
||||||
|
exclude-files:
|
||||||
|
- ".*\\.pb\\.go"
|
||||||
|
- ".*\\.gen\\.go"
|
||||||
|
|
||||||
# Independently from option `exclude` we use default exclude patterns,
|
# Independently from option `exclude` we use default exclude patterns,
|
||||||
# it can be disabled by this option. To list all
|
# it can be disabled by this option. To list all
|
||||||
# excluded by default patterns execute `golangci-lint run --help`.
|
# excluded by default patterns execute `golangci-lint run --help`.
|
||||||
|
@@ -2,22 +2,34 @@ export PATH := $(PATH):`go env GOPATH`/bin
|
|||||||
export GO111MODULE=on
|
export GO111MODULE=on
|
||||||
LDFLAGS := -s -w
|
LDFLAGS := -s -w
|
||||||
|
|
||||||
os-archs=darwin:amd64 darwin:arm64 freebsd:amd64 linux:amd64 linux:arm linux:arm64 windows:amd64 windows:arm64 linux:mips64 linux:mips64le linux:mips:softfloat linux:mipsle:softfloat linux:riscv64
|
os-archs=darwin:amd64 darwin:arm64 freebsd:amd64 linux:amd64 linux:arm:7 linux:arm:5 linux:arm64 windows:amd64 windows:arm64 linux:mips64 linux:mips64le linux:mips:softfloat linux:mipsle:softfloat linux:riscv64 android:arm64
|
||||||
|
|
||||||
all: build
|
all: build
|
||||||
|
|
||||||
build: app
|
build: app
|
||||||
|
|
||||||
app:
|
app:
|
||||||
@$(foreach n, $(os-archs),\
|
@$(foreach n, $(os-archs), \
|
||||||
os=$(shell echo "$(n)" | cut -d : -f 1);\
|
os=$(shell echo "$(n)" | cut -d : -f 1); \
|
||||||
arch=$(shell echo "$(n)" | cut -d : -f 2);\
|
arch=$(shell echo "$(n)" | cut -d : -f 2); \
|
||||||
gomips=$(shell echo "$(n)" | cut -d : -f 3);\
|
extra=$(shell echo "$(n)" | cut -d : -f 3); \
|
||||||
target_suffix=$${os}_$${arch};\
|
flags=''; \
|
||||||
echo "Build $${os}-$${arch}...";\
|
target_suffix=$${os}_$${arch}; \
|
||||||
env CGO_ENABLED=0 GOOS=$${os} GOARCH=$${arch} GOMIPS=$${gomips} go build -trimpath -ldflags "$(LDFLAGS)" -tags frpc -o ./release/frpc_$${target_suffix} ./cmd/frpc;\
|
if [ "$${os}" = "linux" ] && [ "$${arch}" = "arm" ] && [ "$${extra}" != "" ] ; then \
|
||||||
env CGO_ENABLED=0 GOOS=$${os} GOARCH=$${arch} GOMIPS=$${gomips} go build -trimpath -ldflags "$(LDFLAGS)" -tags frps -o ./release/frps_$${target_suffix} ./cmd/frps;\
|
if [ "$${extra}" = "7" ]; then \
|
||||||
echo "Build $${os}-$${arch} done";\
|
flags=GOARM=7; \
|
||||||
|
target_suffix=$${os}_arm_hf; \
|
||||||
|
elif [ "$${extra}" = "5" ]; then \
|
||||||
|
flags=GOARM=5; \
|
||||||
|
target_suffix=$${os}_arm; \
|
||||||
|
fi; \
|
||||||
|
elif [ "$${os}" = "linux" ] && ([ "$${arch}" = "mips" ] || [ "$${arch}" = "mipsle" ]) && [ "$${extra}" != "" ] ; then \
|
||||||
|
flags=GOMIPS=$${extra}; \
|
||||||
|
fi; \
|
||||||
|
echo "Build $${os}-$${arch}$${extra:+ ($${extra})}..."; \
|
||||||
|
env CGO_ENABLED=0 GOOS=$${os} GOARCH=$${arch} $${flags} go build -trimpath -ldflags "$(LDFLAGS)" -tags frpc -o ./release/frpc_$${target_suffix} ./cmd/frpc; \
|
||||||
|
env CGO_ENABLED=0 GOOS=$${os} GOARCH=$${arch} $${flags} go build -trimpath -ldflags "$(LDFLAGS)" -tags frps -o ./release/frps_$${target_suffix} ./cmd/frps; \
|
||||||
|
echo "Build $${os}-$${arch}$${extra:+ ($${extra})} done"; \
|
||||||
)
|
)
|
||||||
@mv ./release/frpc_windows_amd64 ./release/frpc_windows_amd64.exe
|
@mv ./release/frpc_windows_amd64 ./release/frpc_windows_amd64.exe
|
||||||
@mv ./release/frps_windows_amd64 ./release/frps_windows_amd64.exe
|
@mv ./release/frps_windows_amd64 ./release/frps_windows_amd64.exe
|
||||||
|
35
README.md
35
README.md
@@ -78,9 +78,11 @@ frp also offers a P2P connect mode.
|
|||||||
* [URL Routing](#url-routing)
|
* [URL Routing](#url-routing)
|
||||||
* [TCP Port Multiplexing](#tcp-port-multiplexing)
|
* [TCP Port Multiplexing](#tcp-port-multiplexing)
|
||||||
* [Connecting to frps via PROXY](#connecting-to-frps-via-proxy)
|
* [Connecting to frps via PROXY](#connecting-to-frps-via-proxy)
|
||||||
|
* [Port range mapping](#port-range-mapping)
|
||||||
* [Client Plugins](#client-plugins)
|
* [Client Plugins](#client-plugins)
|
||||||
* [Server Manage Plugins](#server-manage-plugins)
|
* [Server Manage Plugins](#server-manage-plugins)
|
||||||
* [SSH Tunnel Gateway](#ssh-tunnel-gateway)
|
* [SSH Tunnel Gateway](#ssh-tunnel-gateway)
|
||||||
|
* [Releated Projects](#releated-projects)
|
||||||
* [Contributing](#contributing)
|
* [Contributing](#contributing)
|
||||||
* [Donation](#donation)
|
* [Donation](#donation)
|
||||||
* [GitHub Sponsors](#github-sponsors)
|
* [GitHub Sponsors](#github-sponsors)
|
||||||
@@ -350,7 +352,6 @@ You may substitute `https2https` for the plugin, and point the `localAddr` to a
|
|||||||
# frpc.toml
|
# frpc.toml
|
||||||
serverAddr = "x.x.x.x"
|
serverAddr = "x.x.x.x"
|
||||||
serverPort = 7000
|
serverPort = 7000
|
||||||
vhostHTTPSPort = 443
|
|
||||||
|
|
||||||
[[proxies]]
|
[[proxies]]
|
||||||
name = "test_https2http"
|
name = "test_https2http"
|
||||||
@@ -803,7 +804,7 @@ You can disable this feature by modify `frps.toml` and `frpc.toml`:
|
|||||||
|
|
||||||
```toml
|
```toml
|
||||||
# frps.toml and frpc.toml, must be same
|
# frps.toml and frpc.toml, must be same
|
||||||
tcpMux = false
|
transport.tcpMux = false
|
||||||
```
|
```
|
||||||
|
|
||||||
### Support KCP Protocol
|
### Support KCP Protocol
|
||||||
@@ -982,7 +983,7 @@ The HTTP request will have the `Host` header rewritten to `Host: dev.example.com
|
|||||||
|
|
||||||
### Setting other HTTP Headers
|
### Setting other HTTP Headers
|
||||||
|
|
||||||
Similar to `Host`, You can override other HTTP request headers with proxy type `http`.
|
Similar to `Host`, You can override other HTTP request and response headers with proxy type `http`.
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
# frpc.toml
|
# frpc.toml
|
||||||
@@ -994,15 +995,16 @@ localPort = 80
|
|||||||
customDomains = ["test.example.com"]
|
customDomains = ["test.example.com"]
|
||||||
hostHeaderRewrite = "dev.example.com"
|
hostHeaderRewrite = "dev.example.com"
|
||||||
requestHeaders.set.x-from-where = "frp"
|
requestHeaders.set.x-from-where = "frp"
|
||||||
|
responseHeaders.set.foo = "bar"
|
||||||
```
|
```
|
||||||
|
|
||||||
In this example, it will set header `x-from-where: frp` in the HTTP request.
|
In this example, it will set header `x-from-where: frp` in the HTTP request and `foo: bar` in the HTTP response.
|
||||||
|
|
||||||
### Get Real IP
|
### Get Real IP
|
||||||
|
|
||||||
#### HTTP X-Forwarded-For
|
#### HTTP X-Forwarded-For
|
||||||
|
|
||||||
This feature is for http proxy only.
|
This feature is for `http` proxies or proxies with the `https2http` and `https2https` plugins enabled.
|
||||||
|
|
||||||
You can get user's real IP from HTTP request headers `X-Forwarded-For`.
|
You can get user's real IP from HTTP request headers `X-Forwarded-For`.
|
||||||
|
|
||||||
@@ -1158,6 +1160,24 @@ serverPort = 7000
|
|||||||
transport.proxyURL = "http://user:pwd@192.168.1.128:8080"
|
transport.proxyURL = "http://user:pwd@192.168.1.128:8080"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Port range mapping
|
||||||
|
|
||||||
|
*Added in v0.56.0*
|
||||||
|
|
||||||
|
We can use the range syntax of Go template combined with the built-in `parseNumberRangePair` function to achieve port range mapping.
|
||||||
|
|
||||||
|
The following example, when run, will create 8 proxies named `test-6000, test-6001 ... test-6007`, each mapping the remote port to the local port.
|
||||||
|
|
||||||
|
```
|
||||||
|
{{- range $_, $v := parseNumberRangePair "6000-6006,6007" "6000-6006,6007" }}
|
||||||
|
[[proxies]]
|
||||||
|
name = "tcp-{{ $v.First }}"
|
||||||
|
type = "tcp"
|
||||||
|
localPort = {{ $v.First }}
|
||||||
|
remotePort = {{ $v.Second }}
|
||||||
|
{{- end }}
|
||||||
|
```
|
||||||
|
|
||||||
### Client Plugins
|
### Client Plugins
|
||||||
|
|
||||||
frpc only forwards requests to local TCP or UDP ports by default.
|
frpc only forwards requests to local TCP or UDP ports by default.
|
||||||
@@ -1225,6 +1245,11 @@ frpc tcp --proxy_name "test-tcp" --local_ip 127.0.0.1 --local_port 8080 --remote
|
|||||||
|
|
||||||
Please refer to this [document](/doc/ssh_tunnel_gateway.md) for more information.
|
Please refer to this [document](/doc/ssh_tunnel_gateway.md) for more information.
|
||||||
|
|
||||||
|
## Releated Projects
|
||||||
|
|
||||||
|
* [gofrp/plugin](https://github.com/gofrp/plugin) - A repository for frp plugins that contains a variety of plugins implemented based on the frp extension mechanism, meeting the customization needs of different scenarios.
|
||||||
|
* [gofrp/tiny-frpc](https://github.com/gofrp/tiny-frpc) - A lightweight version of the frp client (around 3.5MB at minimum) implemented using the ssh protocol, supporting some of the most commonly used features, suitable for devices with limited resources.
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
Interested in getting involved? We would like to help you!
|
Interested in getting involved? We would like to help you!
|
||||||
|
11
README_zh.md
11
README_zh.md
@@ -72,7 +72,12 @@ frp 是一个免费且开源的项目,我们欢迎任何人为其开发和进
|
|||||||
* 贡献代码请提交 PR 至 dev 分支,master 分支仅用于发布稳定可用版本。
|
* 贡献代码请提交 PR 至 dev 分支,master 分支仅用于发布稳定可用版本。
|
||||||
* 如果你有任何其他方面的问题或合作,欢迎发送邮件至 fatedier@gmail.com 。
|
* 如果你有任何其他方面的问题或合作,欢迎发送邮件至 fatedier@gmail.com 。
|
||||||
|
|
||||||
**提醒:和项目相关的问题最好在 [issues](https://github.com/fatedier/frp/issues) 中反馈,这样方便其他有类似问题的人可以快速查找解决方法,并且也避免了我们重复回答一些问题。**
|
**提醒:和项目相关的问题请在 [issues](https://github.com/fatedier/frp/issues) 中反馈,这样方便其他有类似问题的人可以快速查找解决方法,并且也避免了我们重复回答一些问题。**
|
||||||
|
|
||||||
|
## 关联项目
|
||||||
|
|
||||||
|
* [gofrp/plugin](https://github.com/gofrp/plugin) - frp 插件仓库,收录了基于 frp 扩展机制实现的各种插件,满足各种场景下的定制化需求。
|
||||||
|
* [gofrp/tiny-frpc](https://github.com/gofrp/tiny-frpc) - 基于 ssh 协议实现的 frp 客户端的精简版本(最低约 3.5MB 左右),支持常用的部分功能,适用于资源有限的设备。
|
||||||
|
|
||||||
## 赞助
|
## 赞助
|
||||||
|
|
||||||
@@ -93,7 +98,3 @@ frp 是一个免费且开源的项目,我们欢迎任何人为其开发和进
|
|||||||
如果您想了解更多 frp 相关技术以及更新详解,或者寻求任何 frp 使用方面的帮助,都可以通过微信扫描下方的二维码付费加入知识星球的官方社群:
|
如果您想了解更多 frp 相关技术以及更新详解,或者寻求任何 frp 使用方面的帮助,都可以通过微信扫描下方的二维码付费加入知识星球的官方社群:
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
### 微信支付捐赠
|
|
||||||
|
|
||||||

|
|
||||||
|
15
Release.md
15
Release.md
@@ -1 +1,14 @@
|
|||||||
No feature changes, just a fix for the issue of no released assets in version 0.55.0.
|
### Notable Changes
|
||||||
|
|
||||||
|
We have optimized the heartbeat mechanism when tcpmux is enabled (enabled by default). The default value of `heartbeatInterval` has been adjusted to -1. This update ensures that when tcpmux is active, the client does not send additional heartbeats to the server. Since tcpmux incorporates its own heartbeat system, this change effectively reduces unnecessary data consumption, streamlining communication efficiency between client and server.
|
||||||
|
|
||||||
|
When connecting to frps versions older than v0.39.0 might encounter compatibility issues due to changes in the heartbeat mechanism. As a temporary workaround, setting the `heartbeatInterval` to 30 can help maintain stable connectivity with these older versions. We recommend updating to the latest frps version to leverage full functionality and improvements.
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* Show tcpmux proxies on the frps dashboard.
|
||||||
|
* `http` proxy can modify the response header. For example, `responseHeaders.set.foo = "bar"` will add a new header `foo: bar` to the response.
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
|
||||||
|
* When an HTTP proxy request times out, it returns 504 instead of 404 now.
|
||||||
|
File diff suppressed because one or more lines are too long
@@ -4,7 +4,7 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<title>frps dashboard</title>
|
<title>frps dashboard</title>
|
||||||
<script type="module" crossorigin src="./index-Q42Pu2_S.js"></script>
|
<script type="module" crossorigin src="./index-82-40HIG.js"></script>
|
||||||
<link rel="stylesheet" crossorigin href="./index-rzPDshRD.css">
|
<link rel="stylesheet" crossorigin href="./index-rzPDshRD.css">
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
|
@@ -253,7 +253,7 @@ func (svr *Service) apiPutConfig(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := os.WriteFile(svr.configFilePath, body, 0o644); err != nil {
|
if err := os.WriteFile(svr.configFilePath, body, 0o600); err != nil {
|
||||||
res.Code = 500
|
res.Code = 500
|
||||||
res.Msg = fmt.Sprintf("write content to frpc config file error: %v", err)
|
res.Msg = fmt.Sprintf("write content to frpc config file error: %v", err)
|
||||||
log.Warnf("%s", res.Msg)
|
log.Warnf("%s", res.Msg)
|
||||||
|
@@ -24,7 +24,7 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
libdial "github.com/fatedier/golib/net/dial"
|
libnet "github.com/fatedier/golib/net"
|
||||||
fmux "github.com/hashicorp/yamux"
|
fmux "github.com/hashicorp/yamux"
|
||||||
quic "github.com/quic-go/quic-go"
|
quic "github.com/quic-go/quic-go"
|
||||||
"github.com/samber/lo"
|
"github.com/samber/lo"
|
||||||
@@ -169,44 +169,44 @@ func (c *defaultConnectorImpl) realConnect() (net.Conn, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
proxyType, addr, auth, err := libdial.ParseProxyURL(c.cfg.Transport.ProxyURL)
|
proxyType, addr, auth, err := libnet.ParseProxyURL(c.cfg.Transport.ProxyURL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
xl.Errorf("fail to parse proxy url")
|
xl.Errorf("fail to parse proxy url")
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
dialOptions := []libdial.DialOption{}
|
dialOptions := []libnet.DialOption{}
|
||||||
protocol := c.cfg.Transport.Protocol
|
protocol := c.cfg.Transport.Protocol
|
||||||
switch protocol {
|
switch protocol {
|
||||||
case "websocket":
|
case "websocket":
|
||||||
protocol = "tcp"
|
protocol = "tcp"
|
||||||
dialOptions = append(dialOptions, libdial.WithAfterHook(libdial.AfterHook{Hook: netpkg.DialHookWebsocket(protocol, "")}))
|
dialOptions = append(dialOptions, libnet.WithAfterHook(libnet.AfterHook{Hook: netpkg.DialHookWebsocket(protocol, "")}))
|
||||||
dialOptions = append(dialOptions, libdial.WithAfterHook(libdial.AfterHook{
|
dialOptions = append(dialOptions, libnet.WithAfterHook(libnet.AfterHook{
|
||||||
Hook: netpkg.DialHookCustomTLSHeadByte(tlsConfig != nil, lo.FromPtr(c.cfg.Transport.TLS.DisableCustomTLSFirstByte)),
|
Hook: netpkg.DialHookCustomTLSHeadByte(tlsConfig != nil, lo.FromPtr(c.cfg.Transport.TLS.DisableCustomTLSFirstByte)),
|
||||||
}))
|
}))
|
||||||
dialOptions = append(dialOptions, libdial.WithTLSConfig(tlsConfig))
|
dialOptions = append(dialOptions, libnet.WithTLSConfig(tlsConfig))
|
||||||
case "wss":
|
case "wss":
|
||||||
protocol = "tcp"
|
protocol = "tcp"
|
||||||
dialOptions = append(dialOptions, libdial.WithTLSConfigAndPriority(100, tlsConfig))
|
dialOptions = append(dialOptions, libnet.WithTLSConfigAndPriority(100, tlsConfig))
|
||||||
// Make sure that if it is wss, the websocket hook is executed after the tls hook.
|
// Make sure that if it is wss, the websocket hook is executed after the tls hook.
|
||||||
dialOptions = append(dialOptions, libdial.WithAfterHook(libdial.AfterHook{Hook: netpkg.DialHookWebsocket(protocol, tlsConfig.ServerName), Priority: 110}))
|
dialOptions = append(dialOptions, libnet.WithAfterHook(libnet.AfterHook{Hook: netpkg.DialHookWebsocket(protocol, tlsConfig.ServerName), Priority: 110}))
|
||||||
default:
|
default:
|
||||||
dialOptions = append(dialOptions, libdial.WithAfterHook(libdial.AfterHook{
|
dialOptions = append(dialOptions, libnet.WithAfterHook(libnet.AfterHook{
|
||||||
Hook: netpkg.DialHookCustomTLSHeadByte(tlsConfig != nil, lo.FromPtr(c.cfg.Transport.TLS.DisableCustomTLSFirstByte)),
|
Hook: netpkg.DialHookCustomTLSHeadByte(tlsConfig != nil, lo.FromPtr(c.cfg.Transport.TLS.DisableCustomTLSFirstByte)),
|
||||||
}))
|
}))
|
||||||
dialOptions = append(dialOptions, libdial.WithTLSConfig(tlsConfig))
|
dialOptions = append(dialOptions, libnet.WithTLSConfig(tlsConfig))
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.cfg.Transport.ConnectServerLocalIP != "" {
|
if c.cfg.Transport.ConnectServerLocalIP != "" {
|
||||||
dialOptions = append(dialOptions, libdial.WithLocalAddr(c.cfg.Transport.ConnectServerLocalIP))
|
dialOptions = append(dialOptions, libnet.WithLocalAddr(c.cfg.Transport.ConnectServerLocalIP))
|
||||||
}
|
}
|
||||||
dialOptions = append(dialOptions,
|
dialOptions = append(dialOptions,
|
||||||
libdial.WithProtocol(protocol),
|
libnet.WithProtocol(protocol),
|
||||||
libdial.WithTimeout(time.Duration(c.cfg.Transport.DialServerTimeout)*time.Second),
|
libnet.WithTimeout(time.Duration(c.cfg.Transport.DialServerTimeout)*time.Second),
|
||||||
libdial.WithKeepAlive(time.Duration(c.cfg.Transport.DialServerKeepAlive)*time.Second),
|
libnet.WithKeepAlive(time.Duration(c.cfg.Transport.DialServerKeepAlive)*time.Second),
|
||||||
libdial.WithProxy(proxyType, addr),
|
libnet.WithProxy(proxyType, addr),
|
||||||
libdial.WithProxyAuth(auth),
|
libnet.WithProxyAuth(auth),
|
||||||
)
|
)
|
||||||
conn, err := libdial.DialContext(
|
conn, err := libnet.DialContext(
|
||||||
c.ctx,
|
c.ctx,
|
||||||
net.JoinHostPort(c.cfg.ServerAddr, strconv.Itoa(c.cfg.ServerPort)),
|
net.JoinHostPort(c.cfg.ServerAddr, strconv.Itoa(c.cfg.ServerPort)),
|
||||||
dialOptions...,
|
dialOptions...,
|
||||||
|
@@ -20,8 +20,6 @@ import (
|
|||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/samber/lo"
|
|
||||||
|
|
||||||
"github.com/fatedier/frp/client/proxy"
|
"github.com/fatedier/frp/client/proxy"
|
||||||
"github.com/fatedier/frp/client/visitor"
|
"github.com/fatedier/frp/client/visitor"
|
||||||
"github.com/fatedier/frp/pkg/auth"
|
"github.com/fatedier/frp/pkg/auth"
|
||||||
@@ -236,10 +234,8 @@ func (ctl *Control) registerMsgHandlers() {
|
|||||||
func (ctl *Control) heartbeatWorker() {
|
func (ctl *Control) heartbeatWorker() {
|
||||||
xl := ctl.xl
|
xl := ctl.xl
|
||||||
|
|
||||||
// TODO(fatedier): Change default value of HeartbeatInterval to -1 if tcpmux is enabled.
|
|
||||||
// Users can still enable heartbeat feature by setting HeartbeatInterval to a positive value.
|
|
||||||
if ctl.sessionCtx.Common.Transport.HeartbeatInterval > 0 {
|
if ctl.sessionCtx.Common.Transport.HeartbeatInterval > 0 {
|
||||||
// send heartbeat to server
|
// Send heartbeat to server.
|
||||||
sendHeartBeat := func() (bool, error) {
|
sendHeartBeat := func() (bool, error) {
|
||||||
xl.Debugf("send heartbeat to server")
|
xl.Debugf("send heartbeat to server")
|
||||||
pingMsg := &msg.Ping{}
|
pingMsg := &msg.Ping{}
|
||||||
@@ -263,10 +259,8 @@ func (ctl *Control) heartbeatWorker() {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check heartbeat timeout only if TCPMux is not enabled and users don't disable heartbeat feature.
|
// Check heartbeat timeout.
|
||||||
if ctl.sessionCtx.Common.Transport.HeartbeatInterval > 0 && ctl.sessionCtx.Common.Transport.HeartbeatTimeout > 0 &&
|
if ctl.sessionCtx.Common.Transport.HeartbeatInterval > 0 && ctl.sessionCtx.Common.Transport.HeartbeatTimeout > 0 {
|
||||||
!lo.FromPtr(ctl.sessionCtx.Common.Transport.TCPMux) {
|
|
||||||
|
|
||||||
go wait.Until(func() {
|
go wait.Until(func() {
|
||||||
if time.Since(ctl.lastPong.Load().(time.Time)) > time.Duration(ctl.sessionCtx.Common.Transport.HeartbeatTimeout)*time.Second {
|
if time.Since(ctl.lastPong.Load().(time.Time)) > time.Duration(ctl.sessionCtx.Common.Transport.HeartbeatTimeout)*time.Second {
|
||||||
xl.Warnf("heartbeat timeout")
|
xl.Warnf("heartbeat timeout")
|
||||||
|
@@ -40,8 +40,8 @@ type Monitor struct {
|
|||||||
addr string
|
addr string
|
||||||
|
|
||||||
// For http
|
// For http
|
||||||
url string
|
url string
|
||||||
|
header http.Header
|
||||||
failedTimes uint64
|
failedTimes uint64
|
||||||
statusOK bool
|
statusOK bool
|
||||||
statusNormalFn func()
|
statusNormalFn func()
|
||||||
@@ -73,6 +73,11 @@ func NewMonitor(ctx context.Context, cfg v1.HealthCheckConfig, addr string,
|
|||||||
}
|
}
|
||||||
url = s + cfg.Path
|
url = s + cfg.Path
|
||||||
}
|
}
|
||||||
|
header := make(http.Header)
|
||||||
|
for _, h := range cfg.HTTPHeaders {
|
||||||
|
header.Set(h.Name, h.Value)
|
||||||
|
}
|
||||||
|
|
||||||
return &Monitor{
|
return &Monitor{
|
||||||
checkType: cfg.Type,
|
checkType: cfg.Type,
|
||||||
interval: time.Duration(cfg.IntervalSeconds) * time.Second,
|
interval: time.Duration(cfg.IntervalSeconds) * time.Second,
|
||||||
@@ -80,6 +85,7 @@ func NewMonitor(ctx context.Context, cfg v1.HealthCheckConfig, addr string,
|
|||||||
maxFailedTimes: cfg.MaxFailed,
|
maxFailedTimes: cfg.MaxFailed,
|
||||||
addr: addr,
|
addr: addr,
|
||||||
url: url,
|
url: url,
|
||||||
|
header: header,
|
||||||
statusOK: false,
|
statusOK: false,
|
||||||
statusNormalFn: statusNormalFn,
|
statusNormalFn: statusNormalFn,
|
||||||
statusFailedFn: statusFailedFn,
|
statusFailedFn: statusFailedFn,
|
||||||
@@ -163,6 +169,8 @@ func (monitor *Monitor) doHTTPCheck(ctx context.Context) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
req.Header = monitor.header
|
||||||
|
req.Host = monitor.header.Get("Host")
|
||||||
resp, err := http.DefaultClient.Do(req)
|
resp, err := http.DefaultClient.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@@ -25,7 +25,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
libio "github.com/fatedier/golib/io"
|
libio "github.com/fatedier/golib/io"
|
||||||
libdial "github.com/fatedier/golib/net/dial"
|
libnet "github.com/fatedier/golib/net"
|
||||||
pp "github.com/pires/go-proxyproto"
|
pp "github.com/pires/go-proxyproto"
|
||||||
"golang.org/x/time/rate"
|
"golang.org/x/time/rate"
|
||||||
|
|
||||||
@@ -158,33 +158,35 @@ func (pxy *BaseProxy) HandleTCPWorkConnection(workConn net.Conn, m *msg.StartWor
|
|||||||
|
|
||||||
// check if we need to send proxy protocol info
|
// check if we need to send proxy protocol info
|
||||||
var extraInfo plugin.ExtraInfo
|
var extraInfo plugin.ExtraInfo
|
||||||
if baseCfg.Transport.ProxyProtocolVersion != "" {
|
if m.SrcAddr != "" && m.SrcPort != 0 {
|
||||||
if m.SrcAddr != "" && m.SrcPort != 0 {
|
if m.DstAddr == "" {
|
||||||
if m.DstAddr == "" {
|
m.DstAddr = "127.0.0.1"
|
||||||
m.DstAddr = "127.0.0.1"
|
|
||||||
}
|
|
||||||
srcAddr, _ := net.ResolveTCPAddr("tcp", net.JoinHostPort(m.SrcAddr, strconv.Itoa(int(m.SrcPort))))
|
|
||||||
dstAddr, _ := net.ResolveTCPAddr("tcp", net.JoinHostPort(m.DstAddr, strconv.Itoa(int(m.DstPort))))
|
|
||||||
h := &pp.Header{
|
|
||||||
Command: pp.PROXY,
|
|
||||||
SourceAddr: srcAddr,
|
|
||||||
DestinationAddr: dstAddr,
|
|
||||||
}
|
|
||||||
|
|
||||||
if strings.Contains(m.SrcAddr, ".") {
|
|
||||||
h.TransportProtocol = pp.TCPv4
|
|
||||||
} else {
|
|
||||||
h.TransportProtocol = pp.TCPv6
|
|
||||||
}
|
|
||||||
|
|
||||||
if baseCfg.Transport.ProxyProtocolVersion == "v1" {
|
|
||||||
h.Version = 1
|
|
||||||
} else if baseCfg.Transport.ProxyProtocolVersion == "v2" {
|
|
||||||
h.Version = 2
|
|
||||||
}
|
|
||||||
|
|
||||||
extraInfo.ProxyProtocolHeader = h
|
|
||||||
}
|
}
|
||||||
|
srcAddr, _ := net.ResolveTCPAddr("tcp", net.JoinHostPort(m.SrcAddr, strconv.Itoa(int(m.SrcPort))))
|
||||||
|
dstAddr, _ := net.ResolveTCPAddr("tcp", net.JoinHostPort(m.DstAddr, strconv.Itoa(int(m.DstPort))))
|
||||||
|
extraInfo.SrcAddr = srcAddr
|
||||||
|
extraInfo.DstAddr = dstAddr
|
||||||
|
}
|
||||||
|
|
||||||
|
if baseCfg.Transport.ProxyProtocolVersion != "" && m.SrcAddr != "" && m.SrcPort != 0 {
|
||||||
|
h := &pp.Header{
|
||||||
|
Command: pp.PROXY,
|
||||||
|
SourceAddr: extraInfo.SrcAddr,
|
||||||
|
DestinationAddr: extraInfo.DstAddr,
|
||||||
|
}
|
||||||
|
|
||||||
|
if strings.Contains(m.SrcAddr, ".") {
|
||||||
|
h.TransportProtocol = pp.TCPv4
|
||||||
|
} else {
|
||||||
|
h.TransportProtocol = pp.TCPv6
|
||||||
|
}
|
||||||
|
|
||||||
|
if baseCfg.Transport.ProxyProtocolVersion == "v1" {
|
||||||
|
h.Version = 1
|
||||||
|
} else if baseCfg.Transport.ProxyProtocolVersion == "v2" {
|
||||||
|
h.Version = 2
|
||||||
|
}
|
||||||
|
extraInfo.ProxyProtocolHeader = h
|
||||||
}
|
}
|
||||||
|
|
||||||
if pxy.proxyPlugin != nil {
|
if pxy.proxyPlugin != nil {
|
||||||
@@ -195,9 +197,9 @@ func (pxy *BaseProxy) HandleTCPWorkConnection(workConn net.Conn, m *msg.StartWor
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
localConn, err := libdial.Dial(
|
localConn, err := libnet.Dial(
|
||||||
net.JoinHostPort(baseCfg.LocalIP, strconv.Itoa(baseCfg.LocalPort)),
|
net.JoinHostPort(baseCfg.LocalIP, strconv.Itoa(baseCfg.LocalPort)),
|
||||||
libdial.WithTimeout(10*time.Second),
|
libnet.WithTimeout(10*time.Second),
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
workConn.Close()
|
workConn.Close()
|
||||||
|
@@ -19,6 +19,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
"os"
|
||||||
"runtime"
|
"runtime"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
@@ -40,6 +41,12 @@ import (
|
|||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
crypto.DefaultSalt = "frp"
|
crypto.DefaultSalt = "frp"
|
||||||
|
// Disable quic-go's receive buffer warning.
|
||||||
|
os.Setenv("QUIC_GO_DISABLE_RECEIVE_BUFFER_WARNING", "true")
|
||||||
|
// Disable quic-go's ECN support by default. It may cause issues on certain operating systems.
|
||||||
|
if os.Getenv("QUIC_GO_DISABLE_ECN") == "" {
|
||||||
|
os.Setenv("QUIC_GO_DISABLE_ECN", "true")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type cancelErr struct {
|
type cancelErr struct {
|
||||||
@@ -373,18 +380,31 @@ func (svr *Service) stop() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(fatedier): Use StatusExporter to provide query interfaces instead of directly using methods from the Service.
|
func (svr *Service) getProxyStatus(name string) (*proxy.WorkingStatus, bool) {
|
||||||
func (svr *Service) GetProxyStatus(name string) (*proxy.WorkingStatus, error) {
|
|
||||||
svr.ctlMu.RLock()
|
svr.ctlMu.RLock()
|
||||||
ctl := svr.ctl
|
ctl := svr.ctl
|
||||||
svr.ctlMu.RUnlock()
|
svr.ctlMu.RUnlock()
|
||||||
|
|
||||||
if ctl == nil {
|
if ctl == nil {
|
||||||
return nil, fmt.Errorf("control is not running")
|
return nil, false
|
||||||
}
|
}
|
||||||
ws, ok := ctl.pm.GetProxyStatus(name)
|
return ctl.pm.GetProxyStatus(name)
|
||||||
if !ok {
|
}
|
||||||
return nil, fmt.Errorf("proxy [%s] is not found", name)
|
|
||||||
}
|
func (svr *Service) StatusExporter() StatusExporter {
|
||||||
return ws, nil
|
return &statusExporterImpl{
|
||||||
|
getProxyStatusFunc: svr.getProxyStatus,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type StatusExporter interface {
|
||||||
|
GetProxyStatus(name string) (*proxy.WorkingStatus, bool)
|
||||||
|
}
|
||||||
|
|
||||||
|
type statusExporterImpl struct {
|
||||||
|
getProxyStatusFunc func(name string) (*proxy.WorkingStatus, bool)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *statusExporterImpl) GetProxyStatus(name string) (*proxy.WorkingStatus, bool) {
|
||||||
|
return s.getProxyStatusFunc(name)
|
||||||
}
|
}
|
||||||
|
@@ -17,8 +17,10 @@ package main
|
|||||||
import (
|
import (
|
||||||
_ "github.com/fatedier/frp/assets/frpc"
|
_ "github.com/fatedier/frp/assets/frpc"
|
||||||
"github.com/fatedier/frp/cmd/frpc/sub"
|
"github.com/fatedier/frp/cmd/frpc/sub"
|
||||||
|
"github.com/fatedier/frp/pkg/util/system"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
system.EnableCompatibilityMode()
|
||||||
sub.Execute()
|
sub.Execute()
|
||||||
}
|
}
|
||||||
|
@@ -15,13 +15,12 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/fatedier/golib/crypto"
|
|
||||||
|
|
||||||
_ "github.com/fatedier/frp/assets/frps"
|
_ "github.com/fatedier/frp/assets/frps"
|
||||||
_ "github.com/fatedier/frp/pkg/metrics"
|
_ "github.com/fatedier/frp/pkg/metrics"
|
||||||
|
"github.com/fatedier/frp/pkg/util/system"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
crypto.DefaultSalt = "frp"
|
system.EnableCompatibilityMode()
|
||||||
Execute()
|
Execute()
|
||||||
}
|
}
|
||||||
|
@@ -209,6 +209,7 @@ locations = ["/", "/pic"]
|
|||||||
# routeByHTTPUser = abc
|
# routeByHTTPUser = abc
|
||||||
hostHeaderRewrite = "example.com"
|
hostHeaderRewrite = "example.com"
|
||||||
requestHeaders.set.x-from-where = "frp"
|
requestHeaders.set.x-from-where = "frp"
|
||||||
|
responseHeaders.set.foo = "bar"
|
||||||
healthCheck.type = "http"
|
healthCheck.type = "http"
|
||||||
# frpc will send a GET http request '/status' to local http service
|
# frpc will send a GET http request '/status' to local http service
|
||||||
# http service is alive when it return 2xx http response code
|
# http service is alive when it return 2xx http response code
|
||||||
@@ -216,6 +217,10 @@ healthCheck.path = "/status"
|
|||||||
healthCheck.intervalSeconds = 10
|
healthCheck.intervalSeconds = 10
|
||||||
healthCheck.maxFailed = 3
|
healthCheck.maxFailed = 3
|
||||||
healthCheck.timeoutSeconds = 3
|
healthCheck.timeoutSeconds = 3
|
||||||
|
# set health check headers
|
||||||
|
healthCheck.httpHeaders=[
|
||||||
|
{ name = "x-from-where", value = "frp" }
|
||||||
|
]
|
||||||
|
|
||||||
[[proxies]]
|
[[proxies]]
|
||||||
name = "web02"
|
name = "web02"
|
||||||
|
69
go.mod
69
go.mod
@@ -4,79 +4,78 @@ go 1.22
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5
|
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5
|
||||||
github.com/coreos/go-oidc/v3 v3.6.0
|
github.com/coreos/go-oidc/v3 v3.10.0
|
||||||
github.com/fatedier/golib v0.4.0
|
github.com/fatedier/golib v0.5.0
|
||||||
github.com/google/uuid v1.3.0
|
github.com/google/uuid v1.6.0
|
||||||
github.com/gorilla/mux v1.8.0
|
github.com/gorilla/mux v1.8.1
|
||||||
github.com/gorilla/websocket v1.5.0
|
github.com/gorilla/websocket v1.5.0
|
||||||
github.com/hashicorp/yamux v0.1.1
|
github.com/hashicorp/yamux v0.1.1
|
||||||
github.com/onsi/ginkgo/v2 v2.11.0
|
github.com/onsi/ginkgo/v2 v2.17.1
|
||||||
github.com/onsi/gomega v1.27.8
|
github.com/onsi/gomega v1.32.0
|
||||||
github.com/pelletier/go-toml/v2 v2.1.0
|
github.com/pelletier/go-toml/v2 v2.2.0
|
||||||
github.com/pion/stun/v2 v2.0.0
|
github.com/pion/stun/v2 v2.0.0
|
||||||
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.19.0
|
||||||
github.com/quic-go/quic-go v0.41.0
|
github.com/quic-go/quic-go v0.42.0
|
||||||
github.com/rodaine/table v1.1.0
|
github.com/rodaine/table v1.2.0
|
||||||
github.com/samber/lo v1.39.0
|
github.com/samber/lo v1.39.0
|
||||||
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.9.0
|
||||||
github.com/tidwall/gjson v1.17.1
|
github.com/tidwall/gjson v1.17.1
|
||||||
github.com/xtaci/kcp-go/v5 v5.6.7
|
github.com/xtaci/kcp-go/v5 v5.6.8
|
||||||
golang.org/x/crypto v0.18.0
|
golang.org/x/crypto v0.22.0
|
||||||
golang.org/x/net v0.19.0
|
golang.org/x/net v0.24.0
|
||||||
golang.org/x/oauth2 v0.10.0
|
golang.org/x/oauth2 v0.16.0
|
||||||
golang.org/x/sync v0.3.0
|
golang.org/x/sync v0.6.0
|
||||||
golang.org/x/time v0.3.0
|
golang.org/x/time v0.5.0
|
||||||
gopkg.in/ini.v1 v1.67.0
|
gopkg.in/ini.v1 v1.67.0
|
||||||
k8s.io/apimachinery v0.27.4
|
k8s.io/apimachinery v0.28.8
|
||||||
k8s.io/client-go v0.27.4
|
k8s.io/client-go v0.28.8
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/Azure/go-ntlmssp v0.0.0-20200615164410-66371956d46c // indirect
|
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 // indirect
|
||||||
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/v4 v4.0.1 // indirect
|
||||||
github.com/go-logr/logr v1.2.4 // indirect
|
github.com/go-logr/logr v1.4.1 // 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/protobuf v1.5.3 // indirect
|
github.com/golang/protobuf v1.5.4 // indirect
|
||||||
github.com/golang/snappy v0.0.4 // indirect
|
github.com/golang/snappy v0.0.4 // indirect
|
||||||
github.com/google/go-cmp v0.5.9 // indirect
|
github.com/google/go-cmp v0.6.0 // indirect
|
||||||
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 // indirect
|
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 // indirect
|
||||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||||
github.com/klauspost/cpuid/v2 v2.2.6 // indirect
|
github.com/klauspost/cpuid/v2 v2.2.6 // indirect
|
||||||
github.com/klauspost/reedsolomon v1.12.0 // indirect
|
github.com/klauspost/reedsolomon v1.12.0 // indirect
|
||||||
github.com/kr/text v0.2.0 // indirect
|
github.com/kr/text v0.2.0 // indirect
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
|
|
||||||
github.com/pion/dtls/v2 v2.2.7 // indirect
|
github.com/pion/dtls/v2 v2.2.7 // indirect
|
||||||
github.com/pion/logging v0.2.2 // indirect
|
github.com/pion/logging v0.2.2 // indirect
|
||||||
github.com/pion/transport/v2 v2.2.1 // indirect
|
github.com/pion/transport/v2 v2.2.1 // indirect
|
||||||
github.com/pion/transport/v3 v3.0.1 // indirect
|
github.com/pion/transport/v3 v3.0.1 // indirect
|
||||||
github.com/pkg/errors v0.9.1 // indirect
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
github.com/prometheus/client_model v0.3.0 // indirect
|
github.com/prometheus/client_model v0.5.0 // indirect
|
||||||
github.com/prometheus/common v0.42.0 // indirect
|
github.com/prometheus/common v0.48.0 // indirect
|
||||||
github.com/prometheus/procfs v0.10.1 // indirect
|
github.com/prometheus/procfs v0.12.0 // indirect
|
||||||
github.com/rogpeppe/go-internal v1.11.0 // indirect
|
github.com/rogpeppe/go-internal v1.11.0 // indirect
|
||||||
github.com/templexxx/cpu v0.1.0 // indirect
|
github.com/templexxx/cpu v0.1.0 // indirect
|
||||||
github.com/templexxx/xorsimd v0.4.2 // indirect
|
github.com/templexxx/xorsimd v0.4.2 // indirect
|
||||||
github.com/tidwall/match v1.1.1 // indirect
|
github.com/tidwall/match v1.1.1 // indirect
|
||||||
github.com/tidwall/pretty v1.2.0 // indirect
|
github.com/tidwall/pretty v1.2.0 // indirect
|
||||||
github.com/tjfoc/gmsm v1.4.1 // indirect
|
github.com/tjfoc/gmsm v1.4.1 // indirect
|
||||||
go.uber.org/mock v0.3.0 // indirect
|
go.uber.org/mock v0.4.0 // 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.11.0 // indirect
|
golang.org/x/mod v0.14.0 // indirect
|
||||||
golang.org/x/sys v0.16.0 // indirect
|
golang.org/x/sys v0.19.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.17.0 // indirect
|
||||||
google.golang.org/appengine v1.6.7 // indirect
|
google.golang.org/appengine v1.6.8 // indirect
|
||||||
google.golang.org/protobuf v1.31.0 // indirect
|
google.golang.org/protobuf v1.33.0 // indirect
|
||||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
k8s.io/utils v0.0.0-20230209194617-a36077c30491 // indirect
|
k8s.io/utils v0.0.0-20230406110748-d93618cff8a2 // indirect
|
||||||
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
|
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
|
||||||
sigs.k8s.io/yaml v1.3.0 // indirect
|
sigs.k8s.io/yaml v1.3.0 // indirect
|
||||||
)
|
)
|
||||||
|
157
go.sum
157
go.sum
@@ -1,6 +1,6 @@
|
|||||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||||
github.com/Azure/go-ntlmssp v0.0.0-20200615164410-66371956d46c h1:/IBSNwUN8+eKzUzbJPqhK839ygXJ82sde8x3ogr6R28=
|
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 h1:mFRzDkZVAjdal+s7s0MwaRv9igoPqLRdzOLzw/8Xvq8=
|
||||||
github.com/Azure/go-ntlmssp v0.0.0-20200615164410-66371956d46c/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU=
|
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU=
|
||||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
|
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
|
||||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
|
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
|
||||||
@@ -14,8 +14,8 @@ github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5P
|
|||||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||||
github.com/coreos/go-oidc/v3 v3.6.0 h1:AKVxfYw1Gmkn/w96z0DbT/B/xFnzTd3MkZvWLjF4n/o=
|
github.com/coreos/go-oidc/v3 v3.10.0 h1:tDnXHnLyiTVyT/2zLDGj09pFPkhND8Gl8lnTRhoEaJU=
|
||||||
github.com/coreos/go-oidc/v3 v3.6.0/go.mod h1:ZpHUsHBucTUj6WOkrP4E20UPynbLZzhTQ1XKCXkxyPc=
|
github.com/coreos/go-oidc/v3 v3.10.0/go.mod h1:5j11xcw0D3+SGxn6Z/WFADsgcWVMyNAlSQupk0KK3ac=
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
@@ -24,23 +24,21 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
|
|||||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||||
github.com/fatedier/golib v0.4.0 h1:lafvYRMhFmqrfIUChKy/f5AXqs1eDSk+GAUtLexN5bU=
|
github.com/fatedier/golib v0.5.0 h1:hNcH7hgfIFqVWbP+YojCCAj4eO94pPf4dEF8lmq2jWs=
|
||||||
github.com/fatedier/golib v0.4.0/go.mod h1:gpu+1vXxtJ072NYaNsn/YWgojDL8Ap2kFZQtbzT2qkg=
|
github.com/fatedier/golib v0.5.0/go.mod h1:W6kIYkIFxHsTzbgqg5piCxIiDo4LzwgTY6R5W8l9NFQ=
|
||||||
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/v4 v4.0.1 h1:QVEPDE3OluqXBQZDcnNvQrInro2h0e4eqNbnZSWqS6U=
|
||||||
github.com/go-jose/go-jose/v3 v3.0.1/go.mod h1:RNkWWRld676jZEYoV3+XK8L2ZnNSvIsxFMht0mSX+u8=
|
github.com/go-jose/go-jose/v4 v4.0.1/go.mod h1:WVf9LFMHh/QVrmqrOfqun0C45tMe3RoiKJMPvgWwLfY=
|
||||||
github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=
|
github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ=
|
||||||
github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||||
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=
|
||||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
|
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
|
||||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
|
||||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||||
github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
|
|
||||||
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
||||||
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
||||||
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
||||||
@@ -48,24 +46,24 @@ github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:W
|
|||||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
||||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||||
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
|
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||||
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||||
|
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
||||||
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
|
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
|
||||||
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
|
||||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||||
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJYCmNdQXq6neHJOYx3V6jnqNEec=
|
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJYCmNdQXq6neHJOYx3V6jnqNEec=
|
||||||
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||||
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
|
github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
|
||||||
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
|
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
|
||||||
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
|
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
|
||||||
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||||
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||||
@@ -79,16 +77,14 @@ github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
|||||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||||
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
|
github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
|
||||||
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo=
|
github.com/onsi/ginkgo/v2 v2.17.1 h1:V++EzdbhI4ZV4ev0UTIj0PzhzOcReJFyJaLjtSF55M8=
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
|
github.com/onsi/ginkgo/v2 v2.17.1/go.mod h1:llBI3WDLL9Z6taip6f33H76YcWtJv+7R3HigUjbIBOs=
|
||||||
github.com/onsi/ginkgo/v2 v2.11.0 h1:WgqUCUt/lT6yXoQ8Wef0fsNn5cAuMK7+KT9UFRz2tcU=
|
github.com/onsi/gomega v1.32.0 h1:JRYU78fJ1LPxlckP6Txi/EYqJvjtMrDC04/MM5XRHPk=
|
||||||
github.com/onsi/ginkgo/v2 v2.11.0/go.mod h1:ZhrRA5XmEE3x3rhlzamx/JJvujdZoJ2uvgI7kR0iZvM=
|
github.com/onsi/gomega v1.32.0/go.mod h1:a4x4gW6Pz2yK1MAmvluYme5lvYTn61afQ2ETw/8n4Lg=
|
||||||
github.com/onsi/gomega v1.27.8 h1:gegWiwZjBsf2DgiSbf5hpokZ98JVDMcWkUiigk6/KXc=
|
github.com/pelletier/go-toml/v2 v2.2.0 h1:QLgLl2yMN7N+ruc31VynXs1vhMZa7CeHHejIeBAsoHo=
|
||||||
github.com/onsi/gomega v1.27.8/go.mod h1:2J8vzI/s+2shY9XHRApDkdgPo1TKT7P2u6fXeJKFnNQ=
|
github.com/pelletier/go-toml/v2 v2.2.0/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
|
||||||
github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4=
|
|
||||||
github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc=
|
|
||||||
github.com/pion/dtls/v2 v2.2.7 h1:cSUBsETxepsCSFSxC3mc/aDo14qQLMSL+O6IjG28yV8=
|
github.com/pion/dtls/v2 v2.2.7 h1:cSUBsETxepsCSFSxC3mc/aDo14qQLMSL+O6IjG28yV8=
|
||||||
github.com/pion/dtls/v2 v2.2.7/go.mod h1:8WiMkebSHFD0T+dIU+UeBaoV7kDhOW5oDCzZ7WZ/F9s=
|
github.com/pion/dtls/v2 v2.2.7/go.mod h1:8WiMkebSHFD0T+dIU+UeBaoV7kDhOW5oDCzZ7WZ/F9s=
|
||||||
github.com/pion/logging v0.2.2 h1:M9+AIj/+pxNsDfAT64+MAVgJO0rsyLnoJKCqf//DoeY=
|
github.com/pion/logging v0.2.2 h1:M9+AIj/+pxNsDfAT64+MAVgJO0rsyLnoJKCqf//DoeY=
|
||||||
@@ -105,19 +101,21 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
|||||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/prometheus/client_golang v1.16.0 h1:yk/hx9hDbrGHovbci4BY+pRMfSuuat626eFsHb7tmT8=
|
github.com/prometheus/client_golang v1.19.0 h1:ygXvpU1AoN1MhdzckN+PyD9QJOSD4x7kmXYlnfbA6JU=
|
||||||
github.com/prometheus/client_golang v1.16.0/go.mod h1:Zsulrv/L9oM40tJ7T815tM89lFEugiJ9HzIqaAx4LKc=
|
github.com/prometheus/client_golang v1.19.0/go.mod h1:ZRM9uEAypZakd+q/x7+gmsvXdURP+DABIEIjnmDdp+k=
|
||||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||||
github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4=
|
github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw=
|
||||||
github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w=
|
github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI=
|
||||||
github.com/prometheus/common v0.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI1YM=
|
github.com/prometheus/common v0.48.0 h1:QO8U2CdOzSn1BBsmXJXduaaW+dY/5QLjfB8svtSzKKE=
|
||||||
github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc=
|
github.com/prometheus/common v0.48.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc=
|
||||||
github.com/prometheus/procfs v0.10.1 h1:kYK1Va/YMlutzCGazswoHKo//tZVlFpKYh+PymziUAg=
|
github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo=
|
||||||
github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM=
|
github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo=
|
||||||
github.com/quic-go/quic-go v0.41.0 h1:aD8MmHfgqTURWNJy48IYFg2OnxwHT3JL7ahGs73lb4k=
|
github.com/quic-go/quic-go v0.42.0 h1:uSfdap0eveIl8KXnipv9K7nlwZ5IqLlYOpJ58u5utpM=
|
||||||
github.com/quic-go/quic-go v0.41.0/go.mod h1:qCkNjqczPEvgsOnxZ0eCD14lv+B2LHlFAB++CNOh9hA=
|
github.com/quic-go/quic-go v0.42.0/go.mod h1:132kz4kL3F9vxhW3CtQJLDVwcFe5wdWeJXXijhsO57M=
|
||||||
github.com/rodaine/table v1.1.0 h1:/fUlCSdjamMY8VifdQRIu3VWZXYLY7QHFkVorS8NTr4=
|
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
|
||||||
github.com/rodaine/table v1.1.0/go.mod h1:Qu3q5wi1jTQD6B6HsP6szie/S4w1QUQ8pq22pz9iL8g=
|
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||||
|
github.com/rodaine/table v1.2.0 h1:38HEnwK4mKSHQJIkavVj+bst1TEY7j9zhLMWu4QJrMA=
|
||||||
|
github.com/rodaine/table v1.2.0/go.mod h1:wejb/q/Yd4T/SVmBSRMr7GCq3KlcZp3gyNYdLSBhkaE=
|
||||||
github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
|
github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
|
||||||
github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
|
github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
|
||||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
@@ -130,12 +128,14 @@ github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An
|
|||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||||
|
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||||
github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
|
||||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||||
|
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||||
|
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||||
github.com/templexxx/cpu v0.1.0 h1:wVM+WIJP2nYaxVxqgHPD4wGA2aJ9rvrQRV8CvFzNb40=
|
github.com/templexxx/cpu v0.1.0 h1:wVM+WIJP2nYaxVxqgHPD4wGA2aJ9rvrQRV8CvFzNb40=
|
||||||
github.com/templexxx/cpu v0.1.0/go.mod h1:w7Tb+7qgcAlIyX4NhLuDKt78AHA5SzPmq0Wj6HiEnnk=
|
github.com/templexxx/cpu v0.1.0/go.mod h1:w7Tb+7qgcAlIyX4NhLuDKt78AHA5SzPmq0Wj6HiEnnk=
|
||||||
github.com/templexxx/xorsimd v0.4.2 h1:ocZZ+Nvu65LGHmCLZ7OoCtg8Fx8jnHKK37SjvngUoVI=
|
github.com/templexxx/xorsimd v0.4.2 h1:ocZZ+Nvu65LGHmCLZ7OoCtg8Fx8jnHKK37SjvngUoVI=
|
||||||
@@ -148,22 +148,21 @@ github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
|
|||||||
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
||||||
github.com/tjfoc/gmsm v1.4.1 h1:aMe1GlZb+0bLjn+cKTPEvvn9oUEBlJitaZiiBwsbgho=
|
github.com/tjfoc/gmsm v1.4.1 h1:aMe1GlZb+0bLjn+cKTPEvvn9oUEBlJitaZiiBwsbgho=
|
||||||
github.com/tjfoc/gmsm v1.4.1/go.mod h1:j4INPkHWMrhJb38G+J6W4Tw0AbuN8Thu3PbdVYhVcTE=
|
github.com/tjfoc/gmsm v1.4.1/go.mod h1:j4INPkHWMrhJb38G+J6W4Tw0AbuN8Thu3PbdVYhVcTE=
|
||||||
github.com/xtaci/kcp-go/v5 v5.6.7 h1:7+rnxNFIsjEwTXQk4cSZpXM4pO0hqtpwE1UFFoJBffA=
|
github.com/xtaci/kcp-go/v5 v5.6.8 h1:jlI/0jAyjoOjT/SaGB58s4bQMJiNS41A2RKzR6TMWeI=
|
||||||
github.com/xtaci/kcp-go/v5 v5.6.7/go.mod h1:oE9j2NVqAkuKO5o8ByKGch3vgVX3BNf8zqP8JiGq0bM=
|
github.com/xtaci/kcp-go/v5 v5.6.8/go.mod h1:oE9j2NVqAkuKO5o8ByKGch3vgVX3BNf8zqP8JiGq0bM=
|
||||||
github.com/xtaci/lossyconn v0.0.0-20200209145036-adba10fffc37 h1:EWU6Pktpas0n8lLQwDsRyZfmkPeRbdgPtW609es+/9E=
|
github.com/xtaci/lossyconn v0.0.0-20200209145036-adba10fffc37 h1:EWU6Pktpas0n8lLQwDsRyZfmkPeRbdgPtW609es+/9E=
|
||||||
github.com/xtaci/lossyconn v0.0.0-20200209145036-adba10fffc37/go.mod h1:HpMP7DB2CyokmAh4lp0EQnnWhmycP/TvwBGzvuie+H0=
|
github.com/xtaci/lossyconn v0.0.0-20200209145036-adba10fffc37/go.mod h1:HpMP7DB2CyokmAh4lp0EQnnWhmycP/TvwBGzvuie+H0=
|
||||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||||
go.uber.org/mock v0.3.0 h1:3mUxI1No2/60yUYax92Pt8eNOEecx2D3lcXZh2NEZJo=
|
go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU=
|
||||||
go.uber.org/mock v0.3.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc=
|
go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
|
||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
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.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
|
golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
|
||||||
golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc=
|
golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30=
|
||||||
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
|
golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M=
|
||||||
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=
|
||||||
@@ -172,14 +171,13 @@ golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvx
|
|||||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||||
golang.org/x/mod v0.11.0 h1:bUO06HqtnRcc/7l71XBe4WcqTZ+3AH1J59zWDDwLKgU=
|
golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0=
|
||||||
golang.org/x/mod v0.11.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
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-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
@@ -188,19 +186,18 @@ golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
|||||||
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
|
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
|
||||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||||
golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
|
golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
|
||||||
golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c=
|
golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w=
|
||||||
golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U=
|
golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8=
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
golang.org/x/oauth2 v0.10.0 h1:zHCpF2Khkwy4mMB4bv0U37YtJdTGW8jI0glAApi0Kh8=
|
golang.org/x/oauth2 v0.16.0 h1:aDkGMBSYxElaoP81NpoUoz2oo2R2wHdZpGToUxfyQrQ=
|
||||||
golang.org/x/oauth2 v0.10.0/go.mod h1:kTpgurOux7LqtuxjuyZa4Gj2gdezIt/jQtGnNFfypQI=
|
golang.org/x/oauth2 v0.16.0/go.mod h1:hqZ+0LWXsiVoZpeld6jVt06P3adbS2Uu911W1SsJv2o=
|
||||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
|
golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
|
||||||
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
|
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
@@ -214,27 +211,27 @@ 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.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
|
golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o=
|
||||||
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.19.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.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
||||||
golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU=
|
golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU=
|
||||||
golang.org/x/term v0.16.0 h1:m+B6fahuftsE9qjo0VWp2FW0mB3MTJvR0BaMQrq0pmE=
|
golang.org/x/term v0.19.0 h1:+ThwsDv+tYfnJFhF4L8jITxu1tdTWRTZpdsWgEgjL6Q=
|
||||||
golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY=
|
golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk=
|
||||||
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.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
|
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
|
||||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||||
golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||||
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
|
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
|
||||||
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||||
@@ -243,14 +240,14 @@ golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBn
|
|||||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||||
golang.org/x/tools v0.9.3 h1:Gn1I8+64MsuTb/HpH+LmQtNas23LhUVr3rYZ0eKuaMM=
|
golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc=
|
||||||
golang.org/x/tools v0.9.3/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc=
|
golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps=
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||||
google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
|
google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM=
|
||||||
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds=
|
||||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||||
@@ -265,8 +262,8 @@ 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.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||||
google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
|
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
|
||||||
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
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 h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||||
@@ -279,12 +276,12 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
|||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
k8s.io/apimachinery v0.27.4 h1:CdxflD4AF61yewuid0fLl6bM4a3q04jWel0IlP+aYjs=
|
k8s.io/apimachinery v0.28.8 h1:hi/nrxHwk4QLV+W/SHve1bypTE59HCDorLY1stBIxKQ=
|
||||||
k8s.io/apimachinery v0.27.4/go.mod h1:XNfZ6xklnMCOGGFNqXG7bUrQCoR04dh/E7FprV6pb+E=
|
k8s.io/apimachinery v0.28.8/go.mod h1:cBnwIM3fXoRo28SqbV/Ihxf/iviw85KyXOrzxvZQ83U=
|
||||||
k8s.io/client-go v0.27.4 h1:vj2YTtSJ6J4KxaC88P4pMPEQECWMY8gqPqsTgUKzvjk=
|
k8s.io/client-go v0.28.8 h1:TE59Tjd87WKvS2FPBTfIKLFX0nQJ4SSHsnDo5IHjgOw=
|
||||||
k8s.io/client-go v0.27.4/go.mod h1:ragcly7lUlN0SRPk5/ZkGnDjPknzb37TICq07WhI6Xc=
|
k8s.io/client-go v0.28.8/go.mod h1:uDVQ/rPzWpWIy40c6lZ4mUwaEvRWGnpoqSO4FM65P3o=
|
||||||
k8s.io/utils v0.0.0-20230209194617-a36077c30491 h1:r0BAOLElQnnFhE/ApUsg3iHdVYYPBjNSSOMowRZxxsY=
|
k8s.io/utils v0.0.0-20230406110748-d93618cff8a2 h1:qY1Ad8PODbnymg2pRbkyMT/ylpTrCM8P2RJ0yroCyIk=
|
||||||
k8s.io/utils v0.0.0-20230209194617-a36077c30491/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
|
k8s.io/utils v0.0.0-20230406110748-d93618cff8a2/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
|
||||||
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo=
|
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo=
|
||||||
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0=
|
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0=
|
||||||
sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo=
|
sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo=
|
||||||
|
@@ -6,7 +6,7 @@ ROOT=$(unset CDPATH && cd "$(dirname "$SCRIPT")/.." && pwd)
|
|||||||
ginkgo_command=$(which ginkgo 2>/dev/null)
|
ginkgo_command=$(which ginkgo 2>/dev/null)
|
||||||
if [ -z "$ginkgo_command" ]; then
|
if [ -z "$ginkgo_command" ]; then
|
||||||
echo "ginkgo not found, try to install..."
|
echo "ginkgo not found, try to install..."
|
||||||
go install github.com/onsi/ginkgo/v2/ginkgo@v2.11.0
|
go install github.com/onsi/ginkgo/v2/ginkgo@v2.17.1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
debug=false
|
debug=false
|
||||||
|
79
package.sh
79
package.sh
@@ -17,50 +17,57 @@ make -f ./Makefile.cross-compiles
|
|||||||
rm -rf ./release/packages
|
rm -rf ./release/packages
|
||||||
mkdir -p ./release/packages
|
mkdir -p ./release/packages
|
||||||
|
|
||||||
os_all='linux windows darwin freebsd'
|
os_all='linux windows darwin freebsd android'
|
||||||
arch_all='386 amd64 arm arm64 mips64 mips64le mips mipsle riscv64'
|
arch_all='386 amd64 arm arm64 mips64 mips64le mips mipsle riscv64'
|
||||||
|
extra_all='_ hf'
|
||||||
|
|
||||||
cd ./release
|
cd ./release
|
||||||
|
|
||||||
for os in $os_all; do
|
for os in $os_all; do
|
||||||
for arch in $arch_all; do
|
for arch in $arch_all; do
|
||||||
frp_dir_name="frp_${frp_version}_${os}_${arch}"
|
for extra in $extra_all; do
|
||||||
frp_path="./packages/frp_${frp_version}_${os}_${arch}"
|
suffix="${os}_${arch}"
|
||||||
|
if [ "x${extra}" != x"_" ]; then
|
||||||
|
suffix="${os}_${arch}_${extra}"
|
||||||
|
fi
|
||||||
|
frp_dir_name="frp_${frp_version}_${suffix}"
|
||||||
|
frp_path="./packages/frp_${frp_version}_${suffix}"
|
||||||
|
|
||||||
if [ "x${os}" = x"windows" ]; then
|
if [ "x${os}" = x"windows" ]; then
|
||||||
if [ ! -f "./frpc_${os}_${arch}.exe" ]; then
|
if [ ! -f "./frpc_${os}_${arch}.exe" ]; then
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
if [ ! -f "./frps_${os}_${arch}.exe" ]; then
|
if [ ! -f "./frps_${os}_${arch}.exe" ]; then
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
mkdir ${frp_path}
|
mkdir ${frp_path}
|
||||||
mv ./frpc_${os}_${arch}.exe ${frp_path}/frpc.exe
|
mv ./frpc_${os}_${arch}.exe ${frp_path}/frpc.exe
|
||||||
mv ./frps_${os}_${arch}.exe ${frp_path}/frps.exe
|
mv ./frps_${os}_${arch}.exe ${frp_path}/frps.exe
|
||||||
else
|
else
|
||||||
if [ ! -f "./frpc_${os}_${arch}" ]; then
|
if [ ! -f "./frpc_${suffix}" ]; then
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
if [ ! -f "./frps_${os}_${arch}" ]; then
|
if [ ! -f "./frps_${suffix}" ]; then
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
mkdir ${frp_path}
|
mkdir ${frp_path}
|
||||||
mv ./frpc_${os}_${arch} ${frp_path}/frpc
|
mv ./frpc_${suffix} ${frp_path}/frpc
|
||||||
mv ./frps_${os}_${arch} ${frp_path}/frps
|
mv ./frps_${suffix} ${frp_path}/frps
|
||||||
fi
|
fi
|
||||||
cp ../LICENSE ${frp_path}
|
cp ../LICENSE ${frp_path}
|
||||||
cp -f ../conf/frpc.toml ${frp_path}
|
cp -f ../conf/frpc.toml ${frp_path}
|
||||||
cp -f ../conf/frps.toml ${frp_path}
|
cp -f ../conf/frps.toml ${frp_path}
|
||||||
|
|
||||||
# packages
|
# packages
|
||||||
cd ./packages
|
cd ./packages
|
||||||
if [ "x${os}" = x"windows" ]; then
|
if [ "x${os}" = x"windows" ]; then
|
||||||
zip -rq ${frp_dir_name}.zip ${frp_dir_name}
|
zip -rq ${frp_dir_name}.zip ${frp_dir_name}
|
||||||
else
|
else
|
||||||
tar -zcf ${frp_dir_name}.tar.gz ${frp_dir_name}
|
tar -zcf ${frp_dir_name}.tar.gz ${frp_dir_name}
|
||||||
fi
|
fi
|
||||||
cd ..
|
cd ..
|
||||||
rm -rf ${frp_path}
|
rm -rf ${frp_path}
|
||||||
|
done
|
||||||
done
|
done
|
||||||
done
|
done
|
||||||
|
|
||||||
|
@@ -80,7 +80,10 @@ func DetectLegacyINIFormatFromFile(path string) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func RenderWithTemplate(in []byte, values *Values) ([]byte, error) {
|
func RenderWithTemplate(in []byte, values *Values) ([]byte, error) {
|
||||||
tmpl, err := template.New("frp").Parse(string(in))
|
tmpl, err := template.New("frp").Funcs(template.FuncMap{
|
||||||
|
"parseNumberRange": parseNumberRange,
|
||||||
|
"parseNumberRangePair": parseNumberRangePair,
|
||||||
|
}).Parse(string(in))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
52
pkg/config/template.go
Normal file
52
pkg/config/template.go
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
// Copyright 2024 The frp Authors
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/fatedier/frp/pkg/util/util"
|
||||||
|
)
|
||||||
|
|
||||||
|
type NumberPair struct {
|
||||||
|
First int64
|
||||||
|
Second int64
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseNumberRangePair(firstRangeStr, secondRangeStr string) ([]NumberPair, error) {
|
||||||
|
firstRangeNumbers, err := util.ParseRangeNumbers(firstRangeStr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
secondRangeNumbers, err := util.ParseRangeNumbers(secondRangeStr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if len(firstRangeNumbers) != len(secondRangeNumbers) {
|
||||||
|
return nil, fmt.Errorf("first and second range numbers are not in pairs")
|
||||||
|
}
|
||||||
|
pairs := make([]NumberPair, 0, len(firstRangeNumbers))
|
||||||
|
for i := 0; i < len(firstRangeNumbers); i++ {
|
||||||
|
pairs = append(pairs, NumberPair{
|
||||||
|
First: firstRangeNumbers[i],
|
||||||
|
Second: secondRangeNumbers[i],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return pairs, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseNumberRange(firstRangeStr string) ([]int64, error) {
|
||||||
|
return util.ParseRangeNumbers(firstRangeStr)
|
||||||
|
}
|
@@ -136,8 +136,14 @@ func (c *ClientTransportConfig) Complete() {
|
|||||||
c.PoolCount = util.EmptyOr(c.PoolCount, 1)
|
c.PoolCount = util.EmptyOr(c.PoolCount, 1)
|
||||||
c.TCPMux = util.EmptyOr(c.TCPMux, lo.ToPtr(true))
|
c.TCPMux = util.EmptyOr(c.TCPMux, lo.ToPtr(true))
|
||||||
c.TCPMuxKeepaliveInterval = util.EmptyOr(c.TCPMuxKeepaliveInterval, 60)
|
c.TCPMuxKeepaliveInterval = util.EmptyOr(c.TCPMuxKeepaliveInterval, 60)
|
||||||
c.HeartbeatInterval = util.EmptyOr(c.HeartbeatInterval, 30)
|
if lo.FromPtr(c.TCPMux) {
|
||||||
c.HeartbeatTimeout = util.EmptyOr(c.HeartbeatTimeout, 90)
|
// If TCPMux is enabled, heartbeat of application layer is unnecessary because we can rely on heartbeat in tcpmux.
|
||||||
|
c.HeartbeatInterval = util.EmptyOr(c.HeartbeatInterval, -1)
|
||||||
|
c.HeartbeatTimeout = util.EmptyOr(c.HeartbeatTimeout, -1)
|
||||||
|
} else {
|
||||||
|
c.HeartbeatInterval = util.EmptyOr(c.HeartbeatInterval, 30)
|
||||||
|
c.HeartbeatTimeout = util.EmptyOr(c.HeartbeatTimeout, 90)
|
||||||
|
}
|
||||||
c.QUIC.Complete()
|
c.QUIC.Complete()
|
||||||
c.TLS.Complete()
|
c.TLS.Complete()
|
||||||
}
|
}
|
||||||
|
@@ -129,3 +129,8 @@ type HTTPPluginOptions struct {
|
|||||||
type HeaderOperations struct {
|
type HeaderOperations struct {
|
||||||
Set map[string]string `json:"set,omitempty"`
|
Set map[string]string `json:"set,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type HTTPHeader struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Value string `json:"value"`
|
||||||
|
}
|
||||||
|
@@ -97,6 +97,9 @@ type HealthCheckConfig struct {
|
|||||||
// Path specifies the path to send health checks to if the
|
// Path specifies the path to send health checks to if the
|
||||||
// health check type is "http".
|
// health check type is "http".
|
||||||
Path string `json:"path,omitempty"`
|
Path string `json:"path,omitempty"`
|
||||||
|
// HTTPHeaders specifies the headers to send with the health request, if
|
||||||
|
// the health check type is "http".
|
||||||
|
HTTPHeaders []HTTPHeader `json:"httpHeaders,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type DomainConfig struct {
|
type DomainConfig struct {
|
||||||
@@ -288,6 +291,7 @@ type HTTPProxyConfig struct {
|
|||||||
HTTPPassword string `json:"httpPassword,omitempty"`
|
HTTPPassword string `json:"httpPassword,omitempty"`
|
||||||
HostHeaderRewrite string `json:"hostHeaderRewrite,omitempty"`
|
HostHeaderRewrite string `json:"hostHeaderRewrite,omitempty"`
|
||||||
RequestHeaders HeaderOperations `json:"requestHeaders,omitempty"`
|
RequestHeaders HeaderOperations `json:"requestHeaders,omitempty"`
|
||||||
|
ResponseHeaders HeaderOperations `json:"responseHeaders,omitempty"`
|
||||||
RouteByHTTPUser string `json:"routeByHTTPUser,omitempty"`
|
RouteByHTTPUser string `json:"routeByHTTPUser,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -301,6 +305,7 @@ func (c *HTTPProxyConfig) MarshalToMsg(m *msg.NewProxy) {
|
|||||||
m.HTTPUser = c.HTTPUser
|
m.HTTPUser = c.HTTPUser
|
||||||
m.HTTPPwd = c.HTTPPassword
|
m.HTTPPwd = c.HTTPPassword
|
||||||
m.Headers = c.RequestHeaders.Set
|
m.Headers = c.RequestHeaders.Set
|
||||||
|
m.ResponseHeaders = c.ResponseHeaders.Set
|
||||||
m.RouteByHTTPUser = c.RouteByHTTPUser
|
m.RouteByHTTPUser = c.RouteByHTTPUser
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -314,6 +319,7 @@ func (c *HTTPProxyConfig) UnmarshalFromMsg(m *msg.NewProxy) {
|
|||||||
c.HTTPUser = m.HTTPUser
|
c.HTTPUser = m.HTTPUser
|
||||||
c.HTTPPassword = m.HTTPPwd
|
c.HTTPPassword = m.HTTPPwd
|
||||||
c.RequestHeaders.Set = m.Headers
|
c.RequestHeaders.Set = m.Headers
|
||||||
|
c.ResponseHeaders.Set = m.ResponseHeaders
|
||||||
c.RouteByHTTPUser = m.RouteByHTTPUser
|
c.RouteByHTTPUser = m.RouteByHTTPUser
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -179,7 +179,12 @@ func (c *ServerTransportConfig) Complete() {
|
|||||||
c.TCPMuxKeepaliveInterval = util.EmptyOr(c.TCPMuxKeepaliveInterval, 60)
|
c.TCPMuxKeepaliveInterval = util.EmptyOr(c.TCPMuxKeepaliveInterval, 60)
|
||||||
c.TCPKeepAlive = util.EmptyOr(c.TCPKeepAlive, 7200)
|
c.TCPKeepAlive = util.EmptyOr(c.TCPKeepAlive, 7200)
|
||||||
c.MaxPoolCount = util.EmptyOr(c.MaxPoolCount, 5)
|
c.MaxPoolCount = util.EmptyOr(c.MaxPoolCount, 5)
|
||||||
c.HeartbeatTimeout = util.EmptyOr(c.HeartbeatTimeout, 90)
|
if lo.FromPtr(c.TCPMux) {
|
||||||
|
// If TCPMux is enabled, heartbeat of application layer is unnecessary because we can rely on heartbeat in tcpmux.
|
||||||
|
c.HeartbeatTimeout = util.EmptyOr(c.HeartbeatTimeout, -1)
|
||||||
|
} else {
|
||||||
|
c.HeartbeatTimeout = util.EmptyOr(c.HeartbeatTimeout, 90)
|
||||||
|
}
|
||||||
c.QUIC.Complete()
|
c.QUIC.Complete()
|
||||||
if c.TLS.TrustedCaFile != "" {
|
if c.TLS.TrustedCaFile != "" {
|
||||||
c.TLS.Force = true
|
c.TLS.Force = true
|
||||||
|
@@ -121,6 +121,7 @@ type NewProxy struct {
|
|||||||
HTTPPwd string `json:"http_pwd,omitempty"`
|
HTTPPwd string `json:"http_pwd,omitempty"`
|
||||||
HostHeaderRewrite string `json:"host_header_rewrite,omitempty"`
|
HostHeaderRewrite string `json:"host_header_rewrite,omitempty"`
|
||||||
Headers map[string]string `json:"headers,omitempty"`
|
Headers map[string]string `json:"headers,omitempty"`
|
||||||
|
ResponseHeaders map[string]string `json:"response_headers,omitempty"`
|
||||||
RouteByHTTPUser string `json:"route_by_http_user,omitempty"`
|
RouteByHTTPUser string `json:"route_by_http_user,omitempty"`
|
||||||
|
|
||||||
// stcp, sudp, xtcp
|
// stcp, sudp, xtcp
|
||||||
|
@@ -17,7 +17,7 @@ package nathole
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/rand"
|
"math/rand/v2"
|
||||||
"net"
|
"net"
|
||||||
"slices"
|
"slices"
|
||||||
"strconv"
|
"strconv"
|
||||||
@@ -341,7 +341,7 @@ func sendSidMessage(
|
|||||||
TransactionID: transactionID,
|
TransactionID: transactionID,
|
||||||
Sid: sid,
|
Sid: sid,
|
||||||
Response: false,
|
Response: false,
|
||||||
Nonce: strings.Repeat("0", rand.Intn(20)),
|
Nonce: strings.Repeat("0", rand.IntN(20)),
|
||||||
}
|
}
|
||||||
buf, err := EncodeMessage(m, key)
|
buf, err := EncodeMessage(m, key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -398,7 +398,7 @@ func sendSidMessageToRandomPorts(
|
|||||||
used := sets.New[int]()
|
used := sets.New[int]()
|
||||||
getUnusedPort := func() int {
|
getUnusedPort := func() int {
|
||||||
for i := 0; i < 10; i++ {
|
for i := 0; i < 10; i++ {
|
||||||
port := rand.Intn(65535-1024) + 1024
|
port := rand.IntN(65535-1024) + 1024
|
||||||
if !used.Has(port) {
|
if !used.Has(port) {
|
||||||
used.Insert(port)
|
used.Insert(port)
|
||||||
return port
|
return port
|
||||||
|
@@ -19,11 +19,15 @@ package plugin
|
|||||||
import (
|
import (
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"io"
|
"io"
|
||||||
|
stdlog "log"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httputil"
|
"net/http/httputil"
|
||||||
|
|
||||||
|
"github.com/fatedier/golib/pool"
|
||||||
|
|
||||||
v1 "github.com/fatedier/frp/pkg/config/v1"
|
v1 "github.com/fatedier/frp/pkg/config/v1"
|
||||||
|
"github.com/fatedier/frp/pkg/util/log"
|
||||||
netpkg "github.com/fatedier/frp/pkg/util/net"
|
netpkg "github.com/fatedier/frp/pkg/util/net"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -54,6 +58,9 @@ func NewHTTP2HTTPSPlugin(options v1.ClientPluginOptions) (Plugin, error) {
|
|||||||
|
|
||||||
rp := &httputil.ReverseProxy{
|
rp := &httputil.ReverseProxy{
|
||||||
Rewrite: func(r *httputil.ProxyRequest) {
|
Rewrite: func(r *httputil.ProxyRequest) {
|
||||||
|
r.Out.Header["X-Forwarded-For"] = r.In.Header["X-Forwarded-For"]
|
||||||
|
r.Out.Header["X-Forwarded-Host"] = r.In.Header["X-Forwarded-Host"]
|
||||||
|
r.Out.Header["X-Forwarded-Proto"] = r.In.Header["X-Forwarded-Proto"]
|
||||||
req := r.Out
|
req := r.Out
|
||||||
req.URL.Scheme = "https"
|
req.URL.Scheme = "https"
|
||||||
req.URL.Host = p.opts.LocalAddr
|
req.URL.Host = p.opts.LocalAddr
|
||||||
@@ -64,7 +71,9 @@ func NewHTTP2HTTPSPlugin(options v1.ClientPluginOptions) (Plugin, error) {
|
|||||||
req.Header.Set(k, v)
|
req.Header.Set(k, v)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Transport: tr,
|
Transport: tr,
|
||||||
|
BufferPool: pool.NewBuffer(32 * 1024),
|
||||||
|
ErrorLog: stdlog.New(log.NewWriteLogger(log.WarnLevel, 2), "", 0),
|
||||||
}
|
}
|
||||||
|
|
||||||
p.s = &http.Server{
|
p.s = &http.Server{
|
||||||
|
@@ -54,7 +54,8 @@ func NewHTTPProxyPlugin(options v1.ClientPluginOptions) (Plugin, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
hp.s = &http.Server{
|
hp.s = &http.Server{
|
||||||
Handler: hp,
|
Handler: hp,
|
||||||
|
ReadHeaderTimeout: 60 * time.Second,
|
||||||
}
|
}
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
|
@@ -20,12 +20,17 @@ import (
|
|||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
stdlog "log"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httputil"
|
"net/http/httputil"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/fatedier/golib/pool"
|
||||||
|
|
||||||
v1 "github.com/fatedier/frp/pkg/config/v1"
|
v1 "github.com/fatedier/frp/pkg/config/v1"
|
||||||
"github.com/fatedier/frp/pkg/transport"
|
"github.com/fatedier/frp/pkg/transport"
|
||||||
|
"github.com/fatedier/frp/pkg/util/log"
|
||||||
netpkg "github.com/fatedier/frp/pkg/util/net"
|
netpkg "github.com/fatedier/frp/pkg/util/net"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -51,6 +56,8 @@ func NewHTTPS2HTTPPlugin(options v1.ClientPluginOptions) (Plugin, error) {
|
|||||||
|
|
||||||
rp := &httputil.ReverseProxy{
|
rp := &httputil.ReverseProxy{
|
||||||
Rewrite: func(r *httputil.ProxyRequest) {
|
Rewrite: func(r *httputil.ProxyRequest) {
|
||||||
|
r.Out.Header["X-Forwarded-For"] = r.In.Header["X-Forwarded-For"]
|
||||||
|
r.SetXForwarded()
|
||||||
req := r.Out
|
req := r.Out
|
||||||
req.URL.Scheme = "http"
|
req.URL.Scheme = "http"
|
||||||
req.URL.Host = p.opts.LocalAddr
|
req.URL.Host = p.opts.LocalAddr
|
||||||
@@ -61,10 +68,13 @@ func NewHTTPS2HTTPPlugin(options v1.ClientPluginOptions) (Plugin, error) {
|
|||||||
req.Header.Set(k, v)
|
req.Header.Set(k, v)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
BufferPool: pool.NewBuffer(32 * 1024),
|
||||||
|
ErrorLog: stdlog.New(log.NewWriteLogger(log.WarnLevel, 2), "", 0),
|
||||||
}
|
}
|
||||||
|
|
||||||
p.s = &http.Server{
|
p.s = &http.Server{
|
||||||
Handler: rp,
|
Handler: rp,
|
||||||
|
ReadHeaderTimeout: 60 * time.Second,
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -98,8 +108,11 @@ func (p *HTTPS2HTTPPlugin) genTLSConfig() (*tls.Config, error) {
|
|||||||
return config, nil
|
return config, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *HTTPS2HTTPPlugin) Handle(conn io.ReadWriteCloser, realConn net.Conn, _ *ExtraInfo) {
|
func (p *HTTPS2HTTPPlugin) Handle(conn io.ReadWriteCloser, realConn net.Conn, extra *ExtraInfo) {
|
||||||
wrapConn := netpkg.WrapReadWriteCloserToConn(conn, realConn)
|
wrapConn := netpkg.WrapReadWriteCloserToConn(conn, realConn)
|
||||||
|
if extra.SrcAddr != nil {
|
||||||
|
wrapConn.SetRemoteAddr(extra.SrcAddr)
|
||||||
|
}
|
||||||
_ = p.l.PutConn(wrapConn)
|
_ = p.l.PutConn(wrapConn)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -20,12 +20,17 @@ import (
|
|||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
stdlog "log"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httputil"
|
"net/http/httputil"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/fatedier/golib/pool"
|
||||||
|
|
||||||
v1 "github.com/fatedier/frp/pkg/config/v1"
|
v1 "github.com/fatedier/frp/pkg/config/v1"
|
||||||
"github.com/fatedier/frp/pkg/transport"
|
"github.com/fatedier/frp/pkg/transport"
|
||||||
|
"github.com/fatedier/frp/pkg/util/log"
|
||||||
netpkg "github.com/fatedier/frp/pkg/util/net"
|
netpkg "github.com/fatedier/frp/pkg/util/net"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -56,6 +61,8 @@ func NewHTTPS2HTTPSPlugin(options v1.ClientPluginOptions) (Plugin, error) {
|
|||||||
|
|
||||||
rp := &httputil.ReverseProxy{
|
rp := &httputil.ReverseProxy{
|
||||||
Rewrite: func(r *httputil.ProxyRequest) {
|
Rewrite: func(r *httputil.ProxyRequest) {
|
||||||
|
r.Out.Header["X-Forwarded-For"] = r.In.Header["X-Forwarded-For"]
|
||||||
|
r.SetXForwarded()
|
||||||
req := r.Out
|
req := r.Out
|
||||||
req.URL.Scheme = "https"
|
req.URL.Scheme = "https"
|
||||||
req.URL.Host = p.opts.LocalAddr
|
req.URL.Host = p.opts.LocalAddr
|
||||||
@@ -66,11 +73,14 @@ func NewHTTPS2HTTPSPlugin(options v1.ClientPluginOptions) (Plugin, error) {
|
|||||||
req.Header.Set(k, v)
|
req.Header.Set(k, v)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Transport: tr,
|
Transport: tr,
|
||||||
|
BufferPool: pool.NewBuffer(32 * 1024),
|
||||||
|
ErrorLog: stdlog.New(log.NewWriteLogger(log.WarnLevel, 2), "", 0),
|
||||||
}
|
}
|
||||||
|
|
||||||
p.s = &http.Server{
|
p.s = &http.Server{
|
||||||
Handler: rp,
|
Handler: rp,
|
||||||
|
ReadHeaderTimeout: 60 * time.Second,
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -104,8 +114,11 @@ func (p *HTTPS2HTTPSPlugin) genTLSConfig() (*tls.Config, error) {
|
|||||||
return config, nil
|
return config, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *HTTPS2HTTPSPlugin) Handle(conn io.ReadWriteCloser, realConn net.Conn, _ *ExtraInfo) {
|
func (p *HTTPS2HTTPSPlugin) Handle(conn io.ReadWriteCloser, realConn net.Conn, extra *ExtraInfo) {
|
||||||
wrapConn := netpkg.WrapReadWriteCloserToConn(conn, realConn)
|
wrapConn := netpkg.WrapReadWriteCloserToConn(conn, realConn)
|
||||||
|
if extra.SrcAddr != nil {
|
||||||
|
wrapConn.SetRemoteAddr(extra.SrcAddr)
|
||||||
|
}
|
||||||
_ = p.l.PutConn(wrapConn)
|
_ = p.l.PutConn(wrapConn)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -50,6 +50,8 @@ func Create(name string, options v1.ClientPluginOptions) (p Plugin, err error) {
|
|||||||
|
|
||||||
type ExtraInfo struct {
|
type ExtraInfo struct {
|
||||||
ProxyProtocolHeader *pp.Header
|
ProxyProtocolHeader *pp.Header
|
||||||
|
SrcAddr net.Addr
|
||||||
|
DstAddr net.Addr
|
||||||
}
|
}
|
||||||
|
|
||||||
type Plugin interface {
|
type Plugin interface {
|
||||||
|
@@ -60,7 +60,8 @@ func NewStaticFilePlugin(options v1.ClientPluginOptions) (Plugin, error) {
|
|||||||
router.Use(netpkg.NewHTTPAuthMiddleware(opts.HTTPUser, opts.HTTPPassword).SetAuthFailDelay(200 * time.Millisecond).Middleware)
|
router.Use(netpkg.NewHTTPAuthMiddleware(opts.HTTPUser, opts.HTTPPassword).SetAuthFailDelay(200 * time.Millisecond).Middleware)
|
||||||
router.PathPrefix(prefix).Handler(netpkg.MakeHTTPGzipHandler(http.StripPrefix(prefix, http.FileServer(http.Dir(opts.LocalPath))))).Methods("GET")
|
router.PathPrefix(prefix).Handler(netpkg.MakeHTTPGzipHandler(http.StripPrefix(prefix, http.FileServer(http.Dir(opts.LocalPath))))).Methods("GET")
|
||||||
sp.s = &http.Server{
|
sp.s = &http.Server{
|
||||||
Handler: router,
|
Handler: router,
|
||||||
|
ReadHeaderTimeout: 60 * time.Second,
|
||||||
}
|
}
|
||||||
go func() {
|
go func() {
|
||||||
_ = sp.s.Serve(listener)
|
_ = sp.s.Serve(listener)
|
||||||
|
@@ -363,11 +363,13 @@ func (s *TunnelServer) waitProxyStatusReady(name string, timeout time.Duration)
|
|||||||
timer := time.NewTimer(timeout)
|
timer := time.NewTimer(timeout)
|
||||||
defer timer.Stop()
|
defer timer.Stop()
|
||||||
|
|
||||||
|
statusExporter := s.vc.Service().StatusExporter()
|
||||||
|
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-ticker.C:
|
case <-ticker.C:
|
||||||
ps, err := s.vc.Service().GetProxyStatus(name)
|
ps, ok := statusExporter.GetProxyStatus(name)
|
||||||
if err != nil {
|
if !ok {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
switch ps.Phase {
|
switch ps.Phase {
|
||||||
|
@@ -15,11 +15,20 @@
|
|||||||
package log
|
package log
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/fatedier/golib/log"
|
"github.com/fatedier/golib/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
TraceLevel = log.TraceLevel
|
||||||
|
DebugLevel = log.DebugLevel
|
||||||
|
InfoLevel = log.InfoLevel
|
||||||
|
WarnLevel = log.WarnLevel
|
||||||
|
ErrorLevel = log.ErrorLevel
|
||||||
|
)
|
||||||
|
|
||||||
var Logger *log.Logger
|
var Logger *log.Logger
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@@ -77,3 +86,24 @@ func Debugf(format string, v ...interface{}) {
|
|||||||
func Tracef(format string, v ...interface{}) {
|
func Tracef(format string, v ...interface{}) {
|
||||||
Logger.Tracef(format, v...)
|
Logger.Tracef(format, v...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Logf(level log.Level, offset int, format string, v ...interface{}) {
|
||||||
|
Logger.Logf(level, offset, format, v...)
|
||||||
|
}
|
||||||
|
|
||||||
|
type WriteLogger struct {
|
||||||
|
level log.Level
|
||||||
|
offset int
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewWriteLogger(level log.Level, offset int) *WriteLogger {
|
||||||
|
return &WriteLogger{
|
||||||
|
level: level,
|
||||||
|
offset: offset,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *WriteLogger) Write(p []byte) (n int, err error) {
|
||||||
|
Logger.Log(w.level, w.offset, string(bytes.TrimRight(p, "\n")))
|
||||||
|
return len(p), nil
|
||||||
|
}
|
||||||
|
@@ -76,9 +76,11 @@ type WrapReadWriteCloserConn struct {
|
|||||||
io.ReadWriteCloser
|
io.ReadWriteCloser
|
||||||
|
|
||||||
underConn net.Conn
|
underConn net.Conn
|
||||||
|
|
||||||
|
remoteAddr net.Addr
|
||||||
}
|
}
|
||||||
|
|
||||||
func WrapReadWriteCloserToConn(rwc io.ReadWriteCloser, underConn net.Conn) net.Conn {
|
func WrapReadWriteCloserToConn(rwc io.ReadWriteCloser, underConn net.Conn) *WrapReadWriteCloserConn {
|
||||||
return &WrapReadWriteCloserConn{
|
return &WrapReadWriteCloserConn{
|
||||||
ReadWriteCloser: rwc,
|
ReadWriteCloser: rwc,
|
||||||
underConn: underConn,
|
underConn: underConn,
|
||||||
@@ -92,7 +94,14 @@ func (conn *WrapReadWriteCloserConn) LocalAddr() net.Addr {
|
|||||||
return (*net.TCPAddr)(nil)
|
return (*net.TCPAddr)(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (conn *WrapReadWriteCloserConn) SetRemoteAddr(addr net.Addr) {
|
||||||
|
conn.remoteAddr = addr
|
||||||
|
}
|
||||||
|
|
||||||
func (conn *WrapReadWriteCloserConn) RemoteAddr() net.Addr {
|
func (conn *WrapReadWriteCloserConn) RemoteAddr() net.Addr {
|
||||||
|
if conn.remoteAddr != nil {
|
||||||
|
return conn.remoteAddr
|
||||||
|
}
|
||||||
if conn.underConn != nil {
|
if conn.underConn != nil {
|
||||||
return conn.underConn.RemoteAddr()
|
return conn.underConn.RemoteAddr()
|
||||||
}
|
}
|
||||||
|
@@ -5,11 +5,11 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
|
||||||
libdial "github.com/fatedier/golib/net/dial"
|
libnet "github.com/fatedier/golib/net"
|
||||||
"golang.org/x/net/websocket"
|
"golang.org/x/net/websocket"
|
||||||
)
|
)
|
||||||
|
|
||||||
func DialHookCustomTLSHeadByte(enableTLS bool, disableCustomTLSHeadByte bool) libdial.AfterHookFunc {
|
func DialHookCustomTLSHeadByte(enableTLS bool, disableCustomTLSHeadByte bool) libnet.AfterHookFunc {
|
||||||
return func(ctx context.Context, c net.Conn, addr string) (context.Context, net.Conn, error) {
|
return func(ctx context.Context, c net.Conn, addr string) (context.Context, net.Conn, error) {
|
||||||
if enableTLS && !disableCustomTLSHeadByte {
|
if enableTLS && !disableCustomTLSHeadByte {
|
||||||
_, err := c.Write([]byte{byte(FRPTLSHeadByte)})
|
_, err := c.Write([]byte{byte(FRPTLSHeadByte)})
|
||||||
@@ -21,7 +21,7 @@ func DialHookCustomTLSHeadByte(enableTLS bool, disableCustomTLSHeadByte bool) li
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func DialHookWebsocket(protocol string, host string) libdial.AfterHookFunc {
|
func DialHookWebsocket(protocol string, host string) libnet.AfterHookFunc {
|
||||||
return func(ctx context.Context, c net.Conn, addr string) (context.Context, net.Conn, error) {
|
return func(ctx context.Context, c net.Conn, addr string) (context.Context, net.Conn, error) {
|
||||||
if protocol != "wss" {
|
if protocol != "wss" {
|
||||||
protocol = "ws"
|
protocol = "ws"
|
||||||
|
@@ -26,8 +26,8 @@ func SetDefaultDNSAddress(dnsAddress string) {
|
|||||||
// Change default dns server
|
// Change default dns server
|
||||||
net.DefaultResolver = &net.Resolver{
|
net.DefaultResolver = &net.Resolver{
|
||||||
PreferGo: true,
|
PreferGo: true,
|
||||||
Dial: func(ctx context.Context, network, address string) (net.Conn, error) {
|
Dial: func(ctx context.Context, network, _ string) (net.Conn, error) {
|
||||||
return net.Dial("udp", dnsAddress)
|
return net.Dial(network, dnsAddress)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -4,6 +4,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"time"
|
||||||
|
|
||||||
"golang.org/x/net/websocket"
|
"golang.org/x/net/websocket"
|
||||||
)
|
)
|
||||||
@@ -39,8 +40,9 @@ func NewWebsocketListener(ln net.Listener) (wl *WebsocketListener) {
|
|||||||
}))
|
}))
|
||||||
|
|
||||||
wl.server = &http.Server{
|
wl.server = &http.Server{
|
||||||
Addr: ln.Addr().String(),
|
Addr: ln.Addr().String(),
|
||||||
Handler: muxer,
|
Handler: muxer,
|
||||||
|
ReadHeaderTimeout: 60 * time.Second,
|
||||||
}
|
}
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
|
22
pkg/util/system/system.go
Normal file
22
pkg/util/system/system.go
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
// Copyright 2024 The frp Authors
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
//go:build !android
|
||||||
|
|
||||||
|
package system
|
||||||
|
|
||||||
|
// EnableCompatibilityMode enables compatibility mode for different system.
|
||||||
|
// For example, on Android, the inability to obtain the correct time zone will result in incorrect log time output.
|
||||||
|
func EnableCompatibilityMode() {
|
||||||
|
}
|
66
pkg/util/system/system_android.go
Normal file
66
pkg/util/system/system_android.go
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
// Copyright 2024 The frp Authors
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package system
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"net"
|
||||||
|
"os/exec"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func EnableCompatibilityMode() {
|
||||||
|
fixTimezone()
|
||||||
|
fixDNSResolver()
|
||||||
|
}
|
||||||
|
|
||||||
|
// fixTimezone is used to try our best to fix timezone issue on some Android devices.
|
||||||
|
func fixTimezone() {
|
||||||
|
out, err := exec.Command("/system/bin/getprop", "persist.sys.timezone").Output()
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
loc, err := time.LoadLocation(strings.TrimSpace(string(out)))
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
time.Local = loc
|
||||||
|
}
|
||||||
|
|
||||||
|
// fixDNSResolver will first attempt to resolve google.com to check if the current DNS is available.
|
||||||
|
// If it is not available, it will default to using 8.8.8.8 as the DNS server.
|
||||||
|
// This is a workaround for the issue that golang can't get the default DNS servers on Android.
|
||||||
|
func fixDNSResolver() {
|
||||||
|
// First, we attempt to resolve a domain. If resolution is successful, no modifications are necessary.
|
||||||
|
// In real-world scenarios, users may have already configured /etc/resolv.conf, or compiled directly
|
||||||
|
// in the Android environment instead of using cross-platform compilation, so this issue does not arise.
|
||||||
|
if net.DefaultResolver != nil {
|
||||||
|
timeoutCtx, cancel := context.WithTimeout(context.Background(), time.Second)
|
||||||
|
defer cancel()
|
||||||
|
_, err := net.DefaultResolver.LookupHost(timeoutCtx, "google.com")
|
||||||
|
if err == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// If the resolution fails, use 8.8.8.8 as the DNS server.
|
||||||
|
// Note: If there are other methods to obtain the default DNS servers, the default DNS servers should be used preferentially.
|
||||||
|
net.DefaultResolver = &net.Resolver{
|
||||||
|
PreferGo: true,
|
||||||
|
Dial: func(ctx context.Context, network, _ string) (net.Conn, error) {
|
||||||
|
return net.Dial(network, "8.8.8.8:53")
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
@@ -20,7 +20,7 @@ import (
|
|||||||
"crypto/subtle"
|
"crypto/subtle"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"fmt"
|
"fmt"
|
||||||
mathrand "math/rand"
|
mathrand "math/rand/v2"
|
||||||
"net"
|
"net"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -124,7 +124,7 @@ func RandomSleep(duration time.Duration, minRatio, maxRatio float64) time.Durati
|
|||||||
if max <= min {
|
if max <= min {
|
||||||
n = min
|
n = min
|
||||||
} else {
|
} else {
|
||||||
n = mathrand.Int63n(max-min) + min
|
n = mathrand.Int64N(max-min) + min
|
||||||
}
|
}
|
||||||
d := duration * time.Duration(n) / time.Duration(1000)
|
d := duration * time.Duration(n) / time.Duration(1000)
|
||||||
time.Sleep(d)
|
time.Sleep(d)
|
||||||
|
@@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
package version
|
package version
|
||||||
|
|
||||||
var version = "0.55.1"
|
var version = "0.57.0"
|
||||||
|
|
||||||
func Full() string {
|
func Full() string {
|
||||||
return version
|
return version
|
||||||
|
@@ -15,7 +15,6 @@
|
|||||||
package vhost
|
package vhost
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"context"
|
"context"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"errors"
|
"errors"
|
||||||
@@ -59,13 +58,14 @@ func NewHTTPReverseProxy(option HTTPReverseProxyOptions, vhostRouter *Routers) *
|
|||||||
proxy := &httputil.ReverseProxy{
|
proxy := &httputil.ReverseProxy{
|
||||||
// Modify incoming requests by route policies.
|
// Modify incoming requests by route policies.
|
||||||
Rewrite: func(r *httputil.ProxyRequest) {
|
Rewrite: func(r *httputil.ProxyRequest) {
|
||||||
|
r.Out.Header["X-Forwarded-For"] = r.In.Header["X-Forwarded-For"]
|
||||||
r.SetXForwarded()
|
r.SetXForwarded()
|
||||||
req := r.Out
|
req := r.Out
|
||||||
req.URL.Scheme = "http"
|
req.URL.Scheme = "http"
|
||||||
reqRouteInfo := req.Context().Value(RouteInfoKey).(*RequestRouteInfo)
|
reqRouteInfo := req.Context().Value(RouteInfoKey).(*RequestRouteInfo)
|
||||||
oldHost, _ := httppkg.CanonicalHost(reqRouteInfo.Host)
|
originalHost, _ := httppkg.CanonicalHost(reqRouteInfo.Host)
|
||||||
|
|
||||||
rc := rp.GetRouteConfig(oldHost, reqRouteInfo.URL, reqRouteInfo.HTTPUser)
|
rc := req.Context().Value(RouteConfigKey).(*RouteConfig)
|
||||||
if rc != nil {
|
if rc != nil {
|
||||||
if rc.RewriteHost != "" {
|
if rc.RewriteHost != "" {
|
||||||
req.Host = rc.RewriteHost
|
req.Host = rc.RewriteHost
|
||||||
@@ -77,7 +77,7 @@ func NewHTTPReverseProxy(option HTTPReverseProxyOptions, vhostRouter *Routers) *
|
|||||||
endpoint, _ = rc.ChooseEndpointFn()
|
endpoint, _ = rc.ChooseEndpointFn()
|
||||||
reqRouteInfo.Endpoint = endpoint
|
reqRouteInfo.Endpoint = endpoint
|
||||||
log.Tracef("choose endpoint name [%s] for http request host [%s] path [%s] httpuser [%s]",
|
log.Tracef("choose endpoint name [%s] for http request host [%s] path [%s] httpuser [%s]",
|
||||||
endpoint, oldHost, reqRouteInfo.URL, reqRouteInfo.HTTPUser)
|
endpoint, originalHost, reqRouteInfo.URL, reqRouteInfo.HTTPUser)
|
||||||
}
|
}
|
||||||
// Set {domain}.{location}.{routeByHTTPUser}.{endpoint} as URL host here to let http transport reuse connections.
|
// Set {domain}.{location}.{routeByHTTPUser}.{endpoint} as URL host here to let http transport reuse connections.
|
||||||
req.URL.Host = rc.Domain + "." +
|
req.URL.Host = rc.Domain + "." +
|
||||||
@@ -92,6 +92,15 @@ func NewHTTPReverseProxy(option HTTPReverseProxyOptions, vhostRouter *Routers) *
|
|||||||
req.URL.Host = req.Host
|
req.URL.Host = req.Host
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
ModifyResponse: func(r *http.Response) error {
|
||||||
|
rc := r.Request.Context().Value(RouteConfigKey).(*RouteConfig)
|
||||||
|
if rc != nil {
|
||||||
|
for k, v := range rc.ResponseHeaders {
|
||||||
|
r.Header.Set(k, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
},
|
||||||
// Create a connection to one proxy routed by route policy.
|
// Create a connection to one proxy routed by route policy.
|
||||||
Transport: &http.Transport{
|
Transport: &http.Transport{
|
||||||
ResponseHeaderTimeout: rp.responseHeaderTimeout,
|
ResponseHeaderTimeout: rp.responseHeaderTimeout,
|
||||||
@@ -115,10 +124,16 @@ func NewHTTPReverseProxy(option HTTPReverseProxyOptions, vhostRouter *Routers) *
|
|||||||
return nil, nil
|
return nil, nil
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
BufferPool: newWrapPool(),
|
BufferPool: pool.NewBuffer(32 * 1024),
|
||||||
ErrorLog: stdlog.New(newWrapLogger(), "", 0),
|
ErrorLog: stdlog.New(log.NewWriteLogger(log.WarnLevel, 2), "", 0),
|
||||||
ErrorHandler: func(rw http.ResponseWriter, req *http.Request, err error) {
|
ErrorHandler: func(rw http.ResponseWriter, req *http.Request, err error) {
|
||||||
log.Warnf("do http proxy request [host: %s] error: %v", req.Host, err)
|
log.Logf(log.WarnLevel, 1, "do http proxy request [host: %s] error: %v", req.Host, err)
|
||||||
|
if err != nil {
|
||||||
|
if e, ok := err.(net.Error); ok && e.Timeout() {
|
||||||
|
rw.WriteHeader(http.StatusGatewayTimeout)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
rw.WriteHeader(http.StatusNotFound)
|
rw.WriteHeader(http.StatusNotFound)
|
||||||
_, _ = rw.Write(getNotFoundPageContent())
|
_, _ = rw.Write(getNotFoundPageContent())
|
||||||
},
|
},
|
||||||
@@ -151,14 +166,6 @@ func (rp *HTTPReverseProxy) GetRouteConfig(domain, location, routeByHTTPUser str
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rp *HTTPReverseProxy) GetHeaders(domain, location, routeByHTTPUser string) (headers map[string]string) {
|
|
||||||
vr, ok := rp.getVhost(domain, location, routeByHTTPUser)
|
|
||||||
if ok {
|
|
||||||
headers = vr.payload.(*RouteConfig).Headers
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateConnection create a new connection by route config
|
// CreateConnection create a new connection by route config
|
||||||
func (rp *HTTPReverseProxy) CreateConnection(reqRouteInfo *RequestRouteInfo, byEndpoint bool) (net.Conn, error) {
|
func (rp *HTTPReverseProxy) CreateConnection(reqRouteInfo *RequestRouteInfo, byEndpoint bool) (net.Conn, error) {
|
||||||
host, _ := httppkg.CanonicalHost(reqRouteInfo.Host)
|
host, _ := httppkg.CanonicalHost(reqRouteInfo.Host)
|
||||||
@@ -299,8 +306,13 @@ func (rp *HTTPReverseProxy) injectRequestInfoToCtx(req *http.Request) *http.Requ
|
|||||||
RemoteAddr: req.RemoteAddr,
|
RemoteAddr: req.RemoteAddr,
|
||||||
URLHost: req.URL.Host,
|
URLHost: req.URL.Host,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
originalHost, _ := httppkg.CanonicalHost(reqRouteInfo.Host)
|
||||||
|
rc := rp.GetRouteConfig(originalHost, reqRouteInfo.URL, reqRouteInfo.HTTPUser)
|
||||||
|
|
||||||
newctx := req.Context()
|
newctx := req.Context()
|
||||||
newctx = context.WithValue(newctx, RouteInfoKey, reqRouteInfo)
|
newctx = context.WithValue(newctx, RouteInfoKey, reqRouteInfo)
|
||||||
|
newctx = context.WithValue(newctx, RouteConfigKey, rc)
|
||||||
return req.Clone(newctx)
|
return req.Clone(newctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -321,20 +333,3 @@ func (rp *HTTPReverseProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request)
|
|||||||
rp.proxy.ServeHTTP(rw, newreq)
|
rp.proxy.ServeHTTP(rw, newreq)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type wrapPool struct{}
|
|
||||||
|
|
||||||
func newWrapPool() *wrapPool { return &wrapPool{} }
|
|
||||||
|
|
||||||
func (p *wrapPool) Get() []byte { return pool.GetBuf(32 * 1024) }
|
|
||||||
|
|
||||||
func (p *wrapPool) Put(buf []byte) { pool.PutBuf(buf) }
|
|
||||||
|
|
||||||
type wrapLogger struct{}
|
|
||||||
|
|
||||||
func newWrapLogger() *wrapLogger { return &wrapLogger{} }
|
|
||||||
|
|
||||||
func (l *wrapLogger) Write(p []byte) (n int, err error) {
|
|
||||||
log.Warnf("%s", string(bytes.TrimRight(p, "\n")))
|
|
||||||
return len(p), nil
|
|
||||||
}
|
|
||||||
|
@@ -12,7 +12,7 @@ import (
|
|||||||
func TestGetHTTPSHostname(t *testing.T) {
|
func TestGetHTTPSHostname(t *testing.T) {
|
||||||
require := require.New(t)
|
require := require.New(t)
|
||||||
|
|
||||||
l, err := net.Listen("tcp", ":")
|
l, err := net.Listen("tcp", "127.0.0.1:")
|
||||||
require.NoError(err)
|
require.NoError(err)
|
||||||
defer l.Close()
|
defer l.Close()
|
||||||
|
|
||||||
|
@@ -29,7 +29,8 @@ import (
|
|||||||
type RouteInfo string
|
type RouteInfo string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
RouteInfoKey RouteInfo = "routeInfo"
|
RouteInfoKey RouteInfo = "routeInfo"
|
||||||
|
RouteConfigKey RouteInfo = "routeConfig"
|
||||||
)
|
)
|
||||||
|
|
||||||
type RequestRouteInfo struct {
|
type RequestRouteInfo struct {
|
||||||
@@ -113,6 +114,7 @@ type RouteConfig struct {
|
|||||||
Username string
|
Username string
|
||||||
Password string
|
Password string
|
||||||
Headers map[string]string
|
Headers map[string]string
|
||||||
|
ResponseHeaders map[string]string
|
||||||
RouteByHTTPUser string
|
RouteByHTTPUser string
|
||||||
|
|
||||||
CreateConnFn CreateConnFunc
|
CreateConnFn CreateConnFunc
|
||||||
|
@@ -15,7 +15,7 @@
|
|||||||
package wait
|
package wait
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"math/rand"
|
"math/rand/v2"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/fatedier/frp/pkg/util/util"
|
"github.com/fatedier/frp/pkg/util/util"
|
||||||
|
@@ -297,20 +297,18 @@ func (ctl *Control) GetWorkConn() (workConn net.Conn, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (ctl *Control) heartbeatWorker() {
|
func (ctl *Control) heartbeatWorker() {
|
||||||
xl := ctl.xl
|
if ctl.serverCfg.Transport.HeartbeatTimeout <= 0 {
|
||||||
|
return
|
||||||
// Don't need application heartbeat if TCPMux is enabled,
|
|
||||||
// yamux will do same thing.
|
|
||||||
// TODO(fatedier): let default HeartbeatTimeout to -1 if TCPMux is enabled. Users can still set it to positive value to enable it.
|
|
||||||
if !lo.FromPtr(ctl.serverCfg.Transport.TCPMux) && ctl.serverCfg.Transport.HeartbeatTimeout > 0 {
|
|
||||||
go wait.Until(func() {
|
|
||||||
if time.Since(ctl.lastPing.Load().(time.Time)) > time.Duration(ctl.serverCfg.Transport.HeartbeatTimeout)*time.Second {
|
|
||||||
xl.Warnf("heartbeat timeout")
|
|
||||||
ctl.conn.Close()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}, time.Second, ctl.doneCh)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
xl := ctl.xl
|
||||||
|
go wait.Until(func() {
|
||||||
|
if time.Since(ctl.lastPing.Load().(time.Time)) > time.Duration(ctl.serverCfg.Transport.HeartbeatTimeout)*time.Second {
|
||||||
|
xl.Warnf("heartbeat timeout")
|
||||||
|
ctl.conn.Close()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}, time.Second, ctl.doneCh)
|
||||||
}
|
}
|
||||||
|
|
||||||
// block until Control closed
|
// block until Control closed
|
||||||
|
@@ -32,8 +32,6 @@ import (
|
|||||||
"github.com/fatedier/frp/pkg/util/version"
|
"github.com/fatedier/frp/pkg/util/version"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TODO(fatedier): add an API to clean status of all offline proxies.
|
|
||||||
|
|
||||||
type GeneralResponse struct {
|
type GeneralResponse struct {
|
||||||
Code int
|
Code int
|
||||||
Msg string
|
Msg string
|
||||||
@@ -146,7 +144,8 @@ type TCPOutConf struct {
|
|||||||
type TCPMuxOutConf struct {
|
type TCPMuxOutConf struct {
|
||||||
BaseOutConf
|
BaseOutConf
|
||||||
v1.DomainConfig
|
v1.DomainConfig
|
||||||
Multiplexer string `json:"multiplexer"`
|
Multiplexer string `json:"multiplexer"`
|
||||||
|
RouteByHTTPUser string `json:"routeByHTTPUser"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type UDPOutConf struct {
|
type UDPOutConf struct {
|
||||||
|
@@ -58,6 +58,7 @@ func (pxy *HTTPProxy) Run() (remoteAddr string, err error) {
|
|||||||
RewriteHost: pxy.cfg.HostHeaderRewrite,
|
RewriteHost: pxy.cfg.HostHeaderRewrite,
|
||||||
RouteByHTTPUser: pxy.cfg.RouteByHTTPUser,
|
RouteByHTTPUser: pxy.cfg.RouteByHTTPUser,
|
||||||
Headers: pxy.cfg.RequestHeaders.Set,
|
Headers: pxy.cfg.RequestHeaders.Set,
|
||||||
|
ResponseHeaders: pxy.cfg.ResponseHeaders.Set,
|
||||||
Username: pxy.cfg.HTTPUser,
|
Username: pxy.cfg.HTTPUser,
|
||||||
Password: pxy.cfg.HTTPPassword,
|
Password: pxy.cfg.HTTPPassword,
|
||||||
CreateConnFn: pxy.GetRealConn,
|
CreateConnFn: pxy.GetRealConn,
|
||||||
|
@@ -22,9 +22,11 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/fatedier/golib/crypto"
|
||||||
"github.com/fatedier/golib/net/mux"
|
"github.com/fatedier/golib/net/mux"
|
||||||
fmux "github.com/hashicorp/yamux"
|
fmux "github.com/hashicorp/yamux"
|
||||||
quic "github.com/quic-go/quic-go"
|
quic "github.com/quic-go/quic-go"
|
||||||
@@ -59,6 +61,16 @@ const (
|
|||||||
vhostReadWriteTimeout time.Duration = 30 * time.Second
|
vhostReadWriteTimeout time.Duration = 30 * time.Second
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
crypto.DefaultSalt = "frp"
|
||||||
|
// Disable quic-go's receive buffer warning.
|
||||||
|
os.Setenv("QUIC_GO_DISABLE_RECEIVE_BUFFER_WARNING", "true")
|
||||||
|
// Disable quic-go's ECN support by default. It may cause issues on certain operating systems.
|
||||||
|
if os.Getenv("QUIC_GO_DISABLE_ECN") == "" {
|
||||||
|
os.Setenv("QUIC_GO_DISABLE_ECN", "true")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Server service
|
// Server service
|
||||||
type Service struct {
|
type Service struct {
|
||||||
// Dispatch connections to different handlers listen on same port
|
// Dispatch connections to different handlers listen on same port
|
||||||
@@ -274,12 +286,13 @@ func NewService(cfg *v1.ServerConfig) (*Service, error) {
|
|||||||
|
|
||||||
address := net.JoinHostPort(cfg.ProxyBindAddr, strconv.Itoa(cfg.VhostHTTPPort))
|
address := net.JoinHostPort(cfg.ProxyBindAddr, strconv.Itoa(cfg.VhostHTTPPort))
|
||||||
server := &http.Server{
|
server := &http.Server{
|
||||||
Addr: address,
|
Addr: address,
|
||||||
Handler: rp,
|
Handler: rp,
|
||||||
|
ReadHeaderTimeout: 60 * time.Second,
|
||||||
}
|
}
|
||||||
var l net.Listener
|
var l net.Listener
|
||||||
if httpMuxOn {
|
if httpMuxOn {
|
||||||
l = svr.muxer.ListenHttp(1)
|
l = svr.muxer.ListenHTTP(1)
|
||||||
} else {
|
} else {
|
||||||
l, err = net.Listen("tcp", address)
|
l, err = net.Listen("tcp", address)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -296,7 +309,7 @@ func NewService(cfg *v1.ServerConfig) (*Service, error) {
|
|||||||
if cfg.VhostHTTPSPort > 0 {
|
if cfg.VhostHTTPSPort > 0 {
|
||||||
var l net.Listener
|
var l net.Listener
|
||||||
if httpsMuxOn {
|
if httpsMuxOn {
|
||||||
l = svr.muxer.ListenHttps(1)
|
l = svr.muxer.ListenHTTPS(1)
|
||||||
} else {
|
} else {
|
||||||
address := net.JoinHostPort(cfg.ProxyBindAddr, strconv.Itoa(cfg.VhostHTTPSPort))
|
address := net.JoinHostPort(cfg.ProxyBindAddr, strconv.Itoa(cfg.VhostHTTPSPort))
|
||||||
l, err = net.Listen("tcp", address)
|
l, err = net.Listen("tcp", address)
|
||||||
|
@@ -1,11 +1,9 @@
|
|||||||
package framework
|
package framework
|
||||||
|
|
||||||
type FRPClient struct {
|
import (
|
||||||
port int
|
clientsdk "github.com/fatedier/frp/pkg/sdk/client"
|
||||||
}
|
)
|
||||||
|
|
||||||
func (f *Framework) FRPClient(port int) *FRPClient {
|
func (f *Framework) APIClientForFrpc(port int) *clientsdk.Client {
|
||||||
return &FRPClient{
|
return clientsdk.New("127.0.0.1", port)
|
||||||
port: port,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -43,6 +43,10 @@ func ExpectNoErrorWithOffset(offset int, err error, explain ...interface{}) {
|
|||||||
gomega.ExpectWithOffset(1+offset, err).NotTo(gomega.HaveOccurred(), explain...)
|
gomega.ExpectWithOffset(1+offset, err).NotTo(gomega.HaveOccurred(), explain...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ExpectContainSubstring(actual, substr string, explain ...interface{}) {
|
||||||
|
gomega.ExpectWithOffset(1, actual).To(gomega.ContainSubstring(substr), explain...)
|
||||||
|
}
|
||||||
|
|
||||||
// ExpectConsistOf expects actual contains precisely the extra elements. The ordering of the elements does not matter.
|
// ExpectConsistOf expects actual contains precisely the extra elements. The ordering of the elements does not matter.
|
||||||
func ExpectConsistOf(actual interface{}, extra interface{}, explain ...interface{}) {
|
func ExpectConsistOf(actual interface{}, extra interface{}, explain ...interface{}) {
|
||||||
gomega.ExpectWithOffset(1, actual).To(gomega.ConsistOf(extra), explain...)
|
gomega.ExpectWithOffset(1, actual).To(gomega.ConsistOf(extra), explain...)
|
||||||
|
@@ -217,7 +217,7 @@ func (f *Framework) RenderTemplates(templates []string) (outs []string, ports ma
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, t := range templates {
|
for _, t := range templates {
|
||||||
tmpl, err := template.New("").Parse(t)
|
tmpl, err := template.New("frp-e2e").Parse(t)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
@@ -260,7 +260,7 @@ func (f *Framework) SetEnvs(envs []string) {
|
|||||||
|
|
||||||
func (f *Framework) WriteTempFile(name string, content string) string {
|
func (f *Framework) WriteTempFile(name string, content string) string {
|
||||||
filePath := filepath.Join(f.TempDirectory, name)
|
filePath := filepath.Join(f.TempDirectory, name)
|
||||||
err := os.WriteFile(filePath, []byte(content), 0o766)
|
err := os.WriteFile(filePath, []byte(content), 0o600)
|
||||||
ExpectNoError(err)
|
ExpectNoError(err)
|
||||||
return filePath
|
return filePath
|
||||||
}
|
}
|
||||||
|
@@ -27,7 +27,7 @@ func (f *Framework) RunProcesses(serverTemplates []string, clientTemplates []str
|
|||||||
currentServerProcesses := make([]*process.Process, 0, len(serverTemplates))
|
currentServerProcesses := make([]*process.Process, 0, len(serverTemplates))
|
||||||
for i := range serverTemplates {
|
for i := range serverTemplates {
|
||||||
path := filepath.Join(f.TempDirectory, fmt.Sprintf("frp-e2e-server-%d", i))
|
path := filepath.Join(f.TempDirectory, fmt.Sprintf("frp-e2e-server-%d", i))
|
||||||
err = os.WriteFile(path, []byte(outs[i]), 0o666)
|
err = os.WriteFile(path, []byte(outs[i]), 0o600)
|
||||||
ExpectNoError(err)
|
ExpectNoError(err)
|
||||||
|
|
||||||
if TestContext.Debug {
|
if TestContext.Debug {
|
||||||
@@ -48,7 +48,7 @@ func (f *Framework) RunProcesses(serverTemplates []string, clientTemplates []str
|
|||||||
for i := range clientTemplates {
|
for i := range clientTemplates {
|
||||||
index := i + len(serverTemplates)
|
index := i + len(serverTemplates)
|
||||||
path := filepath.Join(f.TempDirectory, fmt.Sprintf("frp-e2e-client-%d", i))
|
path := filepath.Join(f.TempDirectory, fmt.Sprintf("frp-e2e-client-%d", i))
|
||||||
err = os.WriteFile(path, []byte(outs[index]), 0o666)
|
err = os.WriteFile(path, []byte(outs[index]), 0o600)
|
||||||
ExpectNoError(err)
|
ExpectNoError(err)
|
||||||
|
|
||||||
if TestContext.Debug {
|
if TestContext.Debug {
|
||||||
@@ -94,7 +94,7 @@ func (f *Framework) RunFrpc(args ...string) (*process.Process, string, error) {
|
|||||||
func (f *Framework) GenerateConfigFile(content string) string {
|
func (f *Framework) GenerateConfigFile(content string) string {
|
||||||
f.configFileIndex++
|
f.configFileIndex++
|
||||||
path := filepath.Join(f.TempDirectory, fmt.Sprintf("frp-e2e-config-%d", f.configFileIndex))
|
path := filepath.Join(f.TempDirectory, fmt.Sprintf("frp-e2e-config-%d", f.configFileIndex))
|
||||||
err := os.WriteFile(path, []byte(content), 0o666)
|
err := os.WriteFile(path, []byte(content), 0o600)
|
||||||
ExpectNoError(err)
|
ExpectNoError(err)
|
||||||
return path
|
return path
|
||||||
}
|
}
|
||||||
|
@@ -113,7 +113,7 @@ func (e *RequestExpect) Ensure(fns ...EnsureFunc) {
|
|||||||
if !bytes.Equal(e.expectResp, ret.Content) {
|
if !bytes.Equal(e.expectResp, ret.Content) {
|
||||||
flog.Tracef("Response info: %+v", ret)
|
flog.Tracef("Response info: %+v", ret)
|
||||||
}
|
}
|
||||||
ExpectEqualValuesWithOffset(1, ret.Content, e.expectResp, e.explain...)
|
ExpectEqualValuesWithOffset(1, string(ret.Content), string(e.expectResp), e.explain...)
|
||||||
} else {
|
} else {
|
||||||
for _, fn := range fns {
|
for _, fn := range fns {
|
||||||
ok := fn(ret)
|
ok := fn(ret)
|
||||||
|
@@ -8,7 +8,6 @@ import (
|
|||||||
|
|
||||||
"github.com/onsi/ginkgo/v2"
|
"github.com/onsi/ginkgo/v2"
|
||||||
|
|
||||||
clientsdk "github.com/fatedier/frp/pkg/sdk/client"
|
|
||||||
"github.com/fatedier/frp/test/e2e/framework"
|
"github.com/fatedier/frp/test/e2e/framework"
|
||||||
"github.com/fatedier/frp/test/e2e/framework/consts"
|
"github.com/fatedier/frp/test/e2e/framework/consts"
|
||||||
"github.com/fatedier/frp/test/e2e/pkg/request"
|
"github.com/fatedier/frp/test/e2e/pkg/request"
|
||||||
@@ -54,7 +53,7 @@ var _ = ginkgo.Describe("[Feature: ClientManage]", func() {
|
|||||||
framework.NewRequestExpect(f).Port(p2Port).Ensure()
|
framework.NewRequestExpect(f).Port(p2Port).Ensure()
|
||||||
framework.NewRequestExpect(f).Port(p3Port).Ensure()
|
framework.NewRequestExpect(f).Port(p3Port).Ensure()
|
||||||
|
|
||||||
client := clientsdk.New("127.0.0.1", adminPort)
|
client := f.APIClientForFrpc(adminPort)
|
||||||
conf, err := client.GetConfig()
|
conf, err := client.GetConfig()
|
||||||
framework.ExpectNoError(err)
|
framework.ExpectNoError(err)
|
||||||
|
|
||||||
@@ -120,7 +119,7 @@ var _ = ginkgo.Describe("[Feature: ClientManage]", func() {
|
|||||||
|
|
||||||
framework.NewRequestExpect(f).Port(testPort).Ensure()
|
framework.NewRequestExpect(f).Port(testPort).Ensure()
|
||||||
|
|
||||||
client := clientsdk.New("127.0.0.1", adminPort)
|
client := f.APIClientForFrpc(adminPort)
|
||||||
err := client.Stop()
|
err := client.Stop()
|
||||||
framework.ExpectNoError(err)
|
framework.ExpectNoError(err)
|
||||||
|
|
||||||
|
@@ -7,7 +7,6 @@ import (
|
|||||||
|
|
||||||
"github.com/onsi/ginkgo/v2"
|
"github.com/onsi/ginkgo/v2"
|
||||||
|
|
||||||
clientsdk "github.com/fatedier/frp/pkg/sdk/client"
|
|
||||||
"github.com/fatedier/frp/test/e2e/framework"
|
"github.com/fatedier/frp/test/e2e/framework"
|
||||||
"github.com/fatedier/frp/test/e2e/framework/consts"
|
"github.com/fatedier/frp/test/e2e/framework/consts"
|
||||||
"github.com/fatedier/frp/test/e2e/pkg/port"
|
"github.com/fatedier/frp/test/e2e/pkg/port"
|
||||||
@@ -99,7 +98,7 @@ var _ = ginkgo.Describe("[Feature: Server Manager]", func() {
|
|||||||
|
|
||||||
f.RunProcesses([]string{serverConf}, []string{clientConf})
|
f.RunProcesses([]string{serverConf}, []string{clientConf})
|
||||||
|
|
||||||
client := clientsdk.New("127.0.0.1", adminPort)
|
client := f.APIClientForFrpc(adminPort)
|
||||||
|
|
||||||
// tcp random port
|
// tcp random port
|
||||||
status, err := client.GetProxyStatus("tcp")
|
status, err := client.GetProxyStatus("tcp")
|
||||||
|
@@ -12,7 +12,7 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
libdial "github.com/fatedier/golib/net/dial"
|
libnet "github.com/fatedier/golib/net"
|
||||||
|
|
||||||
httppkg "github.com/fatedier/frp/pkg/util/http"
|
httppkg "github.com/fatedier/frp/pkg/util/http"
|
||||||
"github.com/fatedier/frp/test/e2e/pkg/rpc"
|
"github.com/fatedier/frp/test/e2e/pkg/rpc"
|
||||||
@@ -160,11 +160,11 @@ func (r *Request) Do() (*Response, error) {
|
|||||||
if r.protocol != "tcp" {
|
if r.protocol != "tcp" {
|
||||||
return nil, fmt.Errorf("only tcp protocol is allowed for proxy")
|
return nil, fmt.Errorf("only tcp protocol is allowed for proxy")
|
||||||
}
|
}
|
||||||
proxyType, proxyAddress, auth, err := libdial.ParseProxyURL(r.proxyURL)
|
proxyType, proxyAddress, auth, err := libnet.ParseProxyURL(r.proxyURL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("parse ProxyURL error: %v", err)
|
return nil, fmt.Errorf("parse ProxyURL error: %v", err)
|
||||||
}
|
}
|
||||||
conn, err = libdial.Dial(addr, libdial.WithProxy(proxyType, proxyAddress), libdial.WithProxyAuth(auth))
|
conn, err = libnet.Dial(addr, libnet.WithProxy(proxyType, proxyAddress), libnet.WithProxyAuth(auth))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@@ -8,7 +8,6 @@ import (
|
|||||||
|
|
||||||
"github.com/onsi/ginkgo/v2"
|
"github.com/onsi/ginkgo/v2"
|
||||||
|
|
||||||
clientsdk "github.com/fatedier/frp/pkg/sdk/client"
|
|
||||||
"github.com/fatedier/frp/test/e2e/framework"
|
"github.com/fatedier/frp/test/e2e/framework"
|
||||||
"github.com/fatedier/frp/test/e2e/framework/consts"
|
"github.com/fatedier/frp/test/e2e/framework/consts"
|
||||||
"github.com/fatedier/frp/test/e2e/pkg/request"
|
"github.com/fatedier/frp/test/e2e/pkg/request"
|
||||||
@@ -57,7 +56,7 @@ var _ = ginkgo.Describe("[Feature: ClientManage]", func() {
|
|||||||
framework.NewRequestExpect(f).Port(p2Port).Ensure()
|
framework.NewRequestExpect(f).Port(p2Port).Ensure()
|
||||||
framework.NewRequestExpect(f).Port(p3Port).Ensure()
|
framework.NewRequestExpect(f).Port(p3Port).Ensure()
|
||||||
|
|
||||||
client := clientsdk.New("127.0.0.1", adminPort)
|
client := f.APIClientForFrpc(adminPort)
|
||||||
conf, err := client.GetConfig()
|
conf, err := client.GetConfig()
|
||||||
framework.ExpectNoError(err)
|
framework.ExpectNoError(err)
|
||||||
|
|
||||||
@@ -124,7 +123,7 @@ var _ = ginkgo.Describe("[Feature: ClientManage]", func() {
|
|||||||
|
|
||||||
framework.NewRequestExpect(f).Port(testPort).Ensure()
|
framework.NewRequestExpect(f).Port(testPort).Ensure()
|
||||||
|
|
||||||
client := clientsdk.New("127.0.0.1", adminPort)
|
client := f.APIClientForFrpc(adminPort)
|
||||||
err := client.Stop()
|
err := client.Stop()
|
||||||
framework.ExpectNoError(err)
|
framework.ExpectNoError(err)
|
||||||
|
|
||||||
|
@@ -38,6 +38,51 @@ var _ = ginkgo.Describe("[Feature: Config]", func() {
|
|||||||
|
|
||||||
framework.NewRequestExpect(f).PortName(portName).Ensure()
|
framework.NewRequestExpect(f).PortName(portName).Ensure()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
ginkgo.It("Range ports mapping", func() {
|
||||||
|
serverConf := consts.DefaultServerConfig
|
||||||
|
clientConf := consts.DefaultClientConfig
|
||||||
|
|
||||||
|
adminPort := f.AllocPort()
|
||||||
|
|
||||||
|
localPortsRange := "13010-13012,13014"
|
||||||
|
remotePortsRange := "23010-23012,23014"
|
||||||
|
escapeTemplate := func(s string) string {
|
||||||
|
return "{{ `" + s + "` }}"
|
||||||
|
}
|
||||||
|
clientConf += fmt.Sprintf(`
|
||||||
|
webServer.port = %d
|
||||||
|
|
||||||
|
%s
|
||||||
|
[[proxies]]
|
||||||
|
name = "tcp-%s"
|
||||||
|
type = "tcp"
|
||||||
|
localPort = %s
|
||||||
|
remotePort = %s
|
||||||
|
%s
|
||||||
|
`, adminPort,
|
||||||
|
escapeTemplate(fmt.Sprintf(`{{- range $_, $v := parseNumberRangePair "%s" "%s" }}`, localPortsRange, remotePortsRange)),
|
||||||
|
escapeTemplate("{{ $v.First }}"),
|
||||||
|
escapeTemplate("{{ $v.First }}"),
|
||||||
|
escapeTemplate("{{ $v.Second }}"),
|
||||||
|
escapeTemplate("{{- end }}"),
|
||||||
|
)
|
||||||
|
|
||||||
|
f.RunProcesses([]string{serverConf}, []string{clientConf})
|
||||||
|
|
||||||
|
client := f.APIClientForFrpc(adminPort)
|
||||||
|
checkProxyFn := func(name string, localPort, remotePort int) {
|
||||||
|
status, err := client.GetProxyStatus(name)
|
||||||
|
framework.ExpectNoError(err)
|
||||||
|
|
||||||
|
framework.ExpectContainSubstring(status.LocalAddr, fmt.Sprintf(":%d", localPort))
|
||||||
|
framework.ExpectContainSubstring(status.RemoteAddr, fmt.Sprintf(":%d", remotePort))
|
||||||
|
}
|
||||||
|
checkProxyFn("tcp-13010", 13010, 23010)
|
||||||
|
checkProxyFn("tcp-13011", 13011, 23011)
|
||||||
|
checkProxyFn("tcp-13012", 13012, 23012)
|
||||||
|
checkProxyFn("tcp-13014", 13014, 23014)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
ginkgo.Describe("Includes", func() {
|
ginkgo.Describe("Includes", func() {
|
||||||
|
@@ -5,6 +5,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/gorilla/websocket"
|
"github.com/gorilla/websocket"
|
||||||
"github.com/onsi/ginkgo/v2"
|
"github.com/onsi/ginkgo/v2"
|
||||||
@@ -266,7 +267,7 @@ var _ = ginkgo.Describe("[Feature: HTTP]", func() {
|
|||||||
Ensure()
|
Ensure()
|
||||||
})
|
})
|
||||||
|
|
||||||
ginkgo.It("Modify headers", func() {
|
ginkgo.It("Modify request headers", func() {
|
||||||
vhostHTTPPort := f.AllocPort()
|
vhostHTTPPort := f.AllocPort()
|
||||||
serverConf := getDefaultServerConf(vhostHTTPPort)
|
serverConf := getDefaultServerConf(vhostHTTPPort)
|
||||||
|
|
||||||
@@ -291,7 +292,6 @@ var _ = ginkgo.Describe("[Feature: HTTP]", func() {
|
|||||||
|
|
||||||
f.RunProcesses([]string{serverConf}, []string{clientConf})
|
f.RunProcesses([]string{serverConf}, []string{clientConf})
|
||||||
|
|
||||||
// not set auth header
|
|
||||||
framework.NewRequestExpect(f).Port(vhostHTTPPort).
|
framework.NewRequestExpect(f).Port(vhostHTTPPort).
|
||||||
RequestModify(func(r *request.Request) {
|
RequestModify(func(r *request.Request) {
|
||||||
r.HTTP().HTTPHost("normal.example.com")
|
r.HTTP().HTTPHost("normal.example.com")
|
||||||
@@ -300,6 +300,40 @@ var _ = ginkgo.Describe("[Feature: HTTP]", func() {
|
|||||||
Ensure()
|
Ensure()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
ginkgo.It("Modify response headers", func() {
|
||||||
|
vhostHTTPPort := f.AllocPort()
|
||||||
|
serverConf := getDefaultServerConf(vhostHTTPPort)
|
||||||
|
|
||||||
|
localPort := f.AllocPort()
|
||||||
|
localServer := httpserver.New(
|
||||||
|
httpserver.WithBindPort(localPort),
|
||||||
|
httpserver.WithHandler(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
||||||
|
w.WriteHeader(200)
|
||||||
|
})),
|
||||||
|
)
|
||||||
|
f.RunServer("", localServer)
|
||||||
|
|
||||||
|
clientConf := consts.DefaultClientConfig
|
||||||
|
clientConf += fmt.Sprintf(`
|
||||||
|
[[proxies]]
|
||||||
|
name = "test"
|
||||||
|
type = "http"
|
||||||
|
localPort = %d
|
||||||
|
customDomains = ["normal.example.com"]
|
||||||
|
responseHeaders.set.x-from-where = "frp"
|
||||||
|
`, localPort)
|
||||||
|
|
||||||
|
f.RunProcesses([]string{serverConf}, []string{clientConf})
|
||||||
|
|
||||||
|
framework.NewRequestExpect(f).Port(vhostHTTPPort).
|
||||||
|
RequestModify(func(r *request.Request) {
|
||||||
|
r.HTTP().HTTPHost("normal.example.com")
|
||||||
|
}).
|
||||||
|
Ensure(func(res *request.Response) bool {
|
||||||
|
return res.Header.Get("X-From-Where") == "frp"
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
ginkgo.It("Host Header Rewrite", func() {
|
ginkgo.It("Host Header Rewrite", func() {
|
||||||
vhostHTTPPort := f.AllocPort()
|
vhostHTTPPort := f.AllocPort()
|
||||||
serverConf := getDefaultServerConf(vhostHTTPPort)
|
serverConf := getDefaultServerConf(vhostHTTPPort)
|
||||||
@@ -385,4 +419,48 @@ var _ = ginkgo.Describe("[Feature: HTTP]", func() {
|
|||||||
framework.ExpectNoError(err)
|
framework.ExpectNoError(err)
|
||||||
framework.ExpectEqualValues(consts.TestString, string(msg))
|
framework.ExpectEqualValues(consts.TestString, string(msg))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
ginkgo.It("vhostHTTPTimeout", func() {
|
||||||
|
vhostHTTPPort := f.AllocPort()
|
||||||
|
serverConf := getDefaultServerConf(vhostHTTPPort)
|
||||||
|
serverConf += `
|
||||||
|
vhostHTTPTimeout = 2
|
||||||
|
`
|
||||||
|
|
||||||
|
delayDuration := 0 * time.Second
|
||||||
|
localPort := f.AllocPort()
|
||||||
|
localServer := httpserver.New(
|
||||||
|
httpserver.WithBindPort(localPort),
|
||||||
|
httpserver.WithHandler(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
||||||
|
time.Sleep(delayDuration)
|
||||||
|
_, _ = w.Write([]byte(req.Host))
|
||||||
|
})),
|
||||||
|
)
|
||||||
|
f.RunServer("", localServer)
|
||||||
|
|
||||||
|
clientConf := consts.DefaultClientConfig
|
||||||
|
clientConf += fmt.Sprintf(`
|
||||||
|
[[proxies]]
|
||||||
|
name = "test"
|
||||||
|
type = "http"
|
||||||
|
localPort = %d
|
||||||
|
customDomains = ["normal.example.com"]
|
||||||
|
`, localPort)
|
||||||
|
|
||||||
|
f.RunProcesses([]string{serverConf}, []string{clientConf})
|
||||||
|
|
||||||
|
framework.NewRequestExpect(f).Port(vhostHTTPPort).
|
||||||
|
RequestModify(func(r *request.Request) {
|
||||||
|
r.HTTP().HTTPHost("normal.example.com").HTTP().Timeout(time.Second)
|
||||||
|
}).
|
||||||
|
ExpectResp([]byte("normal.example.com")).
|
||||||
|
Ensure()
|
||||||
|
|
||||||
|
delayDuration = 3 * time.Second
|
||||||
|
framework.NewRequestExpect(f).Port(vhostHTTPPort).
|
||||||
|
RequestModify(func(r *request.Request) {
|
||||||
|
r.HTTP().HTTPHost("normal.example.com").HTTP().Timeout(5 * time.Second)
|
||||||
|
}).
|
||||||
|
Ensure(framework.ExpectResponseCode(504))
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
@@ -7,7 +7,6 @@ import (
|
|||||||
|
|
||||||
"github.com/onsi/ginkgo/v2"
|
"github.com/onsi/ginkgo/v2"
|
||||||
|
|
||||||
clientsdk "github.com/fatedier/frp/pkg/sdk/client"
|
|
||||||
"github.com/fatedier/frp/test/e2e/framework"
|
"github.com/fatedier/frp/test/e2e/framework"
|
||||||
"github.com/fatedier/frp/test/e2e/framework/consts"
|
"github.com/fatedier/frp/test/e2e/framework/consts"
|
||||||
"github.com/fatedier/frp/test/e2e/pkg/port"
|
"github.com/fatedier/frp/test/e2e/pkg/port"
|
||||||
@@ -110,7 +109,7 @@ var _ = ginkgo.Describe("[Feature: Server Manager]", func() {
|
|||||||
|
|
||||||
f.RunProcesses([]string{serverConf}, []string{clientConf})
|
f.RunProcesses([]string{serverConf}, []string{clientConf})
|
||||||
|
|
||||||
client := clientsdk.New("127.0.0.1", adminPort)
|
client := f.APIClientForFrpc(adminPort)
|
||||||
|
|
||||||
// tcp random port
|
// tcp random port
|
||||||
status, err := client.GetProxyStatus("tcp")
|
status, err := client.GetProxyStatus("tcp")
|
||||||
|
@@ -2,6 +2,7 @@ package features
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
|
"crypto/tls"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
@@ -9,6 +10,7 @@ import (
|
|||||||
"github.com/onsi/ginkgo/v2"
|
"github.com/onsi/ginkgo/v2"
|
||||||
pp "github.com/pires/go-proxyproto"
|
pp "github.com/pires/go-proxyproto"
|
||||||
|
|
||||||
|
"github.com/fatedier/frp/pkg/transport"
|
||||||
"github.com/fatedier/frp/pkg/util/log"
|
"github.com/fatedier/frp/pkg/util/log"
|
||||||
"github.com/fatedier/frp/test/e2e/framework"
|
"github.com/fatedier/frp/test/e2e/framework"
|
||||||
"github.com/fatedier/frp/test/e2e/framework/consts"
|
"github.com/fatedier/frp/test/e2e/framework/consts"
|
||||||
@@ -21,23 +23,24 @@ import (
|
|||||||
var _ = ginkgo.Describe("[Feature: Real IP]", func() {
|
var _ = ginkgo.Describe("[Feature: Real IP]", func() {
|
||||||
f := framework.NewDefaultFramework()
|
f := framework.NewDefaultFramework()
|
||||||
|
|
||||||
ginkgo.It("HTTP X-Forwarded-For", func() {
|
ginkgo.Describe("HTTP X-forwarded-For", func() {
|
||||||
vhostHTTPPort := f.AllocPort()
|
ginkgo.It("Client Without Header", func() {
|
||||||
serverConf := consts.DefaultServerConfig + fmt.Sprintf(`
|
vhostHTTPPort := f.AllocPort()
|
||||||
|
serverConf := consts.DefaultServerConfig + fmt.Sprintf(`
|
||||||
vhostHTTPPort = %d
|
vhostHTTPPort = %d
|
||||||
`, vhostHTTPPort)
|
`, vhostHTTPPort)
|
||||||
|
|
||||||
localPort := f.AllocPort()
|
localPort := f.AllocPort()
|
||||||
localServer := httpserver.New(
|
localServer := httpserver.New(
|
||||||
httpserver.WithBindPort(localPort),
|
httpserver.WithBindPort(localPort),
|
||||||
httpserver.WithHandler(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
httpserver.WithHandler(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
||||||
_, _ = w.Write([]byte(req.Header.Get("X-Forwarded-For")))
|
_, _ = w.Write([]byte(req.Header.Get("X-Forwarded-For")))
|
||||||
})),
|
})),
|
||||||
)
|
)
|
||||||
f.RunServer("", localServer)
|
f.RunServer("", localServer)
|
||||||
|
|
||||||
clientConf := consts.DefaultClientConfig
|
clientConf := consts.DefaultClientConfig
|
||||||
clientConf += fmt.Sprintf(`
|
clientConf += fmt.Sprintf(`
|
||||||
[[proxies]]
|
[[proxies]]
|
||||||
name = "test"
|
name = "test"
|
||||||
type = "http"
|
type = "http"
|
||||||
@@ -45,14 +48,131 @@ var _ = ginkgo.Describe("[Feature: Real IP]", func() {
|
|||||||
customDomains = ["normal.example.com"]
|
customDomains = ["normal.example.com"]
|
||||||
`, localPort)
|
`, localPort)
|
||||||
|
|
||||||
f.RunProcesses([]string{serverConf}, []string{clientConf})
|
f.RunProcesses([]string{serverConf}, []string{clientConf})
|
||||||
|
|
||||||
framework.NewRequestExpect(f).Port(vhostHTTPPort).
|
framework.NewRequestExpect(f).Port(vhostHTTPPort).
|
||||||
RequestModify(func(r *request.Request) {
|
RequestModify(func(r *request.Request) {
|
||||||
r.HTTP().HTTPHost("normal.example.com")
|
r.HTTP().HTTPHost("normal.example.com")
|
||||||
}).
|
}).
|
||||||
ExpectResp([]byte("127.0.0.1")).
|
ExpectResp([]byte("127.0.0.1")).
|
||||||
Ensure()
|
Ensure()
|
||||||
|
})
|
||||||
|
|
||||||
|
ginkgo.It("Client With Header", func() {
|
||||||
|
vhostHTTPPort := f.AllocPort()
|
||||||
|
serverConf := consts.DefaultServerConfig + fmt.Sprintf(`
|
||||||
|
vhostHTTPPort = %d
|
||||||
|
`, vhostHTTPPort)
|
||||||
|
|
||||||
|
localPort := f.AllocPort()
|
||||||
|
localServer := httpserver.New(
|
||||||
|
httpserver.WithBindPort(localPort),
|
||||||
|
httpserver.WithHandler(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
||||||
|
_, _ = w.Write([]byte(req.Header.Get("X-Forwarded-For")))
|
||||||
|
})),
|
||||||
|
)
|
||||||
|
f.RunServer("", localServer)
|
||||||
|
|
||||||
|
clientConf := consts.DefaultClientConfig
|
||||||
|
clientConf += fmt.Sprintf(`
|
||||||
|
[[proxies]]
|
||||||
|
name = "test"
|
||||||
|
type = "http"
|
||||||
|
localPort = %d
|
||||||
|
customDomains = ["normal.example.com"]
|
||||||
|
`, localPort)
|
||||||
|
|
||||||
|
f.RunProcesses([]string{serverConf}, []string{clientConf})
|
||||||
|
|
||||||
|
framework.NewRequestExpect(f).Port(vhostHTTPPort).
|
||||||
|
RequestModify(func(r *request.Request) {
|
||||||
|
r.HTTP().HTTPHost("normal.example.com")
|
||||||
|
r.HTTP().HTTPHeaders(map[string]string{"x-forwarded-for": "2.2.2.2"})
|
||||||
|
}).
|
||||||
|
ExpectResp([]byte("2.2.2.2, 127.0.0.1")).
|
||||||
|
Ensure()
|
||||||
|
})
|
||||||
|
|
||||||
|
ginkgo.It("http2https plugin", func() {
|
||||||
|
vhostHTTPPort := f.AllocPort()
|
||||||
|
serverConf := consts.DefaultServerConfig + fmt.Sprintf(`
|
||||||
|
vhostHTTPPort = %d
|
||||||
|
`, vhostHTTPPort)
|
||||||
|
|
||||||
|
localPort := f.AllocPort()
|
||||||
|
|
||||||
|
clientConf := consts.DefaultClientConfig
|
||||||
|
clientConf += fmt.Sprintf(`
|
||||||
|
[[proxies]]
|
||||||
|
name = "test"
|
||||||
|
type = "http"
|
||||||
|
customDomains = ["normal.example.com"]
|
||||||
|
[proxies.plugin]
|
||||||
|
type = "http2https"
|
||||||
|
localAddr = "127.0.0.1:%d"
|
||||||
|
`, localPort)
|
||||||
|
|
||||||
|
f.RunProcesses([]string{serverConf}, []string{clientConf})
|
||||||
|
|
||||||
|
tlsConfig, err := transport.NewServerTLSConfig("", "", "")
|
||||||
|
framework.ExpectNoError(err)
|
||||||
|
|
||||||
|
localServer := httpserver.New(
|
||||||
|
httpserver.WithBindPort(localPort),
|
||||||
|
httpserver.WithHandler(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
||||||
|
_, _ = w.Write([]byte(req.Header.Get("X-Forwarded-For")))
|
||||||
|
})),
|
||||||
|
httpserver.WithTLSConfig(tlsConfig),
|
||||||
|
)
|
||||||
|
f.RunServer("", localServer)
|
||||||
|
|
||||||
|
framework.NewRequestExpect(f).Port(vhostHTTPPort).
|
||||||
|
RequestModify(func(r *request.Request) {
|
||||||
|
r.HTTP().HTTPHost("normal.example.com")
|
||||||
|
r.HTTP().HTTPHeaders(map[string]string{"x-forwarded-for": "2.2.2.2, 3.3.3.3"})
|
||||||
|
}).
|
||||||
|
ExpectResp([]byte("2.2.2.2, 3.3.3.3, 127.0.0.1")).
|
||||||
|
Ensure()
|
||||||
|
})
|
||||||
|
|
||||||
|
ginkgo.It("https2http plugin", func() {
|
||||||
|
vhostHTTPSPort := f.AllocPort()
|
||||||
|
serverConf := consts.DefaultServerConfig + fmt.Sprintf(`
|
||||||
|
vhostHTTPSPort = %d
|
||||||
|
`, vhostHTTPSPort)
|
||||||
|
|
||||||
|
localPort := f.AllocPort()
|
||||||
|
|
||||||
|
clientConf := consts.DefaultClientConfig
|
||||||
|
clientConf += fmt.Sprintf(`
|
||||||
|
[[proxies]]
|
||||||
|
name = "test"
|
||||||
|
type = "https"
|
||||||
|
customDomains = ["normal.example.com"]
|
||||||
|
[proxies.plugin]
|
||||||
|
type = "https2http"
|
||||||
|
localAddr = "127.0.0.1:%d"
|
||||||
|
`, localPort)
|
||||||
|
|
||||||
|
f.RunProcesses([]string{serverConf}, []string{clientConf})
|
||||||
|
|
||||||
|
localServer := httpserver.New(
|
||||||
|
httpserver.WithBindPort(localPort),
|
||||||
|
httpserver.WithHandler(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
||||||
|
_, _ = w.Write([]byte(req.Header.Get("X-Forwarded-For")))
|
||||||
|
})),
|
||||||
|
)
|
||||||
|
f.RunServer("", localServer)
|
||||||
|
|
||||||
|
framework.NewRequestExpect(f).Port(vhostHTTPSPort).
|
||||||
|
RequestModify(func(r *request.Request) {
|
||||||
|
r.HTTPS().HTTPHost("normal.example.com").
|
||||||
|
HTTPHeaders(map[string]string{"x-forwarded-for": "2.2.2.2"}).
|
||||||
|
TLSConfig(&tls.Config{ServerName: "normal.example.com", InsecureSkipVerify: true})
|
||||||
|
}).
|
||||||
|
ExpectResp([]byte("2.2.2.2, 127.0.0.1")).
|
||||||
|
Ensure()
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
ginkgo.Describe("Proxy Protocol", func() {
|
ginkgo.Describe("Proxy Protocol", func() {
|
||||||
|
1
web/frps/components.d.ts
vendored
1
web/frps/components.d.ts
vendored
@@ -31,6 +31,7 @@ declare module 'vue' {
|
|||||||
ProxiesSTCP: typeof import('./src/components/ProxiesSTCP.vue')['default']
|
ProxiesSTCP: typeof import('./src/components/ProxiesSTCP.vue')['default']
|
||||||
ProxiesSUDP: typeof import('./src/components/ProxiesSUDP.vue')['default']
|
ProxiesSUDP: typeof import('./src/components/ProxiesSUDP.vue')['default']
|
||||||
ProxiesTCP: typeof import('./src/components/ProxiesTCP.vue')['default']
|
ProxiesTCP: typeof import('./src/components/ProxiesTCP.vue')['default']
|
||||||
|
ProxiesTCPMux: typeof import('./src/components/ProxiesTCPMux.vue')['default']
|
||||||
ProxiesUDP: typeof import('./src/components/ProxiesUDP.vue')['default']
|
ProxiesUDP: typeof import('./src/components/ProxiesUDP.vue')['default']
|
||||||
ProxyView: typeof import('./src/components/ProxyView.vue')['default']
|
ProxyView: typeof import('./src/components/ProxyView.vue')['default']
|
||||||
ProxyViewExpand: typeof import('./src/components/ProxyViewExpand.vue')['default']
|
ProxyViewExpand: typeof import('./src/components/ProxyViewExpand.vue')['default']
|
||||||
|
@@ -39,6 +39,7 @@
|
|||||||
<el-menu-item index="/proxies/udp">UDP</el-menu-item>
|
<el-menu-item index="/proxies/udp">UDP</el-menu-item>
|
||||||
<el-menu-item index="/proxies/http">HTTP</el-menu-item>
|
<el-menu-item index="/proxies/http">HTTP</el-menu-item>
|
||||||
<el-menu-item index="/proxies/https">HTTPS</el-menu-item>
|
<el-menu-item index="/proxies/https">HTTPS</el-menu-item>
|
||||||
|
<el-menu-item index="/proxies/tcpmux">TCPMUX</el-menu-item>
|
||||||
<el-menu-item index="/proxies/stcp">STCP</el-menu-item>
|
<el-menu-item index="/proxies/stcp">STCP</el-menu-item>
|
||||||
<el-menu-item index="/proxies/sudp">SUDP</el-menu-item>
|
<el-menu-item index="/proxies/sudp">SUDP</el-menu-item>
|
||||||
</el-sub-menu>
|
</el-sub-menu>
|
||||||
|
38
web/frps/src/components/ProxiesTCPMux.vue
Normal file
38
web/frps/src/components/ProxiesTCPMux.vue
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
<template>
|
||||||
|
<ProxyView :proxies="proxies" proxyType="tcpmux" @refresh="fetchData" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref } from 'vue'
|
||||||
|
import { TCPMuxProxy } from '../utils/proxy.js'
|
||||||
|
import ProxyView from './ProxyView.vue'
|
||||||
|
|
||||||
|
let proxies = ref<TCPMuxProxy[]>([])
|
||||||
|
|
||||||
|
const fetchData = () => {
|
||||||
|
let tcpmuxHTTPConnectPort: number
|
||||||
|
let subdomainHost: string
|
||||||
|
fetch('../api/serverinfo', { credentials: 'include' })
|
||||||
|
.then((res) => {
|
||||||
|
return res.json()
|
||||||
|
})
|
||||||
|
.then((json) => {
|
||||||
|
tcpmuxHTTPConnectPort = json.tcpmuxHTTPConnectPort
|
||||||
|
subdomainHost = json.subdomainHost
|
||||||
|
|
||||||
|
fetch('../api/proxy/tcpmux', { credentials: 'include' })
|
||||||
|
.then((res) => {
|
||||||
|
return res.json()
|
||||||
|
})
|
||||||
|
.then((json) => {
|
||||||
|
proxies.value = []
|
||||||
|
for (let proxyStats of json.proxies) {
|
||||||
|
proxies.value.push(new TCPMuxProxy(proxyStats, tcpmuxHTTPConnectPort, subdomainHost))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
fetchData()
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style></style>
|
@@ -1,9 +1,9 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-form
|
<el-form
|
||||||
label-position="left"
|
label-position="left"
|
||||||
|
label-width="auto"
|
||||||
inline
|
inline
|
||||||
class="proxy-table-expand"
|
class="proxy-table-expand"
|
||||||
v-if="proxyType === 'http' || proxyType === 'https'"
|
|
||||||
>
|
>
|
||||||
<el-form-item label="Name">
|
<el-form-item label="Name">
|
||||||
<span>{{ row.name }}</span>
|
<span>{{ row.name }}</span>
|
||||||
@@ -11,18 +11,6 @@
|
|||||||
<el-form-item label="Type">
|
<el-form-item label="Type">
|
||||||
<span>{{ row.type }}</span>
|
<span>{{ row.type }}</span>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="Domains">
|
|
||||||
<span>{{ row.customDomains }}</span>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="SubDomain">
|
|
||||||
<span>{{ row.subdomain }}</span>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="locations">
|
|
||||||
<span>{{ row.locations }}</span>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="HostRewrite">
|
|
||||||
<span>{{ row.hostHeaderRewrite }}</span>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="Encryption">
|
<el-form-item label="Encryption">
|
||||||
<span>{{ row.encryption }}</span>
|
<span>{{ row.encryption }}</span>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
@@ -35,30 +23,40 @@
|
|||||||
<el-form-item label="Last Close">
|
<el-form-item label="Last Close">
|
||||||
<span>{{ row.lastCloseTime }}</span>
|
<span>{{ row.lastCloseTime }}</span>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
|
||||||
|
|
||||||
<el-form label-position="left" inline class="proxy-table-expand" v-else>
|
<div v-if="proxyType === 'http' || proxyType === 'https'">
|
||||||
<el-form-item label="Name">
|
<el-form-item label="Domains">
|
||||||
<span>{{ row.name }}</span>
|
<span>{{ row.customDomains }}</span>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="Type">
|
<el-form-item label="SubDomain">
|
||||||
<span>{{ row.type }}</span>
|
<span>{{ row.subdomain }}</span>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="Addr">
|
<el-form-item label="locations">
|
||||||
<span>{{ row.addr }}</span>
|
<span>{{ row.locations }}</span>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="Encryption">
|
<el-form-item label="HostRewrite">
|
||||||
<span>{{ row.encryption }}</span>
|
<span>{{ row.hostHeaderRewrite }}</span>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="Compression">
|
</div>
|
||||||
<span>{{ row.compression }}</span>
|
<div v-else-if="proxyType === 'tcpmux'">
|
||||||
</el-form-item>
|
<el-form-item label="Multiplexer">
|
||||||
<el-form-item label="Last Start">
|
<span>{{ row.multiplexer }}</span>
|
||||||
<span>{{ row.lastStartTime }}</span>
|
</el-form-item>
|
||||||
</el-form-item>
|
<el-form-item label="RouteByHTTPUser">
|
||||||
<el-form-item label="Last Close">
|
<span>{{ row.routeByHTTPUser }}</span>
|
||||||
<span>{{ row.lastCloseTime }}</span>
|
</el-form-item>
|
||||||
</el-form-item>
|
<el-form-item label="Domains">
|
||||||
|
<span>{{ row.customDomains }}</span>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="SubDomain">
|
||||||
|
<span>{{ row.subdomain }}</span>
|
||||||
|
</el-form-item>
|
||||||
|
</div>
|
||||||
|
<div v-else>
|
||||||
|
<el-form-item label="Addr">
|
||||||
|
<span>{{ row.addr }}</span>
|
||||||
|
</el-form-item>
|
||||||
|
</div>
|
||||||
</el-form>
|
</el-form>
|
||||||
|
|
||||||
<div v-if="row.annotations && row.annotations.size > 0">
|
<div v-if="row.annotations && row.annotations.size > 0">
|
||||||
|
@@ -20,10 +20,10 @@
|
|||||||
<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">
|
||||||
<span>{{ data.vhostHTTPPort }}</span>
|
<span>{{ data.vhostHTTPPort }}</span>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="Https Port" v-if="data.vhostHTTPSPort != 0">
|
<el-form-item label="HTTPS Port" v-if="data.vhostHTTPSPort != 0">
|
||||||
<span>{{ data.vhostHTTPSPort }}</span>
|
<span>{{ data.vhostHTTPSPort }}</span>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item
|
<el-form-item
|
||||||
|
@@ -4,6 +4,7 @@ import ProxiesTCP from '../components/ProxiesTCP.vue'
|
|||||||
import ProxiesUDP from '../components/ProxiesUDP.vue'
|
import ProxiesUDP from '../components/ProxiesUDP.vue'
|
||||||
import ProxiesHTTP from '../components/ProxiesHTTP.vue'
|
import ProxiesHTTP from '../components/ProxiesHTTP.vue'
|
||||||
import ProxiesHTTPS from '../components/ProxiesHTTPS.vue'
|
import ProxiesHTTPS from '../components/ProxiesHTTPS.vue'
|
||||||
|
import ProxiesTCPMux from '../components/ProxiesTCPMux.vue'
|
||||||
import ProxiesSTCP from '../components/ProxiesSTCP.vue'
|
import ProxiesSTCP from '../components/ProxiesSTCP.vue'
|
||||||
import ProxiesSUDP from '../components/ProxiesSUDP.vue'
|
import ProxiesSUDP from '../components/ProxiesSUDP.vue'
|
||||||
|
|
||||||
@@ -35,6 +36,11 @@ const router = createRouter({
|
|||||||
name: 'ProxiesHTTPS',
|
name: 'ProxiesHTTPS',
|
||||||
component: ProxiesHTTPS,
|
component: ProxiesHTTPS,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: '/proxies/tcpmux',
|
||||||
|
name: 'ProxiesTCPMux',
|
||||||
|
component: ProxiesTCPMux,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: '/proxies/stcp',
|
path: '/proxies/stcp',
|
||||||
name: 'ProxiesSTCP',
|
name: 'ProxiesSTCP',
|
||||||
|
@@ -110,6 +110,28 @@ class HTTPSProxy extends BaseProxy {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class TCPMuxProxy extends BaseProxy {
|
||||||
|
multiplexer: string
|
||||||
|
routeByHTTPUser: string
|
||||||
|
|
||||||
|
constructor(proxyStats: any, port: number, subdomainHost: string) {
|
||||||
|
super(proxyStats)
|
||||||
|
this.type = 'tcpmux'
|
||||||
|
this.port = port
|
||||||
|
this.multiplexer = ''
|
||||||
|
this.routeByHTTPUser = ''
|
||||||
|
|
||||||
|
if (proxyStats.conf) {
|
||||||
|
this.customDomains = proxyStats.conf.customDomains || this.customDomains
|
||||||
|
this.multiplexer = proxyStats.conf.multiplexer
|
||||||
|
this.routeByHTTPUser = proxyStats.conf.routeByHTTPUser
|
||||||
|
if (proxyStats.conf.subdomain) {
|
||||||
|
this.subdomain = `${proxyStats.conf.subdomain}.${subdomainHost}`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class STCPProxy extends BaseProxy {
|
class STCPProxy extends BaseProxy {
|
||||||
constructor(proxyStats: any) {
|
constructor(proxyStats: any) {
|
||||||
super(proxyStats)
|
super(proxyStats)
|
||||||
@@ -128,6 +150,7 @@ export {
|
|||||||
BaseProxy,
|
BaseProxy,
|
||||||
TCPProxy,
|
TCPProxy,
|
||||||
UDPProxy,
|
UDPProxy,
|
||||||
|
TCPMuxProxy,
|
||||||
HTTPProxy,
|
HTTPProxy,
|
||||||
HTTPSProxy,
|
HTTPSProxy,
|
||||||
STCPProxy,
|
STCPProxy,
|
||||||
|
Reference in New Issue
Block a user