Compare commits

...

7 Commits

Author SHA1 Message Date
David Hume
f123098f6c
Merge b916f66c8410cb892616dc99992dc6fd9d1f4b7e into 4957fd23eed324ba3a2b6087dd74461d6d68bb87 2024-02-19 11:46:02 +01:00
fatedier
4957fd23ee
display go version in make (#4003) 2024-02-19 17:46:47 +08:00
fatedier
2f958c2095
bump quic-go to 0.41.0 (#4002) 2024-02-19 17:17:02 +08:00
fatedier
dc34a68542
support go1.22 and drop support for go1.20 (#4001) 2024-02-19 16:45:25 +08:00
fatedier
3529158f31
proxy supports configuring annotations, which will be displayed in the frps dashboard (#4000) 2024-02-19 16:28:27 +08:00
Gerhard Tan
9152c59570
fix nil map error when using plugin headers in legacy format (#3996)
* fix nil map error when using plugin headers in legacy format

* create map on demand

* better initialization
2024-02-19 13:03:37 +08:00
Xeno
b916f66c84 Fix Dockerfiles 2024-02-06 23:51:00 -06:00
27 changed files with 344 additions and 197 deletions

View File

@ -2,7 +2,7 @@ version: 2
jobs: jobs:
go-version-latest: go-version-latest:
docker: docker:
- image: cimg/go:1.21-node - image: cimg/go:1.22-node
resource_class: large resource_class: large
steps: steps:
- checkout - checkout
@ -10,7 +10,7 @@ jobs:
- run: make alltest - run: make alltest
go-version-last: go-version-last:
docker: docker:
- image: cimg/go:1.20-node - image: cimg/go:1.21-node
resource_class: large resource_class: large
steps: steps:
- checkout - checkout

View File

@ -19,15 +19,15 @@ jobs:
steps: steps:
# environment # environment
- name: Checkout - name: Checkout
uses: actions/checkout@v3 uses: actions/checkout@v4
with: with:
fetch-depth: '0' fetch-depth: '0'
- name: Set up QEMU - name: Set up QEMU
uses: docker/setup-qemu-action@v2 uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx - name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2 uses: docker/setup-buildx-action@v3
# get image tag name # get image tag name
- name: Get Image Tag Name - name: Get Image Tag Name
@ -38,13 +38,13 @@ jobs:
echo "TAG_NAME=${{ github.event.inputs.tag }}" >> $GITHUB_ENV echo "TAG_NAME=${{ github.event.inputs.tag }}" >> $GITHUB_ENV
fi fi
- name: Login to DockerHub - name: Login to DockerHub
uses: docker/login-action@v2 uses: docker/login-action@v3
with: with:
username: ${{ secrets.DOCKERHUB_USERNAME }} username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_PASSWORD }} password: ${{ secrets.DOCKERHUB_PASSWORD }}
- name: Login to the GPR - name: Login to the GPR
uses: docker/login-action@v2 uses: docker/login-action@v3
with: with:
registry: ghcr.io registry: ghcr.io
username: ${{ github.repository_owner }} username: ${{ github.repository_owner }}
@ -72,7 +72,7 @@ jobs:
${{ env.TAG_FRPC_GPR }} ${{ env.TAG_FRPC_GPR }}
- name: Build and push frps - name: Build and push frps
uses: docker/build-push-action@v4 uses: docker/build-push-action@v5
with: with:
context: . context: .
file: ./dockerfiles/Dockerfile-for-frps file: ./dockerfiles/Dockerfile-for-frps

View File

@ -14,28 +14,28 @@ jobs:
name: lint name: lint
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/setup-go@v4 - uses: actions/checkout@v4
with: - uses: actions/setup-go@v5
go-version: '1.21' with:
- uses: actions/checkout@v3 go-version: '1.22'
- name: golangci-lint - name: golangci-lint
uses: golangci/golangci-lint-action@v3 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.55 version: v1.55
# Optional: golangci-lint command line arguments. # Optional: golangci-lint command line arguments.
# args: --issues-exit-code=0 # args: --issues-exit-code=0
# Optional: show only new issues if it's a pull request. The default value is `false`. # Optional: show only new issues if it's a pull request. The default value is `false`.
# only-new-issues: true # only-new-issues: true
# Optional: if set to true then the all caching functionality will be complete disabled, # Optional: if set to true then the all caching functionality will be complete disabled,
# takes precedence over all other caching options. # takes precedence over all other caching options.
# skip-cache: true # skip-cache: true
# Optional: if set to true then the action don't cache or restore ~/go/pkg. # Optional: if set to true then the action don't cache or restore ~/go/pkg.
# skip-pkg-cache: true # skip-pkg-cache: true
# Optional: if set to true then the action don't cache or restore ~/.cache/go-build. # Optional: if set to true then the action don't cache or restore ~/.cache/go-build.
# skip-build-cache: true # skip-build-cache: true

View File

@ -8,21 +8,21 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v3 uses: actions/checkout@v4
with: with:
fetch-depth: 0 fetch-depth: 0
- name: Set up Go - name: Set up Go
uses: actions/setup-go@v4 uses: actions/setup-go@v5
with: with:
go-version: '1.21' go-version: '1.22'
- name: Make All - name: Make All
run: | run: |
./package.sh ./package.sh
- name: Run GoReleaser - name: Run GoReleaser
uses: goreleaser/goreleaser-action@v4 uses: goreleaser/goreleaser-action@v5
with: with:
version: latest version: latest
args: release --clean --release-notes=./Release.md args: release --clean --release-notes=./Release.md

View File

@ -2,10 +2,13 @@ export PATH := $(GOPATH)/bin:$(PATH)
export GO111MODULE=on export GO111MODULE=on
LDFLAGS := -s -w LDFLAGS := -s -w
all: fmt build all: env fmt build
build: frps frpc build: frps frpc
env:
@go version
# compile assets into binary file # compile assets into binary file
file: file:
rm -rf ./assets/frps/static/* rm -rf ./assets/frps/static/*

View File

@ -11,10 +11,6 @@
<a href="https://workos.com/?utm_campaign=github_repo&utm_medium=referral&utm_content=frp&utm_source=github" target="_blank"> <a href="https://workos.com/?utm_campaign=github_repo&utm_medium=referral&utm_content=frp&utm_source=github" target="_blank">
<img width="350px" src="https://raw.githubusercontent.com/fatedier/frp/dev/doc/pic/sponsor_workos.png"> <img width="350px" src="https://raw.githubusercontent.com/fatedier/frp/dev/doc/pic/sponsor_workos.png">
</a> </a>
<a>&nbsp</a>
<a href="https://www.nango.dev?utm_source=github&utm_medium=oss-banner&utm_campaign=fatedier-frp" target="_blank">
<img width="400px" src="https://raw.githubusercontent.com/fatedier/frp/dev/doc/pic/sponsor_nango.png">
</a>
</p> </p>
<!--gold sponsors end--> <!--gold sponsors end-->
@ -526,6 +522,8 @@ Check frp's status and proxies' statistics information by Dashboard.
Configure a port for dashboard to enable this feature: Configure a port for dashboard to enable this feature:
```toml ```toml
# The default value is 127.0.0.1. Change it to 0.0.0.0 when you want to access it from a public network.
webServer.addr = "0.0.0.0"
webServer.port = 7500 webServer.port = 7500
# dashboard's username and password are both optional # dashboard's username and password are both optional
webServer.user = "admin" webServer.user = "admin"
@ -534,8 +532,6 @@ webServer.password = "admin"
Then visit `http://[serverAddr]:7500` to see the dashboard, with username and password both being `admin`. Then visit `http://[serverAddr]:7500` to see the dashboard, with username and password both being `admin`.
Note that if you want your server to be accessed from public networks, then also add `webServer.addr = "0.0.0.0"` line. For security reasons (credits [#3709](https://github.com/fatedier/frp/issues/3709)), value `127.0.0.1` is used by default.
Additionally, you can use HTTPS port by using your domains wildcard or normal SSL certificate: Additionally, you can use HTTPS port by using your domains wildcard or normal SSL certificate:
```toml ```toml

View File

@ -13,10 +13,6 @@ frp 是一个专注于内网穿透的高性能的反向代理应用,支持 TCP
<a href="https://workos.com/?utm_campaign=github_repo&utm_medium=referral&utm_content=frp&utm_source=github" target="_blank"> <a href="https://workos.com/?utm_campaign=github_repo&utm_medium=referral&utm_content=frp&utm_source=github" target="_blank">
<img width="350px" src="https://raw.githubusercontent.com/fatedier/frp/dev/doc/pic/sponsor_workos.png"> <img width="350px" src="https://raw.githubusercontent.com/fatedier/frp/dev/doc/pic/sponsor_workos.png">
</a> </a>
<a>&nbsp</a>
<a href="https://www.nango.dev?utm_source=github&utm_medium=oss-banner&utm_campaign=fatedier-frp" target="_blank">
<img width="400px" src="https://raw.githubusercontent.com/fatedier/frp/dev/doc/pic/sponsor_nango.png">
</a>
</p> </p>
<!--gold sponsors end--> <!--gold sponsors end-->

View File

@ -1,11 +1,3 @@
### Deprecation Notices
* Using an underscore in a flag name is deprecated and has been replaced by a hyphen. The underscore format will remain compatible for some time, until it is completely removed in a future version. For example, `--remote_port` is replaced with `--remote-port`.
### Features ### Features
* The `Refresh` and `ClearOfflineProxies` buttons have been added to the Dashboard of frps. * Proxy supports configuring annotations, which will be displayed in the frps dashboard.
### Fixes
* The host/domain matching in the routing rules has been changed to be case-insensitive.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -4,8 +4,8 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<title>frps dashboard</title> <title>frps dashboard</title>
<script type="module" crossorigin src="./index-1gecbKzv.js"></script> <script type="module" crossorigin src="./index-ky4re_ta.js"></script>
<link rel="stylesheet" crossorigin href="./index-Lf6B06jY.css"> <link rel="stylesheet" crossorigin href="./index-rzPDshRD.css">
</head> </head>
<body> <body>

View File

@ -164,11 +164,16 @@ healthCheck.type = "tcp"
healthCheck.timeoutSeconds = 3 healthCheck.timeoutSeconds = 3
# If continuous failed in 3 times, the proxy will be removed from frps # If continuous failed in 3 times, the proxy will be removed from frps
healthCheck.maxFailed = 3 healthCheck.maxFailed = 3
# every 10 seconds will do a health check # Every 10 seconds will do a health check
healthCheck.intervalSeconds = 10 healthCheck.intervalSeconds = 10
# additional meta info for each proxy # Additional meta info for each proxy. It will be passed to the server-side plugin for use.
metadatas.var1 = "abc" metadatas.var1 = "abc"
metadatas.var2 = "123" metadatas.var2 = "123"
# You can add some extra information to the proxy through annotations.
# These annotations will be displayed on the frps dashboard.
[proxies.annotations]
key1 = "value1"
"prefix/key2" = "value2"
[[proxies]] [[proxies]]
name = "ssh_random" name = "ssh_random"

View File

@ -1,4 +1,4 @@
FROM golang:1.21 AS building FROM golang:1.22 AS building
COPY . /building COPY . /building
WORKDIR /building WORKDIR /building
@ -7,6 +7,6 @@ RUN make frpc
FROM alpine:3 FROM alpine:3
COPY --from=building /building/bin/frpc /usr/bin/frpc COPY --from=building /building/frpc /usr/bin/frpc
ENTRYPOINT ["/usr/bin/frpc"] ENTRYPOINT ["/usr/bin/frpc"]

View File

@ -1,4 +1,4 @@
FROM golang:1.21 AS building FROM golang:1.22 AS building
COPY . /building COPY . /building
WORKDIR /building WORKDIR /building
@ -7,6 +7,6 @@ RUN make frps
FROM alpine:3 FROM alpine:3
COPY --from=building /building/bin/frps /usr/bin/frps COPY --from=building /building/frps /usr/bin/frps
ENTRYPOINT ["/usr/bin/frps"] ENTRYPOINT ["/usr/bin/frps"]

12
go.mod
View File

@ -1,6 +1,6 @@
module github.com/fatedier/frp module github.com/fatedier/frp
go 1.20 go 1.21
require ( require (
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5
@ -18,12 +18,13 @@ require (
github.com/pion/stun v0.6.1 github.com/pion/stun v0.6.1
github.com/pires/go-proxyproto v0.7.0 github.com/pires/go-proxyproto v0.7.0
github.com/prometheus/client_golang v1.16.0 github.com/prometheus/client_golang v1.16.0
github.com/quic-go/quic-go v0.37.7 github.com/quic-go/quic-go v0.41.0
github.com/rodaine/table v1.1.0 github.com/rodaine/table v1.1.0
github.com/samber/lo v1.38.1 github.com/samber/lo v1.38.1
github.com/spf13/cobra v1.8.0 github.com/spf13/cobra v1.8.0
github.com/spf13/pflag v1.0.5 github.com/spf13/pflag v1.0.5
github.com/stretchr/testify v1.8.4 github.com/stretchr/testify v1.8.4
github.com/tidwall/gjson v1.17.1
golang.org/x/crypto v0.17.0 golang.org/x/crypto v0.17.0
golang.org/x/net v0.17.0 golang.org/x/net v0.17.0
golang.org/x/oauth2 v0.10.0 golang.org/x/oauth2 v0.10.0
@ -42,7 +43,6 @@ require (
github.com/go-jose/go-jose/v3 v3.0.1 // indirect github.com/go-jose/go-jose/v3 v3.0.1 // indirect
github.com/go-logr/logr v1.2.4 // indirect github.com/go-logr/logr v1.2.4 // indirect
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
github.com/golang/mock v1.6.0 // indirect
github.com/golang/protobuf v1.5.3 // indirect github.com/golang/protobuf v1.5.3 // 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.5.9 // indirect
@ -60,13 +60,15 @@ require (
github.com/prometheus/client_model v0.3.0 // indirect github.com/prometheus/client_model v0.3.0 // indirect
github.com/prometheus/common v0.42.0 // indirect github.com/prometheus/common v0.42.0 // indirect
github.com/prometheus/procfs v0.10.1 // indirect github.com/prometheus/procfs v0.10.1 // indirect
github.com/quic-go/qtls-go1-20 v0.3.1 // indirect
github.com/rogpeppe/go-internal v1.11.0 // indirect github.com/rogpeppe/go-internal v1.11.0 // indirect
github.com/templexxx/cpufeat v0.0.0-20180724012125-cef66df7f161 // indirect github.com/templexxx/cpufeat v0.0.0-20180724012125-cef66df7f161 // indirect
github.com/templexxx/xor v0.0.0-20191217153810-f85b25db303b // indirect github.com/templexxx/xor v0.0.0-20191217153810-f85b25db303b // indirect
github.com/tidwall/match v1.1.1 // 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
golang.org/x/exp v0.0.0-20221205204356-47842c84f3db // indirect golang.org/x/exp v0.0.0-20221205204356-47842c84f3db // indirect
golang.org/x/mod v0.10.0 // indirect golang.org/x/mod v0.11.0 // indirect
golang.org/x/sys v0.15.0 // indirect golang.org/x/sys v0.15.0 // indirect
golang.org/x/text v0.14.0 // indirect golang.org/x/text v0.14.0 // indirect
golang.org/x/tools v0.9.3 // indirect golang.org/x/tools v0.9.3 // indirect

34
go.sum
View File

@ -40,8 +40,6 @@ github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEe
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/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
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.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=
@ -82,6 +80,7 @@ github.com/klauspost/cpuid/v2 v2.0.6/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa02
github.com/klauspost/reedsolomon v1.9.15 h1:g2erWKD2M6rgnPf89fCji6jNlhMKMdXcuNHMW1SYCIo= github.com/klauspost/reedsolomon v1.9.15 h1:g2erWKD2M6rgnPf89fCji6jNlhMKMdXcuNHMW1SYCIo=
github.com/klauspost/reedsolomon v1.9.15/go.mod h1:eqPAcE7xar5CIzcdfwydOEdcmchAKAP/qs14y4GCBOk= github.com/klauspost/reedsolomon v1.9.15/go.mod h1:eqPAcE7xar5CIzcdfwydOEdcmchAKAP/qs14y4GCBOk=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
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.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
@ -117,10 +116,8 @@ github.com/prometheus/common v0.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI
github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc= github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc=
github.com/prometheus/procfs v0.10.1 h1:kYK1Va/YMlutzCGazswoHKo//tZVlFpKYh+PymziUAg= github.com/prometheus/procfs v0.10.1 h1:kYK1Va/YMlutzCGazswoHKo//tZVlFpKYh+PymziUAg=
github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM= github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM=
github.com/quic-go/qtls-go1-20 v0.3.1 h1:O4BLOM3hwfVF3AcktIylQXyl7Yi2iBNVy5QsV+ySxbg= github.com/quic-go/quic-go v0.41.0 h1:aD8MmHfgqTURWNJy48IYFg2OnxwHT3JL7ahGs73lb4k=
github.com/quic-go/qtls-go1-20 v0.3.1/go.mod h1:X9Nh97ZL80Z+bX/gUXMbipO6OxdiDi58b/fMC9mAL+k= github.com/quic-go/quic-go v0.41.0/go.mod h1:qCkNjqczPEvgsOnxZ0eCD14lv+B2LHlFAB++CNOh9hA=
github.com/quic-go/quic-go v0.37.7 h1:AgKsQLZ1+YCwZd2GYhBUsJDYZwEkA5gENtAjb+MxONU=
github.com/quic-go/quic-go v0.37.7/go.mod h1:YsbH1r4mSHPJcLF4k4zruUkLBqctEMBDR6VPvcYjIsU=
github.com/rodaine/table v1.1.0 h1:/fUlCSdjamMY8VifdQRIu3VWZXYLY7QHFkVorS8NTr4= github.com/rodaine/table v1.1.0 h1:/fUlCSdjamMY8VifdQRIu3VWZXYLY7QHFkVorS8NTr4=
github.com/rodaine/table v1.1.0/go.mod h1:Qu3q5wi1jTQD6B6HsP6szie/S4w1QUQ8pq22pz9iL8g= github.com/rodaine/table v1.1.0/go.mod h1:Qu3q5wi1jTQD6B6HsP6szie/S4w1QUQ8pq22pz9iL8g=
github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
@ -145,14 +142,21 @@ github.com/templexxx/cpufeat v0.0.0-20180724012125-cef66df7f161 h1:89CEmDvlq/F7S
github.com/templexxx/cpufeat v0.0.0-20180724012125-cef66df7f161/go.mod h1:wM7WEvslTq+iOEAMDLSzhVuOt5BRZ05WirO+b09GHQU= github.com/templexxx/cpufeat v0.0.0-20180724012125-cef66df7f161/go.mod h1:wM7WEvslTq+iOEAMDLSzhVuOt5BRZ05WirO+b09GHQU=
github.com/templexxx/xor v0.0.0-20191217153810-f85b25db303b h1:fj5tQ8acgNUr6O8LEplsxDhUIe2573iLkJc+PqnzZTI= github.com/templexxx/xor v0.0.0-20191217153810-f85b25db303b h1:fj5tQ8acgNUr6O8LEplsxDhUIe2573iLkJc+PqnzZTI=
github.com/templexxx/xor v0.0.0-20191217153810-f85b25db303b/go.mod h1:5XA7W9S6mni3h5uvOC75dA3m9CCCaS83lltmc0ukdi4= github.com/templexxx/xor v0.0.0-20191217153810-f85b25db303b/go.mod h1:5XA7W9S6mni3h5uvOC75dA3m9CCCaS83lltmc0ukdi4=
github.com/tidwall/gjson v1.17.1 h1:wlYEnwqAHgzmhNUFfw7Xalt2JzQvsMx2Se4PcoFCT/U=
github.com/tidwall/gjson v1.17.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
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/lossyconn v0.0.0-20200209145036-adba10fffc37 h1:EWU6Pktpas0n8lLQwDsRyZfmkPeRbdgPtW609es+/9E= github.com/xtaci/lossyconn v0.0.0-20200209145036-adba10fffc37 h1:EWU6Pktpas0n8lLQwDsRyZfmkPeRbdgPtW609es+/9E=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= 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.3.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-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/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=
@ -165,11 +169,10 @@ golang.org/x/exp v0.0.0-20221205204356-47842c84f3db/go.mod h1:CxIveKay+FTh1D0yPZ
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
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.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
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.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk= golang.org/x/mod v0.11.0 h1:bUO06HqtnRcc/7l71XBe4WcqTZ+3AH1J59zWDDwLKgU=
golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.11.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
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=
@ -179,7 +182,6 @@ golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR
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=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= 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=
@ -192,7 +194,6 @@ golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJ
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-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-20210220032951-036812b2e83c/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.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
@ -203,8 +204,6 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@ -217,6 +216,7 @@ golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuX
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4= golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4=
golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
@ -233,15 +233,12 @@ golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
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.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
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.9.3 h1:Gn1I8+64MsuTb/HpH+LmQtNas23LhUVr3rYZ0eKuaMM=
golang.org/x/tools v0.9.3/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc= golang.org/x/tools v0.9.3/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc=
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-20191011141410-1b5146add898/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=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/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.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
@ -264,6 +261,7 @@ google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
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/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=

View File

@ -175,6 +175,9 @@ func transformHeadersFromPluginParams(params map[string]string) v1.HeaderOperati
continue continue
} }
if k = strings.TrimPrefix(k, "plugin_header_"); k != "" { if k = strings.TrimPrefix(k, "plugin_header_"); k != "" {
if out.Set == nil {
out.Set = make(map[string]string)
}
out.Set[k] = v out.Set[k] = v
} }
} }

View File

@ -105,9 +105,10 @@ type DomainConfig struct {
} }
type ProxyBaseConfig struct { type ProxyBaseConfig struct {
Name string `json:"name"` Name string `json:"name"`
Type string `json:"type"` Type string `json:"type"`
Transport ProxyTransport `json:"transport,omitempty"` Annotations map[string]string `json:"annotations,omitempty"`
Transport ProxyTransport `json:"transport,omitempty"`
// metadata info for each proxy // metadata info for each proxy
Metadatas map[string]string `json:"metadatas,omitempty"` Metadatas map[string]string `json:"metadatas,omitempty"`
LoadBalancer LoadBalancerConfig `json:"loadBalancer,omitempty"` LoadBalancer LoadBalancerConfig `json:"loadBalancer,omitempty"`
@ -138,6 +139,7 @@ func (c *ProxyBaseConfig) MarshalToMsg(m *msg.NewProxy) {
m.Group = c.LoadBalancer.Group m.Group = c.LoadBalancer.Group
m.GroupKey = c.LoadBalancer.GroupKey m.GroupKey = c.LoadBalancer.GroupKey
m.Metas = c.Metadatas m.Metas = c.Metadatas
m.Annotations = c.Annotations
} }
func (c *ProxyBaseConfig) UnmarshalFromMsg(m *msg.NewProxy) { func (c *ProxyBaseConfig) UnmarshalFromMsg(m *msg.NewProxy) {
@ -154,6 +156,7 @@ func (c *ProxyBaseConfig) UnmarshalFromMsg(m *msg.NewProxy) {
c.LoadBalancer.Group = m.Group c.LoadBalancer.Group = m.Group
c.LoadBalancer.GroupKey = m.GroupKey c.LoadBalancer.GroupKey = m.GroupKey
c.Metadatas = m.Metas c.Metadatas = m.Metas
c.Annotations = m.Annotations
} }
type TypedProxyConfig struct { type TypedProxyConfig struct {

View File

@ -20,6 +20,7 @@ import (
"strings" "strings"
"github.com/samber/lo" "github.com/samber/lo"
"k8s.io/apimachinery/pkg/util/validation"
v1 "github.com/fatedier/frp/pkg/config/v1" v1 "github.com/fatedier/frp/pkg/config/v1"
) )
@ -29,10 +30,12 @@ func validateProxyBaseConfigForClient(c *v1.ProxyBaseConfig) error {
return errors.New("name should not be empty") return errors.New("name should not be empty")
} }
if err := ValidateAnnotations(c.Annotations); err != nil {
return err
}
if !lo.Contains([]string{"", "v1", "v2"}, c.Transport.ProxyProtocolVersion) { if !lo.Contains([]string{"", "v1", "v2"}, c.Transport.ProxyProtocolVersion) {
return fmt.Errorf("not support proxy protocol version: %s", c.Transport.ProxyProtocolVersion) return fmt.Errorf("not support proxy protocol version: %s", c.Transport.ProxyProtocolVersion)
} }
if !lo.Contains([]string{"client", "server"}, c.Transport.BandwidthLimitMode) { if !lo.Contains([]string{"client", "server"}, c.Transport.BandwidthLimitMode) {
return fmt.Errorf("bandwidth limit mode should be client or server") return fmt.Errorf("bandwidth limit mode should be client or server")
} }
@ -61,7 +64,10 @@ func validateProxyBaseConfigForClient(c *v1.ProxyBaseConfig) error {
return nil return nil
} }
func validateProxyBaseConfigForServer(c *v1.ProxyBaseConfig, s *v1.ServerConfig) error { func validateProxyBaseConfigForServer(c *v1.ProxyBaseConfig) error {
if err := ValidateAnnotations(c.Annotations); err != nil {
return err
}
return nil return nil
} }
@ -161,7 +167,7 @@ func validateSUDPProxyConfigForClient(c *v1.SUDPProxyConfig) error {
func ValidateProxyConfigurerForServer(c v1.ProxyConfigurer, s *v1.ServerConfig) error { func ValidateProxyConfigurerForServer(c v1.ProxyConfigurer, s *v1.ServerConfig) error {
base := c.GetBaseConfig() base := c.GetBaseConfig()
if err := validateProxyBaseConfigForServer(base, s); err != nil { if err := validateProxyBaseConfigForServer(base); err != nil {
return err return err
} }
@ -231,3 +237,34 @@ func validateXTCPProxyConfigForServer(c *v1.XTCPProxyConfig, s *v1.ServerConfig)
func validateSUDPProxyConfigForServer(c *v1.SUDPProxyConfig, s *v1.ServerConfig) error { func validateSUDPProxyConfigForServer(c *v1.SUDPProxyConfig, s *v1.ServerConfig) error {
return nil return nil
} }
// ValidateAnnotations validates that a set of annotations are correctly defined.
func ValidateAnnotations(annotations map[string]string) error {
if len(annotations) == 0 {
return nil
}
var errs error
for k := range annotations {
for _, msg := range validation.IsQualifiedName(strings.ToLower(k)) {
errs = AppendError(errs, fmt.Errorf("annotation key %s is invalid: %s", k, msg))
}
}
if err := ValidateAnnotationsSize(annotations); err != nil {
errs = AppendError(errs, err)
}
return errs
}
const TotalAnnotationSizeLimitB int = 256 * (1 << 10) // 256 kB
func ValidateAnnotationsSize(annotations map[string]string) error {
var totalSize int64
for k, v := range annotations {
totalSize += (int64)(len(k)) + (int64)(len(v))
}
if totalSize > (int64)(TotalAnnotationSizeLimitB) {
return fmt.Errorf("annotations size %d is larger than limit %d", totalSize, TotalAnnotationSizeLimitB)
}
return nil
}

View File

@ -108,6 +108,7 @@ type NewProxy struct {
Group string `json:"group,omitempty"` Group string `json:"group,omitempty"`
GroupKey string `json:"group_key,omitempty"` GroupKey string `json:"group_key,omitempty"`
Metas map[string]string `json:"metas,omitempty"` Metas map[string]string `json:"metas,omitempty"`
Annotations map[string]string `json:"annotations,omitempty"`
// tcp and udp only // tcp and udp only
RemotePort int `json:"remote_port,omitempty"` RemotePort int `json:"remote_port,omitempty"`

View File

@ -0,0 +1,54 @@
package basic
import (
"fmt"
"io"
"net/http"
"github.com/onsi/ginkgo/v2"
"github.com/tidwall/gjson"
"github.com/fatedier/frp/test/e2e/framework"
"github.com/fatedier/frp/test/e2e/framework/consts"
)
var _ = ginkgo.Describe("[Feature: Annotations]", func() {
f := framework.NewDefaultFramework()
ginkgo.It("Set Proxy Annotations", func() {
webPort := f.AllocPort()
serverConf := consts.DefaultServerConfig + fmt.Sprintf(`
webServer.port = %d
`, webPort)
p1Port := f.AllocPort()
clientConf := consts.DefaultClientConfig + fmt.Sprintf(`
[[proxies]]
name = "p1"
type = "tcp"
localPort = {{ .%s }}
remotePort = %d
[proxies.annotations]
"frp.e2e.test/foo" = "value1"
"frp.e2e.test/bar" = "value2"
`, framework.TCPEchoServerPort, p1Port)
f.RunProcesses([]string{serverConf}, []string{clientConf})
framework.NewRequestExpect(f).Port(p1Port).Ensure()
// check annotations in frps
resp, err := http.Get(fmt.Sprintf("http://127.0.0.1:%d/api/proxy/tcp/%s", webPort, "p1"))
framework.ExpectNoError(err)
framework.ExpectEqual(resp.StatusCode, 200)
defer resp.Body.Close()
content, err := io.ReadAll(resp.Body)
framework.ExpectNoError(err)
annotations := gjson.Get(string(content), "conf.annotations").Map()
framework.ExpectEqual("value1", annotations["frp.e2e.test/foo"].String())
framework.ExpectEqual("value2", annotations["frp.e2e.test/bar"].String())
})
})

View File

@ -9,19 +9,21 @@ declare module 'vue' {
export interface GlobalComponents { export interface GlobalComponents {
ElButton: typeof import('element-plus/es')['ElButton'] ElButton: typeof import('element-plus/es')['ElButton']
ElCol: typeof import('element-plus/es')['ElCol'] ElCol: typeof import('element-plus/es')['ElCol']
ElDialog: typeof import('element-plus/es')['ElDialog']
ElDivider: typeof import('element-plus/es')['ElDivider']
ElForm: typeof import('element-plus/es')['ElForm'] ElForm: typeof import('element-plus/es')['ElForm']
ElFormItem: typeof import('element-plus/es')['ElFormItem'] ElFormItem: typeof import('element-plus/es')['ElFormItem']
ElMenu: typeof import('element-plus/es')['ElMenu'] ElMenu: typeof import('element-plus/es')['ElMenu']
ElMenuItem: typeof import('element-plus/es')['ElMenuItem'] ElMenuItem: typeof import('element-plus/es')['ElMenuItem']
ElPageHeader: typeof import('element-plus/es')['ElPageHeader'] ElPageHeader: typeof import('element-plus/es')['ElPageHeader']
ElPopconfirm: typeof import('element-plus/es')['ElPopconfirm'] ElPopconfirm: typeof import('element-plus/es')['ElPopconfirm']
ElPopover: typeof import('element-plus/es')['ElPopover']
ElRow: typeof import('element-plus/es')['ElRow'] ElRow: typeof import('element-plus/es')['ElRow']
ElSubMenu: typeof import('element-plus/es')['ElSubMenu'] ElSubMenu: typeof import('element-plus/es')['ElSubMenu']
ElSwitch: typeof import('element-plus/es')['ElSwitch'] ElSwitch: typeof import('element-plus/es')['ElSwitch']
ElTable: typeof import('element-plus/es')['ElTable'] ElTable: typeof import('element-plus/es')['ElTable']
ElTableColumn: typeof import('element-plus/es')['ElTableColumn'] ElTableColumn: typeof import('element-plus/es')['ElTableColumn']
ElTag: typeof import('element-plus/es')['ElTag'] ElTag: typeof import('element-plus/es')['ElTag']
ElText: typeof import('element-plus/es')['ElText']
ElTooltip: typeof import('element-plus/es')['ElTooltip'] ElTooltip: typeof import('element-plus/es')['ElTooltip']
LongSpan: typeof import('./src/components/LongSpan.vue')['default'] LongSpan: typeof import('./src/components/LongSpan.vue')['default']
ProxiesHTTP: typeof import('./src/components/ProxiesHTTP.vue')['default'] ProxiesHTTP: typeof import('./src/components/ProxiesHTTP.vue')['default']

View File

@ -30,27 +30,6 @@
> >
<el-table-column type="expand"> <el-table-column type="expand">
<template #default="props"> <template #default="props">
<el-popover
placement="right"
width="600"
style="margin-left: 0px"
trigger="click"
>
<template #default>
<Traffic :proxyName="props.row.name" />
</template>
<template #reference>
<el-button
type="primary"
size="large"
:name="props.row.name"
style="margin-bottom: 10px"
>Traffic Statistics
</el-button>
</template>
</el-popover>
<ProxyViewExpand :row="props.row" :proxyType="proxyType" /> <ProxyViewExpand :row="props.row" :proxyType="proxyType" />
</template> </template>
</el-table-column> </el-table-column>
@ -82,8 +61,27 @@
<el-tag v-else type="danger">{{ scope.row.status }}</el-tag> <el-tag v-else type="danger">{{ scope.row.status }}</el-tag>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="Operations">
<template #default="scope">
<el-button
type="primary"
:name="scope.row.name"
style="margin-bottom: 10px"
@click="dialogVisibleName = scope.row.name; dialogVisible = true"
>Traffic
</el-button>
</template>
</el-table-column>
</el-table> </el-table>
</div> </div>
<el-dialog
v-model="dialogVisible"
destroy-on-close="true"
:title="dialogVisibleName"
width="700px">
<Traffic :proxyName="dialogVisibleName" />
</el-dialog>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
@ -92,6 +90,7 @@ import type { TableColumnCtx } from 'element-plus'
import type { BaseProxy } from '../utils/proxy.js' import type { BaseProxy } from '../utils/proxy.js'
import { ElMessage } from 'element-plus' import { ElMessage } from 'element-plus'
import ProxyViewExpand from './ProxyViewExpand.vue' import ProxyViewExpand from './ProxyViewExpand.vue'
import { ref } from 'vue'
defineProps<{ defineProps<{
proxies: BaseProxy[] proxies: BaseProxy[]
@ -100,6 +99,9 @@ defineProps<{
const emit = defineEmits(['refresh']) const emit = defineEmits(['refresh'])
const dialogVisible = ref(false)
const dialogVisibleName = ref("")
const formatTrafficIn = (row: BaseProxy, _: TableColumnCtx<BaseProxy>) => { const formatTrafficIn = (row: BaseProxy, _: TableColumnCtx<BaseProxy>) => {
return Humanize.fileSize(row.trafficIn) return Humanize.fileSize(row.trafficIn)
} }

View File

@ -60,11 +60,56 @@
<span>{{ row.lastCloseTime }}</span> <span>{{ row.lastCloseTime }}</span>
</el-form-item> </el-form-item>
</el-form> </el-form>
<div v-if="row.annotations && row.annotations.size > 0">
<el-divider />
<el-text class="title-text" size="large">Annotations</el-text>
<ul>
<li v-for="item in annotationsArray()">
<span class="annotation-key">{{ item.key }}</span>
<span>{{ item.value }}</span>
</li>
</ul>
</div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
defineProps<{
const props = defineProps<{
row: any row: any
proxyType: string proxyType: string
}>() }>()
// annotationsArray returns an array of key-value pairs from the annotations map.
const annotationsArray = (): Array<{ key: string; value: string }> => {
const array: Array<{ key: string; value: any }> = [];
if (props.row.annotations) {
props.row.annotations.forEach((value: any, key: string) => {
array.push({ key, value });
});
}
return array;
}
</script> </script>
<style>
ul {
list-style-type: none;
padding: 5px;
}
ul li {
justify-content: space-between;
padding: 5px;
}
ul .annotation-key {
width: 300px;
display: inline-block;
vertical-align: middle;
}
.title-text {
color: #99a9bf;
}
</style>

View File

@ -1,6 +1,7 @@
class BaseProxy { class BaseProxy {
name: string name: string
type: string type: string
annotations: Map<string, string>
encryption: boolean encryption: boolean
compression: boolean compression: boolean
conns: number conns: number
@ -21,6 +22,13 @@ class BaseProxy {
constructor(proxyStats: any) { constructor(proxyStats: any) {
this.name = proxyStats.name this.name = proxyStats.name
this.type = '' this.type = ''
this.annotations = new Map<string, string>()
if (proxyStats.conf?.annotations) {
for (const key in proxyStats.conf.annotations) {
this.annotations.set(key, proxyStats.conf.annotations[key])
}
}
this.encryption = false this.encryption = false
this.compression = false this.compression = false
this.encryption = this.encryption =