mirror of
https://github.com/fatedier/frp.git
synced 2025-07-27 15:45:39 +00:00
Compare commits
103 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
88e74ff24d | ||
|
18ab58eb25 | ||
|
534dc99d55 | ||
|
fa0593ae2c | ||
|
89fff7d11d | ||
|
38d42dbe4b | ||
|
aa31d7ad0b | ||
|
113e3b0b0d | ||
|
100148d925 | ||
|
6b3daffaf0 | ||
|
5e17bc7bf1 | ||
|
b1b8d9a82b | ||
|
24c7d1d9e2 | ||
|
d205c26480 | ||
|
0eecab06c1 | ||
|
ad3548d332 | ||
|
595aba5a9b | ||
|
679992db25 | ||
|
5cfbb976f4 | ||
|
b03f0ad1e6 | ||
|
804f2910fd | ||
|
a4189ba474 | ||
|
e2d28d9929 | ||
|
9ec84f8143 | ||
|
7678938c08 | ||
|
b2e3946800 | ||
|
af0b7939a7 | ||
|
2f66dc3e99 | ||
|
649df8827c | ||
|
da51adc276 | ||
|
e5af37bc8c | ||
|
8ab474cc97 | ||
|
e8c8d5903a | ||
|
a301046f3d | ||
|
34ab6b0e74 | ||
|
cf66ca10b4 | ||
|
3fbe6b659e | ||
|
6a71d71e58 | ||
|
6ecc97c857 | ||
|
ba492f07c3 | ||
|
9d077b02cf | ||
|
f4e4fbea62 | ||
|
3e721d122b | ||
|
1bc899ec12 | ||
|
6f2571980c | ||
|
8888610d83 | ||
|
fa7c05c617 | ||
|
218b354f82 | ||
|
c652b8ef07 | ||
|
5b8b145577 | ||
|
fe5fb0326b | ||
|
0711295b0a | ||
|
4af85da0c2 | ||
|
bd89eaba2f | ||
|
a72259c604 | ||
|
44eb513f05 | ||
|
eb1e19a821 | ||
|
6c658586f6 | ||
|
888ed25314 | ||
|
21240ed962 | ||
|
6481870d03 | ||
|
a7a4ba270d | ||
|
915d9f4c09 | ||
|
18a2af4703 | ||
|
305e40fa8a | ||
|
10f2620131 | ||
|
4acae540c8 | ||
|
11b13533a0 | ||
|
100d556336 | ||
|
452fe25cc6 | ||
|
63efa6b776 | ||
|
37c27169ac | ||
|
ce677820c6 | ||
|
1f88a7a0b8 | ||
|
eeea7602d9 | ||
|
bf635c0e90 | ||
|
cd31359a27 | ||
|
19739ed31a | ||
|
10100c28d9 | ||
|
88fcc079e8 | ||
|
ddc1e163c4 | ||
|
d20a6d3d75 | ||
|
6194273615 | ||
|
b2311e55e7 | ||
|
07873d471f | ||
|
2dab5d0bca | ||
|
9ca2b586f8 | ||
|
e59eacb8a2 | ||
|
0db4fc07fb | ||
|
70f4caac23 | ||
|
293003fcdb | ||
|
4bfc89d988 | ||
|
22412851b4 | ||
|
e9775bd70f | ||
|
ff7b8b0b62 | ||
|
491c1d7dc4 | ||
|
ea568e8a4f | ||
|
0fb6aeef58 | ||
|
032f33fe5a | ||
|
bbc8b438d5 | ||
|
05b1ace21f | ||
|
cbdd73b94f | ||
|
bf06e3b107 |
@@ -2,14 +2,16 @@ version: 2
|
||||
jobs:
|
||||
go-version-latest:
|
||||
docker:
|
||||
- image: cimg/go:1.17-node
|
||||
- image: cimg/go:1.20-node
|
||||
resource_class: large
|
||||
steps:
|
||||
- checkout
|
||||
- run: make
|
||||
- run: make alltest
|
||||
go-version-last:
|
||||
docker:
|
||||
- image: cimg/go:1.16-node
|
||||
- image: cimg/go:1.19-node
|
||||
resource_class: large
|
||||
steps:
|
||||
- checkout
|
||||
- run: make
|
||||
|
110
.github/workflows/build-and-push-image.yml
vendored
110
.github/workflows/build-and-push-image.yml
vendored
@@ -9,69 +9,25 @@ on:
|
||||
description: 'Image tag'
|
||||
required: true
|
||||
default: 'test'
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
binary:
|
||||
name: Build Golang project
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Set up Go 1.x
|
||||
uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: 1.17
|
||||
|
||||
- run: |
|
||||
# https://github.com/actions/setup-go/issues/107
|
||||
cp -f `which go` /usr/bin/go
|
||||
|
||||
- run: go version
|
||||
|
||||
- name: Check out code into the Go module directory
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Build
|
||||
run: make build
|
||||
|
||||
- name: Archive artifacts for frpc
|
||||
uses: actions/upload-artifact@v1
|
||||
with:
|
||||
name: frpc
|
||||
path: bin/frpc
|
||||
|
||||
- name: Archive artifacts for frps
|
||||
uses: actions/upload-artifact@v1
|
||||
with:
|
||||
name: frps
|
||||
path: bin/frps
|
||||
|
||||
image:
|
||||
name: Build Image from Dockerfile and binaries
|
||||
runs-on: ubuntu-latest
|
||||
needs: binary
|
||||
steps:
|
||||
# environment
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: '0'
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v1
|
||||
uses: docker/setup-qemu-action@v2
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v1
|
||||
|
||||
# download binaries of frpc and frps
|
||||
- name: Download binary of frpc
|
||||
uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: frpc
|
||||
path: bin/frpc
|
||||
|
||||
- name: Download binary of frps
|
||||
uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: frps
|
||||
path: bin/frps
|
||||
uses: docker/setup-buildx-action@v2
|
||||
|
||||
# get image tag name
|
||||
- name: Get Image Tag Name
|
||||
@@ -81,6 +37,18 @@ jobs:
|
||||
else
|
||||
echo "TAG_NAME=${{ github.event.inputs.tag }}" >> $GITHUB_ENV
|
||||
fi
|
||||
- name: Login to DockerHub
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_PASSWORD }}
|
||||
|
||||
- name: Login to the GPR
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.repository_owner }}
|
||||
password: ${{ secrets.GPR_TOKEN }}
|
||||
|
||||
# prepare image tags
|
||||
- name: Prepare Image Tags
|
||||
@@ -92,26 +60,24 @@ jobs:
|
||||
echo "TAG_FRPC_GPR=ghcr.io/fatedier/frpc:${{ env.TAG_NAME }}" >> $GITHUB_ENV
|
||||
echo "TAG_FRPS_GPR=ghcr.io/fatedier/frps:${{ env.TAG_NAME }}" >> $GITHUB_ENV
|
||||
|
||||
# build images
|
||||
- name: Build Images
|
||||
run: |
|
||||
# for Docker hub
|
||||
docker build --file ${{ env.DOCKERFILE_FRPC_PATH }} --tag ${{ env.TAG_FRPC }} .
|
||||
docker build --file ${{ env.DOCKERFILE_FRPS_PATH }} --tag ${{ env.TAG_FRPS }} .
|
||||
# for GPR
|
||||
docker build --file ${{ env.DOCKERFILE_FRPC_PATH }} --tag ${{ env.TAG_FRPC_GPR }} .
|
||||
docker build --file ${{ env.DOCKERFILE_FRPS_PATH }} --tag ${{ env.TAG_FRPS_GPR }} .
|
||||
- name: Build and push frpc
|
||||
uses: docker/build-push-action@v3
|
||||
with:
|
||||
context: .
|
||||
file: ./dockerfiles/Dockerfile-for-frpc
|
||||
platforms: linux/amd64,linux/arm/v7,linux/arm64,linux/ppc64le,linux/s390x
|
||||
push: true
|
||||
tags: |
|
||||
${{ env.TAG_FRPC }}
|
||||
${{ env.TAG_FRPC_GPR }}
|
||||
|
||||
# push to dockerhub
|
||||
- name: Publish to Dockerhub
|
||||
run: |
|
||||
echo ${{ secrets.DOCKERHUB_PASSWORD }} | docker login --username ${{ secrets.DOCKERHUB_USERNAME }} --password-stdin
|
||||
docker push ${{ env.TAG_FRPC }}
|
||||
docker push ${{ env.TAG_FRPS }}
|
||||
|
||||
# push to gpr
|
||||
- name: Publish to GPR
|
||||
run: |
|
||||
echo ${{ secrets.GPR_TOKEN }} | docker login ghcr.io --username ${{ github.repository_owner }} --password-stdin
|
||||
docker push ${{ env.TAG_FRPC_GPR }}
|
||||
docker push ${{ env.TAG_FRPS_GPR }}
|
||||
- name: Build and push frps
|
||||
uses: docker/build-push-action@v3
|
||||
with:
|
||||
context: .
|
||||
file: ./dockerfiles/Dockerfile-for-frps
|
||||
platforms: linux/amd64,linux/arm/v7,linux/arm64,linux/ppc64le,linux/s390x
|
||||
push: true
|
||||
tags: |
|
||||
${{ env.TAG_FRPS }}
|
||||
${{ env.TAG_FRPS_GPR }}
|
||||
|
41
.github/workflows/golangci-lint.yml
vendored
Normal file
41
.github/workflows/golangci-lint.yml
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
name: golangci-lint
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- dev
|
||||
pull_request:
|
||||
permissions:
|
||||
contents: read
|
||||
# Optional: allow read access to pull request. Use with `only-new-issues` option.
|
||||
pull-requests: read
|
||||
jobs:
|
||||
golangci:
|
||||
name: lint
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: '1.20'
|
||||
- uses: actions/checkout@v3
|
||||
- name: golangci-lint
|
||||
uses: golangci/golangci-lint-action@v3
|
||||
with:
|
||||
# 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.51
|
||||
|
||||
# Optional: golangci-lint command line arguments.
|
||||
# args: --issues-exit-code=0
|
||||
|
||||
# Optional: show only new issues if it's a pull request. The default value is `false`.
|
||||
# only-new-issues: true
|
||||
|
||||
# Optional: if set to true then the all caching functionality will be complete disabled,
|
||||
# takes precedence over all other caching options.
|
||||
# skip-cache: true
|
||||
|
||||
# Optional: if set to true then the action don't cache or restore ~/go/pkg.
|
||||
# skip-pkg-cache: true
|
||||
|
||||
# Optional: if set to true then the action don't cache or restore ~/.cache/go-build.
|
||||
# skip-build-cache: true
|
12
.github/workflows/goreleaser.yml
vendored
12
.github/workflows/goreleaser.yml
vendored
@@ -8,25 +8,21 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v2
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: 1.17
|
||||
go-version: '1.20'
|
||||
|
||||
- run: |
|
||||
# https://github.com/actions/setup-go/issues/107
|
||||
cp -f `which go` /usr/bin/go
|
||||
|
||||
- name: Make All
|
||||
run: |
|
||||
./package.sh
|
||||
|
||||
- name: Run GoReleaser
|
||||
uses: goreleaser/goreleaser-action@v2
|
||||
uses: goreleaser/goreleaser-action@v3
|
||||
with:
|
||||
version: latest
|
||||
args: release --rm-dist --release-notes=./Release.md
|
||||
|
12
.github/workflows/stale.yml
vendored
12
.github/workflows/stale.yml
vendored
@@ -8,15 +8,21 @@ on:
|
||||
description: 'In debug mod'
|
||||
required: false
|
||||
default: 'false'
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
stale:
|
||||
permissions:
|
||||
issues: write # for actions/stale to close stale issues
|
||||
pull-requests: write # for actions/stale to close stale PRs
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/stale@v3
|
||||
- uses: actions/stale@v6
|
||||
with:
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
stale-issue-message: 'Issues go stale after 30d of inactivity. Stale issues rot after an additional 7d of inactivity and eventually close.'
|
||||
stale-pr-message: 'Issues go stale after 30d of inactivity. Stale issues rot after an additional 7d of inactivity and eventually close.'
|
||||
stale-pr-message: "PRs go stale after 30d of inactivity. Stale PRs rot after an additional 7d of inactivity and eventually close."
|
||||
stale-issue-label: 'lifecycle/stale'
|
||||
exempt-issue-labels: 'bug,doc,enhancement,future,proposal,question,testing,todo,easy,help wanted,assigned'
|
||||
stale-pr-label: 'lifecycle/stale'
|
||||
@@ -24,3 +30,5 @@ jobs:
|
||||
days-before-stale: 30
|
||||
days-before-close: 7
|
||||
debug-only: ${{ github.event.inputs.debug-only }}
|
||||
exempt-all-pr-milestones: true
|
||||
exempt-all-pr-assignees: true
|
||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@@ -31,6 +31,7 @@ test/bin/
|
||||
vendor/
|
||||
dist/
|
||||
.idea/
|
||||
.vscode/
|
||||
|
||||
# Cache
|
||||
*.swp
|
||||
|
144
.golangci.yml
Normal file
144
.golangci.yml
Normal file
@@ -0,0 +1,144 @@
|
||||
service:
|
||||
golangci-lint-version: 1.51.x # use the fixed version to not introduce new linters unexpectedly
|
||||
|
||||
run:
|
||||
concurrency: 4
|
||||
# timeout for analysis, e.g. 30s, 5m, default is 1m
|
||||
deadline: 20m
|
||||
build-tags:
|
||||
- integ
|
||||
- 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:
|
||||
disable-all: true
|
||||
enable:
|
||||
- unused
|
||||
- errcheck
|
||||
- exportloopref
|
||||
- gocritic
|
||||
- gofumpt
|
||||
- goimports
|
||||
- revive
|
||||
- gosimple
|
||||
- govet
|
||||
- ineffassign
|
||||
- lll
|
||||
- misspell
|
||||
- staticcheck
|
||||
- stylecheck
|
||||
- typecheck
|
||||
- unconvert
|
||||
- unparam
|
||||
- gci
|
||||
- gosec
|
||||
- asciicheck
|
||||
- prealloc
|
||||
- predeclared
|
||||
- makezero
|
||||
fast: false
|
||||
|
||||
linters-settings:
|
||||
errcheck:
|
||||
# report about not checking of errors in type assetions: `a := b.(MyStruct)`;
|
||||
# default is false: such cases aren't reported by default.
|
||||
check-type-assertions: false
|
||||
|
||||
# report about assignment of errors to blank identifier: `num, _ := strconv.Atoi(numStr)`;
|
||||
# default is false: such cases aren't reported by default.
|
||||
check-blank: false
|
||||
govet:
|
||||
# report about shadowed variables
|
||||
check-shadowing: false
|
||||
maligned:
|
||||
# print struct with more effective memory layout or not, false by default
|
||||
suggest-new: true
|
||||
misspell:
|
||||
# Correct spellings using locale preferences for US or UK.
|
||||
# Default is to use a neutral variety of English.
|
||||
# Setting locale to US will correct the British spelling of 'colour' to 'color'.
|
||||
locale: US
|
||||
ignore-words:
|
||||
- cancelled
|
||||
- marshalled
|
||||
lll:
|
||||
# max line length, lines longer will be reported. Default is 120.
|
||||
# '\t' is counted as 1 character by default, and can be changed with the tab-width option
|
||||
line-length: 160
|
||||
# tab width in spaces. Default to 1.
|
||||
tab-width: 1
|
||||
gocritic:
|
||||
disabled-checks:
|
||||
- exitAfterDefer
|
||||
unused:
|
||||
check-exported: false
|
||||
unparam:
|
||||
# Inspect exported functions, default is false. Set to true if no external program/library imports your code.
|
||||
# XXX: if you enable this setting, unparam will report a lot of false-positives in text editors:
|
||||
# if it's called for subdir of a project it can't find external interfaces. All text editor integrations
|
||||
# with golangci-lint call it on a directory with the changed file.
|
||||
check-exported: false
|
||||
gci:
|
||||
sections:
|
||||
- standard
|
||||
- default
|
||||
- prefix(github.com/fatedier/frp/)
|
||||
gosec:
|
||||
severity: "low"
|
||||
confidence: "low"
|
||||
excludes:
|
||||
- G102
|
||||
- G112
|
||||
- G306
|
||||
- G401
|
||||
- G402
|
||||
- G404
|
||||
- G501
|
||||
|
||||
issues:
|
||||
# List of regexps of issue texts to exclude, empty list by default.
|
||||
# But independently from this option we use default exclude patterns,
|
||||
# it can be disabled by `exclude-use-default: false`. To list all
|
||||
# excluded by default patterns execute `golangci-lint run --help`
|
||||
# exclude:
|
||||
# - composite literal uses unkeyed fields
|
||||
|
||||
exclude-rules:
|
||||
# Exclude some linters from running on test files.
|
||||
- path: _test\.go$|^tests/|^samples/
|
||||
linters:
|
||||
- errcheck
|
||||
- maligned
|
||||
|
||||
# keep it until we only support go1.20
|
||||
- linters:
|
||||
- staticcheck
|
||||
text: "SA1019: rand.Seed has been deprecated"
|
||||
|
||||
# Independently from option `exclude` we use default exclude patterns,
|
||||
# it can be disabled by this option. To list all
|
||||
# excluded by default patterns execute `golangci-lint run --help`.
|
||||
# Default value for this option is true.
|
||||
exclude-use-default: true
|
||||
|
||||
# Maximum issues count per one linter. Set to 0 to disable. Default is 50.
|
||||
max-per-linter: 0
|
||||
|
||||
# Maximum count of issues with the same text. Set to 0 to disable. Default is 3.
|
||||
max-same-issues: 0
|
@@ -1,7 +1,10 @@
|
||||
builds:
|
||||
- skip: true
|
||||
checksum:
|
||||
name_template: 'checksums.txt'
|
||||
name_template: '{{ .ProjectName }}_sha256_checksums.txt'
|
||||
algorithm: sha256
|
||||
extra_files:
|
||||
- glob: ./release/packages/*
|
||||
release:
|
||||
# Same as for github
|
||||
# Note: it can only be one: either github, gitlab or gitea
|
||||
|
8
Makefile
8
Makefile
@@ -16,6 +16,12 @@ file:
|
||||
fmt:
|
||||
go fmt ./...
|
||||
|
||||
fmt-more:
|
||||
gofumpt -l -w .
|
||||
|
||||
vet:
|
||||
go vet ./...
|
||||
|
||||
frps:
|
||||
env CGO_ENABLED=0 go build -trimpath -ldflags "$(LDFLAGS)" -o bin/frps ./cmd/frps
|
||||
|
||||
@@ -37,7 +43,7 @@ e2e:
|
||||
e2e-trace:
|
||||
DEBUG=true LOG_LEVEL=trace ./hack/run-e2e.sh
|
||||
|
||||
alltest: gotest e2e
|
||||
alltest: vet gotest e2e
|
||||
|
||||
clean:
|
||||
rm -f ./bin/frpc
|
||||
|
@@ -2,7 +2,7 @@ export PATH := $(GOPATH)/bin:$(PATH)
|
||||
export GO111MODULE=on
|
||||
LDFLAGS := -s -w
|
||||
|
||||
os-archs=darwin:amd64 darwin:arm64 freebsd:386 freebsd:amd64 linux:386 linux:amd64 linux:arm linux:arm64 windows:386 windows:amd64 linux:mips64 linux:mips64le linux:mips:softfloat linux:mipsle:softfloat
|
||||
os-archs=darwin:amd64 darwin:arm64 freebsd:386 freebsd:amd64 linux:386 linux:amd64 linux:arm linux:arm64 windows:386 windows:amd64 linux:mips64 linux:mips64le linux:mips:softfloat linux:mipsle:softfloat linux:riscv64
|
||||
|
||||
all: build
|
||||
|
||||
|
88
README.md
88
README.md
@@ -6,6 +6,17 @@
|
||||
|
||||
[README](README.md) | [中文文档](README_zh.md)
|
||||
|
||||
<h3 align="center">Gold Sponsors</h3>
|
||||
<!--gold sponsors start-->
|
||||
|
||||
<p align="center">
|
||||
<a href="https://workos.com/?utm_campaign=github_repo&utm_medium=referral&utm_content=frp&utm_source=github" target="_blank">
|
||||
<img width="300px" src="https://raw.githubusercontent.com/fatedier/frp/dev/doc/pic/sponsor_workos.png">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
<!--gold sponsors end-->
|
||||
|
||||
## What is frp?
|
||||
|
||||
frp is a fast reverse proxy to help you expose a local server behind a NAT or firewall to the Internet. As of now, it supports **TCP** and **UDP**, as well as **HTTP** and **HTTPS** protocols, where requests can be forwarded to internal services by domain name.
|
||||
@@ -48,6 +59,7 @@ frp also has a P2P connect mode.
|
||||
* [For Each Proxy](#for-each-proxy)
|
||||
* [TCP Stream Multiplexing](#tcp-stream-multiplexing)
|
||||
* [Support KCP Protocol](#support-kcp-protocol)
|
||||
* [Support QUIC Protocol](#support-quic-protocol)
|
||||
* [Connection Pooling](#connection-pooling)
|
||||
* [Load balancing](#load-balancing)
|
||||
* [Service Health Check](#service-health-check)
|
||||
@@ -67,8 +79,7 @@ frp also has a P2P connect mode.
|
||||
* [Development Plan](#development-plan)
|
||||
* [Contributing](#contributing)
|
||||
* [Donation](#donation)
|
||||
* [AliPay](#alipay)
|
||||
* [Wechat Pay](#wechat-pay)
|
||||
* [GitHub Sponsors](#github-sponsors)
|
||||
* [PayPal](#paypal)
|
||||
|
||||
<!-- vim-markdown-toc -->
|
||||
@@ -77,7 +88,9 @@ frp also has a P2P connect mode.
|
||||
|
||||
frp is under development. Try the latest release version in the `master` branch, or use the `dev` branch for the version in development.
|
||||
|
||||
**The protocol might change at a release and we don't promise backwards compatibility. Please check the release log when upgrading the client and the server.**
|
||||
We are working on v2 version and trying to do some code refactor and improvements. It won't be compatible with v1.
|
||||
|
||||
We will switch v0 to v1 at the right time and only accept bug fixes and improvements instead of big feature requirements.
|
||||
|
||||
## Architecture
|
||||
|
||||
@@ -126,7 +139,7 @@ Note that `local_port` (listened on client) and `remote_port` (exposed on server
|
||||
|
||||
`./frpc -c ./frpc.ini`
|
||||
|
||||
5. From another machine, SSH to server B like this (assuming that username is `test`):
|
||||
5. From another machine, SSH to server B via server A like this (assuming that username is `test`):
|
||||
|
||||
`ssh -oPort=6000 test@x.x.x.x`
|
||||
|
||||
@@ -450,6 +463,21 @@ dashboard_pwd = admin
|
||||
|
||||
Then visit `http://[server_addr]:7500` to see the dashboard, with username and password both being `admin`.
|
||||
|
||||
Additionally, you can use HTTPS port by using your domains wildcard or normal SSL certificate:
|
||||
|
||||
```ini
|
||||
[common]
|
||||
dashboard_port = 7500
|
||||
# dashboard's username and password are both optional
|
||||
dashboard_user = admin
|
||||
dashboard_pwd = admin
|
||||
dashboard_tls_mode = true
|
||||
dashboard_tls_cert_file = server.crt
|
||||
dashboard_tls_key_file = server.key
|
||||
```
|
||||
|
||||
Then visit `https://[server_addr]:7500` to see the dashboard in secure HTTPS connection, with username and password both being `admin`.
|
||||
|
||||

|
||||
|
||||
### Admin UI
|
||||
@@ -614,7 +642,7 @@ openssl req -new -sha256 -key server.key \
|
||||
-config <(cat my-openssl.cnf <(printf "\n[SAN]\nsubjectAltName=DNS:localhost,IP:127.0.0.1,DNS:example.server.com")) \
|
||||
-out server.csr
|
||||
|
||||
openssl x509 -req -days 365 \
|
||||
openssl x509 -req -days 365 -sha256 \
|
||||
-in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial \
|
||||
-extfile <(printf "subjectAltName=DNS:localhost,IP:127.0.0.1,DNS:example.server.com") \
|
||||
-out server.crt
|
||||
@@ -629,7 +657,7 @@ openssl req -new -sha256 -key client.key \
|
||||
-config <(cat my-openssl.cnf <(printf "\n[SAN]\nsubjectAltName=DNS:client.com,DNS:example.client.com")) \
|
||||
-out client.csr
|
||||
|
||||
openssl x509 -req -days 365 \
|
||||
openssl x509 -req -days 365 -sha256 \
|
||||
-in client.csr -CA ca.crt -CAkey ca.key -CAcreateserial \
|
||||
-extfile <(printf "subjectAltName=DNS:client.com,DNS:example.client.com") \
|
||||
-out client.crt
|
||||
@@ -685,10 +713,13 @@ type = tcp
|
||||
local_port = 22
|
||||
remote_port = 6000
|
||||
bandwidth_limit = 1MB
|
||||
bandwidth_limit_mode = client
|
||||
```
|
||||
|
||||
Set `bandwidth_limit` in each proxy's configure to enable this feature. Supported units are `MB` and `KB`.
|
||||
|
||||
Set `bandwidth_limit_mode` to `client` or `server` to limit bandwidth on the client or server side. Default is `client`.
|
||||
|
||||
### TCP Stream Multiplexing
|
||||
|
||||
frp supports tcp stream multiplexing since v0.10.0 like HTTP2 Multiplexing, in which case all logic connections to the same frpc are multiplexed into the same TCP connection.
|
||||
@@ -730,6 +761,35 @@ KCP mode uses UDP as the underlying transport. Using KCP in frp:
|
||||
protocol = kcp
|
||||
```
|
||||
|
||||
### Support QUIC Protocol
|
||||
|
||||
QUIC is a new multiplexed transport built on top of UDP.
|
||||
|
||||
Using QUIC in frp:
|
||||
|
||||
1. Enable QUIC in frps:
|
||||
|
||||
```ini
|
||||
# frps.ini
|
||||
[common]
|
||||
bind_port = 7000
|
||||
# Specify a UDP port for QUIC.
|
||||
quic_bind_port = 7000
|
||||
```
|
||||
|
||||
The `quic_bind_port` number can be the same number as `bind_port`, since `bind_port` field specifies a TCP port.
|
||||
|
||||
2. Configure `frpc.ini` to use QUIC to connect to frps:
|
||||
|
||||
```ini
|
||||
# frpc.ini
|
||||
[common]
|
||||
server_addr = x.x.x.x
|
||||
# Same as the 'quic_bind_port' in frps.ini
|
||||
server_port = 7000
|
||||
protocol = quic
|
||||
```
|
||||
|
||||
### Connection Pooling
|
||||
|
||||
By default, frps creates a new frpc connection to the backend service upon a user request. With connection pooling, frps keeps a certain number of pre-established connections, reducing the time needed to establish a connection.
|
||||
@@ -841,7 +901,7 @@ custom_domains = test.example.com
|
||||
host_header_rewrite = dev.example.com
|
||||
```
|
||||
|
||||
The HTTP request will have the the `Host` header rewritten to `Host: dev.example.com` when it reaches the actual web server, although the request from the browser probably has `Host: test.example.com`.
|
||||
The HTTP request will have the `Host` header rewritten to `Host: dev.example.com` when it reaches the actual web server, although the request from the browser probably has `Host: test.example.com`.
|
||||
|
||||
### Setting other HTTP Headers
|
||||
|
||||
@@ -867,7 +927,7 @@ In this example, it will set header `X-From-Where: frp` in the HTTP request.
|
||||
|
||||
This feature is for http proxy only.
|
||||
|
||||
You can get user's real IP from HTTP request headers `X-Forwarded-For` and `X-Real-IP`.
|
||||
You can get user's real IP from HTTP request headers `X-Forwarded-For`.
|
||||
|
||||
#### Proxy Protocol
|
||||
|
||||
@@ -983,11 +1043,13 @@ server_port = 7000
|
||||
type = tcpmux
|
||||
multiplexer = httpconnect
|
||||
custom_domains = test1
|
||||
local_port = 80
|
||||
|
||||
[proxy2]
|
||||
type = tcpmux
|
||||
multiplexer = httpconnect
|
||||
custom_domains = test2
|
||||
local_port = 8080
|
||||
```
|
||||
|
||||
In the above configuration - frps can be contacted on port 1337 with a HTTP CONNECT header such as:
|
||||
@@ -1073,15 +1135,11 @@ Interested in getting involved? We would like to help you!
|
||||
|
||||
If frp helps you a lot, you can support us by:
|
||||
|
||||
frp QQ group: 606194980
|
||||
### GitHub Sponsors
|
||||
|
||||
### AliPay
|
||||
Support us by [Github Sponsors](https://github.com/sponsors/fatedier).
|
||||
|
||||

|
||||
|
||||
### Wechat Pay
|
||||
|
||||

|
||||
You can have your company's logo placed on README file of this project.
|
||||
|
||||
### PayPal
|
||||
|
||||
|
25
README_zh.md
25
README_zh.md
@@ -7,6 +7,17 @@
|
||||
|
||||
frp 是一个专注于内网穿透的高性能的反向代理应用,支持 TCP、UDP、HTTP、HTTPS 等多种协议。可以将内网服务以安全、便捷的方式通过具有公网 IP 节点的中转暴露到公网。
|
||||
|
||||
<h3 align="center">Gold Sponsors</h3>
|
||||
<!--gold sponsors start-->
|
||||
|
||||
<p align="center">
|
||||
<a href="https://workos.com/?utm_campaign=github_repo&utm_medium=referral&utm_content=frp&utm_source=github" target="_blank">
|
||||
<img width="300px" src="https://raw.githubusercontent.com/fatedier/frp/dev/doc/pic/sponsor_workos.png">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
<!--gold sponsors end-->
|
||||
|
||||
## 为什么使用 frp ?
|
||||
|
||||
通过在具有公网 IP 的节点上部署 frp 服务端,可以轻松地将内网服务穿透到公网,同时提供诸多专业的功能特性,这包括:
|
||||
@@ -25,6 +36,10 @@ frp 目前已被很多公司广泛用于测试、生产环境。
|
||||
|
||||
master 分支用于发布稳定版本,dev 分支用于开发,您可以尝试下载最新的 release 版本进行测试。
|
||||
|
||||
我们正在进行 v2 大版本的开发,将会尝试在各个方面进行重构和升级,且不会与 v1 版本进行兼容,预计会持续一段时间。
|
||||
|
||||
现在的 v0 版本将会在合适的时间切换为 v1 版本并且保证兼容性,后续只做 bug 修复和优化,不再进行大的功能性更新。
|
||||
|
||||
## 文档
|
||||
|
||||
完整文档已经迁移至 [https://gofrp.org](https://gofrp.org/docs)。
|
||||
@@ -46,6 +61,12 @@ frp 是一个免费且开源的项目,我们欢迎任何人为其开发和进
|
||||
|
||||
如果您觉得 frp 对你有帮助,欢迎给予我们一定的捐助来维持项目的长期发展。
|
||||
|
||||
### GitHub Sponsors
|
||||
|
||||
您可以通过 [GitHub Sponsors](https://github.com/sponsors/fatedier) 赞助我们。
|
||||
|
||||
企业赞助者可以将贵公司的 Logo 以及链接放置在项目 README 文件中。
|
||||
|
||||
### 知识星球
|
||||
|
||||
如果您想学习 frp 相关的知识和技术,或者寻求任何帮助及咨询,都可以通过微信扫描下方的二维码付费加入知识星球的官方社群:
|
||||
@@ -59,7 +80,3 @@ frp 是一个免费且开源的项目,我们欢迎任何人为其开发和进
|
||||
### 微信支付捐赠
|
||||
|
||||

|
||||
|
||||
### Paypal 捐赠
|
||||
|
||||
海外用户推荐通过 [Paypal](https://www.paypal.me/fatedier) 向我的账户 **fatedier@gmail.com** 进行捐赠。
|
||||
|
@@ -1,8 +1,8 @@
|
||||
### New
|
||||
|
||||
* Add `/healthz` API.
|
||||
* frpc support `disable_custom_tls_first_byte` .If set true, frpc will not send custom header byte.
|
||||
* Added config `bandwidth_limit_mode` in frpc, default value is `client` which is current behavior. Optional value is `server`, to enable bandwidth limit in server. The major aim is to let server plugin has the ability to modify bandwidth limit for each proxy.
|
||||
|
||||
### Improve
|
||||
|
||||
* Use go standard embed package instead of statik.
|
||||
* `dns_server` supports ipv6.
|
||||
* frpc supports graceful shutdown for protocol `quic`.
|
||||
|
@@ -17,37 +17,49 @@ package client
|
||||
import (
|
||||
"net"
|
||||
"net/http"
|
||||
"net/http/pprof"
|
||||
"time"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
|
||||
"github.com/fatedier/frp/assets"
|
||||
frpNet "github.com/fatedier/frp/pkg/util/net"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
|
||||
var (
|
||||
httpServerReadTimeout = 10 * time.Second
|
||||
httpServerWriteTimeout = 10 * time.Second
|
||||
httpServerReadTimeout = 60 * time.Second
|
||||
httpServerWriteTimeout = 60 * time.Second
|
||||
)
|
||||
|
||||
func (svr *Service) RunAdminServer(address string) (err error) {
|
||||
// url router
|
||||
router := mux.NewRouter()
|
||||
|
||||
router.HandleFunc("/healthz", svr.healthz)
|
||||
|
||||
// debug
|
||||
if svr.cfg.PprofEnable {
|
||||
router.HandleFunc("/debug/pprof/cmdline", pprof.Cmdline)
|
||||
router.HandleFunc("/debug/pprof/profile", pprof.Profile)
|
||||
router.HandleFunc("/debug/pprof/symbol", pprof.Symbol)
|
||||
router.HandleFunc("/debug/pprof/trace", pprof.Trace)
|
||||
router.PathPrefix("/debug/pprof/").HandlerFunc(pprof.Index)
|
||||
}
|
||||
|
||||
subRouter := router.NewRoute().Subrouter()
|
||||
user, passwd := svr.cfg.AdminUser, svr.cfg.AdminPwd
|
||||
router.Use(frpNet.NewHTTPAuthMiddleware(user, passwd).Middleware)
|
||||
subRouter.Use(frpNet.NewHTTPAuthMiddleware(user, passwd).Middleware)
|
||||
|
||||
// api, see admin_api.go
|
||||
router.HandleFunc("/healthz", svr.healthz)
|
||||
router.HandleFunc("/api/reload", svr.apiReload).Methods("GET")
|
||||
router.HandleFunc("/api/status", svr.apiStatus).Methods("GET")
|
||||
router.HandleFunc("/api/config", svr.apiGetConfig).Methods("GET")
|
||||
router.HandleFunc("/api/config", svr.apiPutConfig).Methods("PUT")
|
||||
subRouter.HandleFunc("/api/reload", svr.apiReload).Methods("GET")
|
||||
subRouter.HandleFunc("/api/status", svr.apiStatus).Methods("GET")
|
||||
subRouter.HandleFunc("/api/config", svr.apiGetConfig).Methods("GET")
|
||||
subRouter.HandleFunc("/api/config", svr.apiPutConfig).Methods("PUT")
|
||||
|
||||
// view
|
||||
router.Handle("/favicon.ico", http.FileServer(assets.FileSystem)).Methods("GET")
|
||||
router.PathPrefix("/static/").Handler(frpNet.MakeHTTPGzipHandler(http.StripPrefix("/static/", http.FileServer(assets.FileSystem)))).Methods("GET")
|
||||
router.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
subRouter.Handle("/favicon.ico", http.FileServer(assets.FileSystem)).Methods("GET")
|
||||
subRouter.PathPrefix("/static/").Handler(frpNet.MakeHTTPGzipHandler(http.StripPrefix("/static/", http.FileServer(assets.FileSystem)))).Methods("GET")
|
||||
subRouter.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
http.Redirect(w, r, "/static/", http.StatusMovedPermanently)
|
||||
})
|
||||
|
||||
@@ -65,6 +77,8 @@ func (svr *Service) RunAdminServer(address string) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
go server.Serve(ln)
|
||||
go func() {
|
||||
_ = server.Serve(ln)
|
||||
}()
|
||||
return
|
||||
}
|
||||
|
@@ -18,9 +18,11 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/fatedier/frp/client/proxy"
|
||||
@@ -47,7 +49,7 @@ func (svr *Service) apiReload(w http.ResponseWriter, r *http.Request) {
|
||||
log.Info("api response [/api/reload], code [%d]", res.Code)
|
||||
w.WriteHeader(res.Code)
|
||||
if len(res.Msg) > 0 {
|
||||
w.Write([]byte(res.Msg))
|
||||
_, _ = w.Write([]byte(res.Msg))
|
||||
}
|
||||
}()
|
||||
|
||||
@@ -66,7 +68,6 @@ func (svr *Service) apiReload(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
log.Info("success reload conf")
|
||||
return
|
||||
}
|
||||
|
||||
type StatusResp struct {
|
||||
@@ -105,48 +106,48 @@ func NewProxyStatusResp(status *proxy.WorkingStatus, serverAddr string) ProxySta
|
||||
switch cfg := status.Cfg.(type) {
|
||||
case *config.TCPProxyConf:
|
||||
if cfg.LocalPort != 0 {
|
||||
psr.LocalAddr = fmt.Sprintf("%s:%d", cfg.LocalIP, cfg.LocalPort)
|
||||
psr.LocalAddr = net.JoinHostPort(cfg.LocalIP, strconv.Itoa(cfg.LocalPort))
|
||||
}
|
||||
psr.Plugin = cfg.Plugin
|
||||
if status.Err != "" {
|
||||
psr.RemoteAddr = fmt.Sprintf("%s:%d", serverAddr, cfg.RemotePort)
|
||||
psr.RemoteAddr = net.JoinHostPort(serverAddr, strconv.Itoa(cfg.RemotePort))
|
||||
} else {
|
||||
psr.RemoteAddr = serverAddr + status.RemoteAddr
|
||||
}
|
||||
case *config.UDPProxyConf:
|
||||
if cfg.LocalPort != 0 {
|
||||
psr.LocalAddr = fmt.Sprintf("%s:%d", cfg.LocalIP, cfg.LocalPort)
|
||||
psr.LocalAddr = net.JoinHostPort(cfg.LocalIP, strconv.Itoa(cfg.LocalPort))
|
||||
}
|
||||
if status.Err != "" {
|
||||
psr.RemoteAddr = fmt.Sprintf("%s:%d", serverAddr, cfg.RemotePort)
|
||||
psr.RemoteAddr = net.JoinHostPort(serverAddr, strconv.Itoa(cfg.RemotePort))
|
||||
} else {
|
||||
psr.RemoteAddr = serverAddr + status.RemoteAddr
|
||||
}
|
||||
case *config.HTTPProxyConf:
|
||||
if cfg.LocalPort != 0 {
|
||||
psr.LocalAddr = fmt.Sprintf("%s:%d", cfg.LocalIP, cfg.LocalPort)
|
||||
psr.LocalAddr = net.JoinHostPort(cfg.LocalIP, strconv.Itoa(cfg.LocalPort))
|
||||
}
|
||||
psr.Plugin = cfg.Plugin
|
||||
psr.RemoteAddr = status.RemoteAddr
|
||||
case *config.HTTPSProxyConf:
|
||||
if cfg.LocalPort != 0 {
|
||||
psr.LocalAddr = fmt.Sprintf("%s:%d", cfg.LocalIP, cfg.LocalPort)
|
||||
psr.LocalAddr = net.JoinHostPort(cfg.LocalIP, strconv.Itoa(cfg.LocalPort))
|
||||
}
|
||||
psr.Plugin = cfg.Plugin
|
||||
psr.RemoteAddr = status.RemoteAddr
|
||||
case *config.STCPProxyConf:
|
||||
if cfg.LocalPort != 0 {
|
||||
psr.LocalAddr = fmt.Sprintf("%s:%d", cfg.LocalIP, cfg.LocalPort)
|
||||
psr.LocalAddr = net.JoinHostPort(cfg.LocalIP, strconv.Itoa(cfg.LocalPort))
|
||||
}
|
||||
psr.Plugin = cfg.Plugin
|
||||
case *config.XTCPProxyConf:
|
||||
if cfg.LocalPort != 0 {
|
||||
psr.LocalAddr = fmt.Sprintf("%s:%d", cfg.LocalIP, cfg.LocalPort)
|
||||
psr.LocalAddr = net.JoinHostPort(cfg.LocalIP, strconv.Itoa(cfg.LocalPort))
|
||||
}
|
||||
psr.Plugin = cfg.Plugin
|
||||
case *config.SUDPProxyConf:
|
||||
if cfg.LocalPort != 0 {
|
||||
psr.LocalAddr = fmt.Sprintf("%s:%d", cfg.LocalIP, cfg.LocalPort)
|
||||
psr.LocalAddr = net.JoinHostPort(cfg.LocalIP, strconv.Itoa(cfg.LocalPort))
|
||||
}
|
||||
psr.Plugin = cfg.Plugin
|
||||
}
|
||||
@@ -171,7 +172,7 @@ func (svr *Service) apiStatus(w http.ResponseWriter, r *http.Request) {
|
||||
defer func() {
|
||||
log.Info("Http response [/api/status]")
|
||||
buf, _ = json.Marshal(&res)
|
||||
w.Write(buf)
|
||||
_, _ = w.Write(buf)
|
||||
}()
|
||||
|
||||
ps := svr.ctl.pm.GetAllProxyStatus()
|
||||
@@ -200,7 +201,6 @@ func (svr *Service) apiStatus(w http.ResponseWriter, r *http.Request) {
|
||||
sort.Sort(ByProxyStatusResp(res.STCP))
|
||||
sort.Sort(ByProxyStatusResp(res.XTCP))
|
||||
sort.Sort(ByProxyStatusResp(res.SUDP))
|
||||
return
|
||||
}
|
||||
|
||||
// GET api/config
|
||||
@@ -212,7 +212,7 @@ func (svr *Service) apiGetConfig(w http.ResponseWriter, r *http.Request) {
|
||||
log.Info("Http get response [/api/config], code [%d]", res.Code)
|
||||
w.WriteHeader(res.Code)
|
||||
if len(res.Msg) > 0 {
|
||||
w.Write([]byte(res.Msg))
|
||||
_, _ = w.Write([]byte(res.Msg))
|
||||
}
|
||||
}()
|
||||
|
||||
@@ -252,7 +252,7 @@ func (svr *Service) apiPutConfig(w http.ResponseWriter, r *http.Request) {
|
||||
log.Info("Http put response [/api/config], code [%d]", res.Code)
|
||||
w.WriteHeader(res.Code)
|
||||
if len(res.Msg) > 0 {
|
||||
w.Write([]byte(res.Msg))
|
||||
_, _ = w.Write([]byte(res.Msg))
|
||||
}
|
||||
}()
|
||||
|
||||
@@ -313,7 +313,7 @@ func (svr *Service) apiPutConfig(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
content = strings.Join(newRows, "\n")
|
||||
|
||||
err = os.WriteFile(svr.cfgFile, []byte(content), 0644)
|
||||
err = os.WriteFile(svr.cfgFile, []byte(content), 0o644)
|
||||
if err != nil {
|
||||
res.Code = 500
|
||||
res.Msg = fmt.Sprintf("write content to frpc config file error: %v", err)
|
||||
|
@@ -16,25 +16,19 @@ package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"io"
|
||||
"net"
|
||||
"runtime/debug"
|
||||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/fatedier/golib/control/shutdown"
|
||||
"github.com/fatedier/golib/crypto"
|
||||
|
||||
"github.com/fatedier/frp/client/proxy"
|
||||
"github.com/fatedier/frp/pkg/auth"
|
||||
"github.com/fatedier/frp/pkg/config"
|
||||
"github.com/fatedier/frp/pkg/msg"
|
||||
"github.com/fatedier/frp/pkg/transport"
|
||||
frpNet "github.com/fatedier/frp/pkg/util/net"
|
||||
"github.com/fatedier/frp/pkg/util/xlog"
|
||||
|
||||
"github.com/fatedier/golib/control/shutdown"
|
||||
"github.com/fatedier/golib/crypto"
|
||||
fmux "github.com/hashicorp/yamux"
|
||||
)
|
||||
|
||||
type Control struct {
|
||||
@@ -51,8 +45,7 @@ type Control struct {
|
||||
// control connection
|
||||
conn net.Conn
|
||||
|
||||
// tcp stream multiplexing, if enabled
|
||||
session *fmux.Session
|
||||
cm *ConnectionManager
|
||||
|
||||
// put a message in this channel to send it over control connection to server
|
||||
sendCh chan (msg.Message)
|
||||
@@ -78,8 +71,6 @@ type Control struct {
|
||||
// The UDP port that the server is listening on
|
||||
serverUDPPort int
|
||||
|
||||
mu sync.RWMutex
|
||||
|
||||
xl *xlog.Logger
|
||||
|
||||
// service context
|
||||
@@ -89,18 +80,19 @@ type Control struct {
|
||||
authSetter auth.Setter
|
||||
}
|
||||
|
||||
func NewControl(ctx context.Context, runID string, conn net.Conn, session *fmux.Session,
|
||||
func NewControl(
|
||||
ctx context.Context, runID string, conn net.Conn, cm *ConnectionManager,
|
||||
clientCfg config.ClientCommonConf,
|
||||
pxyCfgs map[string]config.ProxyConf,
|
||||
visitorCfgs map[string]config.VisitorConf,
|
||||
serverUDPPort int,
|
||||
authSetter auth.Setter) *Control {
|
||||
|
||||
authSetter auth.Setter,
|
||||
) *Control {
|
||||
// new xlog instance
|
||||
ctl := &Control{
|
||||
runID: runID,
|
||||
conn: conn,
|
||||
session: session,
|
||||
cm: cm,
|
||||
pxyCfgs: pxyCfgs,
|
||||
sendCh: make(chan msg.Message, 100),
|
||||
readCh: make(chan msg.Message, 100),
|
||||
@@ -130,13 +122,13 @@ func (ctl *Control) Run() {
|
||||
|
||||
// start all visitors
|
||||
go ctl.vm.Run()
|
||||
return
|
||||
}
|
||||
|
||||
func (ctl *Control) HandleReqWorkConn(inMsg *msg.ReqWorkConn) {
|
||||
xl := ctl.xl
|
||||
workConn, err := ctl.connectServer()
|
||||
if err != nil {
|
||||
xl.Warn("start new connection to server error: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -155,7 +147,7 @@ func (ctl *Control) HandleReqWorkConn(inMsg *msg.ReqWorkConn) {
|
||||
|
||||
var startMsg msg.StartWorkConn
|
||||
if err = msg.ReadMsgInto(workConn, &startMsg); err != nil {
|
||||
xl.Error("work connection closed before response StartWorkConn message: %v", err)
|
||||
xl.Trace("work connection closed before response StartWorkConn message: %v", err)
|
||||
workConn.Close()
|
||||
return
|
||||
}
|
||||
@@ -192,9 +184,7 @@ func (ctl *Control) GracefulClose(d time.Duration) error {
|
||||
time.Sleep(d)
|
||||
|
||||
ctl.conn.Close()
|
||||
if ctl.session != nil {
|
||||
ctl.session.Close()
|
||||
}
|
||||
ctl.cm.Close()
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -205,44 +195,7 @@ func (ctl *Control) ClosedDoneCh() <-chan struct{} {
|
||||
|
||||
// connectServer return a new connection to frps
|
||||
func (ctl *Control) connectServer() (conn net.Conn, err error) {
|
||||
xl := ctl.xl
|
||||
if ctl.clientCfg.TCPMux {
|
||||
stream, errRet := ctl.session.OpenStream()
|
||||
if errRet != nil {
|
||||
err = errRet
|
||||
xl.Warn("start new connection to server error: %v", err)
|
||||
return
|
||||
}
|
||||
conn = stream
|
||||
} else {
|
||||
var tlsConfig *tls.Config
|
||||
sn := ctl.clientCfg.TLSServerName
|
||||
if sn == "" {
|
||||
sn = ctl.clientCfg.ServerAddr
|
||||
}
|
||||
|
||||
if ctl.clientCfg.TLSEnable {
|
||||
tlsConfig, err = transport.NewClientTLSConfig(
|
||||
ctl.clientCfg.TLSCertFile,
|
||||
ctl.clientCfg.TLSKeyFile,
|
||||
ctl.clientCfg.TLSTrustedCaFile,
|
||||
sn)
|
||||
|
||||
if err != nil {
|
||||
xl.Warn("fail to build tls configuration when connecting to server, err: %v", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
address := net.JoinHostPort(ctl.clientCfg.ServerAddr, strconv.Itoa(ctl.clientCfg.ServerPort))
|
||||
conn, err = frpNet.ConnectServerByProxyWithTLS(ctl.clientCfg.HTTPProxy, ctl.clientCfg.Protocol, address, tlsConfig, ctl.clientCfg.DisableCustomTLSFirstByte)
|
||||
|
||||
if err != nil {
|
||||
xl.Warn("start new connection to server error: %v", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
return
|
||||
return ctl.cm.Connect()
|
||||
}
|
||||
|
||||
// reader read all messages from frps and send to readCh
|
||||
@@ -308,16 +261,27 @@ func (ctl *Control) msgHandler() {
|
||||
}()
|
||||
defer ctl.msgHandlerShutdown.Done()
|
||||
|
||||
hbSend := time.NewTicker(time.Duration(ctl.clientCfg.HeartbeatInterval) * time.Second)
|
||||
defer hbSend.Stop()
|
||||
hbCheck := time.NewTicker(time.Second)
|
||||
defer hbCheck.Stop()
|
||||
var hbSendCh <-chan time.Time
|
||||
// TODO(fatedier): disable heartbeat if TCPMux is enabled.
|
||||
// Just keep it here to keep compatible with old version frps.
|
||||
if ctl.clientCfg.HeartbeatInterval > 0 {
|
||||
hbSend := time.NewTicker(time.Duration(ctl.clientCfg.HeartbeatInterval) * time.Second)
|
||||
defer hbSend.Stop()
|
||||
hbSendCh = hbSend.C
|
||||
}
|
||||
|
||||
var hbCheckCh <-chan time.Time
|
||||
// Check heartbeat timeout only if TCPMux is not enabled and users don't disable heartbeat feature.
|
||||
if ctl.clientCfg.HeartbeatInterval > 0 && ctl.clientCfg.HeartbeatTimeout > 0 && !ctl.clientCfg.TCPMux {
|
||||
hbCheck := time.NewTicker(time.Second)
|
||||
defer hbCheck.Stop()
|
||||
hbCheckCh = hbCheck.C
|
||||
}
|
||||
|
||||
ctl.lastPong = time.Now()
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-hbSend.C:
|
||||
case <-hbSendCh:
|
||||
// send heartbeat to server
|
||||
xl.Debug("send heartbeat to server")
|
||||
pingMsg := &msg.Ping{}
|
||||
@@ -326,7 +290,7 @@ func (ctl *Control) msgHandler() {
|
||||
return
|
||||
}
|
||||
ctl.sendCh <- pingMsg
|
||||
case <-hbCheck.C:
|
||||
case <-hbCheckCh:
|
||||
if time.Since(ctl.lastPong) > time.Duration(ctl.clientCfg.HeartbeatTimeout)*time.Second {
|
||||
xl.Warn("heartbeat timeout")
|
||||
// let reader() stop
|
||||
@@ -362,25 +326,20 @@ func (ctl *Control) worker() {
|
||||
go ctl.reader()
|
||||
go ctl.writer()
|
||||
|
||||
select {
|
||||
case <-ctl.closedCh:
|
||||
// close related channels and wait until other goroutines done
|
||||
close(ctl.readCh)
|
||||
ctl.readerShutdown.WaitDone()
|
||||
ctl.msgHandlerShutdown.WaitDone()
|
||||
<-ctl.closedCh
|
||||
// close related channels and wait until other goroutines done
|
||||
close(ctl.readCh)
|
||||
ctl.readerShutdown.WaitDone()
|
||||
ctl.msgHandlerShutdown.WaitDone()
|
||||
|
||||
close(ctl.sendCh)
|
||||
ctl.writerShutdown.WaitDone()
|
||||
close(ctl.sendCh)
|
||||
ctl.writerShutdown.WaitDone()
|
||||
|
||||
ctl.pm.Close()
|
||||
ctl.vm.Close()
|
||||
ctl.pm.Close()
|
||||
ctl.vm.Close()
|
||||
|
||||
close(ctl.closedDoneCh)
|
||||
if ctl.session != nil {
|
||||
ctl.session.Close()
|
||||
}
|
||||
return
|
||||
}
|
||||
close(ctl.closedDoneCh)
|
||||
ctl.cm.Close()
|
||||
}
|
||||
|
||||
func (ctl *Control) ReloadConf(pxyCfgs map[string]config.ProxyConf, visitorCfgs map[string]config.VisitorConf) error {
|
||||
|
@@ -6,18 +6,9 @@ import (
|
||||
"github.com/fatedier/frp/pkg/msg"
|
||||
)
|
||||
|
||||
type Type int
|
||||
var ErrPayloadType = errors.New("error payload type")
|
||||
|
||||
const (
|
||||
EvStartProxy Type = iota
|
||||
EvCloseProxy
|
||||
)
|
||||
|
||||
var (
|
||||
ErrPayloadType = errors.New("error payload type")
|
||||
)
|
||||
|
||||
type Handler func(evType Type, payload interface{}) error
|
||||
type Handler func(payload interface{}) error
|
||||
|
||||
type StartProxyPayload struct {
|
||||
NewProxyMsg *msg.NewProxy
|
||||
|
@@ -26,9 +26,7 @@ import (
|
||||
"github.com/fatedier/frp/pkg/util/xlog"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrHealthCheckType = errors.New("error health check type")
|
||||
)
|
||||
var ErrHealthCheckType = errors.New("error health check type")
|
||||
|
||||
type Monitor struct {
|
||||
checkType string
|
||||
@@ -54,8 +52,8 @@ type Monitor struct {
|
||||
func NewMonitor(ctx context.Context, checkType string,
|
||||
intervalS int, timeoutS int, maxFailedTimes int,
|
||||
addr string, url string,
|
||||
statusNormalFn func(), statusFailedFn func()) *Monitor {
|
||||
|
||||
statusNormalFn func(), statusFailedFn func(),
|
||||
) *Monitor {
|
||||
if intervalS <= 0 {
|
||||
intervalS = 10
|
||||
}
|
||||
@@ -152,7 +150,7 @@ func (monitor *Monitor) doTCPCheck(ctx context.Context) error {
|
||||
}
|
||||
|
||||
func (monitor *Monitor) doHTTPCheck(ctx context.Context) error {
|
||||
req, err := http.NewRequest("GET", monitor.url, nil)
|
||||
req, err := http.NewRequestWithContext(ctx, "GET", monitor.url, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -161,7 +159,7 @@ func (monitor *Monitor) doHTTPCheck(ctx context.Context) error {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
io.Copy(io.Discard, resp.Body)
|
||||
_, _ = io.Copy(io.Discard, resp.Body)
|
||||
|
||||
if resp.StatusCode/100 != 2 {
|
||||
return fmt.Errorf("do http health check, StatusCode is [%d] not 2xx", resp.StatusCode)
|
||||
|
@@ -17,7 +17,6 @@ package proxy
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"strconv"
|
||||
@@ -25,6 +24,14 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/fatedier/golib/errors"
|
||||
frpIo "github.com/fatedier/golib/io"
|
||||
libdial "github.com/fatedier/golib/net/dial"
|
||||
"github.com/fatedier/golib/pool"
|
||||
fmux "github.com/hashicorp/yamux"
|
||||
pp "github.com/pires/go-proxyproto"
|
||||
"golang.org/x/time/rate"
|
||||
|
||||
"github.com/fatedier/frp/pkg/config"
|
||||
"github.com/fatedier/frp/pkg/msg"
|
||||
plugin "github.com/fatedier/frp/pkg/plugin/client"
|
||||
@@ -32,13 +39,6 @@ import (
|
||||
"github.com/fatedier/frp/pkg/util/limit"
|
||||
frpNet "github.com/fatedier/frp/pkg/util/net"
|
||||
"github.com/fatedier/frp/pkg/util/xlog"
|
||||
|
||||
"github.com/fatedier/golib/errors"
|
||||
frpIo "github.com/fatedier/golib/io"
|
||||
"github.com/fatedier/golib/pool"
|
||||
fmux "github.com/hashicorp/yamux"
|
||||
pp "github.com/pires/go-proxyproto"
|
||||
"golang.org/x/time/rate"
|
||||
)
|
||||
|
||||
// Proxy defines how to handle work connections for different proxy type.
|
||||
@@ -54,7 +54,7 @@ type Proxy interface {
|
||||
func NewProxy(ctx context.Context, pxyConf config.ProxyConf, clientCfg config.ClientCommonConf, serverUDPPort int) (pxy Proxy) {
|
||||
var limiter *rate.Limiter
|
||||
limitBytes := pxyConf.GetBaseInfo().BandwidthLimit.Bytes()
|
||||
if limitBytes > 0 {
|
||||
if limitBytes > 0 && pxyConf.GetBaseInfo().BandwidthLimitMode == config.BandwidthLimitModeClient {
|
||||
limiter = rate.NewLimiter(rate.Limit(float64(limitBytes)), int(limitBytes))
|
||||
}
|
||||
|
||||
@@ -306,7 +306,7 @@ func (pxy *XTCPProxy) InWorkConn(conn net.Conn, m *msg.StartWorkConn) {
|
||||
Sid: natHoleSidMsg.Sid,
|
||||
}
|
||||
raddr, _ := net.ResolveUDPAddr("udp",
|
||||
fmt.Sprintf("%s:%d", pxy.clientCfg.ServerAddr, pxy.serverUDPPort))
|
||||
net.JoinHostPort(pxy.clientCfg.ServerAddr, strconv.Itoa(pxy.serverUDPPort)))
|
||||
clientConn, err := net.DialUDP("udp", nil, raddr)
|
||||
if err != nil {
|
||||
xl.Error("dial server udp addr error: %v", err)
|
||||
@@ -322,7 +322,7 @@ func (pxy *XTCPProxy) InWorkConn(conn net.Conn, m *msg.StartWorkConn) {
|
||||
|
||||
// Wait for client address at most 5 seconds.
|
||||
var natHoleRespMsg msg.NatHoleResp
|
||||
clientConn.SetReadDeadline(time.Now().Add(5 * time.Second))
|
||||
_ = clientConn.SetReadDeadline(time.Now().Add(5 * time.Second))
|
||||
|
||||
buf := pool.GetBuf(1024)
|
||||
n, err := clientConn.Read(buf)
|
||||
@@ -335,8 +335,8 @@ func (pxy *XTCPProxy) InWorkConn(conn net.Conn, m *msg.StartWorkConn) {
|
||||
xl.Error("get natHoleRespMsg error: %v", err)
|
||||
return
|
||||
}
|
||||
clientConn.SetReadDeadline(time.Time{})
|
||||
clientConn.Close()
|
||||
_ = clientConn.SetReadDeadline(time.Time{})
|
||||
_ = clientConn.Close()
|
||||
|
||||
if natHoleRespMsg.Error != "" {
|
||||
xl.Error("natHoleRespMsg get error info: %s", natHoleRespMsg.Error)
|
||||
@@ -346,35 +346,34 @@ func (pxy *XTCPProxy) InWorkConn(conn net.Conn, m *msg.StartWorkConn) {
|
||||
xl.Trace("get natHoleRespMsg, sid [%s], client address [%s] visitor address [%s]", natHoleRespMsg.Sid, natHoleRespMsg.ClientAddr, natHoleRespMsg.VisitorAddr)
|
||||
|
||||
// Send detect message
|
||||
array := strings.Split(natHoleRespMsg.VisitorAddr, ":")
|
||||
if len(array) <= 1 {
|
||||
xl.Error("get NatHoleResp visitor address error: %v", natHoleRespMsg.VisitorAddr)
|
||||
host, portStr, err := net.SplitHostPort(natHoleRespMsg.VisitorAddr)
|
||||
if err != nil {
|
||||
xl.Error("get NatHoleResp visitor address [%s] error: %v", natHoleRespMsg.VisitorAddr, err)
|
||||
}
|
||||
laddr, _ := net.ResolveUDPAddr("udp", clientConn.LocalAddr().String())
|
||||
/*
|
||||
for i := 1000; i < 65000; i++ {
|
||||
pxy.sendDetectMsg(array[0], int64(i), laddr, "a")
|
||||
}
|
||||
*/
|
||||
port, err := strconv.ParseInt(array[1], 10, 64)
|
||||
|
||||
port, err := strconv.ParseInt(portStr, 10, 64)
|
||||
if err != nil {
|
||||
xl.Error("get natHoleResp visitor address error: %v", natHoleRespMsg.VisitorAddr)
|
||||
return
|
||||
}
|
||||
pxy.sendDetectMsg(array[0], int(port), laddr, []byte(natHoleRespMsg.Sid))
|
||||
_ = pxy.sendDetectMsg(host, int(port), laddr, []byte(natHoleRespMsg.Sid))
|
||||
xl.Trace("send all detect msg done")
|
||||
|
||||
msg.WriteMsg(conn, &msg.NatHoleClientDetectOK{})
|
||||
if err := msg.WriteMsg(conn, &msg.NatHoleClientDetectOK{}); err != nil {
|
||||
xl.Error("write message error: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
// Listen for clientConn's address and wait for visitor connection
|
||||
lConn, err := net.ListenUDP("udp", laddr)
|
||||
if err != nil {
|
||||
xl.Error("listen on visitorConn's local adress error: %v", err)
|
||||
xl.Error("listen on visitorConn's local address error: %v", err)
|
||||
return
|
||||
}
|
||||
defer lConn.Close()
|
||||
|
||||
lConn.SetReadDeadline(time.Now().Add(8 * time.Second))
|
||||
_ = lConn.SetReadDeadline(time.Now().Add(8 * time.Second))
|
||||
sidBuf := pool.GetBuf(1024)
|
||||
var uAddr *net.UDPAddr
|
||||
n, uAddr, err = lConn.ReadFromUDP(sidBuf)
|
||||
@@ -382,7 +381,7 @@ func (pxy *XTCPProxy) InWorkConn(conn net.Conn, m *msg.StartWorkConn) {
|
||||
xl.Warn("get sid from visitor error: %v", err)
|
||||
return
|
||||
}
|
||||
lConn.SetReadDeadline(time.Time{})
|
||||
_ = lConn.SetReadDeadline(time.Time{})
|
||||
if string(sidBuf[:n]) != natHoleRespMsg.Sid {
|
||||
xl.Warn("incorrect sid from visitor")
|
||||
return
|
||||
@@ -390,7 +389,10 @@ func (pxy *XTCPProxy) InWorkConn(conn net.Conn, m *msg.StartWorkConn) {
|
||||
pool.PutBuf(sidBuf)
|
||||
xl.Info("nat hole connection make success, sid [%s]", natHoleRespMsg.Sid)
|
||||
|
||||
lConn.WriteToUDP(sidBuf[:n], uAddr)
|
||||
if _, err := lConn.WriteToUDP(sidBuf[:n], uAddr); err != nil {
|
||||
xl.Error("write uaddr error: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
kcpConn, err := frpNet.NewKCPConnFromUDP(lConn, false, uAddr.String())
|
||||
if err != nil {
|
||||
@@ -418,7 +420,7 @@ func (pxy *XTCPProxy) InWorkConn(conn net.Conn, m *msg.StartWorkConn) {
|
||||
}
|
||||
|
||||
func (pxy *XTCPProxy) sendDetectMsg(addr string, port int, laddr *net.UDPAddr, content []byte) (err error) {
|
||||
daddr, err := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", addr, port))
|
||||
daddr, err := net.ResolveUDPAddr("udp", net.JoinHostPort(addr, strconv.Itoa(port)))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -428,12 +430,13 @@ func (pxy *XTCPProxy) sendDetectMsg(addr string, port int, laddr *net.UDPAddr, c
|
||||
return err
|
||||
}
|
||||
|
||||
//uConn := ipv4.NewConn(tConn)
|
||||
//uConn.SetTTL(3)
|
||||
// uConn := ipv4.NewConn(tConn)
|
||||
// uConn.SetTTL(3)
|
||||
|
||||
tConn.Write(content)
|
||||
tConn.Close()
|
||||
return nil
|
||||
if _, err := tConn.Write(content); err != nil {
|
||||
return err
|
||||
}
|
||||
return tConn.Close()
|
||||
}
|
||||
|
||||
// UDP
|
||||
@@ -451,7 +454,7 @@ type UDPProxy struct {
|
||||
}
|
||||
|
||||
func (pxy *UDPProxy) Run() (err error) {
|
||||
pxy.localAddr, err = net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", pxy.cfg.LocalIP, pxy.cfg.LocalPort))
|
||||
pxy.localAddr, err = net.ResolveUDPAddr("udp", net.JoinHostPort(pxy.cfg.LocalIP, strconv.Itoa(pxy.cfg.LocalPort)))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@@ -543,7 +546,7 @@ func (pxy *UDPProxy) InWorkConn(conn net.Conn, m *msg.StartWorkConn) {
|
||||
}
|
||||
}
|
||||
}
|
||||
heartbeatFn := func(conn net.Conn, sendCh chan msg.Message) {
|
||||
heartbeatFn := func(sendCh chan msg.Message) {
|
||||
var errRet error
|
||||
for {
|
||||
time.Sleep(time.Duration(30) * time.Second)
|
||||
@@ -558,7 +561,7 @@ func (pxy *UDPProxy) InWorkConn(conn net.Conn, m *msg.StartWorkConn) {
|
||||
|
||||
go workConnSenderFn(pxy.workConn, pxy.sendCh)
|
||||
go workConnReaderFn(pxy.workConn, pxy.readCh)
|
||||
go heartbeatFn(pxy.workConn, pxy.sendCh)
|
||||
go heartbeatFn(pxy.sendCh)
|
||||
udp.Forwarder(pxy.localAddr, pxy.readCh, pxy.sendCh, int(pxy.clientCfg.UDPPacketSize))
|
||||
}
|
||||
|
||||
@@ -573,7 +576,7 @@ type SUDPProxy struct {
|
||||
}
|
||||
|
||||
func (pxy *SUDPProxy) Run() (err error) {
|
||||
pxy.localAddr, err = net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", pxy.cfg.LocalIP, pxy.cfg.LocalPort))
|
||||
pxy.localAddr, err = net.ResolveUDPAddr("udp", net.JoinHostPort(pxy.cfg.LocalIP, strconv.Itoa(pxy.cfg.LocalPort)))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@@ -689,7 +692,7 @@ func (pxy *SUDPProxy) InWorkConn(conn net.Conn, m *msg.StartWorkConn) {
|
||||
}
|
||||
}
|
||||
|
||||
heartbeatFn := func(conn net.Conn, sendCh chan msg.Message) {
|
||||
heartbeatFn := func(sendCh chan msg.Message) {
|
||||
ticker := time.NewTicker(30 * time.Second)
|
||||
defer func() {
|
||||
ticker.Stop()
|
||||
@@ -715,14 +718,15 @@ func (pxy *SUDPProxy) InWorkConn(conn net.Conn, m *msg.StartWorkConn) {
|
||||
|
||||
go workConnSenderFn(workConn, sendCh)
|
||||
go workConnReaderFn(workConn, readCh)
|
||||
go heartbeatFn(workConn, sendCh)
|
||||
go heartbeatFn(sendCh)
|
||||
|
||||
udp.Forwarder(pxy.localAddr, readCh, sendCh, int(pxy.clientCfg.UDPPacketSize))
|
||||
}
|
||||
|
||||
// Common handler for tcp work connections.
|
||||
func HandleTCPWorkConnection(ctx context.Context, localInfo *config.LocalSvrConf, proxyPlugin plugin.Plugin,
|
||||
baseInfo *config.BaseProxyConf, limiter *rate.Limiter, workConn net.Conn, encKey []byte, m *msg.StartWorkConn) {
|
||||
baseInfo *config.BaseProxyConf, limiter *rate.Limiter, workConn net.Conn, encKey []byte, m *msg.StartWorkConn,
|
||||
) {
|
||||
xl := xlog.FromContextSafe(ctx)
|
||||
var (
|
||||
remote io.ReadWriteCloser
|
||||
@@ -777,7 +781,7 @@ func HandleTCPWorkConnection(ctx context.Context, localInfo *config.LocalSvrConf
|
||||
}
|
||||
|
||||
buf := bytes.NewBuffer(nil)
|
||||
h.WriteTo(buf)
|
||||
_, _ = h.WriteTo(buf)
|
||||
extraInfo = buf.Bytes()
|
||||
}
|
||||
}
|
||||
@@ -790,7 +794,10 @@ func HandleTCPWorkConnection(ctx context.Context, localInfo *config.LocalSvrConf
|
||||
return
|
||||
}
|
||||
|
||||
localConn, err := frpNet.ConnectServer("tcp", fmt.Sprintf("%s:%d", localInfo.LocalIP, localInfo.LocalPort))
|
||||
localConn, err := libdial.Dial(
|
||||
net.JoinHostPort(localInfo.LocalIP, strconv.Itoa(localInfo.LocalPort)),
|
||||
libdial.WithTimeout(10*time.Second),
|
||||
)
|
||||
if err != nil {
|
||||
workConn.Close()
|
||||
xl.Error("connect to local service [%s:%d] error: %v", localInfo.LocalIP, localInfo.LocalPort, err)
|
||||
@@ -801,7 +808,11 @@ func HandleTCPWorkConnection(ctx context.Context, localInfo *config.LocalSvrConf
|
||||
localConn.RemoteAddr().String(), workConn.LocalAddr().String(), workConn.RemoteAddr().String())
|
||||
|
||||
if len(extraInfo) > 0 {
|
||||
localConn.Write(extraInfo)
|
||||
if _, err := localConn.Write(extraInfo); err != nil {
|
||||
workConn.Close()
|
||||
xl.Error("write extraInfo to local conn error: %v", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
frpIo.Join(localConn, remote)
|
||||
|
@@ -6,12 +6,12 @@ import (
|
||||
"net"
|
||||
"sync"
|
||||
|
||||
"github.com/fatedier/golib/errors"
|
||||
|
||||
"github.com/fatedier/frp/client/event"
|
||||
"github.com/fatedier/frp/pkg/config"
|
||||
"github.com/fatedier/frp/pkg/msg"
|
||||
"github.com/fatedier/frp/pkg/util/xlog"
|
||||
|
||||
"github.com/fatedier/golib/errors"
|
||||
)
|
||||
|
||||
type Manager struct {
|
||||
@@ -75,7 +75,7 @@ func (pm *Manager) HandleWorkConn(name string, workConn net.Conn, m *msg.StartWo
|
||||
}
|
||||
}
|
||||
|
||||
func (pm *Manager) HandleEvent(evType event.Type, payload interface{}) error {
|
||||
func (pm *Manager) HandleEvent(payload interface{}) error {
|
||||
var m msg.Message
|
||||
switch e := payload.(type) {
|
||||
case *event.StartProxyPayload:
|
||||
@@ -113,10 +113,8 @@ func (pm *Manager) Reload(pxyCfgs map[string]config.ProxyConf) {
|
||||
cfg, ok := pxyCfgs[name]
|
||||
if !ok {
|
||||
del = true
|
||||
} else {
|
||||
if !pxy.Cfg.Compare(cfg) {
|
||||
del = true
|
||||
}
|
||||
} else if !pxy.Cfg.Compare(cfg) {
|
||||
del = true
|
||||
}
|
||||
|
||||
if del {
|
||||
|
@@ -8,13 +8,13 @@ import (
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/fatedier/golib/errors"
|
||||
|
||||
"github.com/fatedier/frp/client/event"
|
||||
"github.com/fatedier/frp/client/health"
|
||||
"github.com/fatedier/frp/pkg/config"
|
||||
"github.com/fatedier/frp/pkg/msg"
|
||||
"github.com/fatedier/frp/pkg/util/xlog"
|
||||
|
||||
"github.com/fatedier/golib/errors"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -27,9 +27,9 @@ const (
|
||||
)
|
||||
|
||||
var (
|
||||
statusCheckInterval time.Duration = 3 * time.Second
|
||||
waitResponseTimeout = 20 * time.Second
|
||||
startErrTimeout = 30 * time.Second
|
||||
statusCheckInterval = 3 * time.Second
|
||||
waitResponseTimeout = 20 * time.Second
|
||||
startErrTimeout = 30 * time.Second
|
||||
)
|
||||
|
||||
type WorkingStatus struct {
|
||||
@@ -145,7 +145,7 @@ func (pw *Wrapper) Stop() {
|
||||
}
|
||||
|
||||
func (pw *Wrapper) close() {
|
||||
pw.handler(event.EvCloseProxy, &event.CloseProxyPayload{
|
||||
_ = pw.handler(&event.CloseProxyPayload{
|
||||
CloseProxyMsg: &msg.CloseProxy{
|
||||
ProxyName: pw.Name,
|
||||
},
|
||||
@@ -174,7 +174,7 @@ func (pw *Wrapper) checkWorker() {
|
||||
var newProxyMsg msg.NewProxy
|
||||
pw.Cfg.MarshalToMsg(&newProxyMsg)
|
||||
pw.lastSendStartMsg = now
|
||||
pw.handler(event.EvStartProxy, &event.StartProxyPayload{
|
||||
_ = pw.handler(&event.StartProxyPayload{
|
||||
NewProxyMsg: &newProxyMsg,
|
||||
})
|
||||
}
|
||||
@@ -201,7 +201,7 @@ func (pw *Wrapper) checkWorker() {
|
||||
func (pw *Wrapper) statusNormalCallback() {
|
||||
xl := pw.xl
|
||||
atomic.StoreUint32(&pw.health, 0)
|
||||
errors.PanicToError(func() {
|
||||
_ = errors.PanicToError(func() {
|
||||
select {
|
||||
case pw.healthNotifyCh <- struct{}{}:
|
||||
default:
|
||||
@@ -213,7 +213,7 @@ func (pw *Wrapper) statusNormalCallback() {
|
||||
func (pw *Wrapper) statusFailedCallback() {
|
||||
xl := pw.xl
|
||||
atomic.StoreUint32(&pw.health, 1)
|
||||
errors.PanicToError(func() {
|
||||
_ = errors.PanicToError(func() {
|
||||
select {
|
||||
case pw.healthNotifyCh <- struct{}{}:
|
||||
default:
|
||||
|
@@ -17,16 +17,22 @@ package client
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"math/rand"
|
||||
"net"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/fatedier/golib/crypto"
|
||||
libdial "github.com/fatedier/golib/net/dial"
|
||||
fmux "github.com/hashicorp/yamux"
|
||||
quic "github.com/quic-go/quic-go"
|
||||
|
||||
"github.com/fatedier/frp/assets"
|
||||
"github.com/fatedier/frp/pkg/auth"
|
||||
"github.com/fatedier/frp/pkg/config"
|
||||
@@ -34,12 +40,17 @@ import (
|
||||
"github.com/fatedier/frp/pkg/transport"
|
||||
"github.com/fatedier/frp/pkg/util/log"
|
||||
frpNet "github.com/fatedier/frp/pkg/util/net"
|
||||
"github.com/fatedier/frp/pkg/util/util"
|
||||
"github.com/fatedier/frp/pkg/util/version"
|
||||
"github.com/fatedier/frp/pkg/util/xlog"
|
||||
|
||||
fmux "github.com/hashicorp/yamux"
|
||||
)
|
||||
|
||||
func init() {
|
||||
crypto.DefaultSalt = "frp"
|
||||
// TODO: remove this when we drop support for go1.19
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
}
|
||||
|
||||
// Service is a client service.
|
||||
type Service struct {
|
||||
// uniq id got from frps, attach it in loginMsg
|
||||
@@ -72,8 +83,12 @@ type Service struct {
|
||||
cancel context.CancelFunc
|
||||
}
|
||||
|
||||
func NewService(cfg config.ClientCommonConf, pxyCfgs map[string]config.ProxyConf, visitorCfgs map[string]config.VisitorConf, cfgFile string) (svr *Service, err error) {
|
||||
|
||||
func NewService(
|
||||
cfg config.ClientCommonConf,
|
||||
pxyCfgs map[string]config.ProxyConf,
|
||||
visitorCfgs map[string]config.VisitorConf,
|
||||
cfgFile string,
|
||||
) (svr *Service, err error) {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
svr = &Service{
|
||||
authSetter: auth.NewAuthSetter(cfg.ClientConfig),
|
||||
@@ -97,9 +112,24 @@ func (svr *Service) GetController() *Control {
|
||||
func (svr *Service) Run() error {
|
||||
xl := xlog.FromContextSafe(svr.ctx)
|
||||
|
||||
// set custom DNSServer
|
||||
if svr.cfg.DNSServer != "" {
|
||||
dnsAddr := svr.cfg.DNSServer
|
||||
if _, _, err := net.SplitHostPort(dnsAddr); err != nil {
|
||||
dnsAddr = net.JoinHostPort(dnsAddr, "53")
|
||||
}
|
||||
// Change default dns server for frpc
|
||||
net.DefaultResolver = &net.Resolver{
|
||||
PreferGo: true,
|
||||
Dial: func(ctx context.Context, network, address string) (net.Conn, error) {
|
||||
return net.Dial("udp", dnsAddr)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// login to frps
|
||||
for {
|
||||
conn, session, err := svr.login()
|
||||
conn, cm, err := svr.login()
|
||||
if err != nil {
|
||||
xl.Warn("login to server failed: %v", err)
|
||||
|
||||
@@ -108,10 +138,10 @@ func (svr *Service) Run() error {
|
||||
if svr.cfg.LoginFailExit {
|
||||
return err
|
||||
}
|
||||
time.Sleep(10 * time.Second)
|
||||
util.RandomSleep(10*time.Second, 0.9, 1.1)
|
||||
} else {
|
||||
// login success
|
||||
ctl := NewControl(svr.ctx, svr.runID, conn, session, svr.cfg, svr.pxyCfgs, svr.visitorCfgs, svr.serverUDPPort, svr.authSetter)
|
||||
ctl := NewControl(svr.ctx, svr.runID, conn, cm, svr.cfg, svr.pxyCfgs, svr.visitorCfgs, svr.serverUDPPort, svr.authSetter)
|
||||
ctl.Run()
|
||||
svr.ctlMu.Lock()
|
||||
svr.ctl = ctl
|
||||
@@ -157,8 +187,11 @@ func (svr *Service) keepControllerWorking() {
|
||||
|
||||
// the first three retry with no delay
|
||||
if reconnectCounts > 3 {
|
||||
time.Sleep(reconnectDelay)
|
||||
util.RandomSleep(reconnectDelay, 0.9, 1.1)
|
||||
xl.Info("wait %v to reconnect", reconnectDelay)
|
||||
reconnectDelay *= 2
|
||||
} else {
|
||||
util.RandomSleep(time.Second, 0, 0.5)
|
||||
}
|
||||
reconnectCounts++
|
||||
|
||||
@@ -171,28 +204,26 @@ func (svr *Service) keepControllerWorking() {
|
||||
}
|
||||
|
||||
for {
|
||||
xl.Info("try to reconnect to server...")
|
||||
conn, session, err := svr.login()
|
||||
if err != nil {
|
||||
xl.Warn("reconnect to server error: %v", err)
|
||||
time.Sleep(delayTime)
|
||||
if atomic.LoadUint32(&svr.exit) != 0 {
|
||||
return
|
||||
}
|
||||
|
||||
opErr := &net.OpError{}
|
||||
// quick retry for dial error
|
||||
if errors.As(err, &opErr) && opErr.Op == "dial" {
|
||||
delayTime = 2 * time.Second
|
||||
} else {
|
||||
delayTime = delayTime * 2
|
||||
if delayTime > maxDelayTime {
|
||||
delayTime = maxDelayTime
|
||||
}
|
||||
xl.Info("try to reconnect to server...")
|
||||
conn, cm, err := svr.login()
|
||||
if err != nil {
|
||||
xl.Warn("reconnect to server error: %v, wait %v for another retry", err, delayTime)
|
||||
util.RandomSleep(delayTime, 0.9, 1.1)
|
||||
|
||||
delayTime *= 2
|
||||
if delayTime > maxDelayTime {
|
||||
delayTime = maxDelayTime
|
||||
}
|
||||
continue
|
||||
}
|
||||
// reconnect success, init delayTime
|
||||
delayTime = time.Second
|
||||
|
||||
ctl := NewControl(svr.ctx, svr.runID, conn, session, svr.cfg, svr.pxyCfgs, svr.visitorCfgs, svr.serverUDPPort, svr.authSetter)
|
||||
ctl := NewControl(svr.ctx, svr.runID, conn, cm, svr.cfg, svr.pxyCfgs, svr.visitorCfgs, svr.serverUDPPort, svr.authSetter)
|
||||
ctl.Run()
|
||||
svr.ctlMu.Lock()
|
||||
if svr.ctl != nil {
|
||||
@@ -208,56 +239,23 @@ func (svr *Service) keepControllerWorking() {
|
||||
// login creates a connection to frps and registers it self as a client
|
||||
// conn: control connection
|
||||
// session: if it's not nil, using tcp mux
|
||||
func (svr *Service) login() (conn net.Conn, session *fmux.Session, err error) {
|
||||
func (svr *Service) login() (conn net.Conn, cm *ConnectionManager, err error) {
|
||||
xl := xlog.FromContextSafe(svr.ctx)
|
||||
var tlsConfig *tls.Config
|
||||
if svr.cfg.TLSEnable {
|
||||
sn := svr.cfg.TLSServerName
|
||||
if sn == "" {
|
||||
sn = svr.cfg.ServerAddr
|
||||
}
|
||||
cm = NewConnectionManager(svr.ctx, &svr.cfg)
|
||||
|
||||
tlsConfig, err = transport.NewClientTLSConfig(
|
||||
svr.cfg.TLSCertFile,
|
||||
svr.cfg.TLSKeyFile,
|
||||
svr.cfg.TLSTrustedCaFile,
|
||||
sn)
|
||||
if err != nil {
|
||||
xl.Warn("fail to build tls configuration when service login, err: %v", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
address := net.JoinHostPort(svr.cfg.ServerAddr, strconv.Itoa(svr.cfg.ServerPort))
|
||||
conn, err = frpNet.ConnectServerByProxyWithTLS(svr.cfg.HTTPProxy, svr.cfg.Protocol, address, tlsConfig, svr.cfg.DisableCustomTLSFirstByte)
|
||||
if err != nil {
|
||||
return
|
||||
if err = cm.OpenConnection(); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
defer func() {
|
||||
if err != nil {
|
||||
conn.Close()
|
||||
if session != nil {
|
||||
session.Close()
|
||||
}
|
||||
cm.Close()
|
||||
}
|
||||
}()
|
||||
|
||||
if svr.cfg.TCPMux {
|
||||
fmuxCfg := fmux.DefaultConfig()
|
||||
fmuxCfg.KeepAliveInterval = 20 * time.Second
|
||||
fmuxCfg.LogOutput = io.Discard
|
||||
session, err = fmux.Client(conn, fmuxCfg)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
stream, errRet := session.OpenStream()
|
||||
if errRet != nil {
|
||||
session.Close()
|
||||
err = errRet
|
||||
return
|
||||
}
|
||||
conn = stream
|
||||
conn, err = cm.Connect()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
loginMsg := &msg.Login{
|
||||
@@ -281,11 +279,11 @@ func (svr *Service) login() (conn net.Conn, session *fmux.Session, err error) {
|
||||
}
|
||||
|
||||
var loginRespMsg msg.LoginResp
|
||||
conn.SetReadDeadline(time.Now().Add(10 * time.Second))
|
||||
_ = conn.SetReadDeadline(time.Now().Add(10 * time.Second))
|
||||
if err = msg.ReadMsgInto(conn, &loginRespMsg); err != nil {
|
||||
return
|
||||
}
|
||||
conn.SetReadDeadline(time.Time{})
|
||||
_ = conn.SetReadDeadline(time.Time{})
|
||||
|
||||
if loginRespMsg.Error != "" {
|
||||
err = fmt.Errorf("%s", loginRespMsg.Error)
|
||||
@@ -308,7 +306,14 @@ func (svr *Service) ReloadConf(pxyCfgs map[string]config.ProxyConf, visitorCfgs
|
||||
svr.visitorCfgs = visitorCfgs
|
||||
svr.cfgMu.Unlock()
|
||||
|
||||
return svr.ctl.ReloadConf(pxyCfgs, visitorCfgs)
|
||||
svr.ctlMu.RLock()
|
||||
ctl := svr.ctl
|
||||
svr.ctlMu.RUnlock()
|
||||
|
||||
if ctl != nil {
|
||||
return svr.ctl.ReloadConf(pxyCfgs, visitorCfgs)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (svr *Service) Close() {
|
||||
@@ -317,8 +322,168 @@ func (svr *Service) Close() {
|
||||
|
||||
func (svr *Service) GracefulClose(d time.Duration) {
|
||||
atomic.StoreUint32(&svr.exit, 1)
|
||||
|
||||
svr.ctlMu.RLock()
|
||||
if svr.ctl != nil {
|
||||
svr.ctl.GracefulClose(d)
|
||||
}
|
||||
svr.ctlMu.RUnlock()
|
||||
|
||||
svr.cancel()
|
||||
}
|
||||
|
||||
type ConnectionManager struct {
|
||||
ctx context.Context
|
||||
cfg *config.ClientCommonConf
|
||||
|
||||
muxSession *fmux.Session
|
||||
quicConn quic.Connection
|
||||
}
|
||||
|
||||
func NewConnectionManager(ctx context.Context, cfg *config.ClientCommonConf) *ConnectionManager {
|
||||
return &ConnectionManager{
|
||||
ctx: ctx,
|
||||
cfg: cfg,
|
||||
}
|
||||
}
|
||||
|
||||
func (cm *ConnectionManager) OpenConnection() error {
|
||||
xl := xlog.FromContextSafe(cm.ctx)
|
||||
|
||||
// special for quic
|
||||
if strings.EqualFold(cm.cfg.Protocol, "quic") {
|
||||
var tlsConfig *tls.Config
|
||||
var err error
|
||||
sn := cm.cfg.TLSServerName
|
||||
if sn == "" {
|
||||
sn = cm.cfg.ServerAddr
|
||||
}
|
||||
if cm.cfg.TLSEnable {
|
||||
tlsConfig, err = transport.NewClientTLSConfig(
|
||||
cm.cfg.TLSCertFile,
|
||||
cm.cfg.TLSKeyFile,
|
||||
cm.cfg.TLSTrustedCaFile,
|
||||
sn)
|
||||
} else {
|
||||
tlsConfig, err = transport.NewClientTLSConfig("", "", "", sn)
|
||||
}
|
||||
if err != nil {
|
||||
xl.Warn("fail to build tls configuration, err: %v", err)
|
||||
return err
|
||||
}
|
||||
tlsConfig.NextProtos = []string{"frp"}
|
||||
|
||||
conn, err := quic.DialAddr(
|
||||
net.JoinHostPort(cm.cfg.ServerAddr, strconv.Itoa(cm.cfg.ServerPort)),
|
||||
tlsConfig, &quic.Config{
|
||||
MaxIdleTimeout: time.Duration(cm.cfg.QUICMaxIdleTimeout) * time.Second,
|
||||
MaxIncomingStreams: int64(cm.cfg.QUICMaxIncomingStreams),
|
||||
KeepAlivePeriod: time.Duration(cm.cfg.QUICKeepalivePeriod) * time.Second,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cm.quicConn = conn
|
||||
return nil
|
||||
}
|
||||
|
||||
if !cm.cfg.TCPMux {
|
||||
return nil
|
||||
}
|
||||
|
||||
conn, err := cm.realConnect()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmuxCfg := fmux.DefaultConfig()
|
||||
fmuxCfg.KeepAliveInterval = time.Duration(cm.cfg.TCPMuxKeepaliveInterval) * time.Second
|
||||
fmuxCfg.LogOutput = io.Discard
|
||||
session, err := fmux.Client(conn, fmuxCfg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cm.muxSession = session
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cm *ConnectionManager) Connect() (net.Conn, error) {
|
||||
if cm.quicConn != nil {
|
||||
stream, err := cm.quicConn.OpenStreamSync(context.Background())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return frpNet.QuicStreamToNetConn(stream, cm.quicConn), nil
|
||||
} else if cm.muxSession != nil {
|
||||
stream, err := cm.muxSession.OpenStream()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return stream, nil
|
||||
}
|
||||
|
||||
return cm.realConnect()
|
||||
}
|
||||
|
||||
func (cm *ConnectionManager) realConnect() (net.Conn, error) {
|
||||
xl := xlog.FromContextSafe(cm.ctx)
|
||||
var tlsConfig *tls.Config
|
||||
var err error
|
||||
if cm.cfg.TLSEnable {
|
||||
sn := cm.cfg.TLSServerName
|
||||
if sn == "" {
|
||||
sn = cm.cfg.ServerAddr
|
||||
}
|
||||
|
||||
tlsConfig, err = transport.NewClientTLSConfig(
|
||||
cm.cfg.TLSCertFile,
|
||||
cm.cfg.TLSKeyFile,
|
||||
cm.cfg.TLSTrustedCaFile,
|
||||
sn)
|
||||
if err != nil {
|
||||
xl.Warn("fail to build tls configuration, err: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
proxyType, addr, auth, err := libdial.ParseProxyURL(cm.cfg.HTTPProxy)
|
||||
if err != nil {
|
||||
xl.Error("fail to parse proxy url")
|
||||
return nil, err
|
||||
}
|
||||
dialOptions := []libdial.DialOption{}
|
||||
protocol := cm.cfg.Protocol
|
||||
if protocol == "websocket" {
|
||||
protocol = "tcp"
|
||||
dialOptions = append(dialOptions, libdial.WithAfterHook(libdial.AfterHook{Hook: frpNet.DialHookWebsocket()}))
|
||||
}
|
||||
if cm.cfg.ConnectServerLocalIP != "" {
|
||||
dialOptions = append(dialOptions, libdial.WithLocalAddr(cm.cfg.ConnectServerLocalIP))
|
||||
}
|
||||
dialOptions = append(dialOptions,
|
||||
libdial.WithProtocol(protocol),
|
||||
libdial.WithTimeout(time.Duration(cm.cfg.DialServerTimeout)*time.Second),
|
||||
libdial.WithKeepAlive(time.Duration(cm.cfg.DialServerKeepAlive)*time.Second),
|
||||
libdial.WithProxy(proxyType, addr),
|
||||
libdial.WithProxyAuth(auth),
|
||||
libdial.WithTLSConfig(tlsConfig),
|
||||
libdial.WithAfterHook(libdial.AfterHook{
|
||||
Hook: frpNet.DialHookCustomTLSHeadByte(tlsConfig != nil, cm.cfg.DisableCustomTLSFirstByte),
|
||||
}),
|
||||
)
|
||||
conn, err := libdial.Dial(
|
||||
net.JoinHostPort(cm.cfg.ServerAddr, strconv.Itoa(cm.cfg.ServerPort)),
|
||||
dialOptions...,
|
||||
)
|
||||
return conn, err
|
||||
}
|
||||
|
||||
func (cm *ConnectionManager) Close() error {
|
||||
if cm.quicConn != nil {
|
||||
_ = cm.quicConn.CloseWithError(0, "")
|
||||
}
|
||||
if cm.muxSession != nil {
|
||||
_ = cm.muxSession.Close()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@@ -20,20 +20,21 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/fatedier/golib/errors"
|
||||
frpIo "github.com/fatedier/golib/io"
|
||||
"github.com/fatedier/golib/pool"
|
||||
fmux "github.com/hashicorp/yamux"
|
||||
|
||||
"github.com/fatedier/frp/pkg/config"
|
||||
"github.com/fatedier/frp/pkg/msg"
|
||||
"github.com/fatedier/frp/pkg/proto/udp"
|
||||
frpNet "github.com/fatedier/frp/pkg/util/net"
|
||||
"github.com/fatedier/frp/pkg/util/util"
|
||||
"github.com/fatedier/frp/pkg/util/xlog"
|
||||
|
||||
"github.com/fatedier/golib/errors"
|
||||
frpIo "github.com/fatedier/golib/io"
|
||||
"github.com/fatedier/golib/pool"
|
||||
fmux "github.com/hashicorp/yamux"
|
||||
)
|
||||
|
||||
// Visitor is used for forward traffics from local port tot remote service.
|
||||
@@ -70,9 +71,8 @@ func NewVisitor(ctx context.Context, ctl *Control, cfg config.VisitorConf) (visi
|
||||
}
|
||||
|
||||
type BaseVisitor struct {
|
||||
ctl *Control
|
||||
l net.Listener
|
||||
closed bool
|
||||
ctl *Control
|
||||
l net.Listener
|
||||
|
||||
mu sync.RWMutex
|
||||
ctx context.Context
|
||||
@@ -85,7 +85,7 @@ type STCPVisitor struct {
|
||||
}
|
||||
|
||||
func (sv *STCPVisitor) Run() (err error) {
|
||||
sv.l, err = net.Listen("tcp", fmt.Sprintf("%s:%d", sv.cfg.BindAddr, sv.cfg.BindPort))
|
||||
sv.l, err = net.Listen("tcp", net.JoinHostPort(sv.cfg.BindAddr, strconv.Itoa(sv.cfg.BindPort)))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@@ -137,13 +137,13 @@ func (sv *STCPVisitor) handleConn(userConn net.Conn) {
|
||||
}
|
||||
|
||||
var newVisitorConnRespMsg msg.NewVisitorConnResp
|
||||
visitorConn.SetReadDeadline(time.Now().Add(10 * time.Second))
|
||||
_ = visitorConn.SetReadDeadline(time.Now().Add(10 * time.Second))
|
||||
err = msg.ReadMsgInto(visitorConn, &newVisitorConnRespMsg)
|
||||
if err != nil {
|
||||
xl.Warn("get newVisitorConnRespMsg error: %v", err)
|
||||
return
|
||||
}
|
||||
visitorConn.SetReadDeadline(time.Time{})
|
||||
_ = visitorConn.SetReadDeadline(time.Time{})
|
||||
|
||||
if newVisitorConnRespMsg.Error != "" {
|
||||
xl.Warn("start new visitor connection error: %s", newVisitorConnRespMsg.Error)
|
||||
@@ -174,7 +174,7 @@ type XTCPVisitor struct {
|
||||
}
|
||||
|
||||
func (sv *XTCPVisitor) Run() (err error) {
|
||||
sv.l, err = net.Listen("tcp", fmt.Sprintf("%s:%d", sv.cfg.BindAddr, sv.cfg.BindPort))
|
||||
sv.l, err = net.Listen("tcp", net.JoinHostPort(sv.cfg.BindAddr, strconv.Itoa(sv.cfg.BindPort)))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@@ -211,7 +211,7 @@ func (sv *XTCPVisitor) handleConn(userConn net.Conn) {
|
||||
}
|
||||
|
||||
raddr, err := net.ResolveUDPAddr("udp",
|
||||
fmt.Sprintf("%s:%d", sv.ctl.clientCfg.ServerAddr, sv.ctl.serverUDPPort))
|
||||
net.JoinHostPort(sv.ctl.clientCfg.ServerAddr, strconv.Itoa(sv.ctl.serverUDPPort)))
|
||||
if err != nil {
|
||||
xl.Error("resolve server UDP addr error")
|
||||
return
|
||||
@@ -238,7 +238,7 @@ func (sv *XTCPVisitor) handleConn(userConn net.Conn) {
|
||||
|
||||
// Wait for client address at most 10 seconds.
|
||||
var natHoleRespMsg msg.NatHoleResp
|
||||
visitorConn.SetReadDeadline(time.Now().Add(10 * time.Second))
|
||||
_ = visitorConn.SetReadDeadline(time.Now().Add(10 * time.Second))
|
||||
buf := pool.GetBuf(1024)
|
||||
n, err := visitorConn.Read(buf)
|
||||
if err != nil {
|
||||
@@ -251,7 +251,7 @@ func (sv *XTCPVisitor) handleConn(userConn net.Conn) {
|
||||
xl.Warn("get natHoleRespMsg error: %v", err)
|
||||
return
|
||||
}
|
||||
visitorConn.SetReadDeadline(time.Time{})
|
||||
_ = visitorConn.SetReadDeadline(time.Time{})
|
||||
pool.PutBuf(buf)
|
||||
|
||||
if natHoleRespMsg.Error != "" {
|
||||
@@ -278,17 +278,20 @@ func (sv *XTCPVisitor) handleConn(userConn net.Conn) {
|
||||
}
|
||||
defer lConn.Close()
|
||||
|
||||
lConn.Write([]byte(natHoleRespMsg.Sid))
|
||||
if _, err := lConn.Write([]byte(natHoleRespMsg.Sid)); err != nil {
|
||||
xl.Error("write sid error: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
// read ack sid from client
|
||||
sidBuf := pool.GetBuf(1024)
|
||||
lConn.SetReadDeadline(time.Now().Add(8 * time.Second))
|
||||
_ = lConn.SetReadDeadline(time.Now().Add(8 * time.Second))
|
||||
n, err = lConn.Read(sidBuf)
|
||||
if err != nil {
|
||||
xl.Warn("get sid from client error: %v", err)
|
||||
return
|
||||
}
|
||||
lConn.SetReadDeadline(time.Time{})
|
||||
_ = lConn.SetReadDeadline(time.Time{})
|
||||
if string(sidBuf[:n]) != natHoleRespMsg.Sid {
|
||||
xl.Warn("incorrect sid from client")
|
||||
return
|
||||
@@ -352,7 +355,7 @@ type SUDPVisitor struct {
|
||||
func (sv *SUDPVisitor) Run() (err error) {
|
||||
xl := xlog.FromContextSafe(sv.ctx)
|
||||
|
||||
addr, err := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", sv.cfg.BindAddr, sv.cfg.BindPort))
|
||||
addr, err := net.ResolveUDPAddr("udp", net.JoinHostPort(sv.cfg.BindAddr, strconv.Itoa(sv.cfg.BindPort)))
|
||||
if err != nil {
|
||||
return fmt.Errorf("sudp ResolveUDPAddr error: %v", err)
|
||||
}
|
||||
@@ -376,29 +379,33 @@ func (sv *SUDPVisitor) Run() (err error) {
|
||||
func (sv *SUDPVisitor) dispatcher() {
|
||||
xl := xlog.FromContextSafe(sv.ctx)
|
||||
|
||||
var (
|
||||
visitorConn net.Conn
|
||||
err error
|
||||
|
||||
firstPacket *msg.UDPPacket
|
||||
)
|
||||
|
||||
for {
|
||||
// loop for get frpc to frps tcp conn
|
||||
// setup worker
|
||||
// wait worker to finished
|
||||
// retry or exit
|
||||
visitorConn, err := sv.getNewVisitorConn()
|
||||
if err != nil {
|
||||
// check if proxy is closed
|
||||
// if checkCloseCh is close, we will return, other case we will continue to reconnect
|
||||
select {
|
||||
case <-sv.checkCloseCh:
|
||||
select {
|
||||
case firstPacket = <-sv.sendCh:
|
||||
if firstPacket == nil {
|
||||
xl.Info("frpc sudp visitor proxy is closed")
|
||||
return
|
||||
default:
|
||||
}
|
||||
case <-sv.checkCloseCh:
|
||||
xl.Info("frpc sudp visitor proxy is closed")
|
||||
return
|
||||
}
|
||||
|
||||
time.Sleep(3 * time.Second)
|
||||
|
||||
visitorConn, err = sv.getNewVisitorConn()
|
||||
if err != nil {
|
||||
xl.Warn("newVisitorConn to frps error: %v, try to reconnect", err)
|
||||
continue
|
||||
}
|
||||
|
||||
sv.worker(visitorConn)
|
||||
// visitorConn always be closed when worker done.
|
||||
sv.worker(visitorConn, firstPacket)
|
||||
|
||||
select {
|
||||
case <-sv.checkCloseCh:
|
||||
@@ -408,7 +415,7 @@ func (sv *SUDPVisitor) dispatcher() {
|
||||
}
|
||||
}
|
||||
|
||||
func (sv *SUDPVisitor) worker(workConn net.Conn) {
|
||||
func (sv *SUDPVisitor) worker(workConn net.Conn, firstPacket *msg.UDPPacket) {
|
||||
xl := xlog.FromContextSafe(sv.ctx)
|
||||
xl.Debug("starting sudp proxy worker")
|
||||
|
||||
@@ -431,13 +438,13 @@ func (sv *SUDPVisitor) worker(workConn net.Conn) {
|
||||
)
|
||||
|
||||
// frpc will send heartbeat in workConn to frpc visitor for keeping alive
|
||||
conn.SetReadDeadline(time.Now().Add(60 * time.Second))
|
||||
_ = conn.SetReadDeadline(time.Now().Add(60 * time.Second))
|
||||
if rawMsg, errRet = msg.ReadMsg(conn); errRet != nil {
|
||||
xl.Warn("read from workconn for user udp conn error: %v", errRet)
|
||||
return
|
||||
}
|
||||
|
||||
conn.SetReadDeadline(time.Time{})
|
||||
_ = conn.SetReadDeadline(time.Time{})
|
||||
switch m := rawMsg.(type) {
|
||||
case *msg.Ping:
|
||||
xl.Debug("frpc visitor get ping message from frpc")
|
||||
@@ -462,6 +469,14 @@ func (sv *SUDPVisitor) worker(workConn net.Conn) {
|
||||
}()
|
||||
|
||||
var errRet error
|
||||
if firstPacket != nil {
|
||||
if errRet = msg.WriteMsg(conn, firstPacket); errRet != nil {
|
||||
xl.Warn("sender goroutine for udp work connection closed: %v", errRet)
|
||||
return
|
||||
}
|
||||
xl.Trace("send udp package to workConn: %s", firstPacket.Content)
|
||||
}
|
||||
|
||||
for {
|
||||
select {
|
||||
case udpMsg, ok := <-sv.sendCh:
|
||||
@@ -509,12 +524,12 @@ func (sv *SUDPVisitor) getNewVisitorConn() (net.Conn, error) {
|
||||
}
|
||||
|
||||
var newVisitorConnRespMsg msg.NewVisitorConnResp
|
||||
visitorConn.SetReadDeadline(time.Now().Add(10 * time.Second))
|
||||
_ = visitorConn.SetReadDeadline(time.Now().Add(10 * time.Second))
|
||||
err = msg.ReadMsgInto(visitorConn, &newVisitorConnRespMsg)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("frpc read newVisitorConnRespMsg error: %v", err)
|
||||
}
|
||||
visitorConn.SetReadDeadline(time.Time{})
|
||||
_ = visitorConn.SetReadDeadline(time.Time{})
|
||||
|
||||
if newVisitorConnRespMsg.Error != "" {
|
||||
return nil, fmt.Errorf("start new visitor connection error: %s", newVisitorConnRespMsg.Error)
|
||||
|
@@ -65,7 +65,7 @@ func (vm *VisitorManager) Run() {
|
||||
name := cfg.GetBaseInfo().ProxyName
|
||||
if _, exist := vm.visitors[name]; !exist {
|
||||
xl.Info("try to start visitor [%s]", name)
|
||||
vm.startVisitor(cfg)
|
||||
_ = vm.startVisitor(cfg)
|
||||
}
|
||||
}
|
||||
vm.mu.Unlock()
|
||||
@@ -99,10 +99,8 @@ func (vm *VisitorManager) Reload(cfgs map[string]config.VisitorConf) {
|
||||
cfg, ok := cfgs[name]
|
||||
if !ok {
|
||||
del = true
|
||||
} else {
|
||||
if !oldCfg.Compare(cfg) {
|
||||
del = true
|
||||
}
|
||||
} else if !oldCfg.Compare(cfg) {
|
||||
del = true
|
||||
}
|
||||
|
||||
if del {
|
||||
@@ -123,13 +121,12 @@ func (vm *VisitorManager) Reload(cfgs map[string]config.VisitorConf) {
|
||||
if _, ok := vm.cfgs[name]; !ok {
|
||||
vm.cfgs[name] = cfg
|
||||
addNames = append(addNames, name)
|
||||
vm.startVisitor(cfg)
|
||||
_ = vm.startVisitor(cfg)
|
||||
}
|
||||
}
|
||||
if len(addNames) > 0 {
|
||||
xl.Info("visitor added: %v", addNames)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (vm *VisitorManager) Close() {
|
||||
|
@@ -15,18 +15,10 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"time"
|
||||
|
||||
_ "github.com/fatedier/frp/assets/frpc"
|
||||
"github.com/fatedier/frp/cmd/frpc/sub"
|
||||
|
||||
"github.com/fatedier/golib/crypto"
|
||||
)
|
||||
|
||||
func main() {
|
||||
crypto.DefaultSalt = "frp"
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
|
||||
sub.Execute()
|
||||
}
|
||||
|
@@ -19,10 +19,10 @@ import (
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/fatedier/frp/pkg/config"
|
||||
"github.com/fatedier/frp/pkg/consts"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
func init() {
|
||||
@@ -39,6 +39,8 @@ func init() {
|
||||
httpCmd.PersistentFlags().StringVarP(&hostHeaderRewrite, "host_header_rewrite", "", "", "host header rewrite")
|
||||
httpCmd.PersistentFlags().BoolVarP(&useEncryption, "ue", "", false, "use encryption")
|
||||
httpCmd.PersistentFlags().BoolVarP(&useCompression, "uc", "", false, "use compression")
|
||||
httpCmd.PersistentFlags().StringVarP(&bandwidthLimit, "bandwidth_limit", "", "", "bandwidth limit")
|
||||
httpCmd.PersistentFlags().StringVarP(&bandwidthLimitMode, "bandwidth_limit_mode", "", config.BandwidthLimitModeClient, "bandwidth limit mode")
|
||||
|
||||
rootCmd.AddCommand(httpCmd)
|
||||
}
|
||||
@@ -70,6 +72,12 @@ var httpCmd = &cobra.Command{
|
||||
cfg.HostHeaderRewrite = hostHeaderRewrite
|
||||
cfg.UseEncryption = useEncryption
|
||||
cfg.UseCompression = useCompression
|
||||
cfg.BandwidthLimit, err = config.NewBandwidthQuantity(bandwidthLimit)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
cfg.BandwidthLimitMode = bandwidthLimitMode
|
||||
|
||||
err = cfg.CheckForCli()
|
||||
if err != nil {
|
||||
|
@@ -35,6 +35,8 @@ func init() {
|
||||
httpsCmd.PersistentFlags().StringVarP(&subDomain, "sd", "", "", "sub domain")
|
||||
httpsCmd.PersistentFlags().BoolVarP(&useEncryption, "ue", "", false, "use encryption")
|
||||
httpsCmd.PersistentFlags().BoolVarP(&useCompression, "uc", "", false, "use compression")
|
||||
httpsCmd.PersistentFlags().StringVarP(&bandwidthLimit, "bandwidth_limit", "", "", "bandwidth limit")
|
||||
httpsCmd.PersistentFlags().StringVarP(&bandwidthLimitMode, "bandwidth_limit_mode", "", config.BandwidthLimitModeClient, "bandwidth limit mode")
|
||||
|
||||
rootCmd.AddCommand(httpsCmd)
|
||||
}
|
||||
@@ -62,6 +64,12 @@ var httpsCmd = &cobra.Command{
|
||||
cfg.SubDomain = subDomain
|
||||
cfg.UseEncryption = useEncryption
|
||||
cfg.UseCompression = useCompression
|
||||
cfg.BandwidthLimit, err = config.NewBandwidthQuantity(bandwidthLimit)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
cfg.BandwidthLimitMode = bandwidthLimitMode
|
||||
|
||||
err = cfg.CheckForCli()
|
||||
if err != nil {
|
||||
|
@@ -22,9 +22,9 @@ import (
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/fatedier/frp/pkg/config"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/fatedier/frp/pkg/config"
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
@@ -15,23 +15,24 @@
|
||||
package sub
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"net"
|
||||
"os"
|
||||
"os/signal"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/fatedier/frp/client"
|
||||
"github.com/fatedier/frp/pkg/auth"
|
||||
"github.com/fatedier/frp/pkg/config"
|
||||
"github.com/fatedier/frp/pkg/util/log"
|
||||
"github.com/fatedier/frp/pkg/util/version"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -41,6 +42,7 @@ const (
|
||||
|
||||
var (
|
||||
cfgFile string
|
||||
cfgDir string
|
||||
showVersion bool
|
||||
|
||||
serverAddr string
|
||||
@@ -52,35 +54,34 @@ var (
|
||||
logMaxDays int
|
||||
disableLogColor bool
|
||||
|
||||
proxyName string
|
||||
localIP string
|
||||
localPort int
|
||||
remotePort int
|
||||
useEncryption bool
|
||||
useCompression bool
|
||||
customDomains string
|
||||
subDomain string
|
||||
httpUser string
|
||||
httpPwd string
|
||||
locations string
|
||||
hostHeaderRewrite string
|
||||
role string
|
||||
sk string
|
||||
multiplexer string
|
||||
serverName string
|
||||
bindAddr string
|
||||
bindPort int
|
||||
proxyName string
|
||||
localIP string
|
||||
localPort int
|
||||
remotePort int
|
||||
useEncryption bool
|
||||
useCompression bool
|
||||
bandwidthLimit string
|
||||
bandwidthLimitMode string
|
||||
customDomains string
|
||||
subDomain string
|
||||
httpUser string
|
||||
httpPwd string
|
||||
locations string
|
||||
hostHeaderRewrite string
|
||||
role string
|
||||
sk string
|
||||
multiplexer string
|
||||
serverName string
|
||||
bindAddr string
|
||||
bindPort int
|
||||
|
||||
tlsEnable bool
|
||||
|
||||
kcpDoneCh chan struct{}
|
||||
)
|
||||
|
||||
func init() {
|
||||
rootCmd.PersistentFlags().StringVarP(&cfgFile, "config", "c", "./frpc.ini", "config file of frpc")
|
||||
rootCmd.PersistentFlags().StringVarP(&cfgDir, "config_dir", "", "", "config directory, run one frpc service for each file in config directory")
|
||||
rootCmd.PersistentFlags().BoolVarP(&showVersion, "version", "v", false, "version of frpc")
|
||||
|
||||
kcpDoneCh = make(chan struct{})
|
||||
}
|
||||
|
||||
func RegisterCommonFlags(cmd *cobra.Command) {
|
||||
@@ -104,6 +105,32 @@ var rootCmd = &cobra.Command{
|
||||
return nil
|
||||
}
|
||||
|
||||
// If cfgDir is not empty, run multiple frpc service for each config file in cfgDir.
|
||||
// Note that it's only designed for testing. It's not guaranteed to be stable.
|
||||
if cfgDir != "" {
|
||||
var wg sync.WaitGroup
|
||||
_ = filepath.WalkDir(cfgDir, func(path string, d fs.DirEntry, err error) error {
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
if d.IsDir() {
|
||||
return nil
|
||||
}
|
||||
wg.Add(1)
|
||||
time.Sleep(time.Millisecond)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
err := runClient(path)
|
||||
if err != nil {
|
||||
fmt.Printf("frpc service error for config file [%s]\n", path)
|
||||
}
|
||||
}()
|
||||
return nil
|
||||
})
|
||||
wg.Wait()
|
||||
return nil
|
||||
}
|
||||
|
||||
// Do not show command usage here.
|
||||
err := runClient(cfgFile)
|
||||
if err != nil {
|
||||
@@ -120,12 +147,12 @@ func Execute() {
|
||||
}
|
||||
}
|
||||
|
||||
func handleSignal(svr *client.Service) {
|
||||
ch := make(chan os.Signal)
|
||||
func handleSignal(svr *client.Service, doneCh chan struct{}) {
|
||||
ch := make(chan os.Signal, 1)
|
||||
signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM)
|
||||
<-ch
|
||||
svr.GracefulClose(500 * time.Millisecond)
|
||||
close(kcpDoneCh)
|
||||
close(doneCh)
|
||||
}
|
||||
|
||||
func parseClientCommonCfgFromCmd() (cfg config.ClientCommonConf, err error) {
|
||||
@@ -158,7 +185,7 @@ func parseClientCommonCfgFromCmd() (cfg config.ClientCommonConf, err error) {
|
||||
|
||||
cfg.Complete()
|
||||
if err = cfg.Validate(); err != nil {
|
||||
err = fmt.Errorf("Parse config error: %v", err)
|
||||
err = fmt.Errorf("parse config error: %v", err)
|
||||
return
|
||||
}
|
||||
return
|
||||
@@ -178,22 +205,12 @@ func startService(
|
||||
visitorCfgs map[string]config.VisitorConf,
|
||||
cfgFile string,
|
||||
) (err error) {
|
||||
|
||||
log.InitLog(cfg.LogWay, cfg.LogFile, cfg.LogLevel,
|
||||
cfg.LogMaxDays, cfg.DisableLogColor)
|
||||
|
||||
if cfg.DNSServer != "" {
|
||||
s := cfg.DNSServer
|
||||
if !strings.Contains(s, ":") {
|
||||
s += ":53"
|
||||
}
|
||||
// Change default dns server for frpc
|
||||
net.DefaultResolver = &net.Resolver{
|
||||
PreferGo: true,
|
||||
Dial: func(ctx context.Context, network, address string) (net.Conn, error) {
|
||||
return net.Dial("udp", s)
|
||||
},
|
||||
}
|
||||
if cfgFile != "" {
|
||||
log.Trace("start frpc service for config file [%s]", cfgFile)
|
||||
defer log.Trace("frpc service for config file [%s] stopped", cfgFile)
|
||||
}
|
||||
svr, errRet := client.NewService(cfg, pxyCfgs, visitorCfgs, cfgFile)
|
||||
if errRet != nil {
|
||||
@@ -201,14 +218,16 @@ func startService(
|
||||
return
|
||||
}
|
||||
|
||||
// Capture the exit signal if we use kcp.
|
||||
if cfg.Protocol == "kcp" {
|
||||
go handleSignal(svr)
|
||||
closedDoneCh := make(chan struct{})
|
||||
shouldGracefulClose := cfg.Protocol == "kcp" || cfg.Protocol == "quic"
|
||||
// Capture the exit signal if we use kcp or quic.
|
||||
if shouldGracefulClose {
|
||||
go handleSignal(svr, closedDoneCh)
|
||||
}
|
||||
|
||||
err = svr.Run()
|
||||
if err == nil && cfg.Protocol == "kcp" {
|
||||
<-kcpDoneCh
|
||||
if err == nil && shouldGracefulClose {
|
||||
<-closedDoneCh
|
||||
}
|
||||
return
|
||||
}
|
||||
|
@@ -23,11 +23,11 @@ import (
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/fatedier/frp/client"
|
||||
"github.com/fatedier/frp/pkg/config"
|
||||
|
||||
"github.com/rodaine/table"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/fatedier/frp/client"
|
||||
"github.com/fatedier/frp/pkg/config"
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
@@ -18,10 +18,10 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/fatedier/frp/pkg/config"
|
||||
"github.com/fatedier/frp/pkg/consts"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
func init() {
|
||||
@@ -37,6 +37,8 @@ func init() {
|
||||
stcpCmd.PersistentFlags().IntVarP(&bindPort, "bind_port", "", 0, "bind port")
|
||||
stcpCmd.PersistentFlags().BoolVarP(&useEncryption, "ue", "", false, "use encryption")
|
||||
stcpCmd.PersistentFlags().BoolVarP(&useCompression, "uc", "", false, "use compression")
|
||||
stcpCmd.PersistentFlags().StringVarP(&bandwidthLimit, "bandwidth_limit", "", "", "bandwidth limit")
|
||||
stcpCmd.PersistentFlags().StringVarP(&bandwidthLimitMode, "bandwidth_limit_mode", "", config.BandwidthLimitModeClient, "bandwidth limit mode")
|
||||
|
||||
rootCmd.AddCommand(stcpCmd)
|
||||
}
|
||||
@@ -59,7 +61,8 @@ var stcpCmd = &cobra.Command{
|
||||
prefix = user + "."
|
||||
}
|
||||
|
||||
if role == "server" {
|
||||
switch role {
|
||||
case "server":
|
||||
cfg := &config.STCPProxyConf{}
|
||||
cfg.ProxyName = prefix + proxyName
|
||||
cfg.ProxyType = consts.STCPProxy
|
||||
@@ -69,13 +72,19 @@ var stcpCmd = &cobra.Command{
|
||||
cfg.Sk = sk
|
||||
cfg.LocalIP = localIP
|
||||
cfg.LocalPort = localPort
|
||||
cfg.BandwidthLimit, err = config.NewBandwidthQuantity(bandwidthLimit)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
cfg.BandwidthLimitMode = bandwidthLimitMode
|
||||
err = cfg.CheckForCli()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
proxyConfs[cfg.ProxyName] = cfg
|
||||
} else if role == "visitor" {
|
||||
case "visitor":
|
||||
cfg := &config.STCPVisitorConf{}
|
||||
cfg.ProxyName = prefix + proxyName
|
||||
cfg.ProxyType = consts.STCPProxy
|
||||
@@ -92,7 +101,7 @@ var stcpCmd = &cobra.Command{
|
||||
os.Exit(1)
|
||||
}
|
||||
visitorConfs[cfg.ProxyName] = cfg
|
||||
} else {
|
||||
default:
|
||||
fmt.Println("invalid role")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
@@ -18,10 +18,10 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/fatedier/frp/pkg/config"
|
||||
"github.com/fatedier/frp/pkg/consts"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
func init() {
|
||||
@@ -37,6 +37,8 @@ func init() {
|
||||
sudpCmd.PersistentFlags().IntVarP(&bindPort, "bind_port", "", 0, "bind port")
|
||||
sudpCmd.PersistentFlags().BoolVarP(&useEncryption, "ue", "", false, "use encryption")
|
||||
sudpCmd.PersistentFlags().BoolVarP(&useCompression, "uc", "", false, "use compression")
|
||||
sudpCmd.PersistentFlags().StringVarP(&bandwidthLimit, "bandwidth_limit", "", "", "bandwidth limit")
|
||||
sudpCmd.PersistentFlags().StringVarP(&bandwidthLimitMode, "bandwidth_limit_mode", "", config.BandwidthLimitModeClient, "bandwidth limit mode")
|
||||
|
||||
rootCmd.AddCommand(sudpCmd)
|
||||
}
|
||||
@@ -59,7 +61,8 @@ var sudpCmd = &cobra.Command{
|
||||
prefix = user + "."
|
||||
}
|
||||
|
||||
if role == "server" {
|
||||
switch role {
|
||||
case "server":
|
||||
cfg := &config.SUDPProxyConf{}
|
||||
cfg.ProxyName = prefix + proxyName
|
||||
cfg.ProxyType = consts.SUDPProxy
|
||||
@@ -69,13 +72,19 @@ var sudpCmd = &cobra.Command{
|
||||
cfg.Sk = sk
|
||||
cfg.LocalIP = localIP
|
||||
cfg.LocalPort = localPort
|
||||
cfg.BandwidthLimit, err = config.NewBandwidthQuantity(bandwidthLimit)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
cfg.BandwidthLimitMode = bandwidthLimitMode
|
||||
err = cfg.CheckForCli()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
proxyConfs[cfg.ProxyName] = cfg
|
||||
} else if role == "visitor" {
|
||||
case "visitor":
|
||||
cfg := &config.SUDPVisitorConf{}
|
||||
cfg.ProxyName = prefix + proxyName
|
||||
cfg.ProxyType = consts.SUDPProxy
|
||||
@@ -92,7 +101,7 @@ var sudpCmd = &cobra.Command{
|
||||
os.Exit(1)
|
||||
}
|
||||
visitorConfs[cfg.ProxyName] = cfg
|
||||
} else {
|
||||
default:
|
||||
fmt.Println("invalid role")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
@@ -33,6 +33,8 @@ func init() {
|
||||
tcpCmd.PersistentFlags().IntVarP(&remotePort, "remote_port", "r", 0, "remote port")
|
||||
tcpCmd.PersistentFlags().BoolVarP(&useEncryption, "ue", "", false, "use encryption")
|
||||
tcpCmd.PersistentFlags().BoolVarP(&useCompression, "uc", "", false, "use compression")
|
||||
tcpCmd.PersistentFlags().StringVarP(&bandwidthLimit, "bandwidth_limit", "", "", "bandwidth limit")
|
||||
tcpCmd.PersistentFlags().StringVarP(&bandwidthLimitMode, "bandwidth_limit_mode", "", config.BandwidthLimitModeClient, "bandwidth limit mode")
|
||||
|
||||
rootCmd.AddCommand(tcpCmd)
|
||||
}
|
||||
@@ -59,6 +61,12 @@ var tcpCmd = &cobra.Command{
|
||||
cfg.RemotePort = remotePort
|
||||
cfg.UseEncryption = useEncryption
|
||||
cfg.UseCompression = useCompression
|
||||
cfg.BandwidthLimit, err = config.NewBandwidthQuantity(bandwidthLimit)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
cfg.BandwidthLimitMode = bandwidthLimitMode
|
||||
|
||||
err = cfg.CheckForCli()
|
||||
if err != nil {
|
||||
|
@@ -36,6 +36,8 @@ func init() {
|
||||
tcpMuxCmd.PersistentFlags().StringVarP(&multiplexer, "mux", "", "", "multiplexer")
|
||||
tcpMuxCmd.PersistentFlags().BoolVarP(&useEncryption, "ue", "", false, "use encryption")
|
||||
tcpMuxCmd.PersistentFlags().BoolVarP(&useCompression, "uc", "", false, "use compression")
|
||||
tcpMuxCmd.PersistentFlags().StringVarP(&bandwidthLimit, "bandwidth_limit", "", "", "bandwidth limit")
|
||||
tcpMuxCmd.PersistentFlags().StringVarP(&bandwidthLimitMode, "bandwidth_limit_mode", "", config.BandwidthLimitModeClient, "bandwidth limit mode")
|
||||
|
||||
rootCmd.AddCommand(tcpMuxCmd)
|
||||
}
|
||||
@@ -64,6 +66,12 @@ var tcpMuxCmd = &cobra.Command{
|
||||
cfg.Multiplexer = multiplexer
|
||||
cfg.UseEncryption = useEncryption
|
||||
cfg.UseCompression = useCompression
|
||||
cfg.BandwidthLimit, err = config.NewBandwidthQuantity(bandwidthLimit)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
cfg.BandwidthLimitMode = bandwidthLimitMode
|
||||
|
||||
err = cfg.CheckForCli()
|
||||
if err != nil {
|
||||
|
@@ -18,10 +18,10 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/fatedier/frp/pkg/config"
|
||||
"github.com/fatedier/frp/pkg/consts"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
func init() {
|
||||
@@ -33,6 +33,8 @@ func init() {
|
||||
udpCmd.PersistentFlags().IntVarP(&remotePort, "remote_port", "r", 0, "remote port")
|
||||
udpCmd.PersistentFlags().BoolVarP(&useEncryption, "ue", "", false, "use encryption")
|
||||
udpCmd.PersistentFlags().BoolVarP(&useCompression, "uc", "", false, "use compression")
|
||||
udpCmd.PersistentFlags().StringVarP(&bandwidthLimit, "bandwidth_limit", "", "", "bandwidth limit")
|
||||
udpCmd.PersistentFlags().StringVarP(&bandwidthLimitMode, "bandwidth_limit_mode", "", config.BandwidthLimitModeClient, "bandwidth limit mode")
|
||||
|
||||
rootCmd.AddCommand(udpCmd)
|
||||
}
|
||||
@@ -59,6 +61,12 @@ var udpCmd = &cobra.Command{
|
||||
cfg.RemotePort = remotePort
|
||||
cfg.UseEncryption = useEncryption
|
||||
cfg.UseCompression = useCompression
|
||||
cfg.BandwidthLimit, err = config.NewBandwidthQuantity(bandwidthLimit)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
cfg.BandwidthLimitMode = bandwidthLimitMode
|
||||
|
||||
err = cfg.CheckForCli()
|
||||
if err != nil {
|
||||
|
@@ -18,9 +18,9 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/fatedier/frp/pkg/config"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/fatedier/frp/pkg/config"
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
@@ -18,10 +18,10 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/fatedier/frp/pkg/config"
|
||||
"github.com/fatedier/frp/pkg/consts"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
func init() {
|
||||
@@ -37,6 +37,8 @@ func init() {
|
||||
xtcpCmd.PersistentFlags().IntVarP(&bindPort, "bind_port", "", 0, "bind port")
|
||||
xtcpCmd.PersistentFlags().BoolVarP(&useEncryption, "ue", "", false, "use encryption")
|
||||
xtcpCmd.PersistentFlags().BoolVarP(&useCompression, "uc", "", false, "use compression")
|
||||
xtcpCmd.PersistentFlags().StringVarP(&bandwidthLimit, "bandwidth_limit", "", "", "bandwidth limit")
|
||||
xtcpCmd.PersistentFlags().StringVarP(&bandwidthLimitMode, "bandwidth_limit_mode", "", config.BandwidthLimitModeClient, "bandwidth limit mode")
|
||||
|
||||
rootCmd.AddCommand(xtcpCmd)
|
||||
}
|
||||
@@ -59,7 +61,8 @@ var xtcpCmd = &cobra.Command{
|
||||
prefix = user + "."
|
||||
}
|
||||
|
||||
if role == "server" {
|
||||
switch role {
|
||||
case "server":
|
||||
cfg := &config.XTCPProxyConf{}
|
||||
cfg.ProxyName = prefix + proxyName
|
||||
cfg.ProxyType = consts.XTCPProxy
|
||||
@@ -69,13 +72,19 @@ var xtcpCmd = &cobra.Command{
|
||||
cfg.Sk = sk
|
||||
cfg.LocalIP = localIP
|
||||
cfg.LocalPort = localPort
|
||||
cfg.BandwidthLimit, err = config.NewBandwidthQuantity(bandwidthLimit)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
cfg.BandwidthLimitMode = bandwidthLimitMode
|
||||
err = cfg.CheckForCli()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
proxyConfs[cfg.ProxyName] = cfg
|
||||
} else if role == "visitor" {
|
||||
case "visitor":
|
||||
cfg := &config.XTCPVisitorConf{}
|
||||
cfg.ProxyName = prefix + proxyName
|
||||
cfg.ProxyType = consts.XTCPProxy
|
||||
@@ -92,7 +101,7 @@ var xtcpCmd = &cobra.Command{
|
||||
os.Exit(1)
|
||||
}
|
||||
visitorConfs[cfg.ProxyName] = cfg
|
||||
} else {
|
||||
default:
|
||||
fmt.Println("invalid role")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
@@ -26,6 +26,7 @@ import (
|
||||
|
||||
func main() {
|
||||
crypto.DefaultSalt = "frp"
|
||||
// TODO: remove this when we drop support for go1.19
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
|
||||
Execute()
|
||||
|
@@ -18,14 +18,14 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/fatedier/frp/pkg/auth"
|
||||
"github.com/fatedier/frp/pkg/config"
|
||||
"github.com/fatedier/frp/pkg/util/log"
|
||||
"github.com/fatedier/frp/pkg/util/util"
|
||||
"github.com/fatedier/frp/pkg/util/version"
|
||||
"github.com/fatedier/frp/server"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -37,31 +37,31 @@ var (
|
||||
cfgFile string
|
||||
showVersion bool
|
||||
|
||||
bindAddr string
|
||||
bindPort int
|
||||
bindUDPPort int
|
||||
kcpBindPort int
|
||||
proxyBindAddr string
|
||||
vhostHTTPPort int
|
||||
vhostHTTPSPort int
|
||||
vhostHTTPTimeout int64
|
||||
dashboardAddr string
|
||||
dashboardPort int
|
||||
dashboardUser string
|
||||
dashboardPwd string
|
||||
enablePrometheus bool
|
||||
assetsDir string
|
||||
logFile string
|
||||
logLevel string
|
||||
logMaxDays int64
|
||||
disableLogColor bool
|
||||
token string
|
||||
subDomainHost string
|
||||
tcpMux bool
|
||||
allowPorts string
|
||||
maxPoolCount int64
|
||||
maxPortsPerClient int64
|
||||
tlsOnly bool
|
||||
bindAddr string
|
||||
bindPort int
|
||||
bindUDPPort int
|
||||
kcpBindPort int
|
||||
proxyBindAddr string
|
||||
vhostHTTPPort int
|
||||
vhostHTTPSPort int
|
||||
vhostHTTPTimeout int64
|
||||
dashboardAddr string
|
||||
dashboardPort int
|
||||
dashboardUser string
|
||||
dashboardPwd string
|
||||
enablePrometheus bool
|
||||
logFile string
|
||||
logLevel string
|
||||
logMaxDays int64
|
||||
disableLogColor bool
|
||||
token string
|
||||
subDomainHost string
|
||||
allowPorts string
|
||||
maxPortsPerClient int64
|
||||
tlsOnly bool
|
||||
dashboardTLSMode bool
|
||||
dashboardTLSCertFile string
|
||||
dashboardTLSKeyFile string
|
||||
)
|
||||
|
||||
func init() {
|
||||
@@ -91,6 +91,9 @@ func init() {
|
||||
rootCmd.PersistentFlags().StringVarP(&allowPorts, "allow_ports", "", "", "allow ports")
|
||||
rootCmd.PersistentFlags().Int64VarP(&maxPortsPerClient, "max_ports_per_client", "", 0, "max ports per client")
|
||||
rootCmd.PersistentFlags().BoolVarP(&tlsOnly, "tls_only", "", false, "frps tls only")
|
||||
rootCmd.PersistentFlags().BoolVarP(&dashboardTLSMode, "dashboard_tls_mode", "", false, "dashboard tls mode")
|
||||
rootCmd.PersistentFlags().StringVarP(&dashboardTLSCertFile, "dashboard_tls_cert_file", "", "", "dashboard tls cert file")
|
||||
rootCmd.PersistentFlags().StringVarP(&dashboardTLSKeyFile, "dashboard_tls_key_file", "", "", "dashboard tls key file")
|
||||
}
|
||||
|
||||
var rootCmd = &cobra.Command{
|
||||
@@ -145,7 +148,7 @@ func parseServerCommonCfg(fileType int, source []byte) (cfg config.ServerCommonC
|
||||
cfg.Complete()
|
||||
err = cfg.Validate()
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Parse config error: %v", err)
|
||||
err = fmt.Errorf("parse config error: %v", err)
|
||||
return
|
||||
}
|
||||
return
|
||||
@@ -167,6 +170,9 @@ func parseServerCommonCfgFromCmd() (cfg config.ServerCommonConf, err error) {
|
||||
cfg.DashboardUser = dashboardUser
|
||||
cfg.DashboardPwd = dashboardPwd
|
||||
cfg.EnablePrometheus = enablePrometheus
|
||||
cfg.DashboardTLSCertFile = dashboardTLSCertFile
|
||||
cfg.DashboardTLSKeyFile = dashboardTLSKeyFile
|
||||
cfg.DashboardTLSMode = dashboardTLSMode
|
||||
cfg.LogFile = logFile
|
||||
cfg.LogLevel = logLevel
|
||||
cfg.LogMaxDays = logMaxDays
|
||||
@@ -180,7 +186,7 @@ func parseServerCommonCfgFromCmd() (cfg config.ServerCommonConf, err error) {
|
||||
// e.g. 1000-2000,2001,2002,3000-4000
|
||||
ports, errRet := util.ParseRangeNumbers(allowPorts)
|
||||
if errRet != nil {
|
||||
err = fmt.Errorf("Parse conf error: allow_ports: %v", errRet)
|
||||
err = fmt.Errorf("parse conf error: allow_ports: %v", errRet)
|
||||
return
|
||||
}
|
||||
|
||||
|
@@ -18,9 +18,9 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/fatedier/frp/pkg/config"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/fatedier/frp/pkg/config"
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
@@ -6,6 +6,13 @@
|
||||
server_addr = 0.0.0.0
|
||||
server_port = 7000
|
||||
|
||||
# The maximum amount of time a dial to server will wait for a connect to complete. Default value is 10 seconds.
|
||||
# dial_server_timeout = 10
|
||||
|
||||
# dial_server_keepalive specifies the interval between keep-alive probes for an active network connection between frpc and frps.
|
||||
# If negative, keep-alive probes are disabled.
|
||||
# dial_server_keepalive = 7200
|
||||
|
||||
# if you want to connect frps by http proxy or socks5 proxy or ntlm proxy, you can set http_proxy here or in global environment variables
|
||||
# it only works when protocol is tcp
|
||||
# http_proxy = http://user:passwd@192.168.1.128:8080
|
||||
@@ -33,6 +40,8 @@ authenticate_new_work_conns = false
|
||||
# auth token
|
||||
token = 12345678
|
||||
|
||||
authentication_method =
|
||||
|
||||
# oidc_client_id specifies the client ID to use to get a token in OIDC authentication if AuthenticationMethod == "oidc".
|
||||
# By default, this value is "".
|
||||
oidc_client_id =
|
||||
@@ -44,10 +53,19 @@ oidc_client_secret =
|
||||
# oidc_audience specifies the audience of the token in OIDC authentication if AuthenticationMethod == "oidc". By default, this value is "".
|
||||
oidc_audience =
|
||||
|
||||
# oidc_scope specifies the permisssions of the token in OIDC authentication if AuthenticationMethod == "oidc". By default, this value is "".
|
||||
oidc_scope =
|
||||
|
||||
# oidc_token_endpoint_url specifies the URL which implements OIDC Token Endpoint.
|
||||
# It will be used to get an OIDC token if AuthenticationMethod == "oidc". By default, this value is "".
|
||||
oidc_token_endpoint_url =
|
||||
|
||||
# oidc_additional_xxx specifies additional parameters to be sent to the OIDC Token Endpoint.
|
||||
# For example, if you want to specify the "audience" parameter, you can set as follow.
|
||||
# frp will add "audience=<value>" "var1=<value>" to the additional parameters.
|
||||
# oidc_additional_audience = https://dev.auth.com/api/v2/
|
||||
# oidc_additional_var1 = foobar
|
||||
|
||||
# set admin address for control frpc's action by http api such as reload
|
||||
admin_addr = 127.0.0.1
|
||||
admin_port = 7400
|
||||
@@ -60,7 +78,11 @@ admin_pwd = admin
|
||||
pool_count = 5
|
||||
|
||||
# if tcp stream multiplexing is used, default is true, it must be same with frps
|
||||
tcp_mux = true
|
||||
# tcp_mux = true
|
||||
|
||||
# specify keep alive interval for tcp mux.
|
||||
# only valid if tcp_mux is true.
|
||||
# tcp_mux_keepalive_interval = 60
|
||||
|
||||
# your proxy name will be changed to {user}.{proxy}
|
||||
user = your_name
|
||||
@@ -70,9 +92,18 @@ user = your_name
|
||||
login_fail_exit = true
|
||||
|
||||
# communication protocol used to connect to server
|
||||
# now it supports tcp, kcp and websocket, default is tcp
|
||||
# supports tcp, kcp, quic and websocket now, default is tcp
|
||||
protocol = tcp
|
||||
|
||||
# set client binding ip when connect server, default is empty.
|
||||
# only when protocol = tcp or websocket, the value will be used.
|
||||
connect_server_local_ip = 0.0.0.0
|
||||
|
||||
# quic protocol options
|
||||
# quic_keepalive_period = 10
|
||||
# quic_max_idle_timeout = 30
|
||||
# quic_max_incoming_streams = 100000
|
||||
|
||||
# if tls_enable is true, frpc will connect frps by tls
|
||||
tls_enable = true
|
||||
|
||||
@@ -84,12 +115,13 @@ tls_enable = true
|
||||
# specify a dns server, so frpc will use this instead of default one
|
||||
# dns_server = 8.8.8.8
|
||||
|
||||
# proxy names you want to start seperated by ','
|
||||
# proxy names you want to start separated by ','
|
||||
# default is empty, means all proxies
|
||||
# start = ssh,dns
|
||||
|
||||
# heartbeat configure, it's not recommended to modify the default value
|
||||
# the default value of heartbeat_interval is 10 and heartbeat_timeout is 90
|
||||
# The default value of heartbeat_interval is 10 and heartbeat_timeout is 90. Set negative value
|
||||
# to disable it.
|
||||
# heartbeat_interval = 30
|
||||
# heartbeat_timeout = 90
|
||||
|
||||
@@ -109,6 +141,10 @@ udp_packet_size = 1500
|
||||
# If DisableCustomTLSFirstByte is true, frpc will not send that custom byte.
|
||||
disable_custom_tls_first_byte = false
|
||||
|
||||
# Enable golang pprof handlers in admin listener.
|
||||
# Admin port must be set first.
|
||||
pprof_enable = false
|
||||
|
||||
# 'ssh' is the unique proxy name
|
||||
# if user in [common] section is not empty, it will be changed to {user}.{proxy} such as 'your_name.ssh'
|
||||
[ssh]
|
||||
@@ -118,6 +154,8 @@ local_ip = 127.0.0.1
|
||||
local_port = 22
|
||||
# limit bandwidth for this proxy, unit is KB and MB
|
||||
bandwidth_limit = 1MB
|
||||
# where to limit bandwidth, can be 'client' or 'server', default is 'client'
|
||||
bandwidth_limit_mode = client
|
||||
# true or false, if true, messages between frps and frpc will be encrypted, default is false
|
||||
use_encryption = false
|
||||
# if true, message will be compressed
|
||||
@@ -190,6 +228,8 @@ subdomain = web01
|
||||
custom_domains = web01.yourdomain.com
|
||||
# locations is only available for http type
|
||||
locations = /,/pic
|
||||
# route requests to this service if http basic auto user is abc
|
||||
# route_by_http_user = abc
|
||||
host_header_rewrite = example.com
|
||||
# params with prefix "header_" will be used to update http request headers
|
||||
header_X-From-Where = frp
|
||||
@@ -322,3 +362,4 @@ multiplexer = httpconnect
|
||||
local_ip = 127.0.0.1
|
||||
local_port = 10701
|
||||
custom_domains = tunnel1
|
||||
# route_by_http_user = user1
|
||||
|
@@ -9,10 +9,18 @@ bind_port = 7000
|
||||
# udp port to help make udp hole to penetrate nat
|
||||
bind_udp_port = 7001
|
||||
|
||||
# udp port used for kcp protocol, it can be same with 'bind_port'
|
||||
# if not set, kcp is disabled in frps
|
||||
# udp port used for kcp protocol, it can be same with 'bind_port'.
|
||||
# if not set, kcp is disabled in frps.
|
||||
kcp_bind_port = 7000
|
||||
|
||||
# udp port used for quic protocol.
|
||||
# if not set, quic is disabled in frps.
|
||||
# quic_bind_port = 7002
|
||||
# quic protocol options
|
||||
# quic_keepalive_period = 10
|
||||
# quic_max_idle_timeout = 30
|
||||
# quic_max_incoming_streams = 100000
|
||||
|
||||
# specify which address proxy will listen for, default value is same with bind_addr
|
||||
# proxy_bind_addr = 127.0.0.1
|
||||
|
||||
@@ -30,6 +38,9 @@ vhost_https_port = 443
|
||||
# HTTP CONNECT requests. By default, this value is 0.
|
||||
# tcpmux_httpconnect_port = 1337
|
||||
|
||||
# If tcpmux_passthrough is true, frps won't do any update on traffic.
|
||||
# tcpmux_passthrough = false
|
||||
|
||||
# set dashboard_addr and dashboard_port to view dashboard of frps
|
||||
# dashboard_addr's default value is same with bind_addr
|
||||
# dashboard is available only if dashboard_port is set
|
||||
@@ -40,6 +51,11 @@ dashboard_port = 7500
|
||||
dashboard_user = admin
|
||||
dashboard_pwd = admin
|
||||
|
||||
# dashboard TLS mode
|
||||
dashboard_tls_mode = false
|
||||
# dashboard_tls_cert_file = server.crt
|
||||
# dashboard_tls_key_file = server.key
|
||||
|
||||
# enable_prometheus will export prometheus metrics on {dashboard_addr}:{dashboard_port} in /metrics api.
|
||||
enable_prometheus = true
|
||||
|
||||
@@ -86,13 +102,12 @@ oidc_audience =
|
||||
# By default, this value is false.
|
||||
oidc_skip_expiry_check = false
|
||||
|
||||
|
||||
# oidc_skip_issuer_check specifies whether to skip checking if the OIDC token's issuer claim matches the issuer specified in OidcIssuer.
|
||||
# By default, this value is false.
|
||||
oidc_skip_issuer_check = false
|
||||
|
||||
# heartbeat configure, it's not recommended to modify the default value
|
||||
# the default value of heartbeat_timeout is 90
|
||||
# the default value of heartbeat_timeout is 90. Set negative value to disable it.
|
||||
# heartbeat_timeout = 90
|
||||
|
||||
# user_conn_timeout configure, it's not recommended to modify the default value
|
||||
@@ -120,7 +135,15 @@ tls_only = false
|
||||
subdomain_host = frps.com
|
||||
|
||||
# if tcp stream multiplexing is used, default is true
|
||||
tcp_mux = true
|
||||
# tcp_mux = true
|
||||
|
||||
# specify keep alive interval for tcp mux.
|
||||
# only valid if tcp_mux is true.
|
||||
# tcp_mux_keepalive_interval = 60
|
||||
|
||||
# tcp_keepalive specifies the interval between keep-alive probes for an active network connection between frpc and frps.
|
||||
# If negative, keep-alive probes are disabled.
|
||||
# tcp_keepalive = 7200
|
||||
|
||||
# custom 404 page for HTTP requests
|
||||
# custom_404_page = /path/to/404.html
|
||||
@@ -130,6 +153,10 @@ tcp_mux = true
|
||||
# It affects the udp and sudp proxy.
|
||||
udp_packet_size = 1500
|
||||
|
||||
# Enable golang pprof handlers in dashboard listener.
|
||||
# Dashboard port must be set first
|
||||
pprof_enable = false
|
||||
|
||||
[plugin.user-manager]
|
||||
addr = 127.0.0.1:9000
|
||||
path = /handler
|
||||
|
@@ -1,15 +0,0 @@
|
||||
[Unit]
|
||||
Description=Frp Client Service
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=nobody
|
||||
Restart=on-failure
|
||||
RestartSec=5s
|
||||
ExecStart=/usr/bin/frpc -c /etc/frp/frpc.ini
|
||||
ExecReload=/usr/bin/frpc reload -c /etc/frp/frpc.ini
|
||||
LimitNOFILE=1048576
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
@@ -1,15 +0,0 @@
|
||||
[Unit]
|
||||
Description=Frp Client Service
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=nobody
|
||||
Restart=on-failure
|
||||
RestartSec=5s
|
||||
ExecStart=/usr/bin/frpc -c /etc/frp/%i.ini
|
||||
ExecReload=/usr/bin/frpc reload -c /etc/frp/%i.ini
|
||||
LimitNOFILE=1048576
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
@@ -1,14 +0,0 @@
|
||||
[Unit]
|
||||
Description=Frp Server Service
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=nobody
|
||||
Restart=on-failure
|
||||
RestartSec=5s
|
||||
ExecStart=/usr/bin/frps -c /etc/frp/frps.ini
|
||||
LimitNOFILE=1048576
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
@@ -1,14 +0,0 @@
|
||||
[Unit]
|
||||
Description=Frp Server Service
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=nobody
|
||||
Restart=on-failure
|
||||
RestartSec=5s
|
||||
ExecStart=/usr/bin/frps -c /etc/frp/%i.ini
|
||||
LimitNOFILE=1048576
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
BIN
doc/pic/sponsor_doppler.png
Normal file
BIN
doc/pic/sponsor_doppler.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 41 KiB |
BIN
doc/pic/sponsor_workos.png
Normal file
BIN
doc/pic/sponsor_workos.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 37 KiB |
@@ -70,7 +70,7 @@ The response can look like any of the following:
|
||||
|
||||
### Operation
|
||||
|
||||
Currently `Login`, `NewProxy`, `Ping`, `NewWorkConn` and `NewUserConn` operations are supported.
|
||||
Currently `Login`, `NewProxy`, `CloseProxy`, `Ping`, `NewWorkConn` and `NewUserConn` operations are supported.
|
||||
|
||||
#### Login
|
||||
|
||||
@@ -88,7 +88,8 @@ Client login operation
|
||||
"privilege_key": <string>,
|
||||
"run_id": <string>,
|
||||
"pool_count": <int>,
|
||||
"metas": map<string>string
|
||||
"metas": map<string>string,
|
||||
"client_address": <string>
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -109,6 +110,8 @@ Create new proxy
|
||||
"proxy_type": <string>,
|
||||
"use_encryption": <bool>,
|
||||
"use_compression": <bool>,
|
||||
"bandwidth_limit": <string>,
|
||||
"bandwidth_limit_mode": <string>,
|
||||
"group": <string>,
|
||||
"group_key": <string>,
|
||||
|
||||
@@ -135,6 +138,26 @@ Create new proxy
|
||||
}
|
||||
```
|
||||
|
||||
#### CloseProxy
|
||||
|
||||
A previously created proxy is closed.
|
||||
|
||||
Please note that one request will be sent for every proxy that is closed, do **NOT** use this
|
||||
if you have too many proxies bound to a single client, as this may exhaust the server's resources.
|
||||
|
||||
```
|
||||
{
|
||||
"content": {
|
||||
"user": {
|
||||
"user": <string>,
|
||||
"metas": map<string>string
|
||||
"run_id": <string>
|
||||
},
|
||||
"proxy_name": <string>
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Ping
|
||||
|
||||
Heartbeat from frpc
|
||||
|
@@ -1,228 +0,0 @@
|
||||
### 服务端管理插件
|
||||
|
||||
frp 管理插件的作用是在不侵入自身代码的前提下,扩展 frp 服务端的能力。
|
||||
|
||||
frp 管理插件会以单独进程的形式运行,并且监听在一个端口上,对外提供 RPC 接口,响应 frps 的请求。
|
||||
|
||||
frps 在执行某些操作前,会根据配置向管理插件发送 RPC 请求,根据管理插件的响应来执行相应的操作。
|
||||
|
||||
### RPC 请求
|
||||
|
||||
管理插件接收到操作请求后,可以给出三种回应。
|
||||
|
||||
* 拒绝操作,需要返回拒绝操作的原因。
|
||||
* 允许操作,不需要修改操作内容。
|
||||
* 允许操作,对操作请求进行修改后,返回修改后的内容。
|
||||
|
||||
### 接口
|
||||
|
||||
接口路径可以在 frps 配置中为每个插件单独配置,这里以 `/handler` 为例。
|
||||
|
||||
Request
|
||||
|
||||
```
|
||||
POST /handler
|
||||
{
|
||||
"version": "0.1.0",
|
||||
"op": "Login",
|
||||
"content": {
|
||||
... // 具体的操作信息
|
||||
}
|
||||
}
|
||||
|
||||
请求 Header
|
||||
X-Frp-Reqid: 用于追踪请求
|
||||
```
|
||||
|
||||
Response
|
||||
|
||||
非 200 的返回都认为是请求异常。
|
||||
|
||||
拒绝执行操作
|
||||
|
||||
```
|
||||
{
|
||||
"reject": true,
|
||||
"reject_reason": "invalid user"
|
||||
}
|
||||
```
|
||||
|
||||
允许且内容不需要变动
|
||||
|
||||
```
|
||||
{
|
||||
"reject": false,
|
||||
"unchange": true
|
||||
}
|
||||
```
|
||||
|
||||
允许且需要替换操作内容
|
||||
|
||||
```
|
||||
{
|
||||
"unchange": "false",
|
||||
"content": {
|
||||
... // 替换后的操作信息,格式必须和请求时的一致
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 操作类型
|
||||
|
||||
目前插件支持管理的操作类型有 `Login`、`NewProxy`、`Ping`、`NewWorkConn` 和 `NewUserConn`。
|
||||
|
||||
#### Login
|
||||
|
||||
用户登录操作信息
|
||||
|
||||
```
|
||||
{
|
||||
"content": {
|
||||
"version": <string>,
|
||||
"hostname": <string>,
|
||||
"os": <string>,
|
||||
"arch": <string>,
|
||||
"user": <string>,
|
||||
"timestamp": <int64>,
|
||||
"privilege_key": <string>,
|
||||
"run_id": <string>,
|
||||
"pool_count": <int>,
|
||||
"metas": map<string>string
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### NewProxy
|
||||
|
||||
创建代理的相关信息
|
||||
|
||||
```
|
||||
{
|
||||
"content": {
|
||||
"user": {
|
||||
"user": <string>,
|
||||
"metas": map<string>string
|
||||
},
|
||||
"proxy_name": <string>,
|
||||
"proxy_type": <string>,
|
||||
"use_encryption": <bool>,
|
||||
"use_compression": <bool>,
|
||||
"group": <string>,
|
||||
"group_key": <string>,
|
||||
|
||||
// tcp and udp only
|
||||
"remote_port": <int>,
|
||||
|
||||
// http and https only
|
||||
"custom_domains": []<string>,
|
||||
"subdomain": <string>,
|
||||
"locations": <string>,
|
||||
"http_user": <string>,
|
||||
"http_pwd": <string>,
|
||||
"host_header_rewrite": <string>,
|
||||
"headers": map<string>string,
|
||||
|
||||
"metas": map<string>string
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Ping
|
||||
|
||||
心跳相关信息
|
||||
|
||||
```
|
||||
{
|
||||
"content": {
|
||||
"user": {
|
||||
"user": <string>,
|
||||
"metas": map<string>string
|
||||
"run_id": <string>
|
||||
},
|
||||
"timestamp": <int64>,
|
||||
"privilege_key": <string>
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### NewWorkConn
|
||||
|
||||
新增 `frpc` 连接相关信息
|
||||
|
||||
```
|
||||
{
|
||||
"content": {
|
||||
"user": {
|
||||
"user": <string>,
|
||||
"metas": map<string>string
|
||||
"run_id": <string>
|
||||
},
|
||||
"run_id": <string>
|
||||
"timestamp": <int64>,
|
||||
"privilege_key": <string>
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### NewUserConn
|
||||
|
||||
新增 `proxy` 连接相关信息 (支持 `tcp`、`stcp`、`https` 和 `tcpmux` 协议)。
|
||||
|
||||
```
|
||||
{
|
||||
"content": {
|
||||
"user": {
|
||||
"user": <string>,
|
||||
"metas": map<string>string
|
||||
"run_id": <string>
|
||||
},
|
||||
"proxy_name": <string>,
|
||||
"proxy_type": <string>,
|
||||
"remote_addr": <string>
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### frps 中插件配置
|
||||
|
||||
```ini
|
||||
[common]
|
||||
bind_port = 7000
|
||||
|
||||
[plugin.user-manager]
|
||||
addr = 127.0.0.1:9000
|
||||
path = /handler
|
||||
ops = Login
|
||||
|
||||
[plugin.port-manager]
|
||||
addr = 127.0.0.1:9001
|
||||
path = /handler
|
||||
ops = NewProxy
|
||||
```
|
||||
|
||||
addr: 插件监听的网络地址。
|
||||
path: 插件监听的 HTTP 请求路径。
|
||||
ops: 插件需要处理的操作列表,多个 op 以英文逗号分隔。
|
||||
|
||||
### 元数据
|
||||
|
||||
为了减少 frps 的代码修改,同时提高管理插件的扩展能力,在 frpc 的配置文件中引入自定义元数据的概念。元数据会在调用 RPC 请求时发送给插件。
|
||||
|
||||
元数据以 `meta_` 开头,可以配置多个,元数据分为两种,一种配置在 `common` 下,一种配置在各个 proxy 中。
|
||||
|
||||
```
|
||||
# frpc.ini
|
||||
[common]
|
||||
server_addr = 127.0.0.1
|
||||
server_port = 7000
|
||||
user = fake
|
||||
meta_token = fake
|
||||
meta_version = 1.0.0
|
||||
|
||||
[ssh]
|
||||
type = tcp
|
||||
local_port = 22
|
||||
remote_port = 6000
|
||||
meta_id = 123
|
||||
```
|
@@ -1,14 +1,12 @@
|
||||
FROM alpine:3.12.0 AS temp
|
||||
FROM golang:1.20 AS building
|
||||
|
||||
COPY bin/frpc /tmp
|
||||
COPY . /building
|
||||
WORKDIR /building
|
||||
|
||||
RUN chmod -R 777 /tmp/frpc
|
||||
RUN make frpc
|
||||
|
||||
FROM alpine:3
|
||||
|
||||
FROM alpine:3.12.0
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY --from=temp /tmp/frpc /usr/bin
|
||||
COPY --from=building /building/bin/frpc /usr/bin/frpc
|
||||
|
||||
ENTRYPOINT ["/usr/bin/frpc"]
|
||||
|
@@ -1,14 +1,12 @@
|
||||
FROM alpine:3.12.0 AS temp
|
||||
FROM golang:1.20 AS building
|
||||
|
||||
COPY bin/frps /tmp
|
||||
COPY . /building
|
||||
WORKDIR /building
|
||||
|
||||
RUN chmod -R 777 /tmp/frps
|
||||
RUN make frps
|
||||
|
||||
FROM alpine:3
|
||||
|
||||
FROM alpine:3.12.0
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY --from=temp /tmp/frps /usr/bin
|
||||
COPY --from=building /building/bin/frps /usr/bin/frps
|
||||
|
||||
ENTRYPOINT ["/usr/bin/frps"]
|
||||
|
90
go.mod
90
go.mod
@@ -1,39 +1,77 @@
|
||||
module github.com/fatedier/frp
|
||||
|
||||
go 1.16
|
||||
go 1.20
|
||||
|
||||
require (
|
||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5
|
||||
github.com/coreos/go-oidc v2.2.1+incompatible
|
||||
github.com/coreos/go-oidc/v3 v3.4.0
|
||||
github.com/fatedier/beego v0.0.0-20171024143340-6c6a4f5bd5eb
|
||||
github.com/fatedier/golib v0.1.1-0.20200901083111-1f870741e185
|
||||
github.com/fatedier/golib v0.1.1-0.20220321042308-c306138b83ac
|
||||
github.com/fatedier/kcp-go v2.0.4-0.20190803094908-fe8645b0a904+incompatible
|
||||
github.com/go-playground/validator/v10 v10.6.1
|
||||
github.com/google/uuid v1.2.0
|
||||
github.com/go-playground/validator/v10 v10.11.0
|
||||
github.com/google/uuid v1.3.0
|
||||
github.com/gorilla/mux v1.8.0
|
||||
github.com/gorilla/websocket v1.4.2
|
||||
github.com/hashicorp/yamux v0.0.0-20210707203944-259a57b3608c
|
||||
github.com/klauspost/cpuid v1.2.0 // indirect
|
||||
github.com/klauspost/reedsolomon v1.9.1 // indirect
|
||||
github.com/leodido/go-urn v1.2.1 // indirect
|
||||
github.com/gorilla/websocket v1.5.0
|
||||
github.com/hashicorp/yamux v0.1.1
|
||||
github.com/onsi/ginkgo v1.16.4
|
||||
github.com/onsi/gomega v1.13.0
|
||||
github.com/pires/go-proxyproto v0.5.0
|
||||
github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35 // indirect
|
||||
github.com/prometheus/client_golang v1.11.0
|
||||
github.com/onsi/gomega v1.20.2
|
||||
github.com/pires/go-proxyproto v0.6.2
|
||||
github.com/prometheus/client_golang v1.13.0
|
||||
github.com/quic-go/quic-go v0.32.0
|
||||
github.com/rodaine/table v1.0.1
|
||||
github.com/spf13/cobra v1.1.3
|
||||
github.com/stretchr/testify v1.7.0
|
||||
github.com/templexxx/cpufeat v0.0.0-20170927014610-3794dfbfb047 // indirect
|
||||
github.com/templexxx/xor v0.0.0-20170926022130-0af8e873c554 // indirect
|
||||
github.com/tjfoc/gmsm v0.0.0-20171124023159-98aa888b79d8 // indirect
|
||||
github.com/xtaci/lossyconn v0.0.0-20190602105132-8df528c0c9ae // indirect
|
||||
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781
|
||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d
|
||||
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22 // indirect
|
||||
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba
|
||||
gopkg.in/ini.v1 v1.62.0
|
||||
gopkg.in/square/go-jose.v2 v2.4.1 // indirect
|
||||
k8s.io/apimachinery v0.21.2
|
||||
k8s.io/client-go v0.21.2
|
||||
golang.org/x/net v0.4.0
|
||||
golang.org/x/oauth2 v0.3.0
|
||||
golang.org/x/time v0.0.0-20220210224613-90d013bbcef8
|
||||
gopkg.in/ini.v1 v1.67.0
|
||||
k8s.io/apimachinery v0.25.0
|
||||
k8s.io/client-go v0.25.0
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/Azure/go-ntlmssp v0.0.0-20200615164410-66371956d46c // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.1.2 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/fsnotify/fsnotify v1.4.9 // indirect
|
||||
github.com/go-playground/locales v0.14.0 // indirect
|
||||
github.com/go-playground/universal-translator v0.18.0 // indirect
|
||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect
|
||||
github.com/golang/mock v1.6.0 // indirect
|
||||
github.com/golang/protobuf v1.5.2 // indirect
|
||||
github.com/golang/snappy v0.0.3 // indirect
|
||||
github.com/google/go-cmp v0.5.8 // indirect
|
||||
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.0.0 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.0.6 // indirect
|
||||
github.com/klauspost/reedsolomon v1.9.15 // indirect
|
||||
github.com/leodido/go-urn v1.2.1 // indirect
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect
|
||||
github.com/nxadm/tail v1.4.8 // indirect
|
||||
github.com/onsi/ginkgo/v2 v2.2.0 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/prometheus/client_model v0.2.0 // indirect
|
||||
github.com/prometheus/common v0.37.0 // indirect
|
||||
github.com/prometheus/procfs v0.8.0 // indirect
|
||||
github.com/quic-go/qtls-go1-18 v0.2.0 // indirect
|
||||
github.com/quic-go/qtls-go1-19 v0.2.0 // indirect
|
||||
github.com/quic-go/qtls-go1-20 v0.1.0 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
github.com/templexxx/cpufeat v0.0.0-20180724012125-cef66df7f161 // indirect
|
||||
github.com/templexxx/xor v0.0.0-20191217153810-f85b25db303b // indirect
|
||||
github.com/tjfoc/gmsm v1.4.1 // indirect
|
||||
golang.org/x/crypto v0.4.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20221205204356-47842c84f3db // indirect
|
||||
golang.org/x/mod v0.6.0 // indirect
|
||||
golang.org/x/sys v0.3.0 // indirect
|
||||
golang.org/x/text v0.5.0 // indirect
|
||||
golang.org/x/tools v0.2.0 // indirect
|
||||
google.golang.org/appengine v1.6.7 // indirect
|
||||
google.golang.org/protobuf v1.28.1 // indirect
|
||||
gopkg.in/square/go-jose.v2 v2.6.0 // indirect
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed // indirect
|
||||
)
|
||||
|
577
go.sum
577
go.sum
@@ -9,45 +9,68 @@ cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6T
|
||||
cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=
|
||||
cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
|
||||
cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc=
|
||||
cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk=
|
||||
cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
|
||||
cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
|
||||
cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
|
||||
cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI=
|
||||
cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk=
|
||||
cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg=
|
||||
cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8=
|
||||
cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0=
|
||||
cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY=
|
||||
cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM=
|
||||
cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY=
|
||||
cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ=
|
||||
cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI=
|
||||
cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4=
|
||||
cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc=
|
||||
cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA=
|
||||
cloud.google.com/go v0.100.2/go.mod h1:4Xra9TjzAeYHrl5+oeLlzbM2k3mjVhZh4UqTZ//w99A=
|
||||
cloud.google.com/go v0.102.0/go.mod h1:oWcCzKlqJ5zgHQt9YsaeTY9KzIvjyy0ArmiBUgpQ+nc=
|
||||
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
|
||||
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
|
||||
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
|
||||
cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
|
||||
cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
|
||||
cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
|
||||
cloud.google.com/go/compute v0.1.0/go.mod h1:GAesmwr110a34z04OlxYkATPBEfVhkymfTBXtfbBFow=
|
||||
cloud.google.com/go/compute v1.3.0/go.mod h1:cCZiE1NHEtai4wiufUhW8I8S1JKkAnhnQJWM7YD99wM=
|
||||
cloud.google.com/go/compute v1.5.0/go.mod h1:9SMHyhJlzhlkJqrPAc839t2BZFTSk6Jdj6mkzQJeu0M=
|
||||
cloud.google.com/go/compute v1.6.0/go.mod h1:T29tfhtVbq1wvAPo0E3+7vhgmkOYeXjhFvz/FMzPu0s=
|
||||
cloud.google.com/go/compute v1.6.1/go.mod h1:g85FgpzFvNULZ+S8AYq87axRKuf2Kh7deLqV/jJ3thU=
|
||||
cloud.google.com/go/compute v1.7.0/go.mod h1:435lt8av5oL9P3fv1OEzSbSUe+ybHXGMPQHHZWZxy9U=
|
||||
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
|
||||
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
|
||||
cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk=
|
||||
cloud.google.com/go/iam v0.3.0/go.mod h1:XzJPvDayI+9zsASAFO68Hk07u3z+f+JrT2xXNdp4bnY=
|
||||
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
|
||||
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
|
||||
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
|
||||
cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU=
|
||||
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
|
||||
cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
|
||||
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
|
||||
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
|
||||
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
|
||||
cloud.google.com/go/storage v1.22.1/go.mod h1:S8N1cAStu7BOeFfE8KAQzmyyLkK8p/vmRq6kuBTW58Y=
|
||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||
github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
|
||||
github.com/Azure/go-autorest/autorest v0.11.12/go.mod h1:eipySxLmqSyC5s5k1CLupqet0PSENBEDP93LQ9a8QYw=
|
||||
github.com/Azure/go-autorest/autorest/adal v0.9.5/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A=
|
||||
github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74=
|
||||
github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k=
|
||||
github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8=
|
||||
github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU=
|
||||
github.com/Azure/go-ntlmssp v0.0.0-20200615164410-66371956d46c h1:/IBSNwUN8+eKzUzbJPqhK839ygXJ82sde8x3ogr6R28=
|
||||
github.com/Azure/go-ntlmssp v0.0.0-20200615164410-66371956d46c/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
|
||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
|
||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
|
||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
|
||||
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
|
||||
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
|
||||
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
|
||||
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
|
||||
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/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||
@@ -55,18 +78,27 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r
|
||||
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
|
||||
github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
|
||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||
github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
|
||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
|
||||
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||
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/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||
github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI=
|
||||
github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
|
||||
github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
||||
github.com/coreos/go-oidc v2.2.1+incompatible h1:mh48q/BqXqgjVHpy2ZY7WnWAbenxRjsz9N1i1YxjHAk=
|
||||
github.com/coreos/go-oidc v2.2.1+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc=
|
||||
github.com/coreos/go-oidc/v3 v3.4.0 h1:xz7elHb/LDwm/ERpwHd+5nb7wFHL32rsr6bBOgaeu6g=
|
||||
github.com/coreos/go-oidc/v3 v3.4.0/go.mod h1:eHUXhZtXPQLgEaDrOVTgwbgmz1xGOkJNye6h3zkD2Pw=
|
||||
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
||||
@@ -77,20 +109,23 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
|
||||
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
|
||||
github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
|
||||
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
|
||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/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.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po=
|
||||
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
|
||||
github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
|
||||
github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
|
||||
github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
|
||||
github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
|
||||
github.com/fatedier/beego v0.0.0-20171024143340-6c6a4f5bd5eb h1:wCrNShQidLmvVWn/0PikGmpdP0vtQmnvyRg3ZBEhczw=
|
||||
github.com/fatedier/beego v0.0.0-20171024143340-6c6a4f5bd5eb/go.mod h1:wx3gB6dbIfBRcucp94PI9Bt3I0F2c/MyNEWuhzpWiwk=
|
||||
github.com/fatedier/golib v0.1.1-0.20200901083111-1f870741e185 h1:2p4W5xYizIYwhiGQgeHOQcRD2O84j0tjD40P6gUCRrk=
|
||||
github.com/fatedier/golib v0.1.1-0.20200901083111-1f870741e185/go.mod h1:MUs+IH/MGJNz5Cj2JVJBPZBKw2exON7LzO3HrJHmGiQ=
|
||||
github.com/fatedier/golib v0.1.1-0.20220321042308-c306138b83ac h1:td1FJwN/oz8+9GldeEm3YdBX0Husc0FSPywLesZxi4w=
|
||||
github.com/fatedier/golib v0.1.1-0.20220321042308-c306138b83ac/go.mod h1:fLV0TLwHqrnB/L3jbNl67Gn6PCLggDGHniX1wLrA2Qo=
|
||||
github.com/fatedier/kcp-go v2.0.4-0.20190803094908-fe8645b0a904+incompatible h1:ssXat9YXFvigNge/IkkZvFMn8yeYKFX+uI6wn2mLJ74=
|
||||
github.com/fatedier/kcp-go v2.0.4-0.20190803094908-fe8645b0a904+incompatible/go.mod h1:YpCOaxj7vvMThhIQ9AfTOPW2sfztQR5WDfs7AflSy4s=
|
||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
|
||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||
@@ -101,31 +136,25 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2
|
||||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
|
||||
github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0=
|
||||
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
||||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
|
||||
github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
|
||||
github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
|
||||
github.com/go-logr/logr v0.4.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
|
||||
github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg=
|
||||
github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
|
||||
github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc=
|
||||
github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8=
|
||||
github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo=
|
||||
github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
|
||||
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
|
||||
github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A=
|
||||
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||
github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q=
|
||||
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
|
||||
github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no=
|
||||
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
|
||||
github.com/go-playground/validator/v10 v10.6.1 h1:W6TRDXt4WcWp4c4nf/G+6BkGdhiIo0k417gfr+V6u4I=
|
||||
github.com/go-playground/validator/v10 v10.6.1/go.mod h1:xm76BBt941f7yWdGnI2DVPFFg1UK3YY04qifoXU3lOk=
|
||||
github.com/go-playground/locales v0.14.0 h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb8WugfUU=
|
||||
github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs=
|
||||
github.com/go-playground/universal-translator v0.18.0 h1:82dyy6p4OuJq4/CByFNOn/jYrnRPArHwAcmLoJZxyho=
|
||||
github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA=
|
||||
github.com/go-playground/validator/v10 v10.11.0 h1:0W+xRM511GY47Yy3bZUbJVitCNg2BOGlCyvTqsp/xIw=
|
||||
github.com/go-playground/validator/v10 v10.11.0/go.mod h1:i+3WkQ1FvaUjjxh1kSvIA4dMGDBiPU55YFDl0WbKdWU=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I=
|
||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
@@ -136,11 +165,17 @@ github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfb
|
||||
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
|
||||
github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
|
||||
github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8=
|
||||
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.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.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||
github.com/golang/protobuf v1.3.4/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.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
||||
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
||||
@@ -150,46 +185,71 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD
|
||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM=
|
||||
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
|
||||
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
|
||||
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/golang/snappy v0.0.3 h1:fHPg5GQYlCeLIPB9BZqMVR5nR9A+IM5zcgeTdjMYmLA=
|
||||
github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
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.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.1/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.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
|
||||
github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
|
||||
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
||||
github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
||||
github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk=
|
||||
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||
github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
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/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.2.0 h1:qJYtXnJRWmpe7m/3XlyhrsLrEURqHRM2kxzoxXqyUDs=
|
||||
github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.0.0-20220520183353-fd19c99a87aa/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8=
|
||||
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
||||
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
||||
github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
|
||||
github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0=
|
||||
github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM=
|
||||
github.com/googleapis/gax-go/v2 v2.2.0/go.mod h1:as02EH8zWkzwUoLbBaFeQ+arQaj/OthfcblKl4IGNaM=
|
||||
github.com/googleapis/gax-go/v2 v2.3.0/go.mod h1:b8LNqSzNabLiUpXKkY7HAR5jr6bIT99EXz9pXxye9YM=
|
||||
github.com/googleapis/gax-go/v2 v2.4.0/go.mod h1:XOTVJ59hdnfJLIP/dh8n5CGryZR2LxK9wbMD5+iXC6c=
|
||||
github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
|
||||
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
|
||||
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
|
||||
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
|
||||
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/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
|
||||
github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q=
|
||||
github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
|
||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
@@ -210,11 +270,11 @@ github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO
|
||||
github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
|
||||
github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
|
||||
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
|
||||
github.com/hashicorp/yamux v0.0.0-20210707203944-259a57b3608c h1:nqkErwUGfpZZMqj29WZ9U/wz2OpJVDuiokLhE/3Y7IQ=
|
||||
github.com/hashicorp/yamux v0.0.0-20210707203944-259a57b3608c/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ=
|
||||
github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE=
|
||||
github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
|
||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
||||
@@ -222,35 +282,32 @@ github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX
|
||||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
|
||||
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
|
||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
|
||||
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/klauspost/cpuid v1.2.0 h1:NMpwD2G9JSFOE1/TJjGSo5zG7Yb2bTe7eq1jH+irmeE=
|
||||
github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
|
||||
github.com/klauspost/reedsolomon v1.9.1 h1:kYrT1MlR4JH6PqOpC+okdb9CDTcwEC/BqpzK4WFyXL8=
|
||||
github.com/klauspost/reedsolomon v1.9.1/go.mod h1:CwCi+NUr9pqSVktrkN+Ondf06rkhYZ/pcNv7fu+8Un4=
|
||||
github.com/klauspost/cpuid/v2 v2.0.6 h1:dQ5ueTiftKxp0gyjKSx5+8BtPWkyQbd95m8Gys/RarI=
|
||||
github.com/klauspost/cpuid/v2 v2.0.6/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||
github.com/klauspost/reedsolomon v1.9.15 h1:g2erWKD2M6rgnPf89fCji6jNlhMKMdXcuNHMW1SYCIo=
|
||||
github.com/klauspost/reedsolomon v1.9.15/go.mod h1:eqPAcE7xar5CIzcdfwydOEdcmchAKAP/qs14y4GCBOk=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
|
||||
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
|
||||
github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w=
|
||||
github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
|
||||
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
|
||||
@@ -266,39 +323,32 @@ github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS4
|
||||
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
|
||||
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
||||
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
|
||||
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
|
||||
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
|
||||
github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
|
||||
github.com/onsi/ginkgo v1.16.2/go.mod h1:CObGmKUOKaSC0RjmoAK7tKyn4Azo5P2IWuoMnvwxz1E=
|
||||
github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc=
|
||||
github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
|
||||
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
|
||||
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/onsi/ginkgo/v2 v2.2.0 h1:3ZNA3L1c5FYDFTTxbFeVGGD8jYvjYauHD30YgLxVsNI=
|
||||
github.com/onsi/ginkgo/v2 v2.2.0/go.mod h1:MEH45j8TBi6u9BMogfbp0stKC5cdGjumZj5Y7AG4VIk=
|
||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
||||
github.com/onsi/gomega v1.13.0 h1:7lLHu94wT9Ij0o6EWWclhu0aOh32VxhkwEJvzuWPeak=
|
||||
github.com/onsi/gomega v1.13.0/go.mod h1:lRk9szgn8TxENtWd0Tp4c3wjlRfMTMH27I+3Je41yGY=
|
||||
github.com/onsi/gomega v1.20.2 h1:8uQq0zMgLEfa0vRrrBgaJF2gyW9Da9BmfGV+OyUzfkY=
|
||||
github.com/onsi/gomega v1.20.2/go.mod h1:iYAIXgPSaDHak0LCMA+AWBpIKBr8WZicMxnE8luStNc=
|
||||
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
||||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
|
||||
github.com/pires/go-proxyproto v0.5.0 h1:A4Jv4ZCaV3AFJeGh5mGwkz4iuWUYMlQ7IoO/GTuSuLo=
|
||||
github.com/pires/go-proxyproto v0.5.0/go.mod h1:Odh9VFOZJCf9G8cLW5o435Xf1J95Jw9Gw5rnCjcwzAY=
|
||||
github.com/pires/go-proxyproto v0.6.2 h1:KAZ7UteSOt6urjme6ZldyFm4wDe/z0ZUP0Yv0Dos0d8=
|
||||
github.com/pires/go-proxyproto v0.6.2/go.mod h1:Odh9VFOZJCf9G8cLW5o435Xf1J95Jw9Gw5rnCjcwzAY=
|
||||
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
@@ -306,14 +356,14 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
|
||||
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/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
|
||||
github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35 h1:J9b7z+QKAmPf4YLrFg6oQUotqHQeUNWwkvo7jZp1GLU=
|
||||
github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA=
|
||||
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
|
||||
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
|
||||
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
|
||||
github.com/prometheus/client_golang v1.11.0 h1:HNkLOAEQMIDv/K+04rukrLx6ch7msSRwf3/SASFAGtQ=
|
||||
github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
|
||||
github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY=
|
||||
github.com/prometheus/client_golang v1.13.0 h1:b71QUfeo5M8gq2+evJdTPfZhYMAU0uKPkyPJ7TPsloU=
|
||||
github.com/prometheus/client_golang v1.13.0/go.mod h1:vTeo+zgvILHsnnj/39Ou/1fPN5nJFOEMgftOUOmlvYQ=
|
||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
@@ -323,19 +373,35 @@ github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7q
|
||||
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
|
||||
github.com/prometheus/common v0.26.0 h1:iMAkS2TDoNWnKM+Kopnx/8tnEStIfpYA0ur0xQzzhMQ=
|
||||
github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc=
|
||||
github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls=
|
||||
github.com/prometheus/common v0.37.0 h1:ccBbHCgIiT9uSoFY0vX8H3zsNR5eLt17/RQLUvn8pXE=
|
||||
github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA=
|
||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
|
||||
github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4=
|
||||
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
|
||||
github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
|
||||
github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo=
|
||||
github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4=
|
||||
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
||||
github.com/quic-go/qtls-go1-18 v0.2.0 h1:5ViXqBZ90wpUcZS0ge79rf029yx0dYB0McyPJwqqj7U=
|
||||
github.com/quic-go/qtls-go1-18 v0.2.0/go.mod h1:moGulGHK7o6O8lSPSZNoOwcLvJKJ85vVNc7oJFD65bc=
|
||||
github.com/quic-go/qtls-go1-19 v0.2.0 h1:Cvn2WdhyViFUHoOqK52i51k4nDX8EwIh5VJiVM4nttk=
|
||||
github.com/quic-go/qtls-go1-19 v0.2.0/go.mod h1:ySOI96ew8lnoKPtSqx2BlI5wCpUVPT05RMAlajtnyOI=
|
||||
github.com/quic-go/qtls-go1-20 v0.1.0 h1:d1PK3ErFy9t7zxKsG3NXBJXZjp/kMLoIb3y/kV54oAI=
|
||||
github.com/quic-go/qtls-go1-20 v0.1.0/go.mod h1:JKtK6mjbAVcUTN/9jZpvLbGxvdWIKS8uT7EiStoU1SM=
|
||||
github.com/quic-go/quic-go v0.32.0 h1:lY02md31s1JgPiiyfqJijpu/UX/Iun304FI3yUqX7tA=
|
||||
github.com/quic-go/quic-go v0.32.0/go.mod h1:/fCsKANhQIeD5l76c2JFU+07gVE3KaA0FP+0zMWwfwo=
|
||||
github.com/rodaine/table v1.0.1 h1:U/VwCnUxlVYxw8+NJiLIuCxA/xa6jL38MY3FYysVWWQ=
|
||||
github.com/rodaine/table v1.0.1/go.mod h1:UVEtfBsflpeEcD56nF4F5AocNFta0ZuolpSVdPtlmP4=
|
||||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
||||
github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8=
|
||||
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
|
||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
||||
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
|
||||
@@ -343,9 +409,7 @@ github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeV
|
||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||
github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
|
||||
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
|
||||
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||
@@ -355,14 +419,12 @@ github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkU
|
||||
github.com/spf13/cobra v1.1.3 h1:xghbfqPkxzxP3C/f3n5DdpAbdKLj4ZE4BWQI362l53M=
|
||||
github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo=
|
||||
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
|
||||
github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
@@ -371,38 +433,43 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
|
||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
|
||||
github.com/templexxx/cpufeat v0.0.0-20170927014610-3794dfbfb047 h1:K+jtWCOuZgCra7eXZ/VWn2FbJmrA/D058mTXhh2rq+8=
|
||||
github.com/templexxx/cpufeat v0.0.0-20170927014610-3794dfbfb047/go.mod h1:wM7WEvslTq+iOEAMDLSzhVuOt5BRZ05WirO+b09GHQU=
|
||||
github.com/templexxx/xor v0.0.0-20170926022130-0af8e873c554 h1:pexgSe+JCFuxG+uoMZLO+ce8KHtdHGhst4cs6rw3gmk=
|
||||
github.com/templexxx/xor v0.0.0-20170926022130-0af8e873c554/go.mod h1:5XA7W9S6mni3h5uvOC75dA3m9CCCaS83lltmc0ukdi4=
|
||||
github.com/tjfoc/gmsm v0.0.0-20171124023159-98aa888b79d8 h1:6CNSDqI1wiE+JqyOy5Qt/yo/DoNI2/QmmOZeiCid2Nw=
|
||||
github.com/tjfoc/gmsm v0.0.0-20171124023159-98aa888b79d8/go.mod h1:XxO4hdhhrzAd+G4CjDqaOkd0hUzmtPR/d3EiBBMn/wc=
|
||||
github.com/templexxx/cpufeat v0.0.0-20180724012125-cef66df7f161 h1:89CEmDvlq/F7SJEOqkIdNDGJXrQIhuIx9D2DBXjavSU=
|
||||
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/go.mod h1:5XA7W9S6mni3h5uvOC75dA3m9CCCaS83lltmc0ukdi4=
|
||||
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/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
||||
github.com/xtaci/lossyconn v0.0.0-20190602105132-8df528c0c9ae h1:J0GxkO96kL4WF+AIT3M4mfUVinOCPgf2uUWYFUzN0sM=
|
||||
github.com/xtaci/lossyconn v0.0.0-20190602105132-8df528c0c9ae/go.mod h1:gXtu8J62kEgmN++bm9BVICuT/e8yiLI2KFobd/TRFsE=
|
||||
github.com/xtaci/lossyconn v0.0.0-20200209145036-adba10fffc37 h1:EWU6Pktpas0n8lLQwDsRyZfmkPeRbdgPtW609es+/9E=
|
||||
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
||||
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
||||
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
|
||||
go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
|
||||
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
|
||||
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
||||
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190228161510-8dd112bcdc25/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-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/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-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83 h1:/ZScEX8SfEmUGRHs0gxpqteO5nfNW6axyZbBdw9A12g=
|
||||
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||
golang.org/x/crypto v0.0.0-20201012173705-84dcc777aaee/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.4.0 h1:UVQgzMY87xqpKNgb+kDsll2Igd33HszWHFLmpaRMq/8=
|
||||
golang.org/x/crypto v0.4.0/go.mod h1:3quD/ATkf6oY+rnes5c3ExXTbLc8mueNue5/DoinL80=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||
@@ -413,6 +480,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
|
||||
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
|
||||
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
|
||||
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/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
@@ -425,6 +494,8 @@ golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHl
|
||||
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
|
||||
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
|
||||
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
|
||||
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
||||
@@ -433,6 +504,11 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB
|
||||
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.6.0 h1:b9gGHsz9/HhJ3HF5DHQytPpuwocVTChQJK3AvoLRD5I=
|
||||
golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI=
|
||||
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-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
@@ -442,7 +518,6 @@ golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73r
|
||||
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/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-20190228165749-92fc7df08ae7/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-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
@@ -450,8 +525,8 @@ golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn
|
||||
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/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-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
@@ -459,26 +534,71 @@ golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLL
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20210224082022-3d97a244fca7/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781 h1:DzZ89McO9/gWPsQXS/FVKAlG02ZjaQ6AlZRBimEYOd0=
|
||||
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
|
||||
golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
|
||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||
golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/net v0.0.0-20220325170049-de3da57026de/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/net v0.0.0-20220412020605-290c469a71a5/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.0.0-20220826154423-83b083e8dc8b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
|
||||
golang.org/x/net v0.4.0 h1:Q5QPcMlvfxFTAPV0+07Xz/MpK9NTXu2VDUuy0FeMfaU=
|
||||
golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d h1:TzXSXBo42m9gQenoE3b9BGiEpg5IG2JkU5FkPIawgtw=
|
||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
|
||||
golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
|
||||
golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
|
||||
golang.org/x/oauth2 v0.0.0-20220608161450-d0670ef3b1eb/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE=
|
||||
golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg=
|
||||
golang.org/x/oauth2 v0.3.0 h1:6l90koy8/LaBLmLu8jpHeHexzMwEita0zFfYlggy2F8=
|
||||
golang.org/x/oauth2 v0.3.0/go.mod h1:rQrIauxkUhJ6CuwEXwymO2/eh4xz2ZWF1nBkcxS+tGk=
|
||||
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-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/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-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/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-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/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-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
@@ -493,13 +613,11 @@ golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@@ -511,33 +629,72 @@ golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/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-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/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-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22 h1:RqytpXGR1iVNX7psjB3ff8y7sNFinVFvkx1c8SjBkio=
|
||||
golang.org/x/sys v0.0.0-20210603125802-9665404d3644/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-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220328115105-d36c6a25d886/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220502124256-b6088ccd6cba/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/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-20220610221304-9f5ed59c137d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.3.0 h1:w8ZOecv6NaNa/zC8944JTU3vz4u6Lagfk4RPQxv92NQ=
|
||||
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/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.1-0.20180807135948-17ff2d5776d2/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.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
|
||||
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.5.0 h1:OLmvp0KP+FVG99Ct/qFiL/Fhk4zp4QQnZ7b2U+5piUM=
|
||||
golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba h1:O8mE0/t419eoIwhTFpKVkHiTs/Igowgfkj25AcZrtiE=
|
||||
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44=
|
||||
golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/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=
|
||||
@@ -550,7 +707,6 @@ golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBn
|
||||
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
@@ -571,15 +727,38 @@ golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapK
|
||||
golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
|
||||
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
|
||||
golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
|
||||
golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE=
|
||||
golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
|
||||
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.2.0 h1:G6AHpWxTMGY1KyEYoAQ5WTtIekUUvDNjan3ugu60JvE=
|
||||
golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA=
|
||||
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-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
|
||||
golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
|
||||
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
|
||||
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
|
||||
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
|
||||
@@ -589,13 +768,44 @@ google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsb
|
||||
google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
||||
google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||
google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||
google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||
google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||
google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||
google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
|
||||
google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
|
||||
google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
|
||||
google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
|
||||
google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg=
|
||||
google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE=
|
||||
google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8=
|
||||
google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU=
|
||||
google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94=
|
||||
google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo=
|
||||
google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4=
|
||||
google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw=
|
||||
google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU=
|
||||
google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k=
|
||||
google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE=
|
||||
google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE=
|
||||
google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI=
|
||||
google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I=
|
||||
google.golang.org/api v0.63.0/go.mod h1:gs4ij2ffTRXwuzzgJl/56BdwJaA194ijkfn++9tDuPo=
|
||||
google.golang.org/api v0.67.0/go.mod h1:ShHKP8E60yPsKNw/w8w+VYaj9H6buA5UqDp8dhbQZ6g=
|
||||
google.golang.org/api v0.70.0/go.mod h1:Bs4ZM2HGifEvXwd50TtW70ovgJffJYw2oRCOFU/SkfA=
|
||||
google.golang.org/api v0.71.0/go.mod h1:4PyU6e6JogV1f9eA4voyrTY2batOLdgZ5qZ5HOCc4j8=
|
||||
google.golang.org/api v0.74.0/go.mod h1:ZpfMZOVRMywNyvJFeqL9HRWBgAuRfSjJFpe9QtRRyDs=
|
||||
google.golang.org/api v0.75.0/go.mod h1:pU9QmyHLnzlpar1Mjt4IbapUCy8J+6HD6GeELN69ljA=
|
||||
google.golang.org/api v0.78.0/go.mod h1:1Sg78yoMLOhlQTeF+ARBoytAcH1NNyyl390YMy6rKmw=
|
||||
google.golang.org/api v0.80.0/go.mod h1:xY3nI94gbvBrE0J6NHXhxOmW97HG7Khjkku6AFB3Hyg=
|
||||
google.golang.org/api v0.84.0/go.mod h1:NTsGnUFJMYROtiquksZHBWtHfeMC7iYthki7Eq3pa8o=
|
||||
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.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
|
||||
google.golang.org/appengine v1.6.5 h1:tycE03LOZYQNhDpS27tcQdAzLCVMaj7QT2SXxebnpCM=
|
||||
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
|
||||
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
@@ -613,15 +823,99 @@ google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvx
|
||||
google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA=
|
||||
google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=
|
||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
||||
google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
|
||||
google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20210329143202-679c6ae281ee/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A=
|
||||
google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A=
|
||||
google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A=
|
||||
google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
|
||||
google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
|
||||
google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
|
||||
google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24=
|
||||
google.golang.org/genproto v0.0.0-20210713002101-d411969a0d9a/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k=
|
||||
google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k=
|
||||
google.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48=
|
||||
google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48=
|
||||
google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w=
|
||||
google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
|
||||
google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
|
||||
google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
|
||||
google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
|
||||
google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
|
||||
google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||
google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||
google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||
google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||
google.golang.org/genproto v0.0.0-20211221195035-429b39de9b1c/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||
google.golang.org/genproto v0.0.0-20220126215142-9970aeb2e350/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||
google.golang.org/genproto v0.0.0-20220207164111-0872dc986b00/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||
google.golang.org/genproto v0.0.0-20220218161850-94dd64e39d7c/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
|
||||
google.golang.org/genproto v0.0.0-20220222213610-43724f9ea8cf/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
|
||||
google.golang.org/genproto v0.0.0-20220304144024-325a89244dc8/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
|
||||
google.golang.org/genproto v0.0.0-20220310185008-1973136f34c6/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
|
||||
google.golang.org/genproto v0.0.0-20220324131243-acbaeb5b85eb/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E=
|
||||
google.golang.org/genproto v0.0.0-20220407144326-9054f6ed7bac/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
|
||||
google.golang.org/genproto v0.0.0-20220413183235-5e96e2839df9/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
|
||||
google.golang.org/genproto v0.0.0-20220414192740-2d67ff6cf2b4/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
|
||||
google.golang.org/genproto v0.0.0-20220421151946-72621c1f0bd3/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
|
||||
google.golang.org/genproto v0.0.0-20220429170224-98d788798c3e/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
|
||||
google.golang.org/genproto v0.0.0-20220505152158-f39f71e6c8f3/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4=
|
||||
google.golang.org/genproto v0.0.0-20220518221133-4f43b3371335/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4=
|
||||
google.golang.org/genproto v0.0.0-20220523171625-347a074981d8/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4=
|
||||
google.golang.org/genproto v0.0.0-20220608133413-ed9918b62aac/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA=
|
||||
google.golang.org/genproto v0.0.0-20220616135557-88e70c0c3a90/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
|
||||
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
|
||||
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
|
||||
google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||
google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||
google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||
google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
|
||||
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
|
||||
google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8=
|
||||
google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
||||
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
||||
google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
||||
google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
|
||||
google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
|
||||
google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
|
||||
google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=
|
||||
google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=
|
||||
google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
|
||||
google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
|
||||
google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
|
||||
google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ=
|
||||
google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
|
||||
google.golang.org/grpc v1.46.2/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
|
||||
google.golang.org/grpc v1.47.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
|
||||
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
@@ -630,57 +924,56 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi
|
||||
google.golang.org/protobuf v1.22.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.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
|
||||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk=
|
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
|
||||
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
|
||||
gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/ini.v1 v1.62.0 h1:duBzk771uxoUuOlyRLkHsygud9+5lrlGjdFBb4mSKDU=
|
||||
gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
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/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
|
||||
gopkg.in/square/go-jose.v2 v2.4.1 h1:H0TmLt7/KmzlrDOpa1F+zr0Tk90PbJYBfsVUmRLrf9Y=
|
||||
gopkg.in/square/go-jose.v2 v2.4.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
|
||||
gopkg.in/square/go-jose.v2 v2.6.0 h1:NGk74WTnPKBNUhNzQX7PYcTLUjoq7mzKk2OKbvwk2iI=
|
||||
gopkg.in/square/go-jose.v2 v2.6.0/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/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.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
||||
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||
k8s.io/api v0.21.2/go.mod h1:Lv6UGJZ1rlMI1qusN8ruAp9PUBFyBwpEHAdG24vIsiU=
|
||||
k8s.io/apimachinery v0.21.2 h1:vezUc/BHqWlQDnZ+XkrpXSmnANSLbpnlpwo0Lhk0gpc=
|
||||
k8s.io/apimachinery v0.21.2/go.mod h1:CdTY8fU/BlvAbJ2z/8kBwimGki5Zp8/fbVuLY8gJumM=
|
||||
k8s.io/client-go v0.21.2 h1:Q1j4L/iMN4pTw6Y4DWppBoUxgKO8LbffEMVEV00MUp0=
|
||||
k8s.io/client-go v0.21.2/go.mod h1:HdJ9iknWpbl3vMGtib6T2PyI/VYxiZfq936WNVHBRrA=
|
||||
k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
|
||||
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||
k8s.io/apimachinery v0.25.0 h1:MlP0r6+3XbkUG2itd6vp3oxbtdQLQI94fD5gCS+gnoU=
|
||||
k8s.io/apimachinery v0.25.0/go.mod h1:qMx9eAk0sZQGsXGu86fab8tZdffHbwUfsvzqKn4mfB0=
|
||||
k8s.io/client-go v0.25.0 h1:CVWIaCETLMBNiTUta3d5nzRbXvY5Hy9Dpl+VvREpu5E=
|
||||
k8s.io/client-go v0.25.0/go.mod h1:lxykvypVfKilxhTklov0wz1FoaUZ8X4EwbhS6rpRfN8=
|
||||
k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE=
|
||||
k8s.io/klog/v2 v2.8.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec=
|
||||
k8s.io/kube-openapi v0.0.0-20210305001622-591a79e4bda7/go.mod h1:wXW5VT87nVfh/iLV8FpR2uDvrFyomxbtb1KivDbvPTE=
|
||||
k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
|
||||
k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed h1:jAne/RjBTyawwAy0utX5eqigAwz/lQhTmy+Hr/Cpue4=
|
||||
k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
|
||||
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
||||
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
||||
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw=
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.1.0/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw=
|
||||
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
|
||||
|
@@ -5,7 +5,7 @@ ROOT=$(unset CDPATH && cd $(dirname "${BASH_SOURCE[0]}")/.. && pwd)
|
||||
which ginkgo &> /dev/null
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "ginkgo not found, try to install..."
|
||||
go install github.com/onsi/ginkgo/ginkgo@latest
|
||||
go install github.com/onsi/ginkgo/ginkgo@v1.16.5
|
||||
fi
|
||||
|
||||
debug=false
|
||||
|
@@ -15,7 +15,7 @@ rm -rf ./release/packages
|
||||
mkdir -p ./release/packages
|
||||
|
||||
os_all='linux windows darwin freebsd'
|
||||
arch_all='386 amd64 arm arm64 mips64 mips64le mips mipsle'
|
||||
arch_all='386 amd64 arm arm64 mips64 mips64le mips mipsle riscv64'
|
||||
|
||||
cd ./release
|
||||
|
||||
|
@@ -18,10 +18,10 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/fatedier/frp/pkg/msg"
|
||||
|
||||
"github.com/coreos/go-oidc"
|
||||
"github.com/coreos/go-oidc/v3/oidc"
|
||||
"golang.org/x/oauth2/clientcredentials"
|
||||
|
||||
"github.com/fatedier/frp/pkg/msg"
|
||||
)
|
||||
|
||||
type OidcClientConfig struct {
|
||||
@@ -34,20 +34,30 @@ type OidcClientConfig struct {
|
||||
// is "".
|
||||
OidcClientSecret string `ini:"oidc_client_secret" json:"oidc_client_secret"`
|
||||
// OidcAudience specifies the audience of the token in OIDC authentication
|
||||
//if AuthenticationMethod == "oidc". By default, this value is "".
|
||||
// if AuthenticationMethod == "oidc". By default, this value is "".
|
||||
OidcAudience string `ini:"oidc_audience" json:"oidc_audience"`
|
||||
// OidcScope specifies the scope of the token in OIDC authentication
|
||||
// if AuthenticationMethod == "oidc". By default, this value is "".
|
||||
OidcScope string `ini:"oidc_scope" json:"oidc_scope"`
|
||||
// OidcTokenEndpointURL specifies the URL which implements OIDC Token Endpoint.
|
||||
// It will be used to get an OIDC token if AuthenticationMethod == "oidc".
|
||||
// By default, this value is "".
|
||||
OidcTokenEndpointURL string `ini:"oidc_token_endpoint_url" json:"oidc_token_endpoint_url"`
|
||||
|
||||
// OidcAdditionalEndpointParams specifies additional parameters to be sent
|
||||
// this field will be transfer to map[string][]string in OIDC token generator
|
||||
// The field will be set by prefix "oidc_additional_"
|
||||
OidcAdditionalEndpointParams map[string]string `ini:"-" json:"oidc_additional_endpoint_params"`
|
||||
}
|
||||
|
||||
func getDefaultOidcClientConf() OidcClientConfig {
|
||||
return OidcClientConfig{
|
||||
OidcClientID: "",
|
||||
OidcClientSecret: "",
|
||||
OidcAudience: "",
|
||||
OidcTokenEndpointURL: "",
|
||||
OidcClientID: "",
|
||||
OidcClientSecret: "",
|
||||
OidcAudience: "",
|
||||
OidcScope: "",
|
||||
OidcTokenEndpointURL: "",
|
||||
OidcAdditionalEndpointParams: make(map[string]string),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,11 +98,21 @@ type OidcAuthProvider struct {
|
||||
}
|
||||
|
||||
func NewOidcAuthSetter(baseCfg BaseConfig, cfg OidcClientConfig) *OidcAuthProvider {
|
||||
eps := make(map[string][]string)
|
||||
for k, v := range cfg.OidcAdditionalEndpointParams {
|
||||
eps[k] = []string{v}
|
||||
}
|
||||
|
||||
if cfg.OidcAudience != "" {
|
||||
eps["audience"] = []string{cfg.OidcAudience}
|
||||
}
|
||||
|
||||
tokenGenerator := &clientcredentials.Config{
|
||||
ClientID: cfg.OidcClientID,
|
||||
ClientSecret: cfg.OidcClientSecret,
|
||||
Scopes: []string{cfg.OidcAudience},
|
||||
TokenURL: cfg.OidcTokenEndpointURL,
|
||||
ClientID: cfg.OidcClientID,
|
||||
ClientSecret: cfg.OidcClientSecret,
|
||||
Scopes: []string{cfg.OidcScope},
|
||||
TokenURL: cfg.OidcTokenEndpointURL,
|
||||
EndpointParams: eps,
|
||||
}
|
||||
|
||||
return &OidcAuthProvider{
|
||||
|
@@ -20,10 +20,10 @@ import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"gopkg.in/ini.v1"
|
||||
|
||||
"github.com/fatedier/frp/pkg/auth"
|
||||
"github.com/fatedier/frp/pkg/util/util"
|
||||
|
||||
"gopkg.in/ini.v1"
|
||||
)
|
||||
|
||||
// ClientCommonConf contains information for a client service. It is
|
||||
@@ -38,6 +38,15 @@ type ClientCommonConf struct {
|
||||
// ServerPort specifies the port to connect to the server on. By default,
|
||||
// this value is 7000.
|
||||
ServerPort int `ini:"server_port" json:"server_port"`
|
||||
// The maximum amount of time a dial to server will wait for a connect to complete.
|
||||
DialServerTimeout int64 `ini:"dial_server_timeout" json:"dial_server_timeout"`
|
||||
// DialServerKeepAlive specifies the interval between keep-alive probes for an active network connection between frpc and frps.
|
||||
// If negative, keep-alive probes are disabled.
|
||||
DialServerKeepAlive int64 `ini:"dial_server_keepalive" json:"dial_server_keepalive"`
|
||||
// ConnectServerLocalIP specifies the address of the client bind when it connect to server.
|
||||
// By default, this value is empty.
|
||||
// this value only use in TCP/Websocket protocol. Not support in KCP protocol.
|
||||
ConnectServerLocalIP string `ini:"connect_server_local_ip" json:"connect_server_local_ip"`
|
||||
// HTTPProxy specifies a proxy address to connect to the server through. If
|
||||
// this value is "", the server will be connected to directly. By default,
|
||||
// this value is read from the "http_proxy" environment variable.
|
||||
@@ -86,6 +95,9 @@ type ClientCommonConf struct {
|
||||
// the server must have TCP multiplexing enabled as well. By default, this
|
||||
// value is true.
|
||||
TCPMux bool `ini:"tcp_mux" json:"tcp_mux"`
|
||||
// TCPMuxKeepaliveInterval specifies the keep alive interval for TCP stream multipler.
|
||||
// If TCPMux is true, heartbeat of application layer is unnecessary because it can only rely on heartbeat in TCPMux.
|
||||
TCPMuxKeepaliveInterval int64 `ini:"tcp_mux_keepalive_interval" json:"tcp_mux_keepalive_interval"`
|
||||
// User specifies a prefix for proxy names to distinguish them from other
|
||||
// clients. If this value is not "", proxy names will automatically be
|
||||
// changed to "{user}.{proxy_name}". By default, this value is "".
|
||||
@@ -101,11 +113,15 @@ type ClientCommonConf struct {
|
||||
// all supplied proxies are enabled. By default, this value is an empty
|
||||
// set.
|
||||
Start []string `ini:"start" json:"start"`
|
||||
//Start map[string]struct{} `json:"start"`
|
||||
// Start map[string]struct{} `json:"start"`
|
||||
// Protocol specifies the protocol to use when interacting with the server.
|
||||
// Valid values are "tcp", "kcp" and "websocket". By default, this value
|
||||
// Valid values are "tcp", "kcp", "quic" and "websocket". By default, this value
|
||||
// is "tcp".
|
||||
Protocol string `ini:"protocol" json:"protocol"`
|
||||
// QUIC protocol options
|
||||
QUICKeepalivePeriod int `ini:"quic_keepalive_period" json:"quic_keepalive_period" validate:"gte=0"`
|
||||
QUICMaxIdleTimeout int `ini:"quic_max_idle_timeout" json:"quic_max_idle_timeout" validate:"gte=0"`
|
||||
QUICMaxIncomingStreams int `ini:"quic_max_incoming_streams" json:"quic_max_incoming_streams" validate:"gte=0"`
|
||||
// TLSEnable specifies whether or not TLS should be used when communicating
|
||||
// with the server. If "tls_cert_file" and "tls_key_file" are valid,
|
||||
// client will load the supplied tls configuration.
|
||||
@@ -121,7 +137,7 @@ type ClientCommonConf struct {
|
||||
// It only works when "tls_enable" is valid and tls configuration of server
|
||||
// has been specified.
|
||||
TLSTrustedCaFile string `ini:"tls_trusted_ca_file" json:"tls_trusted_ca_file"`
|
||||
// TLSServerName specifices the custom server name of tls certificate. By
|
||||
// TLSServerName specifies the custom server name of tls certificate. By
|
||||
// default, server name if same to ServerAddr.
|
||||
TLSServerName string `ini:"tls_server_name" json:"tls_server_name"`
|
||||
// By default, frpc will connect frps with first custom byte if tls is enabled.
|
||||
@@ -129,11 +145,11 @@ type ClientCommonConf struct {
|
||||
DisableCustomTLSFirstByte bool `ini:"disable_custom_tls_first_byte" json:"disable_custom_tls_first_byte"`
|
||||
// HeartBeatInterval specifies at what interval heartbeats are sent to the
|
||||
// server, in seconds. It is not recommended to change this value. By
|
||||
// default, this value is 30.
|
||||
// default, this value is 30. Set negative value to disable it.
|
||||
HeartbeatInterval int64 `ini:"heartbeat_interval" json:"heartbeat_interval"`
|
||||
// HeartBeatTimeout specifies the maximum allowed heartbeat response delay
|
||||
// before the connection is terminated, in seconds. It is not recommended
|
||||
// to change this value. By default, this value is 90.
|
||||
// to change this value. By default, this value is 90. Set negative value to disable it.
|
||||
HeartbeatTimeout int64 `ini:"heartbeat_timeout" json:"heartbeat_timeout"`
|
||||
// Client meta info
|
||||
Metas map[string]string `ini:"-" json:"metas"`
|
||||
@@ -142,41 +158,39 @@ type ClientCommonConf struct {
|
||||
UDPPacketSize int64 `ini:"udp_packet_size" json:"udp_packet_size"`
|
||||
// Include other config files for proxies.
|
||||
IncludeConfigFiles []string `ini:"includes" json:"includes"`
|
||||
// Enable golang pprof handlers in admin listener.
|
||||
// Admin port must be set first.
|
||||
PprofEnable bool `ini:"pprof_enable" json:"pprof_enable"`
|
||||
}
|
||||
|
||||
// GetDefaultClientConf returns a client configuration with default values.
|
||||
func GetDefaultClientConf() ClientCommonConf {
|
||||
return ClientCommonConf{
|
||||
ClientConfig: auth.GetDefaultClientConf(),
|
||||
ServerAddr: "0.0.0.0",
|
||||
ServerPort: 7000,
|
||||
HTTPProxy: os.Getenv("http_proxy"),
|
||||
LogFile: "console",
|
||||
LogWay: "console",
|
||||
LogLevel: "info",
|
||||
LogMaxDays: 3,
|
||||
DisableLogColor: false,
|
||||
AdminAddr: "127.0.0.1",
|
||||
AdminPort: 0,
|
||||
AdminUser: "",
|
||||
AdminPwd: "",
|
||||
AssetsDir: "",
|
||||
PoolCount: 1,
|
||||
TCPMux: true,
|
||||
User: "",
|
||||
DNSServer: "",
|
||||
LoginFailExit: true,
|
||||
Start: make([]string, 0),
|
||||
Protocol: "tcp",
|
||||
TLSEnable: false,
|
||||
TLSCertFile: "",
|
||||
TLSKeyFile: "",
|
||||
TLSTrustedCaFile: "",
|
||||
HeartbeatInterval: 30,
|
||||
HeartbeatTimeout: 90,
|
||||
Metas: make(map[string]string),
|
||||
UDPPacketSize: 1500,
|
||||
IncludeConfigFiles: make([]string, 0),
|
||||
ClientConfig: auth.GetDefaultClientConf(),
|
||||
ServerAddr: "0.0.0.0",
|
||||
ServerPort: 7000,
|
||||
DialServerTimeout: 10,
|
||||
DialServerKeepAlive: 7200,
|
||||
HTTPProxy: os.Getenv("http_proxy"),
|
||||
LogFile: "console",
|
||||
LogWay: "console",
|
||||
LogLevel: "info",
|
||||
LogMaxDays: 3,
|
||||
AdminAddr: "127.0.0.1",
|
||||
PoolCount: 1,
|
||||
TCPMux: true,
|
||||
TCPMuxKeepaliveInterval: 60,
|
||||
LoginFailExit: true,
|
||||
Start: make([]string, 0),
|
||||
Protocol: "tcp",
|
||||
QUICKeepalivePeriod: 10,
|
||||
QUICMaxIdleTimeout: 30,
|
||||
QUICMaxIncomingStreams: 100000,
|
||||
HeartbeatInterval: 30,
|
||||
HeartbeatTimeout: 90,
|
||||
Metas: make(map[string]string),
|
||||
UDPPacketSize: 1500,
|
||||
IncludeConfigFiles: make([]string, 0),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -189,15 +203,13 @@ func (cfg *ClientCommonConf) Complete() {
|
||||
}
|
||||
|
||||
func (cfg *ClientCommonConf) Validate() error {
|
||||
if cfg.HeartbeatInterval <= 0 {
|
||||
return fmt.Errorf("invalid heartbeat_interval")
|
||||
if cfg.HeartbeatTimeout > 0 && cfg.HeartbeatInterval > 0 {
|
||||
if cfg.HeartbeatTimeout < cfg.HeartbeatInterval {
|
||||
return fmt.Errorf("invalid heartbeat_timeout, heartbeat_timeout is less than heartbeat_interval")
|
||||
}
|
||||
}
|
||||
|
||||
if cfg.HeartbeatTimeout < cfg.HeartbeatInterval {
|
||||
return fmt.Errorf("invalid heartbeat_timeout, heartbeat_timeout is less than heartbeat_interval")
|
||||
}
|
||||
|
||||
if cfg.TLSEnable == false {
|
||||
if !cfg.TLSEnable {
|
||||
if cfg.TLSCertFile != "" {
|
||||
fmt.Println("WARNING! tls_cert_file is invalid when tls_enable is false")
|
||||
}
|
||||
@@ -211,7 +223,7 @@ func (cfg *ClientCommonConf) Validate() error {
|
||||
}
|
||||
}
|
||||
|
||||
if cfg.Protocol != "tcp" && cfg.Protocol != "kcp" && cfg.Protocol != "websocket" {
|
||||
if cfg.Protocol != "tcp" && cfg.Protocol != "kcp" && cfg.Protocol != "websocket" && cfg.Protocol != "quic" {
|
||||
return fmt.Errorf("invalid protocol")
|
||||
}
|
||||
|
||||
@@ -252,6 +264,8 @@ func UnmarshalClientConfFromIni(source interface{}) (ClientCommonConf, error) {
|
||||
}
|
||||
|
||||
common.Metas = GetMapWithoutPrefix(s.KeysHash(), "meta_")
|
||||
common.ClientConfig.OidcAdditionalEndpointParams = GetMapWithoutPrefix(s.KeysHash(), "oidc_additional_")
|
||||
|
||||
return common, nil
|
||||
}
|
||||
|
||||
@@ -262,7 +276,6 @@ func LoadAllProxyConfsFromIni(
|
||||
source interface{},
|
||||
start []string,
|
||||
) (map[string]ProxyConf, map[string]VisitorConf, error) {
|
||||
|
||||
f, err := ini.LoadSources(ini.LoadOptions{
|
||||
Insensitive: false,
|
||||
InsensitiveSections: false,
|
||||
@@ -347,7 +360,6 @@ func LoadAllProxyConfsFromIni(
|
||||
}
|
||||
|
||||
func renderRangeProxyTemplates(f *ini.File, section *ini.Section) error {
|
||||
|
||||
// Validation
|
||||
localPortStr := section.Key("local_port").String()
|
||||
remotePortStr := section.Key("remote_port").String()
|
||||
@@ -385,8 +397,12 @@ func renderRangeProxyTemplates(f *ini.File, section *ini.Section) error {
|
||||
}
|
||||
|
||||
copySection(section, tmpsection)
|
||||
tmpsection.NewKey("local_port", fmt.Sprintf("%d", localPorts[i]))
|
||||
tmpsection.NewKey("remote_port", fmt.Sprintf("%d", remotePorts[i]))
|
||||
if _, err := tmpsection.NewKey("local_port", fmt.Sprintf("%d", localPorts[i])); err != nil {
|
||||
return fmt.Errorf("local_port new key in section error: %v", err)
|
||||
}
|
||||
if _, err := tmpsection.NewKey("remote_port", fmt.Sprintf("%d", remotePorts[i])); err != nil {
|
||||
return fmt.Errorf("remote_port new key in section error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -394,6 +410,6 @@ func renderRangeProxyTemplates(f *ini.File, section *ini.Section) error {
|
||||
|
||||
func copySection(source, target *ini.Section) {
|
||||
for key, value := range source.KeysHash() {
|
||||
target.NewKey(key, value)
|
||||
_, _ = target.NewKey(key, value)
|
||||
}
|
||||
}
|
||||
|
@@ -17,18 +17,17 @@ package config
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/fatedier/frp/pkg/auth"
|
||||
"github.com/fatedier/frp/pkg/consts"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
const (
|
||||
testUser = "test"
|
||||
)
|
||||
|
||||
var (
|
||||
testClientBytesWithFull = []byte(`
|
||||
var testClientBytesWithFull = []byte(`
|
||||
# [common] is integral section
|
||||
[common]
|
||||
server_addr = 0.0.0.9
|
||||
@@ -75,6 +74,7 @@ var (
|
||||
local_ip = 127.0.0.9
|
||||
local_port = 29
|
||||
bandwidth_limit = 19MB
|
||||
bandwidth_limit_mode = server
|
||||
use_encryption
|
||||
use_compression
|
||||
remote_port = 6009
|
||||
@@ -237,7 +237,6 @@ var (
|
||||
use_encryption = false
|
||||
use_compression = false
|
||||
`)
|
||||
)
|
||||
|
||||
func Test_LoadClientCommonConf(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
@@ -259,33 +258,39 @@ func Test_LoadClientCommonConf(t *testing.T) {
|
||||
OidcTokenEndpointURL: "endpoint_url",
|
||||
},
|
||||
},
|
||||
ServerAddr: "0.0.0.9",
|
||||
ServerPort: 7009,
|
||||
HTTPProxy: "http://user:passwd@192.168.1.128:8080",
|
||||
LogFile: "./frpc.log9",
|
||||
LogWay: "file",
|
||||
LogLevel: "info9",
|
||||
LogMaxDays: 39,
|
||||
DisableLogColor: false,
|
||||
AdminAddr: "127.0.0.9",
|
||||
AdminPort: 7409,
|
||||
AdminUser: "admin9",
|
||||
AdminPwd: "admin9",
|
||||
AssetsDir: "./static9",
|
||||
PoolCount: 59,
|
||||
TCPMux: true,
|
||||
User: "your_name",
|
||||
LoginFailExit: true,
|
||||
Protocol: "tcp",
|
||||
TLSEnable: true,
|
||||
TLSCertFile: "client.crt",
|
||||
TLSKeyFile: "client.key",
|
||||
TLSTrustedCaFile: "ca.crt",
|
||||
TLSServerName: "example.com",
|
||||
DNSServer: "8.8.8.9",
|
||||
Start: []string{"ssh", "dns"},
|
||||
HeartbeatInterval: 39,
|
||||
HeartbeatTimeout: 99,
|
||||
ServerAddr: "0.0.0.9",
|
||||
ServerPort: 7009,
|
||||
DialServerTimeout: 10,
|
||||
DialServerKeepAlive: 7200,
|
||||
HTTPProxy: "http://user:passwd@192.168.1.128:8080",
|
||||
LogFile: "./frpc.log9",
|
||||
LogWay: "file",
|
||||
LogLevel: "info9",
|
||||
LogMaxDays: 39,
|
||||
DisableLogColor: false,
|
||||
AdminAddr: "127.0.0.9",
|
||||
AdminPort: 7409,
|
||||
AdminUser: "admin9",
|
||||
AdminPwd: "admin9",
|
||||
AssetsDir: "./static9",
|
||||
PoolCount: 59,
|
||||
TCPMux: true,
|
||||
TCPMuxKeepaliveInterval: 60,
|
||||
User: "your_name",
|
||||
LoginFailExit: true,
|
||||
Protocol: "tcp",
|
||||
QUICKeepalivePeriod: 10,
|
||||
QUICMaxIdleTimeout: 30,
|
||||
QUICMaxIncomingStreams: 100000,
|
||||
TLSEnable: true,
|
||||
TLSCertFile: "client.crt",
|
||||
TLSKeyFile: "client.key",
|
||||
TLSTrustedCaFile: "ca.crt",
|
||||
TLSServerName: "example.com",
|
||||
DNSServer: "8.8.8.9",
|
||||
Start: []string{"ssh", "dns"},
|
||||
HeartbeatInterval: 39,
|
||||
HeartbeatTimeout: 99,
|
||||
Metas: map[string]string{
|
||||
"var1": "123",
|
||||
"var2": "234",
|
||||
@@ -305,13 +310,14 @@ func Test_LoadClientBasicConf(t *testing.T) {
|
||||
proxyExpected := map[string]ProxyConf{
|
||||
testUser + ".ssh": &TCPProxyConf{
|
||||
BaseProxyConf: BaseProxyConf{
|
||||
ProxyName: testUser + ".ssh",
|
||||
ProxyType: consts.TCPProxy,
|
||||
UseCompression: true,
|
||||
UseEncryption: true,
|
||||
Group: "test_group",
|
||||
GroupKey: "123456",
|
||||
BandwidthLimit: MustBandwidthQuantity("19MB"),
|
||||
ProxyName: testUser + ".ssh",
|
||||
ProxyType: consts.TCPProxy,
|
||||
UseCompression: true,
|
||||
UseEncryption: true,
|
||||
Group: "test_group",
|
||||
GroupKey: "123456",
|
||||
BandwidthLimit: MustBandwidthQuantity("19MB"),
|
||||
BandwidthLimitMode: BandwidthLimitModeServer,
|
||||
Metas: map[string]string{
|
||||
"var1": "123",
|
||||
"var2": "234",
|
||||
@@ -338,6 +344,7 @@ func Test_LoadClientBasicConf(t *testing.T) {
|
||||
LocalIP: "127.0.0.9",
|
||||
LocalPort: 29,
|
||||
},
|
||||
BandwidthLimitMode: BandwidthLimitModeClient,
|
||||
},
|
||||
RemotePort: 9,
|
||||
},
|
||||
@@ -349,6 +356,7 @@ func Test_LoadClientBasicConf(t *testing.T) {
|
||||
LocalIP: "127.0.0.9",
|
||||
LocalPort: 6010,
|
||||
},
|
||||
BandwidthLimitMode: BandwidthLimitModeClient,
|
||||
},
|
||||
RemotePort: 6010,
|
||||
},
|
||||
@@ -360,6 +368,7 @@ func Test_LoadClientBasicConf(t *testing.T) {
|
||||
LocalIP: "127.0.0.9",
|
||||
LocalPort: 6011,
|
||||
},
|
||||
BandwidthLimitMode: BandwidthLimitModeClient,
|
||||
},
|
||||
RemotePort: 6011,
|
||||
},
|
||||
@@ -371,6 +380,7 @@ func Test_LoadClientBasicConf(t *testing.T) {
|
||||
LocalIP: "127.0.0.9",
|
||||
LocalPort: 6019,
|
||||
},
|
||||
BandwidthLimitMode: BandwidthLimitModeClient,
|
||||
},
|
||||
RemotePort: 6019,
|
||||
},
|
||||
@@ -384,6 +394,7 @@ func Test_LoadClientBasicConf(t *testing.T) {
|
||||
LocalIP: "114.114.114.114",
|
||||
LocalPort: 59,
|
||||
},
|
||||
BandwidthLimitMode: BandwidthLimitModeClient,
|
||||
},
|
||||
RemotePort: 6009,
|
||||
},
|
||||
@@ -397,6 +408,7 @@ func Test_LoadClientBasicConf(t *testing.T) {
|
||||
LocalIP: "114.114.114.114",
|
||||
LocalPort: 6000,
|
||||
},
|
||||
BandwidthLimitMode: BandwidthLimitModeClient,
|
||||
},
|
||||
RemotePort: 6000,
|
||||
},
|
||||
@@ -410,6 +422,7 @@ func Test_LoadClientBasicConf(t *testing.T) {
|
||||
LocalIP: "114.114.114.114",
|
||||
LocalPort: 6010,
|
||||
},
|
||||
BandwidthLimitMode: BandwidthLimitModeClient,
|
||||
},
|
||||
RemotePort: 6010,
|
||||
},
|
||||
@@ -423,6 +436,7 @@ func Test_LoadClientBasicConf(t *testing.T) {
|
||||
LocalIP: "114.114.114.114",
|
||||
LocalPort: 6011,
|
||||
},
|
||||
BandwidthLimitMode: BandwidthLimitModeClient,
|
||||
},
|
||||
RemotePort: 6011,
|
||||
},
|
||||
@@ -443,6 +457,7 @@ func Test_LoadClientBasicConf(t *testing.T) {
|
||||
HealthCheckIntervalS: 19,
|
||||
HealthCheckURL: "http://127.0.0.9:89/status",
|
||||
},
|
||||
BandwidthLimitMode: BandwidthLimitModeClient,
|
||||
},
|
||||
DomainConf: DomainConf{
|
||||
CustomDomains: []string{"web02.yourdomain.com"},
|
||||
@@ -467,6 +482,7 @@ func Test_LoadClientBasicConf(t *testing.T) {
|
||||
LocalPort: 8009,
|
||||
},
|
||||
ProxyProtocolVersion: "v2",
|
||||
BandwidthLimitMode: BandwidthLimitModeClient,
|
||||
},
|
||||
DomainConf: DomainConf{
|
||||
CustomDomains: []string{"web02.yourdomain.com"},
|
||||
@@ -481,6 +497,7 @@ func Test_LoadClientBasicConf(t *testing.T) {
|
||||
LocalIP: "127.0.0.1",
|
||||
LocalPort: 22,
|
||||
},
|
||||
BandwidthLimitMode: BandwidthLimitModeClient,
|
||||
},
|
||||
Role: "server",
|
||||
Sk: "abcdefg",
|
||||
@@ -493,6 +510,7 @@ func Test_LoadClientBasicConf(t *testing.T) {
|
||||
LocalIP: "127.0.0.1",
|
||||
LocalPort: 22,
|
||||
},
|
||||
BandwidthLimitMode: BandwidthLimitModeClient,
|
||||
},
|
||||
Role: "server",
|
||||
Sk: "abcdefg",
|
||||
@@ -505,6 +523,7 @@ func Test_LoadClientBasicConf(t *testing.T) {
|
||||
LocalIP: "127.0.0.1",
|
||||
LocalPort: 10701,
|
||||
},
|
||||
BandwidthLimitMode: BandwidthLimitModeClient,
|
||||
},
|
||||
DomainConf: DomainConf{
|
||||
CustomDomains: []string{"tunnel1"},
|
||||
@@ -523,6 +542,7 @@ func Test_LoadClientBasicConf(t *testing.T) {
|
||||
"plugin_unix_path": "/var/run/docker.sock",
|
||||
},
|
||||
},
|
||||
BandwidthLimitMode: BandwidthLimitModeClient,
|
||||
},
|
||||
RemotePort: 6003,
|
||||
},
|
||||
@@ -538,6 +558,7 @@ func Test_LoadClientBasicConf(t *testing.T) {
|
||||
"plugin_http_passwd": "abc",
|
||||
},
|
||||
},
|
||||
BandwidthLimitMode: BandwidthLimitModeClient,
|
||||
},
|
||||
RemotePort: 6004,
|
||||
},
|
||||
@@ -553,6 +574,7 @@ func Test_LoadClientBasicConf(t *testing.T) {
|
||||
"plugin_passwd": "abc",
|
||||
},
|
||||
},
|
||||
BandwidthLimitMode: BandwidthLimitModeClient,
|
||||
},
|
||||
RemotePort: 6005,
|
||||
},
|
||||
@@ -570,6 +592,7 @@ func Test_LoadClientBasicConf(t *testing.T) {
|
||||
"plugin_http_passwd": "abc",
|
||||
},
|
||||
},
|
||||
BandwidthLimitMode: BandwidthLimitModeClient,
|
||||
},
|
||||
RemotePort: 6006,
|
||||
},
|
||||
@@ -588,6 +611,7 @@ func Test_LoadClientBasicConf(t *testing.T) {
|
||||
"plugin_header_X-From-Where": "frp",
|
||||
},
|
||||
},
|
||||
BandwidthLimitMode: BandwidthLimitModeClient,
|
||||
},
|
||||
DomainConf: DomainConf{
|
||||
CustomDomains: []string{"test.yourdomain.com"},
|
||||
@@ -606,6 +630,7 @@ func Test_LoadClientBasicConf(t *testing.T) {
|
||||
"plugin_header_X-From-Where": "frp",
|
||||
},
|
||||
},
|
||||
BandwidthLimitMode: BandwidthLimitModeClient,
|
||||
},
|
||||
DomainConf: DomainConf{
|
||||
CustomDomains: []string{"test.yourdomain.com"},
|
||||
|
@@ -42,7 +42,7 @@ func ParseClientConfig(filePath string) (
|
||||
}
|
||||
cfg.Complete()
|
||||
if err = cfg.Validate(); err != nil {
|
||||
err = fmt.Errorf("Parse config error: %v", err)
|
||||
err = fmt.Errorf("parse config error: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
|
@@ -16,13 +16,15 @@ package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"gopkg.in/ini.v1"
|
||||
|
||||
"github.com/fatedier/frp/pkg/consts"
|
||||
"github.com/fatedier/frp/pkg/msg"
|
||||
|
||||
"gopkg.in/ini.v1"
|
||||
)
|
||||
|
||||
// Proxy
|
||||
@@ -139,6 +141,10 @@ type BaseProxyConf struct {
|
||||
// BandwidthLimit limit the bandwidth
|
||||
// 0 means no limit
|
||||
BandwidthLimit BandwidthQuantity `ini:"bandwidth_limit" json:"bandwidth_limit"`
|
||||
// BandwidthLimitMode specifies whether to limit the bandwidth on the
|
||||
// client or server side. Valid values include "client" and "server".
|
||||
// By default, this value is "client".
|
||||
BandwidthLimitMode string `ini:"bandwidth_limit_mode" json:"bandwidth_limit_mode"`
|
||||
|
||||
// meta info for each proxy
|
||||
Metas map[string]string `ini:"-" json:"metas"`
|
||||
@@ -162,6 +168,7 @@ type HTTPProxyConf struct {
|
||||
HTTPPwd string `ini:"http_pwd" json:"http_pwd"`
|
||||
HostHeaderRewrite string `ini:"host_header_rewrite" json:"host_header_rewrite"`
|
||||
Headers map[string]string `ini:"-" json:"headers"`
|
||||
RouteByHTTPUser string `ini:"route_by_http_user" json:"route_by_http_user"`
|
||||
}
|
||||
|
||||
// HTTPS
|
||||
@@ -178,8 +185,9 @@ type TCPProxyConf struct {
|
||||
|
||||
// TCPMux
|
||||
type TCPMuxProxyConf struct {
|
||||
BaseProxyConf `ini:",extends"`
|
||||
DomainConf `ini:",extends"`
|
||||
BaseProxyConf `ini:",extends"`
|
||||
DomainConf `ini:",extends"`
|
||||
RouteByHTTPUser string `ini:"route_by_http_user" json:"route_by_http_user"`
|
||||
|
||||
Multiplexer string `ini:"multiplexer"`
|
||||
}
|
||||
@@ -315,6 +323,7 @@ func defaultBaseProxyConf(proxyType string) BaseProxyConf {
|
||||
LocalSvrConf: LocalSvrConf{
|
||||
LocalIP: "127.0.0.1",
|
||||
},
|
||||
BandwidthLimitMode: BandwidthLimitModeClient,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -331,6 +340,7 @@ func (cfg *BaseProxyConf) compare(cmp *BaseProxyConf) bool {
|
||||
cfg.GroupKey != cmp.GroupKey ||
|
||||
cfg.ProxyProtocolVersion != cmp.ProxyProtocolVersion ||
|
||||
!cfg.BandwidthLimit.Equal(&cmp.BandwidthLimit) ||
|
||||
cfg.BandwidthLimitMode != cmp.BandwidthLimitMode ||
|
||||
!reflect.DeepEqual(cfg.Metas, cmp.Metas) {
|
||||
return false
|
||||
}
|
||||
@@ -370,7 +380,7 @@ func (cfg *BaseProxyConf) decorate(prefix string, name string, section *ini.Sect
|
||||
}
|
||||
|
||||
if cfg.HealthCheckType == "http" && cfg.Plugin == "" && cfg.HealthCheckURL != "" {
|
||||
s := fmt.Sprintf("http://%s:%d", cfg.LocalIP, cfg.LocalPort)
|
||||
s := "http://" + net.JoinHostPort(cfg.LocalIP, strconv.Itoa(cfg.LocalPort))
|
||||
if !strings.HasPrefix(cfg.HealthCheckURL, "/") {
|
||||
s += "/"
|
||||
}
|
||||
@@ -385,6 +395,11 @@ func (cfg *BaseProxyConf) marshalToMsg(pMsg *msg.NewProxy) {
|
||||
pMsg.ProxyType = cfg.ProxyType
|
||||
pMsg.UseEncryption = cfg.UseEncryption
|
||||
pMsg.UseCompression = cfg.UseCompression
|
||||
pMsg.BandwidthLimit = cfg.BandwidthLimit.String()
|
||||
// leave it empty for default value to reduce traffic
|
||||
if cfg.BandwidthLimitMode != "client" {
|
||||
pMsg.BandwidthLimitMode = cfg.BandwidthLimitMode
|
||||
}
|
||||
pMsg.Group = cfg.Group
|
||||
pMsg.GroupKey = cfg.GroupKey
|
||||
pMsg.Metas = cfg.Metas
|
||||
@@ -395,6 +410,12 @@ func (cfg *BaseProxyConf) unmarshalFromMsg(pMsg *msg.NewProxy) {
|
||||
cfg.ProxyType = pMsg.ProxyType
|
||||
cfg.UseEncryption = pMsg.UseEncryption
|
||||
cfg.UseCompression = pMsg.UseCompression
|
||||
if pMsg.BandwidthLimit != "" {
|
||||
cfg.BandwidthLimit, _ = NewBandwidthQuantity(pMsg.BandwidthLimit)
|
||||
}
|
||||
if pMsg.BandwidthLimitMode != "" {
|
||||
cfg.BandwidthLimitMode = pMsg.BandwidthLimitMode
|
||||
}
|
||||
cfg.Group = pMsg.Group
|
||||
cfg.GroupKey = pMsg.GroupKey
|
||||
cfg.Metas = pMsg.Metas
|
||||
@@ -407,6 +428,10 @@ func (cfg *BaseProxyConf) checkForCli() (err error) {
|
||||
}
|
||||
}
|
||||
|
||||
if cfg.BandwidthLimitMode != "client" && cfg.BandwidthLimitMode != "server" {
|
||||
return fmt.Errorf("bandwidth_limit_mode should be client or server")
|
||||
}
|
||||
|
||||
if err = cfg.LocalSvrConf.checkForCli(); err != nil {
|
||||
return
|
||||
}
|
||||
@@ -416,7 +441,10 @@ func (cfg *BaseProxyConf) checkForCli() (err error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cfg *BaseProxyConf) checkForSvr(conf ServerCommonConf) error {
|
||||
func (cfg *BaseProxyConf) checkForSvr() (err error) {
|
||||
if cfg.BandwidthLimitMode != "client" && cfg.BandwidthLimitMode != "server" {
|
||||
return fmt.Errorf("bandwidth_limit_mode should be client or server")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -557,6 +585,9 @@ func (cfg *TCPProxyConf) CheckForCli() (err error) {
|
||||
}
|
||||
|
||||
func (cfg *TCPProxyConf) CheckForSvr(serverCfg ServerCommonConf) error {
|
||||
if err := cfg.BaseProxyConf.checkForSvr(); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -576,7 +607,7 @@ func (cfg *TCPMuxProxyConf) Compare(cmp ProxyConf) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
if cfg.Multiplexer != cmpConf.Multiplexer {
|
||||
if cfg.Multiplexer != cmpConf.Multiplexer || cfg.RouteByHTTPUser != cmpConf.RouteByHTTPUser {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -601,6 +632,7 @@ func (cfg *TCPMuxProxyConf) UnmarshalFromMsg(pMsg *msg.NewProxy) {
|
||||
cfg.CustomDomains = pMsg.CustomDomains
|
||||
cfg.SubDomain = pMsg.SubDomain
|
||||
cfg.Multiplexer = pMsg.Multiplexer
|
||||
cfg.RouteByHTTPUser = pMsg.RouteByHTTPUser
|
||||
}
|
||||
|
||||
func (cfg *TCPMuxProxyConf) MarshalToMsg(pMsg *msg.NewProxy) {
|
||||
@@ -610,6 +642,7 @@ func (cfg *TCPMuxProxyConf) MarshalToMsg(pMsg *msg.NewProxy) {
|
||||
pMsg.CustomDomains = cfg.CustomDomains
|
||||
pMsg.SubDomain = cfg.SubDomain
|
||||
pMsg.Multiplexer = cfg.Multiplexer
|
||||
pMsg.RouteByHTTPUser = cfg.RouteByHTTPUser
|
||||
}
|
||||
|
||||
func (cfg *TCPMuxProxyConf) CheckForCli() (err error) {
|
||||
@@ -630,6 +663,10 @@ func (cfg *TCPMuxProxyConf) CheckForCli() (err error) {
|
||||
}
|
||||
|
||||
func (cfg *TCPMuxProxyConf) CheckForSvr(serverCfg ServerCommonConf) (err error) {
|
||||
if err := cfg.BaseProxyConf.checkForSvr(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if cfg.Multiplexer != consts.HTTPConnectTCPMultiplexer {
|
||||
return fmt.Errorf("proxy [%s] incorrect multiplexer [%s]", cfg.ProxyName, cfg.Multiplexer)
|
||||
}
|
||||
@@ -701,6 +738,9 @@ func (cfg *UDPProxyConf) CheckForCli() (err error) {
|
||||
}
|
||||
|
||||
func (cfg *UDPProxyConf) CheckForSvr(serverCfg ServerCommonConf) error {
|
||||
if err := cfg.BaseProxyConf.checkForSvr(); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -724,6 +764,7 @@ func (cfg *HTTPProxyConf) Compare(cmp ProxyConf) bool {
|
||||
cfg.HTTPUser != cmpConf.HTTPUser ||
|
||||
cfg.HTTPPwd != cmpConf.HTTPPwd ||
|
||||
cfg.HostHeaderRewrite != cmpConf.HostHeaderRewrite ||
|
||||
cfg.RouteByHTTPUser != cmpConf.RouteByHTTPUser ||
|
||||
!reflect.DeepEqual(cfg.Headers, cmpConf.Headers) {
|
||||
return false
|
||||
}
|
||||
@@ -754,6 +795,7 @@ func (cfg *HTTPProxyConf) UnmarshalFromMsg(pMsg *msg.NewProxy) {
|
||||
cfg.HTTPUser = pMsg.HTTPUser
|
||||
cfg.HTTPPwd = pMsg.HTTPPwd
|
||||
cfg.Headers = pMsg.Headers
|
||||
cfg.RouteByHTTPUser = pMsg.RouteByHTTPUser
|
||||
}
|
||||
|
||||
func (cfg *HTTPProxyConf) MarshalToMsg(pMsg *msg.NewProxy) {
|
||||
@@ -767,6 +809,7 @@ func (cfg *HTTPProxyConf) MarshalToMsg(pMsg *msg.NewProxy) {
|
||||
pMsg.HTTPUser = cfg.HTTPUser
|
||||
pMsg.HTTPPwd = cfg.HTTPPwd
|
||||
pMsg.Headers = cfg.Headers
|
||||
pMsg.RouteByHTTPUser = cfg.RouteByHTTPUser
|
||||
}
|
||||
|
||||
func (cfg *HTTPProxyConf) CheckForCli() (err error) {
|
||||
@@ -783,6 +826,10 @@ func (cfg *HTTPProxyConf) CheckForCli() (err error) {
|
||||
}
|
||||
|
||||
func (cfg *HTTPProxyConf) CheckForSvr(serverCfg ServerCommonConf) (err error) {
|
||||
if err := cfg.BaseProxyConf.checkForSvr(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if serverCfg.VhostHTTPPort == 0 {
|
||||
return fmt.Errorf("type [http] not support when vhost_http_port is not set")
|
||||
}
|
||||
@@ -855,6 +902,10 @@ func (cfg *HTTPSProxyConf) CheckForCli() (err error) {
|
||||
}
|
||||
|
||||
func (cfg *HTTPSProxyConf) CheckForSvr(serverCfg ServerCommonConf) (err error) {
|
||||
if err := cfg.BaseProxyConf.checkForSvr(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if serverCfg.VhostHTTPSPort == 0 {
|
||||
return fmt.Errorf("type [https] not support when vhost_https_port is not set")
|
||||
}
|
||||
@@ -927,6 +978,9 @@ func (cfg *SUDPProxyConf) CheckForCli() (err error) {
|
||||
}
|
||||
|
||||
func (cfg *SUDPProxyConf) CheckForSvr(serverCfg ServerCommonConf) error {
|
||||
if err := cfg.BaseProxyConf.checkForSvr(); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -993,6 +1047,9 @@ func (cfg *STCPProxyConf) CheckForCli() (err error) {
|
||||
}
|
||||
|
||||
func (cfg *STCPProxyConf) CheckForSvr(serverCfg ServerCommonConf) error {
|
||||
if err := cfg.BaseProxyConf.checkForSvr(); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -1059,5 +1116,8 @@ func (cfg *XTCPProxyConf) CheckForCli() (err error) {
|
||||
}
|
||||
|
||||
func (cfg *XTCPProxyConf) CheckForSvr(serverCfg ServerCommonConf) error {
|
||||
if err := cfg.BaseProxyConf.checkForSvr(); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@@ -17,10 +17,10 @@ package config
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/fatedier/frp/pkg/consts"
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"gopkg.in/ini.v1"
|
||||
|
||||
"github.com/fatedier/frp/pkg/consts"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -49,7 +49,6 @@ func Test_Proxy_UnmarshalFromIni(t *testing.T) {
|
||||
source []byte
|
||||
expected ProxyConf
|
||||
}{
|
||||
|
||||
{
|
||||
sname: "ssh",
|
||||
source: []byte(`
|
||||
@@ -59,6 +58,7 @@ func Test_Proxy_UnmarshalFromIni(t *testing.T) {
|
||||
local_ip = 127.0.0.9
|
||||
local_port = 29
|
||||
bandwidth_limit = 19MB
|
||||
bandwidth_limit_mode = server
|
||||
use_encryption
|
||||
use_compression
|
||||
remote_port = 6009
|
||||
@@ -72,13 +72,14 @@ func Test_Proxy_UnmarshalFromIni(t *testing.T) {
|
||||
meta_var2 = 234`),
|
||||
expected: &TCPProxyConf{
|
||||
BaseProxyConf: BaseProxyConf{
|
||||
ProxyName: testProxyPrefix + "ssh",
|
||||
ProxyType: consts.TCPProxy,
|
||||
UseCompression: true,
|
||||
UseEncryption: true,
|
||||
Group: "test_group",
|
||||
GroupKey: "123456",
|
||||
BandwidthLimit: MustBandwidthQuantity("19MB"),
|
||||
ProxyName: testProxyPrefix + "ssh",
|
||||
ProxyType: consts.TCPProxy,
|
||||
UseCompression: true,
|
||||
UseEncryption: true,
|
||||
Group: "test_group",
|
||||
GroupKey: "123456",
|
||||
BandwidthLimit: MustBandwidthQuantity("19MB"),
|
||||
BandwidthLimitMode: BandwidthLimitModeServer,
|
||||
Metas: map[string]string{
|
||||
"var1": "123",
|
||||
"var2": "234",
|
||||
@@ -115,6 +116,7 @@ func Test_Proxy_UnmarshalFromIni(t *testing.T) {
|
||||
LocalIP: "127.0.0.9",
|
||||
LocalPort: 29,
|
||||
},
|
||||
BandwidthLimitMode: BandwidthLimitModeClient,
|
||||
},
|
||||
RemotePort: 9,
|
||||
},
|
||||
@@ -140,6 +142,7 @@ func Test_Proxy_UnmarshalFromIni(t *testing.T) {
|
||||
LocalIP: "114.114.114.114",
|
||||
LocalPort: 59,
|
||||
},
|
||||
BandwidthLimitMode: BandwidthLimitModeClient,
|
||||
},
|
||||
RemotePort: 6009,
|
||||
},
|
||||
@@ -183,6 +186,7 @@ func Test_Proxy_UnmarshalFromIni(t *testing.T) {
|
||||
HealthCheckIntervalS: 19,
|
||||
HealthCheckURL: "http://127.0.0.9:89/status",
|
||||
},
|
||||
BandwidthLimitMode: BandwidthLimitModeClient,
|
||||
},
|
||||
DomainConf: DomainConf{
|
||||
CustomDomains: []string{"web02.yourdomain.com"},
|
||||
@@ -221,6 +225,7 @@ func Test_Proxy_UnmarshalFromIni(t *testing.T) {
|
||||
LocalPort: 8009,
|
||||
},
|
||||
ProxyProtocolVersion: "v2",
|
||||
BandwidthLimitMode: BandwidthLimitModeClient,
|
||||
},
|
||||
DomainConf: DomainConf{
|
||||
CustomDomains: []string{"web02.yourdomain.com"},
|
||||
@@ -247,6 +252,7 @@ func Test_Proxy_UnmarshalFromIni(t *testing.T) {
|
||||
LocalIP: "127.0.0.1",
|
||||
LocalPort: 22,
|
||||
},
|
||||
BandwidthLimitMode: BandwidthLimitModeClient,
|
||||
},
|
||||
Role: "server",
|
||||
Sk: "abcdefg",
|
||||
@@ -271,6 +277,7 @@ func Test_Proxy_UnmarshalFromIni(t *testing.T) {
|
||||
LocalIP: "127.0.0.1",
|
||||
LocalPort: 22,
|
||||
},
|
||||
BandwidthLimitMode: BandwidthLimitModeClient,
|
||||
},
|
||||
Role: "server",
|
||||
Sk: "abcdefg",
|
||||
@@ -294,6 +301,7 @@ func Test_Proxy_UnmarshalFromIni(t *testing.T) {
|
||||
LocalIP: "127.0.0.1",
|
||||
LocalPort: 10701,
|
||||
},
|
||||
BandwidthLimitMode: BandwidthLimitModeClient,
|
||||
},
|
||||
DomainConf: DomainConf{
|
||||
CustomDomains: []string{"tunnel1"},
|
||||
@@ -348,6 +356,7 @@ func Test_RangeProxy_UnmarshalFromIni(t *testing.T) {
|
||||
LocalIP: "127.0.0.9",
|
||||
LocalPort: 6010,
|
||||
},
|
||||
BandwidthLimitMode: BandwidthLimitModeClient,
|
||||
},
|
||||
RemotePort: 6010,
|
||||
},
|
||||
@@ -359,6 +368,7 @@ func Test_RangeProxy_UnmarshalFromIni(t *testing.T) {
|
||||
LocalIP: "127.0.0.9",
|
||||
LocalPort: 6011,
|
||||
},
|
||||
BandwidthLimitMode: BandwidthLimitModeClient,
|
||||
},
|
||||
RemotePort: 6011,
|
||||
},
|
||||
@@ -370,6 +380,7 @@ func Test_RangeProxy_UnmarshalFromIni(t *testing.T) {
|
||||
LocalIP: "127.0.0.9",
|
||||
LocalPort: 6019,
|
||||
},
|
||||
BandwidthLimitMode: BandwidthLimitModeClient,
|
||||
},
|
||||
RemotePort: 6019,
|
||||
},
|
||||
@@ -397,6 +408,7 @@ func Test_RangeProxy_UnmarshalFromIni(t *testing.T) {
|
||||
LocalIP: "114.114.114.114",
|
||||
LocalPort: 6000,
|
||||
},
|
||||
BandwidthLimitMode: BandwidthLimitModeClient,
|
||||
},
|
||||
RemotePort: 6000,
|
||||
},
|
||||
@@ -410,6 +422,7 @@ func Test_RangeProxy_UnmarshalFromIni(t *testing.T) {
|
||||
LocalIP: "114.114.114.114",
|
||||
LocalPort: 6010,
|
||||
},
|
||||
BandwidthLimitMode: BandwidthLimitModeClient,
|
||||
},
|
||||
RemotePort: 6010,
|
||||
},
|
||||
@@ -423,6 +436,7 @@ func Test_RangeProxy_UnmarshalFromIni(t *testing.T) {
|
||||
LocalIP: "114.114.114.114",
|
||||
LocalPort: 6011,
|
||||
},
|
||||
BandwidthLimitMode: BandwidthLimitModeClient,
|
||||
},
|
||||
RemotePort: 6011,
|
||||
},
|
||||
@@ -457,5 +471,4 @@ func Test_RangeProxy_UnmarshalFromIni(t *testing.T) {
|
||||
|
||||
assert.Equal(c.expected, actual)
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -18,12 +18,12 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/go-playground/validator/v10"
|
||||
"gopkg.in/ini.v1"
|
||||
|
||||
"github.com/fatedier/frp/pkg/auth"
|
||||
plugin "github.com/fatedier/frp/pkg/plugin/server"
|
||||
"github.com/fatedier/frp/pkg/util/util"
|
||||
|
||||
"github.com/go-playground/validator/v10"
|
||||
"gopkg.in/ini.v1"
|
||||
)
|
||||
|
||||
// ServerCommonConf contains information for a server service. It is
|
||||
@@ -46,6 +46,14 @@ type ServerCommonConf struct {
|
||||
// value is 0, the server will not listen for KCP connections. By default,
|
||||
// this value is 0.
|
||||
KCPBindPort int `ini:"kcp_bind_port" json:"kcp_bind_port" validate:"gte=0,lte=65535"`
|
||||
// QUICBindPort specifies the QUIC port that the server listens on.
|
||||
// Set this value to 0 will disable this feature.
|
||||
// By default, the value is 0.
|
||||
QUICBindPort int `ini:"quic_bind_port" json:"quic_bind_port" validate:"gte=0,lte=65535"`
|
||||
// QUIC protocol options
|
||||
QUICKeepalivePeriod int `ini:"quic_keepalive_period" json:"quic_keepalive_period" validate:"gte=0"`
|
||||
QUICMaxIdleTimeout int `ini:"quic_max_idle_timeout" json:"quic_max_idle_timeout" validate:"gte=0"`
|
||||
QUICMaxIncomingStreams int `ini:"quic_max_incoming_streams" json:"quic_max_incoming_streams" validate:"gte=0"`
|
||||
// ProxyBindAddr specifies the address that the proxy binds to. This value
|
||||
// may be the same as BindAddr.
|
||||
ProxyBindAddr string `ini:"proxy_bind_addr" json:"proxy_bind_addr"`
|
||||
@@ -62,6 +70,8 @@ type ServerCommonConf struct {
|
||||
// requests on one single port. If it's not - it will listen on this value for
|
||||
// HTTP CONNECT requests. By default, this value is 0.
|
||||
TCPMuxHTTPConnectPort int `ini:"tcpmux_httpconnect_port" json:"tcpmux_httpconnect_port" validate:"gte=0,lte=65535"`
|
||||
// If TCPMuxPassthrough is true, frps won't do any update on traffic.
|
||||
TCPMuxPassthrough bool `ini:"tcpmux_passthrough" json:"tcpmux_passthrough"`
|
||||
// VhostHTTPTimeout specifies the response header timeout for the Vhost
|
||||
// HTTP server, in seconds. By default, this value is 60.
|
||||
VhostHTTPTimeout int64 `ini:"vhost_http_timeout" json:"vhost_http_timeout"`
|
||||
@@ -72,6 +82,17 @@ type ServerCommonConf struct {
|
||||
// value is 0, the dashboard will not be started. By default, this value is
|
||||
// 0.
|
||||
DashboardPort int `ini:"dashboard_port" json:"dashboard_port" validate:"gte=0,lte=65535"`
|
||||
// DashboardTLSCertFile specifies the path of the cert file that the server will
|
||||
// load. If "dashboard_tls_cert_file", "dashboard_tls_key_file" are valid, the server will use this
|
||||
// supplied tls configuration.
|
||||
DashboardTLSCertFile string `ini:"dashboard_tls_cert_file" json:"dashboard_tls_cert_file"`
|
||||
// DashboardTLSKeyFile specifies the path of the secret key that the server will
|
||||
// load. If "dashboard_tls_cert_file", "dashboard_tls_key_file" are valid, the server will use this
|
||||
// supplied tls configuration.
|
||||
DashboardTLSKeyFile string `ini:"dashboard_tls_key_file" json:"dashboard_tls_key_file"`
|
||||
// DashboardTLSMode specifies the mode of the dashboard between HTTP or HTTPS modes. By
|
||||
// default, this value is false, which is HTTP mode.
|
||||
DashboardTLSMode bool `ini:"dashboard_tls_mode" json:"dashboard_tls_mode"`
|
||||
// DashboardUser specifies the username that the dashboard will use for
|
||||
// login.
|
||||
DashboardUser string `ini:"dashboard_user" json:"dashboard_user"`
|
||||
@@ -118,6 +139,12 @@ type ServerCommonConf struct {
|
||||
// from a client to share a single TCP connection. By default, this value
|
||||
// is true.
|
||||
TCPMux bool `ini:"tcp_mux" json:"tcp_mux"`
|
||||
// TCPMuxKeepaliveInterval specifies the keep alive interval for TCP stream multipler.
|
||||
// If TCPMux is true, heartbeat of application layer is unnecessary because it can only rely on heartbeat in TCPMux.
|
||||
TCPMuxKeepaliveInterval int64 `ini:"tcp_mux_keepalive_interval" json:"tcp_mux_keepalive_interval"`
|
||||
// TCPKeepAlive specifies the interval between keep-alive probes for an active network connection between frpc and frps.
|
||||
// If negative, keep-alive probes are disabled.
|
||||
TCPKeepAlive int64 `ini:"tcp_keepalive" json:"tcp_keepalive"`
|
||||
// Custom404Page specifies a path to a custom 404 page to display. If this
|
||||
// value is "", a default page will be displayed. By default, this value is
|
||||
// "".
|
||||
@@ -154,7 +181,7 @@ type ServerCommonConf struct {
|
||||
TLSTrustedCaFile string `ini:"tls_trusted_ca_file" json:"tls_trusted_ca_file"`
|
||||
// HeartBeatTimeout specifies the maximum time to wait for a heartbeat
|
||||
// before terminating the connection. It is not recommended to change this
|
||||
// value. By default, this value is 90.
|
||||
// value. By default, this value is 90. Set negative value to disable it.
|
||||
HeartbeatTimeout int64 `ini:"heartbeat_timeout" json:"heartbeat_timeout"`
|
||||
// UserConnTimeout specifies the maximum time to wait for a work
|
||||
// connection. By default, this value is 10.
|
||||
@@ -164,53 +191,42 @@ type ServerCommonConf struct {
|
||||
// UDPPacketSize specifies the UDP packet size
|
||||
// By default, this value is 1500
|
||||
UDPPacketSize int64 `ini:"udp_packet_size" json:"udp_packet_size"`
|
||||
// Enable golang pprof handlers in dashboard listener.
|
||||
// Dashboard port must be set first.
|
||||
PprofEnable bool `ini:"pprof_enable" json:"pprof_enable"`
|
||||
}
|
||||
|
||||
// GetDefaultServerConf returns a server configuration with reasonable
|
||||
// defaults.
|
||||
func GetDefaultServerConf() ServerCommonConf {
|
||||
return ServerCommonConf{
|
||||
ServerConfig: auth.GetDefaultServerConf(),
|
||||
BindAddr: "0.0.0.0",
|
||||
BindPort: 7000,
|
||||
BindUDPPort: 0,
|
||||
KCPBindPort: 0,
|
||||
ProxyBindAddr: "",
|
||||
VhostHTTPPort: 0,
|
||||
VhostHTTPSPort: 0,
|
||||
TCPMuxHTTPConnectPort: 0,
|
||||
VhostHTTPTimeout: 60,
|
||||
DashboardAddr: "0.0.0.0",
|
||||
DashboardPort: 0,
|
||||
DashboardUser: "",
|
||||
DashboardPwd: "",
|
||||
EnablePrometheus: false,
|
||||
AssetsDir: "",
|
||||
LogFile: "console",
|
||||
LogWay: "console",
|
||||
LogLevel: "info",
|
||||
LogMaxDays: 3,
|
||||
DisableLogColor: false,
|
||||
DetailedErrorsToClient: true,
|
||||
SubDomainHost: "",
|
||||
TCPMux: true,
|
||||
AllowPorts: make(map[int]struct{}),
|
||||
MaxPoolCount: 5,
|
||||
MaxPortsPerClient: 0,
|
||||
TLSOnly: false,
|
||||
TLSCertFile: "",
|
||||
TLSKeyFile: "",
|
||||
TLSTrustedCaFile: "",
|
||||
HeartbeatTimeout: 90,
|
||||
UserConnTimeout: 10,
|
||||
Custom404Page: "",
|
||||
HTTPPlugins: make(map[string]plugin.HTTPPluginOptions),
|
||||
UDPPacketSize: 1500,
|
||||
ServerConfig: auth.GetDefaultServerConf(),
|
||||
BindAddr: "0.0.0.0",
|
||||
BindPort: 7000,
|
||||
QUICKeepalivePeriod: 10,
|
||||
QUICMaxIdleTimeout: 30,
|
||||
QUICMaxIncomingStreams: 100000,
|
||||
VhostHTTPTimeout: 60,
|
||||
DashboardAddr: "0.0.0.0",
|
||||
LogFile: "console",
|
||||
LogWay: "console",
|
||||
LogLevel: "info",
|
||||
LogMaxDays: 3,
|
||||
DetailedErrorsToClient: true,
|
||||
TCPMux: true,
|
||||
TCPMuxKeepaliveInterval: 60,
|
||||
TCPKeepAlive: 7200,
|
||||
AllowPorts: make(map[int]struct{}),
|
||||
MaxPoolCount: 5,
|
||||
MaxPortsPerClient: 0,
|
||||
HeartbeatTimeout: 90,
|
||||
UserConnTimeout: 10,
|
||||
HTTPPlugins: make(map[string]plugin.HTTPPluginOptions),
|
||||
UDPPacketSize: 1500,
|
||||
}
|
||||
}
|
||||
|
||||
func UnmarshalServerConfFromIni(source interface{}) (ServerCommonConf, error) {
|
||||
|
||||
f, err := ini.LoadSources(ini.LoadOptions{
|
||||
Insensitive: false,
|
||||
InsensitiveSections: false,
|
||||
@@ -282,6 +298,23 @@ func (cfg *ServerCommonConf) Complete() {
|
||||
}
|
||||
|
||||
func (cfg *ServerCommonConf) Validate() error {
|
||||
if !cfg.DashboardTLSMode {
|
||||
if cfg.DashboardTLSCertFile != "" {
|
||||
fmt.Println("WARNING! dashboard_tls_cert_file is invalid when dashboard_tls_mode is false")
|
||||
}
|
||||
|
||||
if cfg.DashboardTLSKeyFile != "" {
|
||||
fmt.Println("WARNING! dashboard_tls_key_file is invalid when dashboard_tls_mode is false")
|
||||
}
|
||||
} else {
|
||||
if cfg.DashboardTLSCertFile == "" {
|
||||
return fmt.Errorf("ERROR! dashboard_tls_cert_file must be specified when dashboard_tls_mode is true")
|
||||
}
|
||||
|
||||
if cfg.DashboardTLSKeyFile == "" {
|
||||
return fmt.Errorf("ERROR! dashboard_tls_cert_file must be specified when dashboard_tls_mode is true")
|
||||
}
|
||||
}
|
||||
return validator.New().Struct(cfg)
|
||||
}
|
||||
|
||||
|
@@ -17,10 +17,10 @@ package config
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/fatedier/frp/pkg/auth"
|
||||
plugin "github.com/fatedier/frp/pkg/plugin/server"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func Test_LoadServerCommonConf(t *testing.T) {
|
||||
@@ -106,6 +106,9 @@ func Test_LoadServerCommonConf(t *testing.T) {
|
||||
BindPort: 7009,
|
||||
BindUDPPort: 7008,
|
||||
KCPBindPort: 7007,
|
||||
QUICKeepalivePeriod: 10,
|
||||
QUICMaxIdleTimeout: 30,
|
||||
QUICMaxIncomingStreams: 100000,
|
||||
ProxyBindAddr: "127.0.0.9",
|
||||
VhostHTTPPort: 89,
|
||||
VhostHTTPSPort: 449,
|
||||
@@ -126,20 +129,22 @@ func Test_LoadServerCommonConf(t *testing.T) {
|
||||
HeartbeatTimeout: 99,
|
||||
UserConnTimeout: 9,
|
||||
AllowPorts: map[int]struct{}{
|
||||
10: struct{}{},
|
||||
11: struct{}{},
|
||||
12: struct{}{},
|
||||
99: struct{}{},
|
||||
10: {},
|
||||
11: {},
|
||||
12: {},
|
||||
99: {},
|
||||
},
|
||||
MaxPoolCount: 59,
|
||||
MaxPortsPerClient: 9,
|
||||
TLSOnly: true,
|
||||
TLSCertFile: "server.crt",
|
||||
TLSKeyFile: "server.key",
|
||||
TLSTrustedCaFile: "ca.crt",
|
||||
SubDomainHost: "frps.com",
|
||||
TCPMux: true,
|
||||
UDPPacketSize: 1509,
|
||||
MaxPoolCount: 59,
|
||||
MaxPortsPerClient: 9,
|
||||
TLSOnly: true,
|
||||
TLSCertFile: "server.crt",
|
||||
TLSKeyFile: "server.key",
|
||||
TLSTrustedCaFile: "ca.crt",
|
||||
SubDomainHost: "frps.com",
|
||||
TCPMux: true,
|
||||
TCPMuxKeepaliveInterval: 60,
|
||||
TCPKeepAlive: 7200,
|
||||
UDPPacketSize: 1509,
|
||||
|
||||
HTTPPlugins: map[string]plugin.HTTPPluginOptions{
|
||||
"user-manager": {
|
||||
@@ -174,27 +179,32 @@ func Test_LoadServerCommonConf(t *testing.T) {
|
||||
AuthenticateNewWorkConns: false,
|
||||
},
|
||||
},
|
||||
BindAddr: "0.0.0.9",
|
||||
BindPort: 7009,
|
||||
BindUDPPort: 7008,
|
||||
ProxyBindAddr: "0.0.0.9",
|
||||
VhostHTTPTimeout: 60,
|
||||
DashboardAddr: "0.0.0.0",
|
||||
DashboardUser: "",
|
||||
DashboardPwd: "",
|
||||
EnablePrometheus: false,
|
||||
LogFile: "console",
|
||||
LogWay: "console",
|
||||
LogLevel: "info",
|
||||
LogMaxDays: 3,
|
||||
DetailedErrorsToClient: true,
|
||||
TCPMux: true,
|
||||
AllowPorts: make(map[int]struct{}),
|
||||
MaxPoolCount: 5,
|
||||
HeartbeatTimeout: 90,
|
||||
UserConnTimeout: 10,
|
||||
HTTPPlugins: make(map[string]plugin.HTTPPluginOptions),
|
||||
UDPPacketSize: 1500,
|
||||
BindAddr: "0.0.0.9",
|
||||
BindPort: 7009,
|
||||
BindUDPPort: 7008,
|
||||
QUICKeepalivePeriod: 10,
|
||||
QUICMaxIdleTimeout: 30,
|
||||
QUICMaxIncomingStreams: 100000,
|
||||
ProxyBindAddr: "0.0.0.9",
|
||||
VhostHTTPTimeout: 60,
|
||||
DashboardAddr: "0.0.0.0",
|
||||
DashboardUser: "",
|
||||
DashboardPwd: "",
|
||||
EnablePrometheus: false,
|
||||
LogFile: "console",
|
||||
LogWay: "console",
|
||||
LogLevel: "info",
|
||||
LogMaxDays: 3,
|
||||
DetailedErrorsToClient: true,
|
||||
TCPMux: true,
|
||||
TCPMuxKeepaliveInterval: 60,
|
||||
TCPKeepAlive: 7200,
|
||||
AllowPorts: make(map[int]struct{}),
|
||||
MaxPoolCount: 5,
|
||||
HeartbeatTimeout: 90,
|
||||
UserConnTimeout: 10,
|
||||
HTTPPlugins: make(map[string]plugin.HTTPPluginOptions),
|
||||
UDPPacketSize: 1500,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
@@ -24,6 +24,9 @@ import (
|
||||
const (
|
||||
MB = 1024 * 1024
|
||||
KB = 1024
|
||||
|
||||
BandwidthLimitModeClient = "client"
|
||||
BandwidthLimitModeServer = "server"
|
||||
)
|
||||
|
||||
type BandwidthQuantity struct {
|
||||
@@ -75,21 +78,22 @@ func (q *BandwidthQuantity) UnmarshalString(s string) error {
|
||||
f float64
|
||||
err error
|
||||
)
|
||||
if strings.HasSuffix(s, "MB") {
|
||||
switch {
|
||||
case strings.HasSuffix(s, "MB"):
|
||||
base = MB
|
||||
fstr := strings.TrimSuffix(s, "MB")
|
||||
f, err = strconv.ParseFloat(fstr, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else if strings.HasSuffix(s, "KB") {
|
||||
case strings.HasSuffix(s, "KB"):
|
||||
base = KB
|
||||
fstr := strings.TrimSuffix(s, "KB")
|
||||
f, err = strconv.ParseFloat(fstr, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
default:
|
||||
return errors.New("unit not support")
|
||||
}
|
||||
|
||||
|
@@ -21,19 +21,17 @@ import (
|
||||
"text/template"
|
||||
)
|
||||
|
||||
var (
|
||||
glbEnvs map[string]string
|
||||
)
|
||||
var glbEnvs map[string]string
|
||||
|
||||
func init() {
|
||||
glbEnvs = make(map[string]string)
|
||||
envs := os.Environ()
|
||||
for _, env := range envs {
|
||||
kv := strings.Split(env, "=")
|
||||
if len(kv) != 2 {
|
||||
pair := strings.SplitN(env, "=", 2)
|
||||
if len(pair) != 2 {
|
||||
continue
|
||||
}
|
||||
glbEnvs[kv[0]] = kv[1]
|
||||
glbEnvs[pair[0]] = pair[1]
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -18,9 +18,9 @@ import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
"github.com/fatedier/frp/pkg/consts"
|
||||
|
||||
"gopkg.in/ini.v1"
|
||||
|
||||
"github.com/fatedier/frp/pkg/consts"
|
||||
)
|
||||
|
||||
// Visitor
|
||||
@@ -136,6 +136,7 @@ func (cfg *BaseVisitorConf) check() (err error) {
|
||||
}
|
||||
|
||||
func (cfg *BaseVisitorConf) unmarshalFromIni(prefix string, name string, section *ini.Section) error {
|
||||
_ = section
|
||||
|
||||
// Custom decoration after basic unmarshal:
|
||||
// proxy name
|
||||
|
@@ -17,10 +17,10 @@ package config
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/fatedier/frp/pkg/consts"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"gopkg.in/ini.v1"
|
||||
|
||||
"github.com/fatedier/frp/pkg/consts"
|
||||
)
|
||||
|
||||
const testVisitorPrefix = "test."
|
||||
|
@@ -16,26 +16,26 @@ package consts
|
||||
|
||||
var (
|
||||
// proxy status
|
||||
Idle string = "idle"
|
||||
Working string = "working"
|
||||
Closed string = "closed"
|
||||
Online string = "online"
|
||||
Offline string = "offline"
|
||||
Idle = "idle"
|
||||
Working = "working"
|
||||
Closed = "closed"
|
||||
Online = "online"
|
||||
Offline = "offline"
|
||||
|
||||
// proxy type
|
||||
TCPProxy string = "tcp"
|
||||
UDPProxy string = "udp"
|
||||
TCPMuxProxy string = "tcpmux"
|
||||
HTTPProxy string = "http"
|
||||
HTTPSProxy string = "https"
|
||||
STCPProxy string = "stcp"
|
||||
XTCPProxy string = "xtcp"
|
||||
SUDPProxy string = "sudp"
|
||||
TCPProxy = "tcp"
|
||||
UDPProxy = "udp"
|
||||
TCPMuxProxy = "tcpmux"
|
||||
HTTPProxy = "http"
|
||||
HTTPSProxy = "https"
|
||||
STCPProxy = "stcp"
|
||||
XTCPProxy = "xtcp"
|
||||
SUDPProxy = "sudp"
|
||||
|
||||
// authentication method
|
||||
TokenAuthMethod string = "token"
|
||||
OidcAuthMethod string = "oidc"
|
||||
TokenAuthMethod = "token"
|
||||
OidcAuthMethod = "oidc"
|
||||
|
||||
// TCP multiplexer
|
||||
HTTPConnectTCPMultiplexer string = "httpconnect"
|
||||
HTTPConnectTCPMultiplexer = "httpconnect"
|
||||
)
|
||||
|
@@ -30,7 +30,7 @@ func EnablePrometheus() {
|
||||
sm.Add(prometheus.ServerMetrics)
|
||||
}
|
||||
|
||||
var sm *serverMetrics = &serverMetrics{}
|
||||
var sm = &serverMetrics{}
|
||||
|
||||
func init() {
|
||||
metrics.Register(sm)
|
||||
|
@@ -23,9 +23,12 @@ import (
|
||||
server "github.com/fatedier/frp/server/metrics"
|
||||
)
|
||||
|
||||
var sm *serverMetrics = newServerMetrics()
|
||||
var ServerMetrics server.ServerMetrics
|
||||
var StatsCollector Collector
|
||||
var (
|
||||
sm = newServerMetrics()
|
||||
|
||||
ServerMetrics server.ServerMetrics
|
||||
StatsCollector Collector
|
||||
)
|
||||
|
||||
func init() {
|
||||
ServerMetrics = sm
|
||||
|
@@ -4,5 +4,7 @@ import (
|
||||
"github.com/fatedier/frp/pkg/metrics/aggregate"
|
||||
)
|
||||
|
||||
var EnableMem = aggregate.EnableMem
|
||||
var EnablePrometheus = aggregate.EnablePrometheus
|
||||
var (
|
||||
EnableMem = aggregate.EnableMem
|
||||
EnablePrometheus = aggregate.EnablePrometheus
|
||||
)
|
||||
|
@@ -1,9 +1,9 @@
|
||||
package prometheus
|
||||
|
||||
import (
|
||||
"github.com/fatedier/frp/server/metrics"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
|
||||
"github.com/fatedier/frp/server/metrics"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@@ -22,9 +22,7 @@ import (
|
||||
|
||||
type Message = jsonMsg.Message
|
||||
|
||||
var (
|
||||
msgCtl *jsonMsg.MsgCtl
|
||||
)
|
||||
var msgCtl *jsonMsg.MsgCtl
|
||||
|
||||
func init() {
|
||||
msgCtl = jsonMsg.NewMsgCtl()
|
||||
|
189
pkg/msg/msg.go
189
pkg/msg/msg.go
@@ -14,7 +14,9 @@
|
||||
|
||||
package msg
|
||||
|
||||
import "net"
|
||||
import (
|
||||
"net"
|
||||
)
|
||||
|
||||
const (
|
||||
TypeLogin = 'o'
|
||||
@@ -37,158 +39,157 @@ const (
|
||||
TypeNatHoleSid = '5'
|
||||
)
|
||||
|
||||
var (
|
||||
msgTypeMap = map[byte]interface{}{
|
||||
TypeLogin: Login{},
|
||||
TypeLoginResp: LoginResp{},
|
||||
TypeNewProxy: NewProxy{},
|
||||
TypeNewProxyResp: NewProxyResp{},
|
||||
TypeCloseProxy: CloseProxy{},
|
||||
TypeNewWorkConn: NewWorkConn{},
|
||||
TypeReqWorkConn: ReqWorkConn{},
|
||||
TypeStartWorkConn: StartWorkConn{},
|
||||
TypeNewVisitorConn: NewVisitorConn{},
|
||||
TypeNewVisitorConnResp: NewVisitorConnResp{},
|
||||
TypePing: Ping{},
|
||||
TypePong: Pong{},
|
||||
TypeUDPPacket: UDPPacket{},
|
||||
TypeNatHoleVisitor: NatHoleVisitor{},
|
||||
TypeNatHoleClient: NatHoleClient{},
|
||||
TypeNatHoleResp: NatHoleResp{},
|
||||
TypeNatHoleClientDetectOK: NatHoleClientDetectOK{},
|
||||
TypeNatHoleSid: NatHoleSid{},
|
||||
}
|
||||
)
|
||||
var msgTypeMap = map[byte]interface{}{
|
||||
TypeLogin: Login{},
|
||||
TypeLoginResp: LoginResp{},
|
||||
TypeNewProxy: NewProxy{},
|
||||
TypeNewProxyResp: NewProxyResp{},
|
||||
TypeCloseProxy: CloseProxy{},
|
||||
TypeNewWorkConn: NewWorkConn{},
|
||||
TypeReqWorkConn: ReqWorkConn{},
|
||||
TypeStartWorkConn: StartWorkConn{},
|
||||
TypeNewVisitorConn: NewVisitorConn{},
|
||||
TypeNewVisitorConnResp: NewVisitorConnResp{},
|
||||
TypePing: Ping{},
|
||||
TypePong: Pong{},
|
||||
TypeUDPPacket: UDPPacket{},
|
||||
TypeNatHoleVisitor: NatHoleVisitor{},
|
||||
TypeNatHoleClient: NatHoleClient{},
|
||||
TypeNatHoleResp: NatHoleResp{},
|
||||
TypeNatHoleClientDetectOK: NatHoleClientDetectOK{},
|
||||
TypeNatHoleSid: NatHoleSid{},
|
||||
}
|
||||
|
||||
// When frpc start, client send this message to login to server.
|
||||
type Login struct {
|
||||
Version string `json:"version"`
|
||||
Hostname string `json:"hostname"`
|
||||
Os string `json:"os"`
|
||||
Arch string `json:"arch"`
|
||||
User string `json:"user"`
|
||||
PrivilegeKey string `json:"privilege_key"`
|
||||
Timestamp int64 `json:"timestamp"`
|
||||
RunID string `json:"run_id"`
|
||||
Metas map[string]string `json:"metas"`
|
||||
Version string `json:"version,omitempty"`
|
||||
Hostname string `json:"hostname,omitempty"`
|
||||
Os string `json:"os,omitempty"`
|
||||
Arch string `json:"arch,omitempty"`
|
||||
User string `json:"user,omitempty"`
|
||||
PrivilegeKey string `json:"privilege_key,omitempty"`
|
||||
Timestamp int64 `json:"timestamp,omitempty"`
|
||||
RunID string `json:"run_id,omitempty"`
|
||||
Metas map[string]string `json:"metas,omitempty"`
|
||||
|
||||
// Some global configures.
|
||||
PoolCount int `json:"pool_count"`
|
||||
PoolCount int `json:"pool_count,omitempty"`
|
||||
}
|
||||
|
||||
type LoginResp struct {
|
||||
Version string `json:"version"`
|
||||
RunID string `json:"run_id"`
|
||||
ServerUDPPort int `json:"server_udp_port"`
|
||||
Error string `json:"error"`
|
||||
Version string `json:"version,omitempty"`
|
||||
RunID string `json:"run_id,omitempty"`
|
||||
ServerUDPPort int `json:"server_udp_port,omitempty"`
|
||||
Error string `json:"error,omitempty"`
|
||||
}
|
||||
|
||||
// When frpc login success, send this message to frps for running a new proxy.
|
||||
type NewProxy struct {
|
||||
ProxyName string `json:"proxy_name"`
|
||||
ProxyType string `json:"proxy_type"`
|
||||
UseEncryption bool `json:"use_encryption"`
|
||||
UseCompression bool `json:"use_compression"`
|
||||
Group string `json:"group"`
|
||||
GroupKey string `json:"group_key"`
|
||||
Metas map[string]string `json:"metas"`
|
||||
ProxyName string `json:"proxy_name,omitempty"`
|
||||
ProxyType string `json:"proxy_type,omitempty"`
|
||||
UseEncryption bool `json:"use_encryption,omitempty"`
|
||||
UseCompression bool `json:"use_compression,omitempty"`
|
||||
BandwidthLimit string `json:"bandwidth_limit,omitempty"`
|
||||
BandwidthLimitMode string `json:"bandwidth_limit_mode,omitempty"`
|
||||
Group string `json:"group,omitempty"`
|
||||
GroupKey string `json:"group_key,omitempty"`
|
||||
Metas map[string]string `json:"metas,omitempty"`
|
||||
|
||||
// tcp and udp only
|
||||
RemotePort int `json:"remote_port"`
|
||||
RemotePort int `json:"remote_port,omitempty"`
|
||||
|
||||
// http and https only
|
||||
CustomDomains []string `json:"custom_domains"`
|
||||
SubDomain string `json:"subdomain"`
|
||||
Locations []string `json:"locations"`
|
||||
HTTPUser string `json:"http_user"`
|
||||
HTTPPwd string `json:"http_pwd"`
|
||||
HostHeaderRewrite string `json:"host_header_rewrite"`
|
||||
Headers map[string]string `json:"headers"`
|
||||
CustomDomains []string `json:"custom_domains,omitempty"`
|
||||
SubDomain string `json:"subdomain,omitempty"`
|
||||
Locations []string `json:"locations,omitempty"`
|
||||
HTTPUser string `json:"http_user,omitempty"`
|
||||
HTTPPwd string `json:"http_pwd,omitempty"`
|
||||
HostHeaderRewrite string `json:"host_header_rewrite,omitempty"`
|
||||
Headers map[string]string `json:"headers,omitempty"`
|
||||
RouteByHTTPUser string `json:"route_by_http_user,omitempty"`
|
||||
|
||||
// stcp
|
||||
Sk string `json:"sk"`
|
||||
Sk string `json:"sk,omitempty"`
|
||||
|
||||
// tcpmux
|
||||
Multiplexer string `json:"multiplexer"`
|
||||
Multiplexer string `json:"multiplexer,omitempty"`
|
||||
}
|
||||
|
||||
type NewProxyResp struct {
|
||||
ProxyName string `json:"proxy_name"`
|
||||
RemoteAddr string `json:"remote_addr"`
|
||||
Error string `json:"error"`
|
||||
ProxyName string `json:"proxy_name,omitempty"`
|
||||
RemoteAddr string `json:"remote_addr,omitempty"`
|
||||
Error string `json:"error,omitempty"`
|
||||
}
|
||||
|
||||
type CloseProxy struct {
|
||||
ProxyName string `json:"proxy_name"`
|
||||
ProxyName string `json:"proxy_name,omitempty"`
|
||||
}
|
||||
|
||||
type NewWorkConn struct {
|
||||
RunID string `json:"run_id"`
|
||||
PrivilegeKey string `json:"privilege_key"`
|
||||
Timestamp int64 `json:"timestamp"`
|
||||
RunID string `json:"run_id,omitempty"`
|
||||
PrivilegeKey string `json:"privilege_key,omitempty"`
|
||||
Timestamp int64 `json:"timestamp,omitempty"`
|
||||
}
|
||||
|
||||
type ReqWorkConn struct {
|
||||
}
|
||||
type ReqWorkConn struct{}
|
||||
|
||||
type StartWorkConn struct {
|
||||
ProxyName string `json:"proxy_name"`
|
||||
SrcAddr string `json:"src_addr"`
|
||||
DstAddr string `json:"dst_addr"`
|
||||
SrcPort uint16 `json:"src_port"`
|
||||
DstPort uint16 `json:"dst_port"`
|
||||
Error string `json:"error"`
|
||||
ProxyName string `json:"proxy_name,omitempty"`
|
||||
SrcAddr string `json:"src_addr,omitempty"`
|
||||
DstAddr string `json:"dst_addr,omitempty"`
|
||||
SrcPort uint16 `json:"src_port,omitempty"`
|
||||
DstPort uint16 `json:"dst_port,omitempty"`
|
||||
Error string `json:"error,omitempty"`
|
||||
}
|
||||
|
||||
type NewVisitorConn struct {
|
||||
ProxyName string `json:"proxy_name"`
|
||||
SignKey string `json:"sign_key"`
|
||||
Timestamp int64 `json:"timestamp"`
|
||||
UseEncryption bool `json:"use_encryption"`
|
||||
UseCompression bool `json:"use_compression"`
|
||||
ProxyName string `json:"proxy_name,omitempty"`
|
||||
SignKey string `json:"sign_key,omitempty"`
|
||||
Timestamp int64 `json:"timestamp,omitempty"`
|
||||
UseEncryption bool `json:"use_encryption,omitempty"`
|
||||
UseCompression bool `json:"use_compression,omitempty"`
|
||||
}
|
||||
|
||||
type NewVisitorConnResp struct {
|
||||
ProxyName string `json:"proxy_name"`
|
||||
Error string `json:"error"`
|
||||
ProxyName string `json:"proxy_name,omitempty"`
|
||||
Error string `json:"error,omitempty"`
|
||||
}
|
||||
|
||||
type Ping struct {
|
||||
PrivilegeKey string `json:"privilege_key"`
|
||||
Timestamp int64 `json:"timestamp"`
|
||||
PrivilegeKey string `json:"privilege_key,omitempty"`
|
||||
Timestamp int64 `json:"timestamp,omitempty"`
|
||||
}
|
||||
|
||||
type Pong struct {
|
||||
Error string `json:"error"`
|
||||
Error string `json:"error,omitempty"`
|
||||
}
|
||||
|
||||
type UDPPacket struct {
|
||||
Content string `json:"c"`
|
||||
LocalAddr *net.UDPAddr `json:"l"`
|
||||
RemoteAddr *net.UDPAddr `json:"r"`
|
||||
Content string `json:"c,omitempty"`
|
||||
LocalAddr *net.UDPAddr `json:"l,omitempty"`
|
||||
RemoteAddr *net.UDPAddr `json:"r,omitempty"`
|
||||
}
|
||||
|
||||
type NatHoleVisitor struct {
|
||||
ProxyName string `json:"proxy_name"`
|
||||
SignKey string `json:"sign_key"`
|
||||
Timestamp int64 `json:"timestamp"`
|
||||
ProxyName string `json:"proxy_name,omitempty"`
|
||||
SignKey string `json:"sign_key,omitempty"`
|
||||
Timestamp int64 `json:"timestamp,omitempty"`
|
||||
}
|
||||
|
||||
type NatHoleClient struct {
|
||||
ProxyName string `json:"proxy_name"`
|
||||
Sid string `json:"sid"`
|
||||
ProxyName string `json:"proxy_name,omitempty"`
|
||||
Sid string `json:"sid,omitempty"`
|
||||
}
|
||||
|
||||
type NatHoleResp struct {
|
||||
Sid string `json:"sid"`
|
||||
VisitorAddr string `json:"visitor_addr"`
|
||||
ClientAddr string `json:"client_addr"`
|
||||
Error string `json:"error"`
|
||||
Sid string `json:"sid,omitempty"`
|
||||
VisitorAddr string `json:"visitor_addr,omitempty"`
|
||||
ClientAddr string `json:"client_addr,omitempty"`
|
||||
Error string `json:"error,omitempty"`
|
||||
}
|
||||
|
||||
type NatHoleClientDetectOK struct {
|
||||
}
|
||||
type NatHoleClientDetectOK struct{}
|
||||
|
||||
type NatHoleSid struct {
|
||||
Sid string `json:"sid"`
|
||||
Sid string `json:"sid,omitempty"`
|
||||
}
|
||||
|
@@ -7,15 +7,15 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/fatedier/golib/errors"
|
||||
"github.com/fatedier/golib/pool"
|
||||
|
||||
"github.com/fatedier/frp/pkg/msg"
|
||||
"github.com/fatedier/frp/pkg/util/log"
|
||||
"github.com/fatedier/frp/pkg/util/util"
|
||||
|
||||
"github.com/fatedier/golib/errors"
|
||||
"github.com/fatedier/golib/pool"
|
||||
)
|
||||
|
||||
// Timeout seconds.
|
||||
// NatHoleTimeout seconds.
|
||||
var NatHoleTimeout int64 = 10
|
||||
|
||||
type SidRequest struct {
|
||||
@@ -107,7 +107,7 @@ func (nc *Controller) HandleVisitor(m *msg.NatHoleVisitor, raddr *net.UDPAddr) {
|
||||
session := &Session{
|
||||
Sid: sid,
|
||||
VisitorAddr: raddr,
|
||||
NotifyCh: make(chan struct{}, 0),
|
||||
NotifyCh: make(chan struct{}),
|
||||
}
|
||||
nc.mu.Lock()
|
||||
clientCfg, ok := nc.clientCfgs[m.ProxyName]
|
||||
@@ -115,14 +115,14 @@ func (nc *Controller) HandleVisitor(m *msg.NatHoleVisitor, raddr *net.UDPAddr) {
|
||||
nc.mu.Unlock()
|
||||
errInfo := fmt.Sprintf("xtcp server for [%s] doesn't exist", m.ProxyName)
|
||||
log.Debug(errInfo)
|
||||
nc.listener.WriteToUDP(nc.GenNatHoleResponse(nil, errInfo), raddr)
|
||||
_, _ = nc.listener.WriteToUDP(nc.GenNatHoleResponse(nil, errInfo), raddr)
|
||||
return
|
||||
}
|
||||
if m.SignKey != util.GetAuthKey(clientCfg.Sk, m.Timestamp) {
|
||||
nc.mu.Unlock()
|
||||
errInfo := fmt.Sprintf("xtcp connection of [%s] auth failed", m.ProxyName)
|
||||
log.Debug(errInfo)
|
||||
nc.listener.WriteToUDP(nc.GenNatHoleResponse(nil, errInfo), raddr)
|
||||
_, _ = nc.listener.WriteToUDP(nc.GenNatHoleResponse(nil, errInfo), raddr)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -151,7 +151,7 @@ func (nc *Controller) HandleVisitor(m *msg.NatHoleVisitor, raddr *net.UDPAddr) {
|
||||
case <-session.NotifyCh:
|
||||
resp := nc.GenNatHoleResponse(session, "")
|
||||
log.Trace("send nat hole response to visitor")
|
||||
nc.listener.WriteToUDP(resp, raddr)
|
||||
_, _ = nc.listener.WriteToUDP(resp, raddr)
|
||||
case <-time.After(time.Duration(NatHoleTimeout) * time.Second):
|
||||
return
|
||||
}
|
||||
@@ -169,7 +169,7 @@ func (nc *Controller) HandleClient(m *msg.NatHoleClient, raddr *net.UDPAddr) {
|
||||
|
||||
resp := nc.GenNatHoleResponse(session, "")
|
||||
log.Trace("send nat hole response to client")
|
||||
nc.listener.WriteToUDP(resp, raddr)
|
||||
_, _ = nc.listener.WriteToUDP(resp, raddr)
|
||||
}
|
||||
|
||||
func (nc *Controller) GenNatHoleResponse(session *Session, errInfo string) []byte {
|
||||
|
@@ -86,17 +86,20 @@ func NewHTTP2HTTPSPlugin(params map[string]string) (Plugin, error) {
|
||||
}
|
||||
|
||||
p.s = &http.Server{
|
||||
Handler: rp,
|
||||
Handler: rp,
|
||||
ReadHeaderTimeout: 0,
|
||||
}
|
||||
|
||||
go p.s.Serve(listener)
|
||||
go func() {
|
||||
_ = p.s.Serve(listener)
|
||||
}()
|
||||
|
||||
return p, nil
|
||||
}
|
||||
|
||||
func (p *HTTP2HTTPSPlugin) Handle(conn io.ReadWriteCloser, realConn net.Conn, extraBufToLocal []byte) {
|
||||
wrapConn := frpNet.WrapReadWriteCloserToConn(conn, realConn)
|
||||
p.l.PutConn(wrapConn)
|
||||
_ = p.l.PutConn(wrapConn)
|
||||
}
|
||||
|
||||
func (p *HTTP2HTTPSPlugin) Name() string {
|
||||
|
@@ -22,10 +22,10 @@ import (
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
frpNet "github.com/fatedier/frp/pkg/util/net"
|
||||
|
||||
frpIo "github.com/fatedier/golib/io"
|
||||
gnet "github.com/fatedier/golib/net"
|
||||
|
||||
frpNet "github.com/fatedier/frp/pkg/util/net"
|
||||
)
|
||||
|
||||
const PluginHTTPProxy = "http_proxy"
|
||||
@@ -56,7 +56,9 @@ func NewHTTPProxyPlugin(params map[string]string) (Plugin, error) {
|
||||
Handler: hp,
|
||||
}
|
||||
|
||||
go hp.s.Serve(listener)
|
||||
go func() {
|
||||
_ = hp.s.Serve(listener)
|
||||
}()
|
||||
return hp, nil
|
||||
}
|
||||
|
||||
@@ -86,8 +88,7 @@ func (hp *HTTPProxy) Handle(conn io.ReadWriteCloser, realConn net.Conn, extraBuf
|
||||
return
|
||||
}
|
||||
|
||||
hp.l.PutConn(sc)
|
||||
return
|
||||
_ = hp.l.PutConn(sc)
|
||||
}
|
||||
|
||||
func (hp *HTTPProxy) Close() error {
|
||||
@@ -153,7 +154,7 @@ func (hp *HTTPProxy) ConnectHandler(rw http.ResponseWriter, req *http.Request) {
|
||||
client.Close()
|
||||
return
|
||||
}
|
||||
client.Write([]byte("HTTP/1.1 200 OK\r\n\r\n"))
|
||||
_, _ = client.Write([]byte("HTTP/1.1 200 OK\r\n\r\n"))
|
||||
|
||||
go frpIo.Join(remote, client)
|
||||
}
|
||||
@@ -188,7 +189,10 @@ func (hp *HTTPProxy) handleConnectReq(req *http.Request, rwc io.ReadWriteCloser)
|
||||
defer rwc.Close()
|
||||
if ok := hp.Auth(req); !ok {
|
||||
res := getBadResponse()
|
||||
res.Write(rwc)
|
||||
_ = res.Write(rwc)
|
||||
if res.Body != nil {
|
||||
res.Body.Close()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -200,10 +204,10 @@ func (hp *HTTPProxy) handleConnectReq(req *http.Request, rwc io.ReadWriteCloser)
|
||||
ProtoMajor: 1,
|
||||
ProtoMinor: 1,
|
||||
}
|
||||
res.Write(rwc)
|
||||
_ = res.Write(rwc)
|
||||
return
|
||||
}
|
||||
rwc.Write([]byte("HTTP/1.1 200 OK\r\n\r\n"))
|
||||
_, _ = rwc.Write([]byte("HTTP/1.1 200 OK\r\n\r\n"))
|
||||
|
||||
frpIo.Join(remote, rwc)
|
||||
}
|
||||
|
@@ -23,6 +23,7 @@ import (
|
||||
"net/http/httputil"
|
||||
"strings"
|
||||
|
||||
"github.com/fatedier/frp/pkg/transport"
|
||||
frpNet "github.com/fatedier/frp/pkg/util/net"
|
||||
)
|
||||
|
||||
@@ -58,12 +59,6 @@ func NewHTTPS2HTTPPlugin(params map[string]string) (Plugin, error) {
|
||||
}
|
||||
}
|
||||
|
||||
if crtPath == "" {
|
||||
return nil, fmt.Errorf("plugin_crt_path is required")
|
||||
}
|
||||
if keyPath == "" {
|
||||
return nil, fmt.Errorf("plugin_key_path is required")
|
||||
}
|
||||
if localAddr == "" {
|
||||
return nil, fmt.Errorf("plugin_local_addr is required")
|
||||
}
|
||||
@@ -96,13 +91,24 @@ func NewHTTPS2HTTPPlugin(params map[string]string) (Plugin, error) {
|
||||
Handler: rp,
|
||||
}
|
||||
|
||||
tlsConfig, err := p.genTLSConfig()
|
||||
var (
|
||||
tlsConfig *tls.Config
|
||||
err error
|
||||
)
|
||||
if crtPath != "" || keyPath != "" {
|
||||
tlsConfig, err = p.genTLSConfig()
|
||||
} else {
|
||||
tlsConfig, err = transport.NewServerTLSConfig("", "", "")
|
||||
tlsConfig.InsecureSkipVerify = true
|
||||
}
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("gen TLS config error: %v", err)
|
||||
}
|
||||
ln := tls.NewListener(listener, tlsConfig)
|
||||
|
||||
go p.s.Serve(ln)
|
||||
go func() {
|
||||
_ = p.s.Serve(ln)
|
||||
}()
|
||||
return p, nil
|
||||
}
|
||||
|
||||
@@ -118,7 +124,7 @@ func (p *HTTPS2HTTPPlugin) genTLSConfig() (*tls.Config, error) {
|
||||
|
||||
func (p *HTTPS2HTTPPlugin) Handle(conn io.ReadWriteCloser, realConn net.Conn, extraBufToLocal []byte) {
|
||||
wrapConn := frpNet.WrapReadWriteCloserToConn(conn, realConn)
|
||||
p.l.PutConn(wrapConn)
|
||||
_ = p.l.PutConn(wrapConn)
|
||||
}
|
||||
|
||||
func (p *HTTPS2HTTPPlugin) Name() string {
|
||||
|
@@ -23,6 +23,7 @@ import (
|
||||
"net/http/httputil"
|
||||
"strings"
|
||||
|
||||
"github.com/fatedier/frp/pkg/transport"
|
||||
frpNet "github.com/fatedier/frp/pkg/util/net"
|
||||
)
|
||||
|
||||
@@ -58,12 +59,6 @@ func NewHTTPS2HTTPSPlugin(params map[string]string) (Plugin, error) {
|
||||
}
|
||||
}
|
||||
|
||||
if crtPath == "" {
|
||||
return nil, fmt.Errorf("plugin_crt_path is required")
|
||||
}
|
||||
if keyPath == "" {
|
||||
return nil, fmt.Errorf("plugin_key_path is required")
|
||||
}
|
||||
if localAddr == "" {
|
||||
return nil, fmt.Errorf("plugin_local_addr is required")
|
||||
}
|
||||
@@ -101,13 +96,24 @@ func NewHTTPS2HTTPSPlugin(params map[string]string) (Plugin, error) {
|
||||
Handler: rp,
|
||||
}
|
||||
|
||||
tlsConfig, err := p.genTLSConfig()
|
||||
var (
|
||||
tlsConfig *tls.Config
|
||||
err error
|
||||
)
|
||||
if crtPath != "" || keyPath != "" {
|
||||
tlsConfig, err = p.genTLSConfig()
|
||||
} else {
|
||||
tlsConfig, err = transport.NewServerTLSConfig("", "", "")
|
||||
tlsConfig.InsecureSkipVerify = true
|
||||
}
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("gen TLS config error: %v", err)
|
||||
}
|
||||
ln := tls.NewListener(listener, tlsConfig)
|
||||
|
||||
go p.s.Serve(ln)
|
||||
go func() {
|
||||
_ = p.s.Serve(ln)
|
||||
}()
|
||||
return p, nil
|
||||
}
|
||||
|
||||
@@ -123,11 +129,11 @@ func (p *HTTPS2HTTPSPlugin) genTLSConfig() (*tls.Config, error) {
|
||||
|
||||
func (p *HTTPS2HTTPSPlugin) Handle(conn io.ReadWriteCloser, realConn net.Conn, extraBufToLocal []byte) {
|
||||
wrapConn := frpNet.WrapReadWriteCloserToConn(conn, realConn)
|
||||
p.l.PutConn(wrapConn)
|
||||
_ = p.l.PutConn(wrapConn)
|
||||
}
|
||||
|
||||
func (p *HTTPS2HTTPSPlugin) Name() string {
|
||||
return PluginHTTPS2HTTP
|
||||
return PluginHTTPS2HTTPS
|
||||
}
|
||||
|
||||
func (p *HTTPS2HTTPSPlugin) Close() error {
|
||||
|
@@ -19,9 +19,9 @@ import (
|
||||
"log"
|
||||
"net"
|
||||
|
||||
frpNet "github.com/fatedier/frp/pkg/util/net"
|
||||
|
||||
gosocks5 "github.com/armon/go-socks5"
|
||||
|
||||
frpNet "github.com/fatedier/frp/pkg/util/net"
|
||||
)
|
||||
|
||||
const PluginSocks5 = "socks5"
|
||||
@@ -32,9 +32,6 @@ func init() {
|
||||
|
||||
type Socks5Plugin struct {
|
||||
Server *gosocks5.Server
|
||||
|
||||
user string
|
||||
passwd string
|
||||
}
|
||||
|
||||
func NewSocks5Plugin(params map[string]string) (p Plugin, err error) {
|
||||
@@ -56,7 +53,7 @@ func NewSocks5Plugin(params map[string]string) (p Plugin, err error) {
|
||||
func (sp *Socks5Plugin) Handle(conn io.ReadWriteCloser, realConn net.Conn, extraBufToLocal []byte) {
|
||||
defer conn.Close()
|
||||
wrapConn := frpNet.WrapReadWriteCloserToConn(conn, realConn)
|
||||
sp.Server.ServeConn(wrapConn)
|
||||
_ = sp.Server.ServeConn(wrapConn)
|
||||
}
|
||||
|
||||
func (sp *Socks5Plugin) Name() string {
|
||||
|
@@ -19,9 +19,9 @@ import (
|
||||
"net"
|
||||
"net/http"
|
||||
|
||||
frpNet "github.com/fatedier/frp/pkg/util/net"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
|
||||
frpNet "github.com/fatedier/frp/pkg/util/net"
|
||||
)
|
||||
|
||||
const PluginStaticFile = "static_file"
|
||||
@@ -69,13 +69,15 @@ func NewStaticFilePlugin(params map[string]string) (Plugin, error) {
|
||||
sp.s = &http.Server{
|
||||
Handler: router,
|
||||
}
|
||||
go sp.s.Serve(listener)
|
||||
go func() {
|
||||
_ = sp.s.Serve(listener)
|
||||
}()
|
||||
return sp, nil
|
||||
}
|
||||
|
||||
func (sp *StaticFilePlugin) Handle(conn io.ReadWriteCloser, realConn net.Conn, extraBufToLocal []byte) {
|
||||
wrapConn := frpNet.WrapReadWriteCloserToConn(conn, realConn)
|
||||
sp.l.PutConn(wrapConn)
|
||||
_ = sp.l.PutConn(wrapConn)
|
||||
}
|
||||
|
||||
func (sp *StaticFilePlugin) Name() string {
|
||||
|
@@ -57,7 +57,9 @@ func (uds *UnixDomainSocketPlugin) Handle(conn io.ReadWriteCloser, realConn net.
|
||||
return
|
||||
}
|
||||
if len(extraBufToLocal) > 0 {
|
||||
localConn.Write(extraBufToLocal)
|
||||
if _, err := localConn.Write(extraBufToLocal); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
frpIo.Join(localConn, conn)
|
||||
|
@@ -43,12 +43,12 @@ type httpPlugin struct {
|
||||
}
|
||||
|
||||
func NewHTTPPluginOptions(options HTTPPluginOptions) Plugin {
|
||||
var url = fmt.Sprintf("%s%s", options.Addr, options.Path)
|
||||
url := fmt.Sprintf("%s%s", options.Addr, options.Path)
|
||||
|
||||
var client *http.Client
|
||||
if strings.HasPrefix(url, "https://") {
|
||||
tr := &http.Transport{
|
||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: options.TLSVerify == false},
|
||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: !options.TLSVerify},
|
||||
}
|
||||
client = &http.Client{Transport: tr}
|
||||
} else {
|
||||
|
@@ -18,6 +18,7 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/fatedier/frp/pkg/util/util"
|
||||
"github.com/fatedier/frp/pkg/util/xlog"
|
||||
@@ -26,6 +27,7 @@ import (
|
||||
type Manager struct {
|
||||
loginPlugins []Plugin
|
||||
newProxyPlugins []Plugin
|
||||
closeProxyPlugins []Plugin
|
||||
pingPlugins []Plugin
|
||||
newWorkConnPlugins []Plugin
|
||||
newUserConnPlugins []Plugin
|
||||
@@ -35,6 +37,7 @@ func NewManager() *Manager {
|
||||
return &Manager{
|
||||
loginPlugins: make([]Plugin, 0),
|
||||
newProxyPlugins: make([]Plugin, 0),
|
||||
closeProxyPlugins: make([]Plugin, 0),
|
||||
pingPlugins: make([]Plugin, 0),
|
||||
newWorkConnPlugins: make([]Plugin, 0),
|
||||
newUserConnPlugins: make([]Plugin, 0),
|
||||
@@ -48,6 +51,9 @@ func (m *Manager) Register(p Plugin) {
|
||||
if p.IsSupport(OpNewProxy) {
|
||||
m.newProxyPlugins = append(m.newProxyPlugins, p)
|
||||
}
|
||||
if p.IsSupport(OpCloseProxy) {
|
||||
m.closeProxyPlugins = append(m.closeProxyPlugins, p)
|
||||
}
|
||||
if p.IsSupport(OpPing) {
|
||||
m.pingPlugins = append(m.pingPlugins, p)
|
||||
}
|
||||
@@ -127,6 +133,31 @@ func (m *Manager) NewProxy(content *NewProxyContent) (*NewProxyContent, error) {
|
||||
return content, nil
|
||||
}
|
||||
|
||||
func (m *Manager) CloseProxy(content *CloseProxyContent) error {
|
||||
if len(m.closeProxyPlugins) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
errs := make([]string, 0)
|
||||
reqid, _ := util.RandID()
|
||||
xl := xlog.New().AppendPrefix("reqid: " + reqid)
|
||||
ctx := xlog.NewContext(context.Background(), xl)
|
||||
ctx = NewReqidContext(ctx, reqid)
|
||||
|
||||
for _, p := range m.closeProxyPlugins {
|
||||
_, _, err := p.Handle(ctx, OpCloseProxy, *content)
|
||||
if err != nil {
|
||||
xl.Warn("send CloseProxy request to plugin [%s] error: %v", p.Name(), err)
|
||||
errs = append(errs, fmt.Sprintf("[%s]: %v", p.Name(), err))
|
||||
}
|
||||
}
|
||||
|
||||
if len(errs) > 0 {
|
||||
return fmt.Errorf("send CloseProxy request to plugin errors: %s", strings.Join(errs, "; "))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Manager) Ping(content *PingContent) (*PingContent, error) {
|
||||
if len(m.pingPlugins) == 0 {
|
||||
return content, nil
|
||||
@@ -180,7 +211,7 @@ func (m *Manager) NewWorkConn(content *NewWorkConnContent) (*NewWorkConnContent,
|
||||
ctx = NewReqidContext(ctx, reqid)
|
||||
|
||||
for _, p := range m.newWorkConnPlugins {
|
||||
res, retContent, err = p.Handle(ctx, OpPing, *content)
|
||||
res, retContent, err = p.Handle(ctx, OpNewWorkConn, *content)
|
||||
if err != nil {
|
||||
xl.Warn("send NewWorkConn request to plugin [%s] error: %v", p.Name(), err)
|
||||
return nil, errors.New("send NewWorkConn request to plugin error")
|
||||
|
@@ -23,6 +23,7 @@ const (
|
||||
|
||||
OpLogin = "Login"
|
||||
OpNewProxy = "NewProxy"
|
||||
OpCloseProxy = "CloseProxy"
|
||||
OpPing = "Ping"
|
||||
OpNewWorkConn = "NewWorkConn"
|
||||
OpNewUserConn = "NewUserConn"
|
||||
|
@@ -33,6 +33,8 @@ type Response struct {
|
||||
|
||||
type LoginContent struct {
|
||||
msg.Login
|
||||
|
||||
ClientAddress string `json:"client_address,omitempty"`
|
||||
}
|
||||
|
||||
type UserInfo struct {
|
||||
@@ -46,6 +48,11 @@ type NewProxyContent struct {
|
||||
msg.NewProxy
|
||||
}
|
||||
|
||||
type CloseProxyContent struct {
|
||||
User UserInfo `json:"user"`
|
||||
msg.CloseProxy
|
||||
}
|
||||
|
||||
type PingContent struct {
|
||||
User UserInfo `json:"user"`
|
||||
msg.Ping
|
||||
|
@@ -20,10 +20,10 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/fatedier/frp/pkg/msg"
|
||||
|
||||
"github.com/fatedier/golib/errors"
|
||||
"github.com/fatedier/golib/pool"
|
||||
|
||||
"github.com/fatedier/frp/pkg/msg"
|
||||
)
|
||||
|
||||
func NewUDPPacket(buf []byte, laddr, raddr *net.UDPAddr) *msg.UDPPacket {
|
||||
@@ -47,7 +47,7 @@ func ForwardUserConn(udpConn *net.UDPConn, readCh <-chan *msg.UDPPacket, sendCh
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
udpConn.WriteToUDP(buf, udpMsg.RemoteAddr)
|
||||
_, _ = udpConn.WriteToUDP(buf, udpMsg.RemoteAddr)
|
||||
}
|
||||
}()
|
||||
|
||||
@@ -70,9 +70,7 @@ func ForwardUserConn(udpConn *net.UDPConn, readCh <-chan *msg.UDPPacket, sendCh
|
||||
}
|
||||
|
||||
func Forwarder(dstAddr *net.UDPAddr, readCh <-chan *msg.UDPPacket, sendCh chan<- msg.Message, bufSize int) {
|
||||
var (
|
||||
mu sync.RWMutex
|
||||
)
|
||||
var mu sync.RWMutex
|
||||
udpConnMap := make(map[string]*net.UDPConn)
|
||||
|
||||
// read from dstAddr and write to sendCh
|
||||
@@ -87,7 +85,7 @@ func Forwarder(dstAddr *net.UDPAddr, readCh <-chan *msg.UDPPacket, sendCh chan<-
|
||||
|
||||
buf := pool.GetBuf(bufSize)
|
||||
for {
|
||||
udpConn.SetReadDeadline(time.Now().Add(30 * time.Second))
|
||||
_ = udpConn.SetReadDeadline(time.Now().Add(30 * time.Second))
|
||||
n, _, err := udpConn.ReadFromUDP(buf)
|
||||
if err != nil {
|
||||
return
|
||||
|
@@ -19,7 +19,7 @@ func newCustomTLSKeyPair(certfile, keyfile string) (*tls.Certificate, error) {
|
||||
}
|
||||
|
||||
func newRandomTLSKeyPair() *tls.Certificate {
|
||||
key, err := rsa.GenerateKey(rand.Reader, 1024)
|
||||
key, err := rsa.GenerateKey(rand.Reader, 2048)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
@@ -58,7 +58,7 @@ func newCertPool(caPath string) (*x509.CertPool, error) {
|
||||
}
|
||||
|
||||
func NewServerTLSConfig(certPath, keyPath, caPath string) (*tls.Config, error) {
|
||||
var base = &tls.Config{}
|
||||
base := &tls.Config{}
|
||||
|
||||
if certPath == "" || keyPath == "" {
|
||||
// server will generate tls conf by itself
|
||||
@@ -87,7 +87,7 @@ func NewServerTLSConfig(certPath, keyPath, caPath string) (*tls.Config, error) {
|
||||
}
|
||||
|
||||
func NewClientTLSConfig(certPath, keyPath, caPath, serverName string) (*tls.Config, error) {
|
||||
var base = &tls.Config{}
|
||||
base := &tls.Config{}
|
||||
|
||||
if certPath == "" || keyPath == "" {
|
||||
// client will not generate tls conf by itself
|
||||
@@ -100,6 +100,8 @@ func NewClientTLSConfig(certPath, keyPath, caPath, serverName string) (*tls.Conf
|
||||
base.Certificates = []tls.Certificate{*cert}
|
||||
}
|
||||
|
||||
base.ServerName = serverName
|
||||
|
||||
if caPath != "" {
|
||||
pool, err := newCertPool(caPath)
|
||||
if err != nil {
|
||||
@@ -107,7 +109,6 @@ func NewClientTLSConfig(certPath, keyPath, caPath, serverName string) (*tls.Conf
|
||||
}
|
||||
|
||||
base.RootCAs = pool
|
||||
base.ServerName = serverName
|
||||
base.InsecureSkipVerify = false
|
||||
} else {
|
||||
base.InsecureSkipVerify = true
|
||||
|
@@ -40,19 +40,19 @@ func SetLogFile(logWay string, logFile string, maxdays int64, disableLogColor bo
|
||||
if logWay == "console" {
|
||||
params := ""
|
||||
if disableLogColor {
|
||||
params = fmt.Sprintf(`{"color": false}`)
|
||||
params = `{"color": false}`
|
||||
}
|
||||
Log.SetLogger("console", params)
|
||||
_ = Log.SetLogger("console", params)
|
||||
} else {
|
||||
params := fmt.Sprintf(`{"filename": "%s", "maxdays": %d}`, logFile, maxdays)
|
||||
Log.SetLogger("file", params)
|
||||
_ = Log.SetLogger("file", params)
|
||||
}
|
||||
}
|
||||
|
||||
// SetLogLevel set log level, default is warning
|
||||
// value: error, warning, info, debug, trace
|
||||
func SetLogLevel(logLevel string) {
|
||||
level := 4 // warning
|
||||
var level int
|
||||
switch logLevel {
|
||||
case "error":
|
||||
level = 3
|
||||
@@ -65,7 +65,7 @@ func SetLogLevel(logLevel string) {
|
||||
case "trace":
|
||||
level = 8
|
||||
default:
|
||||
level = 4
|
||||
level = 4 // warning
|
||||
}
|
||||
Log.SetLevel(level)
|
||||
}
|
||||
|
@@ -16,18 +16,15 @@ package net
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/fatedier/frp/pkg/util/xlog"
|
||||
quic "github.com/quic-go/quic-go"
|
||||
|
||||
gnet "github.com/fatedier/golib/net"
|
||||
kcp "github.com/fatedier/kcp-go"
|
||||
"github.com/fatedier/frp/pkg/util/xlog"
|
||||
)
|
||||
|
||||
type ContextGetter interface {
|
||||
@@ -189,55 +186,33 @@ func (statsConn *StatsConn) Close() (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func ConnectServer(protocol string, addr string) (c net.Conn, err error) {
|
||||
switch protocol {
|
||||
case "tcp":
|
||||
return net.Dial("tcp", addr)
|
||||
case "kcp":
|
||||
kcpConn, errRet := kcp.DialWithOptions(addr, nil, 10, 3)
|
||||
if errRet != nil {
|
||||
err = errRet
|
||||
return
|
||||
}
|
||||
kcpConn.SetStreamMode(true)
|
||||
kcpConn.SetWriteDelay(true)
|
||||
kcpConn.SetNoDelay(1, 20, 2, 1)
|
||||
kcpConn.SetWindowSize(128, 512)
|
||||
kcpConn.SetMtu(1350)
|
||||
kcpConn.SetACKNoDelay(false)
|
||||
kcpConn.SetReadBuffer(4194304)
|
||||
kcpConn.SetWriteBuffer(4194304)
|
||||
c = kcpConn
|
||||
return
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupport protocol: %s", protocol)
|
||||
type wrapQuicStream struct {
|
||||
quic.Stream
|
||||
c quic.Connection
|
||||
}
|
||||
|
||||
func QuicStreamToNetConn(s quic.Stream, c quic.Connection) net.Conn {
|
||||
return &wrapQuicStream{
|
||||
Stream: s,
|
||||
c: c,
|
||||
}
|
||||
}
|
||||
|
||||
func ConnectServerByProxy(proxyURL string, protocol string, addr string) (c net.Conn, err error) {
|
||||
switch protocol {
|
||||
case "tcp":
|
||||
return gnet.DialTcpByProxy(proxyURL, addr)
|
||||
case "kcp":
|
||||
// http proxy is not supported for kcp
|
||||
return ConnectServer(protocol, addr)
|
||||
case "websocket":
|
||||
return ConnectWebsocketServer(addr)
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupport protocol: %s", protocol)
|
||||
func (conn *wrapQuicStream) LocalAddr() net.Addr {
|
||||
if conn.c != nil {
|
||||
return conn.c.LocalAddr()
|
||||
}
|
||||
return (*net.TCPAddr)(nil)
|
||||
}
|
||||
|
||||
func ConnectServerByProxyWithTLS(proxyURL string, protocol string, addr string, tlsConfig *tls.Config, disableCustomTLSHeadByte bool) (c net.Conn, err error) {
|
||||
c, err = ConnectServerByProxy(proxyURL, protocol, addr)
|
||||
if err != nil {
|
||||
return
|
||||
func (conn *wrapQuicStream) RemoteAddr() net.Addr {
|
||||
if conn.c != nil {
|
||||
return conn.c.RemoteAddr()
|
||||
}
|
||||
|
||||
if tlsConfig == nil {
|
||||
return
|
||||
}
|
||||
|
||||
c = WrapTLSClientConn(c, tlsConfig, disableCustomTLSHeadByte)
|
||||
return
|
||||
return (*net.TCPAddr)(nil)
|
||||
}
|
||||
|
||||
func (conn *wrapQuicStream) Close() error {
|
||||
conn.Stream.CancelRead(0)
|
||||
return conn.Stream.Close()
|
||||
}
|
||||
|
44
pkg/util/net/dial.go
Normal file
44
pkg/util/net/dial.go
Normal file
@@ -0,0 +1,44 @@
|
||||
package net
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
"net/url"
|
||||
|
||||
libdial "github.com/fatedier/golib/net/dial"
|
||||
"golang.org/x/net/websocket"
|
||||
)
|
||||
|
||||
func DialHookCustomTLSHeadByte(enableTLS bool, disableCustomTLSHeadByte bool) libdial.AfterHookFunc {
|
||||
return func(ctx context.Context, c net.Conn, addr string) (context.Context, net.Conn, error) {
|
||||
if enableTLS && !disableCustomTLSHeadByte {
|
||||
_, err := c.Write([]byte{byte(FRPTLSHeadByte)})
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
}
|
||||
return ctx, c, nil
|
||||
}
|
||||
}
|
||||
|
||||
func DialHookWebsocket() libdial.AfterHookFunc {
|
||||
return func(ctx context.Context, c net.Conn, addr string) (context.Context, net.Conn, error) {
|
||||
addr = "ws://" + addr + FrpWebsocketPath
|
||||
uri, err := url.Parse(addr)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
origin := "http://" + uri.Host
|
||||
cfg, err := websocket.NewConfig(addr, origin)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
conn, err := websocket.NewClient(cfg, c)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
return ctx, conn, nil
|
||||
}
|
||||
}
|
@@ -32,8 +32,8 @@ func ListenKcp(address string) (l *KCPListener, err error) {
|
||||
if err != nil {
|
||||
return l, err
|
||||
}
|
||||
listener.SetReadBuffer(4194304)
|
||||
listener.SetWriteBuffer(4194304)
|
||||
_ = listener.SetReadBuffer(4194304)
|
||||
_ = listener.SetWriteBuffer(4194304)
|
||||
|
||||
l = &KCPListener{
|
||||
listener: listener,
|
||||
|
@@ -23,40 +23,30 @@ import (
|
||||
gnet "github.com/fatedier/golib/net"
|
||||
)
|
||||
|
||||
var (
|
||||
FRPTLSHeadByte = 0x17
|
||||
)
|
||||
|
||||
func WrapTLSClientConn(c net.Conn, tlsConfig *tls.Config, disableCustomTLSHeadByte bool) (out net.Conn) {
|
||||
if !disableCustomTLSHeadByte {
|
||||
c.Write([]byte{byte(FRPTLSHeadByte)})
|
||||
}
|
||||
out = tls.Client(c, tlsConfig)
|
||||
return
|
||||
}
|
||||
var FRPTLSHeadByte = 0x17
|
||||
|
||||
func CheckAndEnableTLSServerConnWithTimeout(
|
||||
c net.Conn, tlsConfig *tls.Config, tlsOnly bool, timeout time.Duration,
|
||||
) (out net.Conn, isTLS bool, custom bool, err error) {
|
||||
|
||||
sc, r := gnet.NewSharedConnSize(c, 2)
|
||||
buf := make([]byte, 1)
|
||||
var n int
|
||||
c.SetReadDeadline(time.Now().Add(timeout))
|
||||
_ = c.SetReadDeadline(time.Now().Add(timeout))
|
||||
n, err = r.Read(buf)
|
||||
c.SetReadDeadline(time.Time{})
|
||||
_ = c.SetReadDeadline(time.Time{})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if n == 1 && int(buf[0]) == FRPTLSHeadByte {
|
||||
switch {
|
||||
case n == 1 && int(buf[0]) == FRPTLSHeadByte:
|
||||
out = tls.Server(c, tlsConfig)
|
||||
isTLS = true
|
||||
custom = true
|
||||
} else if n == 1 && int(buf[0]) == 0x16 {
|
||||
case n == 1 && int(buf[0]) == 0x16:
|
||||
out = tls.Server(sc, tlsConfig)
|
||||
isTLS = true
|
||||
} else {
|
||||
default:
|
||||
if tlsOnly {
|
||||
err = fmt.Errorf("non-TLS connection received on a TlsOnly server")
|
||||
return
|
||||
|
@@ -18,6 +18,7 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
@@ -54,7 +55,7 @@ func NewFakeUDPConn(l *UDPListener, laddr, raddr net.Addr) *FakeUDPConn {
|
||||
for {
|
||||
time.Sleep(5 * time.Second)
|
||||
fc.mu.RLock()
|
||||
if time.Now().Sub(fc.lastActive) > 10*time.Second {
|
||||
if time.Since(fc.lastActive) > 10*time.Second {
|
||||
fc.mu.RUnlock()
|
||||
fc.Close()
|
||||
break
|
||||
@@ -67,8 +68,7 @@ func NewFakeUDPConn(l *UDPListener, laddr, raddr net.Addr) *FakeUDPConn {
|
||||
|
||||
func (c *FakeUDPConn) putPacket(content []byte) {
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
}
|
||||
_ = recover()
|
||||
}()
|
||||
|
||||
select {
|
||||
@@ -108,7 +108,7 @@ func (c *FakeUDPConn) Write(b []byte) (n int, err error) {
|
||||
LocalAddr: c.localAddr,
|
||||
RemoteAddr: c.remoteAddr,
|
||||
}
|
||||
c.l.writeUDPPacket(packet)
|
||||
_ = c.l.writeUDPPacket(packet)
|
||||
|
||||
c.mu.Lock()
|
||||
c.lastActive = time.Now()
|
||||
@@ -163,7 +163,7 @@ type UDPListener struct {
|
||||
}
|
||||
|
||||
func ListenUDP(bindAddr string, bindPort int) (l *UDPListener, err error) {
|
||||
udpAddr, err := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", bindAddr, bindPort))
|
||||
udpAddr, err := net.ResolveUDPAddr("udp", net.JoinHostPort(bindAddr, strconv.Itoa(bindPort)))
|
||||
if err != nil {
|
||||
return l, err
|
||||
}
|
||||
@@ -207,7 +207,7 @@ func ListenUDP(bindAddr string, bindPort int) (l *UDPListener, err error) {
|
||||
}
|
||||
|
||||
if addr, ok := packet.RemoteAddr.(*net.UDPAddr); ok {
|
||||
readConn.WriteToUDP(packet.Buf, addr)
|
||||
_, _ = readConn.WriteToUDP(packet.Buf, addr)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
@@ -2,18 +2,14 @@ package net
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"time"
|
||||
"strconv"
|
||||
|
||||
"golang.org/x/net/websocket"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrWebsocketListenerClosed = errors.New("websocket listener closed")
|
||||
)
|
||||
var ErrWebsocketListenerClosed = errors.New("websocket listener closed")
|
||||
|
||||
const (
|
||||
FrpWebsocketPath = "/~!frp"
|
||||
@@ -23,8 +19,7 @@ type WebsocketListener struct {
|
||||
ln net.Listener
|
||||
acceptCh chan net.Conn
|
||||
|
||||
server *http.Server
|
||||
httpMutex *http.ServeMux
|
||||
server *http.Server
|
||||
}
|
||||
|
||||
// NewWebsocketListener to handle websocket connections
|
||||
@@ -49,12 +44,14 @@ func NewWebsocketListener(ln net.Listener) (wl *WebsocketListener) {
|
||||
Handler: muxer,
|
||||
}
|
||||
|
||||
go wl.server.Serve(ln)
|
||||
go func() {
|
||||
_ = wl.server.Serve(ln)
|
||||
}()
|
||||
return
|
||||
}
|
||||
|
||||
func ListenWebsocket(bindAddr string, bindPort int) (*WebsocketListener, error) {
|
||||
tcpLn, err := net.Listen("tcp", fmt.Sprintf("%s:%d", bindAddr, bindPort))
|
||||
tcpLn, err := net.Listen("tcp", net.JoinHostPort(bindAddr, strconv.Itoa(bindPort)))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -77,27 +74,3 @@ func (p *WebsocketListener) Close() error {
|
||||
func (p *WebsocketListener) Addr() net.Addr {
|
||||
return p.ln.Addr()
|
||||
}
|
||||
|
||||
// addr: domain:port
|
||||
func ConnectWebsocketServer(addr string) (net.Conn, error) {
|
||||
addr = "ws://" + addr + FrpWebsocketPath
|
||||
uri, err := url.Parse(addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
origin := "http://" + uri.Host
|
||||
cfg, err := websocket.NewConfig(addr, origin)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.Dialer = &net.Dialer{
|
||||
Timeout: 10 * time.Second,
|
||||
}
|
||||
|
||||
conn, err := websocket.DialConfig(cfg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return conn, nil
|
||||
}
|
||||
|
@@ -22,20 +22,27 @@ import (
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
gnet "github.com/fatedier/golib/net"
|
||||
|
||||
"github.com/fatedier/frp/pkg/util/util"
|
||||
"github.com/fatedier/frp/pkg/util/vhost"
|
||||
)
|
||||
|
||||
type HTTPConnectTCPMuxer struct {
|
||||
*vhost.Muxer
|
||||
|
||||
passthrough bool
|
||||
authRequired bool // Not supported until we really need this.
|
||||
}
|
||||
|
||||
func NewHTTPConnectTCPMuxer(listener net.Listener, timeout time.Duration) (*HTTPConnectTCPMuxer, error) {
|
||||
mux, err := vhost.NewMuxer(listener, getHostFromHTTPConnect, nil, sendHTTPOk, nil, timeout)
|
||||
return &HTTPConnectTCPMuxer{mux}, err
|
||||
func NewHTTPConnectTCPMuxer(listener net.Listener, passthrough bool, timeout time.Duration) (*HTTPConnectTCPMuxer, error) {
|
||||
ret := &HTTPConnectTCPMuxer{passthrough: passthrough, authRequired: false}
|
||||
mux, err := vhost.NewMuxer(listener, ret.getHostFromHTTPConnect, nil, ret.sendConnectResponse, nil, timeout)
|
||||
ret.Muxer = mux
|
||||
return ret, err
|
||||
}
|
||||
|
||||
func readHTTPConnectRequest(rd io.Reader) (host string, err error) {
|
||||
func (muxer *HTTPConnectTCPMuxer) readHTTPConnectRequest(rd io.Reader) (host string, httpUser string, err error) {
|
||||
bufioReader := bufio.NewReader(rd)
|
||||
|
||||
req, err := http.ReadRequest(bufioReader)
|
||||
@@ -48,21 +55,49 @@ func readHTTPConnectRequest(rd io.Reader) (host string, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
host = util.GetHostFromAddr(req.Host)
|
||||
host, _ = util.CanonicalHost(req.Host)
|
||||
proxyAuth := req.Header.Get("Proxy-Authorization")
|
||||
if proxyAuth != "" {
|
||||
httpUser, _, _ = util.ParseBasicAuth(proxyAuth)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func sendHTTPOk(c net.Conn) error {
|
||||
return util.OkResponse().Write(c)
|
||||
func (muxer *HTTPConnectTCPMuxer) sendConnectResponse(c net.Conn, reqInfo map[string]string) error {
|
||||
if muxer.passthrough {
|
||||
return nil
|
||||
}
|
||||
res := util.OkResponse()
|
||||
if res.Body != nil {
|
||||
defer res.Body.Close()
|
||||
}
|
||||
return res.Write(c)
|
||||
}
|
||||
|
||||
func getHostFromHTTPConnect(c net.Conn) (_ net.Conn, _ map[string]string, err error) {
|
||||
func (muxer *HTTPConnectTCPMuxer) getHostFromHTTPConnect(c net.Conn) (net.Conn, map[string]string, error) {
|
||||
reqInfoMap := make(map[string]string, 0)
|
||||
host, err := readHTTPConnectRequest(c)
|
||||
sc, rd := gnet.NewSharedConn(c)
|
||||
|
||||
host, httpUser, err := muxer.readHTTPConnectRequest(rd)
|
||||
if err != nil {
|
||||
return nil, reqInfoMap, err
|
||||
}
|
||||
|
||||
reqInfoMap["Host"] = host
|
||||
reqInfoMap["Scheme"] = "tcp"
|
||||
return c, reqInfoMap, nil
|
||||
reqInfoMap["HTTPUser"] = httpUser
|
||||
|
||||
outConn := c
|
||||
if muxer.passthrough {
|
||||
outConn = sc
|
||||
if muxer.authRequired && httpUser == "" {
|
||||
resp := util.ProxyUnauthorizedResponse()
|
||||
if resp.Body != nil {
|
||||
defer resp.Body.Close()
|
||||
}
|
||||
_ = resp.Write(c)
|
||||
outConn = c
|
||||
}
|
||||
}
|
||||
return outConn, reqInfoMap, nil
|
||||
}
|
||||
|
@@ -15,6 +15,7 @@
|
||||
package util
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"net"
|
||||
"net/http"
|
||||
"strings"
|
||||
@@ -34,15 +35,18 @@ func OkResponse() *http.Response {
|
||||
return res
|
||||
}
|
||||
|
||||
// TODO: use "CanonicalHost" func to replace all "GetHostFromAddr" func.
|
||||
func GetHostFromAddr(addr string) (host string) {
|
||||
strs := strings.Split(addr, ":")
|
||||
if len(strs) > 1 {
|
||||
host = strs[0]
|
||||
} else {
|
||||
host = addr
|
||||
func ProxyUnauthorizedResponse() *http.Response {
|
||||
header := make(http.Header)
|
||||
header.Set("Proxy-Authenticate", `Basic realm="Restricted"`)
|
||||
res := &http.Response{
|
||||
Status: "Proxy Authentication Required",
|
||||
StatusCode: 407,
|
||||
Proto: "HTTP/1.1",
|
||||
ProtoMajor: 1,
|
||||
ProtoMinor: 1,
|
||||
Header: header,
|
||||
}
|
||||
return
|
||||
return res
|
||||
}
|
||||
|
||||
// canonicalHost strips port from host if present and returns the canonicalized
|
||||
@@ -56,10 +60,8 @@ func CanonicalHost(host string) (string, error) {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
if strings.HasSuffix(host, ".") {
|
||||
// Strip trailing dot from fully qualified domain names.
|
||||
host = host[:len(host)-1]
|
||||
}
|
||||
// Strip trailing dot from fully qualified domain names.
|
||||
host = strings.TrimSuffix(host, ".")
|
||||
return host, nil
|
||||
}
|
||||
|
||||
@@ -75,3 +77,21 @@ func hasPort(host string) bool {
|
||||
}
|
||||
return host[0] == '[' && strings.Contains(host, "]:")
|
||||
}
|
||||
|
||||
func ParseBasicAuth(auth string) (username, password string, ok bool) {
|
||||
const prefix = "Basic "
|
||||
// Case insensitive prefix match. See Issue 22736.
|
||||
if len(auth) < len(prefix) || !strings.EqualFold(auth[:len(prefix)], prefix) {
|
||||
return
|
||||
}
|
||||
c, err := base64.StdEncoding.DecodeString(auth[len(prefix):])
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
cs := string(c)
|
||||
s := strings.IndexByte(cs, ':')
|
||||
if s < 0 {
|
||||
return
|
||||
}
|
||||
return cs[:s], cs[s+1:], true
|
||||
}
|
||||
|
@@ -19,8 +19,11 @@ import (
|
||||
"crypto/rand"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
mathrand "math/rand"
|
||||
"net"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// RandID return a rand string used in frp.
|
||||
@@ -41,9 +44,9 @@ func RandIDWithLen(idLen int) (id string, err error) {
|
||||
}
|
||||
|
||||
func GetAuthKey(token string, timestamp int64) (key string) {
|
||||
token = token + fmt.Sprintf("%d", timestamp)
|
||||
md5Ctx := md5.New()
|
||||
md5Ctx.Write([]byte(token))
|
||||
md5Ctx.Write([]byte(strconv.FormatInt(timestamp, 10)))
|
||||
data := md5Ctx.Sum(nil)
|
||||
return hex.EncodeToString(data)
|
||||
}
|
||||
@@ -52,7 +55,7 @@ func CanonicalAddr(host string, port int) (addr string) {
|
||||
if port == 80 || port == 443 {
|
||||
addr = host
|
||||
} else {
|
||||
addr = fmt.Sprintf("%s:%d", host, port)
|
||||
addr = net.JoinHostPort(host, strconv.Itoa(port))
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -67,7 +70,8 @@ func ParseRangeNumbers(rangeStr string) (numbers []int64, err error) {
|
||||
numArray := strings.Split(numRangeStr, "-")
|
||||
// length: only 1 or 2 is correct
|
||||
rangeType := len(numArray)
|
||||
if rangeType == 1 {
|
||||
switch rangeType {
|
||||
case 1:
|
||||
// single number
|
||||
singleNum, errRet := strconv.ParseInt(strings.TrimSpace(numArray[0]), 10, 64)
|
||||
if errRet != nil {
|
||||
@@ -75,7 +79,7 @@ func ParseRangeNumbers(rangeStr string) (numbers []int64, err error) {
|
||||
return
|
||||
}
|
||||
numbers = append(numbers, singleNum)
|
||||
} else if rangeType == 2 {
|
||||
case 2:
|
||||
// range numbers
|
||||
min, errRet := strconv.ParseInt(strings.TrimSpace(numArray[0]), 10, 64)
|
||||
if errRet != nil {
|
||||
@@ -94,7 +98,7 @@ func ParseRangeNumbers(rangeStr string) (numbers []int64, err error) {
|
||||
for i := min; i <= max; i++ {
|
||||
numbers = append(numbers, i)
|
||||
}
|
||||
} else {
|
||||
default:
|
||||
err = fmt.Errorf("range number is invalid")
|
||||
return
|
||||
}
|
||||
@@ -108,3 +112,17 @@ func GenerateResponseErrorString(summary string, err error, detailed bool) strin
|
||||
}
|
||||
return summary
|
||||
}
|
||||
|
||||
func RandomSleep(duration time.Duration, minRatio, maxRatio float64) time.Duration {
|
||||
min := int64(minRatio * 1000.0)
|
||||
max := int64(maxRatio * 1000.0)
|
||||
var n int64
|
||||
if max <= min {
|
||||
n = min
|
||||
} else {
|
||||
n = mathrand.Int63n(max-min) + min
|
||||
}
|
||||
d := duration * time.Duration(n) / time.Duration(1000)
|
||||
time.Sleep(d)
|
||||
return d
|
||||
}
|
||||
|
@@ -19,7 +19,7 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
var version string = "0.38.0"
|
||||
var version = "0.47.0"
|
||||
|
||||
func Full() string {
|
||||
return version
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user