Compare commits

...
94 Commits
Author SHA1 Message Date
xjasonlyu 8fcd8fee85 Fix(fd): compile error 2021-11-01 14:01:21 +08:00
xjasonlyu e06cce1dd4 Chore: update go modules
$ go mod tidy -compat=1.17
2021-11-01 13:07:07 +08:00
xjasonlyu 867cfefa76 Chore(workflows/go): ignore docs 2021-10-19 21:13:14 +08:00
xjasonlyu 176324412b Chore: update README 2021-10-19 21:11:29 +08:00
xjasonlyu 66e9c6d4e9 Chore: update modules 2021-10-17 14:30:19 +08:00
xjasonlyu 3928350e57 Chore: minor reposition 2021-10-17 14:29:08 +08:00
xjasonlyu f6ba31f121 Feature: support fd device
Experimental support for file descriptor based device, may be used like `fd://3`
2021-10-17 14:21:37 +08:00
xjasonlyu bf3f4599cc Chore(tun): remove with options 2021-10-17 14:12:54 +08:00
xjasonlyu dc8e4f1ba1 Feature: new fd driver 2021-10-17 14:07:11 +08:00
xjasonlyu ad53cc7ffe Chore: correct a typo 2021-10-12 19:55:21 +08:00
xjasonlyu 10022388a0 Chore(workflows): ignore GSC tags 2021-10-04 13:32:18 +08:00
xjasonlyu 377aae12c7 Platform: Windows ARM64 2021-10-04 13:13:31 +08:00
xjasonlyu 3f5b3c9eb3 Chore: update go modules 2021-10-04 11:35:37 +08:00
xjasonlyu 07ce5e6422 Feature: socks5 over unix domain socket(UDS) support
this feature is compatible with tor proxy.
2021-09-09 12:50:23 +08:00
xjasonlyu e1ca5069e0 Revert(engine): default scheme
This reverts commit a86608e31a.
2021-09-09 12:10:57 +08:00
xjasonlyu 05f4938053 Chore: minor improvement 2021-09-05 23:34:02 +08:00
xjasonlyu a86608e31a Optimize(engine): default scheme 2021-09-04 22:11:08 +08:00
xjasonlyu c478adee34 Fix: rwbased interface implementation 2021-09-04 21:46:40 +08:00
xjasonlyu a3f1713d14 Chore: update modules 2021-09-04 21:45:56 +08:00
xjasonlyu 525d424fca Chore: go1.17 build constraints 2021-08-21 10:48:37 +08:00
xjasonlyu f1420b9592 Chore: update go modules 2021-08-21 10:38:27 +08:00
xjasonlyu 4601b4ef74 Chore: bump go version to 1.17 2021-08-21 10:29:29 +08:00
xjasonlyu 85cf694b8f Chore: bump mod version 2021-08-13 11:44:34 +08:00
xjasonlyu bf59ddf897 Refactor: move to transport 2021-07-19 14:08:46 +08:00
xjasonlyu ccc35c3c1b Refactor(tunnel): using parseAddr 2021-07-19 14:04:17 +08:00
xjasonlyu e77c12156a Chore: update modules 2021-07-18 16:32:48 +08:00
xjasonlyu f60e5add20 Fix(socks4): various improvement 2021-07-18 16:29:23 +08:00
xjasonlyu ebc275c5f7 Fix(socks4): using io.ReadFull 2021-07-17 13:03:43 +08:00
xjasonlyu b6d4272e58 Chore: disable nightly release 2021-07-17 10:48:19 +08:00
xjasonlyu 591361abb3 Refactor(socks4a): using isReservedIP 2021-07-17 10:44:59 +08:00
xjasonlyu 7dea46e6f2 Chore: update README 2021-07-16 20:26:41 +08:00
xjasonlyu e0d6c6d5af Feature: SOCKS4/SOCKS4A proxy support 2021-07-16 20:23:00 +08:00
xjasonlyu ca331e5ef6 Chore: bump mod version 2021-07-16 18:42:22 +08:00
xjasonlyu ab2f4043f7 Feature: HTTP proxy support 2021-07-16 18:39:46 +08:00
xjasonlyu 33e2aed86c Refactor(proxy): replace with safeConnClose 2021-07-16 17:51:58 +08:00
xjasonlyu c2ad0930b0 Fix: invalid workflow file 2021-07-16 17:07:50 +08:00
xjasonlyu 5e90e34f93 Chore: update actions 2021-07-16 17:05:53 +08:00
xjasonlyu 991ad5a967 Chore: remove NewBase 2021-07-16 16:43:50 +08:00
xjasonlyu 27ecddbbf6 Chore: update go modules
Main modules:
- gvisor.dev/gvisor v0.0.0-20210528151111-2153eaa44276 => v0.0.0-20210715005044-a22d3ae8e0fd
- golang.zx2c4.com/wireguard v0.0.0-20210525143454-64cb82f2b3f5 => v0.0.0-20210624150102-15b24b6179e0
2021-07-15 20:01:55 +08:00
xjasonlyu 842920c39b Feature: add reject proxy 2021-07-15 19:54:56 +08:00
xjasonlyu 67cc84d1d0 Chore: update go modules 2021-05-31 18:33:22 +08:00
xjasonlyu 94c0b4a873 Chore: rename SetForwarding to SetForwardingDefaultAndAllNICs 2021-05-24 17:19:02 +08:00
xjasonlyu 659f4c3020 Chore: update go modules 2021-05-24 17:18:11 +08:00
xjasonlyu b95e2794b3 Chore: comment text 2021-05-13 14:06:07 +08:00
xjasonlyu 70afaf3d55 Fix(stack): update udp transport 2021-05-13 13:29:26 +08:00
xjasonlyu b51ad6feb1 Fix(rwbased): endpoint interface 2021-05-13 13:13:22 +08:00
xjasonlyu 9618b7a7b8 Chore: update go modules
use original gvisor tcpip stack.
2021-05-13 13:10:32 +08:00
xjasonlyu 60021cc0ef Chore: update discussions 2021-05-05 13:40:41 +08:00
xjasonlyu 293fab7635 Chore: update README_ZH 2021-05-05 13:20:33 +08:00
Jason LyuandGitHub 1c4e782314 Update issue templates 2021-05-05 13:01:17 +08:00
xjasonlyu 66710aa203 Fix: panics with invalid ss url (https://github.com/xjasonlyu/tun2socks/issues/49) 2021-05-05 11:59:47 +08:00
xjasonlyu 3f7fdc1d83 Fix: atomic operation panic
This reverts commit 094199656b.
2021-03-22 13:04:49 +08:00
xjasonlyu 1bd8029562 Optimize: use gvisor tun for linux 2021-03-21 21:13:07 +08:00
xjasonlyu a1847d7153 Fix: udp for gvisor stack 2021-03-21 20:57:18 +08:00
xjasonlyu 36144e7484 Chore: update dependencies 2021-03-21 20:44:57 +08:00
xjasonlyu 094199656b Chore: make set operation atomic 2021-03-13 11:50:14 +08:00
xjasonlyu f41b844e43 Chore: minor changes in actions 2021-03-03 12:56:02 +08:00
xjasonlyu 688d74a407 Chore: add more info to socks5 2021-03-03 12:46:31 +08:00
xjasonlyu 1b2dddff31 Chore: update dependencies 2021-03-02 23:25:52 +08:00
xjasonlyu 82ac59b0f2 Fix: invalid argument when set MTU (https://github.com/xjasonlyu/tun2socks/issues/33) 2021-03-01 21:37:46 +08:00
xjasonlyu 6887c1180e Chore: add udp-timeout option to docker image 2021-02-28 14:16:23 +08:00
xjasonlyu 9502706ed9 Feature: add an option to set udp timeout 2021-02-26 14:22:16 +08:00
xjasonlyu ec4d98c4bf Fix: reset udp timeout after sending 2021-02-26 09:50:34 +08:00
xjasonlyu ee932ff16c Chore: update static check command 2021-02-22 14:16:39 +08:00
xjasonlyu a8fdfe537d Chore: update dependencies 2021-02-22 12:39:47 +08:00
xjasonlyu ac07d3d6fd Feature: add 32bit support 2021-02-17 17:42:06 +08:00
xjasonlyu d5d4b17256 Fix: dirty commit string 2021-02-17 17:02:15 +08:00
xjasonlyu 4531a74a20 Feature: add darwin-arm64 support (https://github.com/xjasonlyu/tun2socks/issues/29) 2021-02-17 16:12:01 +08:00
xjasonlyu b15f93225b Chore: bump to go1.16 2021-02-17 16:10:11 +08:00
xjasonlyu edf76afd11 Chore: tidy Dockerfile 2021-02-17 13:32:39 +08:00
xjasonlyu bb702f57d8 Feature: add linux-s390x 2021-02-15 20:18:33 +08:00
xjasonlyu b5980dd79d Chore: update README 2021-02-14 20:46:08 +08:00
xjasonlyu 2fee5a6d55 Chore: update dependencies 2021-02-14 20:41:50 +08:00
xjasonlyu b2b7e8bc46 Chore(tun): minor changes 2021-02-14 20:38:26 +08:00
xjasonlyu 0e1e04acc7 Fix: avoid extra copy on windows 2021-02-14 20:25:04 +08:00
xjasonlyu 361a8133c9 Chore: spaces to tab 2021-02-14 17:33:12 +08:00
xjasonlyu 3f73becd66 Fix: ignore static check 2021-02-14 15:50:44 +08:00
xjasonlyu 14b905c125 Feature: full 64bit support 2021-02-14 15:45:42 +08:00
xjasonlyu 4294f56125 Chore: use gVisor 20210213011838-e7ae604b523e 2021-02-14 11:44:54 +08:00
xjasonlyu d98e2234d9 Chore: always use zip to release 2021-02-14 11:21:36 +08:00
xjasonlyu 43b8dd885d Chore: udp timeout => 60s 2021-02-13 13:18:30 +08:00
xjasonlyu 3e3990ef8d Chore: update README 2021-02-12 14:41:33 +08:00
xjasonlyu 88e9402793 Chore: go workflow ignore docker 2021-02-11 22:26:59 +08:00
xjasonlyu f0129eb7ca Chore: optimize docker/entrypoint.sh 2021-02-11 18:51:05 +08:00
xjasonlyu fe9be45844 Chore: tidy go.sum 2021-02-11 16:56:20 +08:00
xjasonlyu b54d9936f9 Chore: unexported globals with _
Use uber’s go style.
2021-02-11 16:10:40 +08:00
xjasonlyu 7e6a9b6a09 Chore: add a comment to dialer 2021-02-11 16:04:20 +08:00
xjasonlyu 454ea0a49b Fix(log): default level may race
Rename global variables in uber’s style.
2021-02-11 15:56:45 +08:00
xjasonlyu 04d0e1e9a7 Chore: move to wiki 2021-02-11 14:19:37 +08:00
xjasonlyu e849c9a451 Fix(stack/udp): shadow variables 2021-02-11 14:01:36 +08:00
xjasonlyu c28690bfc9 Fix: deprecate metadata.Valid method 2021-02-11 13:55:53 +08:00
xjasonlyu 7955052b01 Chore: adjust version output format 2021-02-11 13:40:01 +08:00
xjasonlyu 7e55b71b30 Fix: replace pflag with flag
pflag was deprecated due to poor maintenance
2021-02-11 13:06:12 +08:00
xjasonlyu c96c5946c8 Fix: /proc/sys permission in docker 2021-02-10 20:21:22 +08:00
64 changed files with 1344 additions and 1193 deletions
+1 -1
View File
@@ -2,5 +2,5 @@
.gitignore
# Other
bin/*
build/*
docs/*
+33
View File
@@ -0,0 +1,33 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''
---
**Environment**
- OS: [e.g. `Ubuntu-20.04`]
- Version: [e.g. `v2.1.0`]
- Network: [e.g. route tables, iptables rules]
**Log**
Paste the tun2socks log below with the log level set to `DEBUG`.
```
```
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. [First Step]
2. [Second Step]
3. ……
**Expected behavior**
A clear and concise description of what you expected to happen.
**Additional context**
Add any other context about the problem here.
+20
View File
@@ -0,0 +1,20 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: ''
assignees: ''
---
**Is your feature request related to a problem?**
A clear and concise description of what the problem is.
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.
+14 -14
View File
@@ -3,12 +3,12 @@ name: Publish Docker Image
on:
push:
branches:
- dev
- 'main'
tags:
- '*'
paths-ignore:
- 'docs/**'
- '**.md'
- 'docs/**'
jobs:
@@ -45,29 +45,29 @@ jobs:
username: xjasonlyu
password: ${{ secrets.CR_PAT }}
- name: Build and Push (dev)
if: github.ref == 'refs/heads/dev'
uses: docker/build-push-action@v2
with:
context: .
push: true
platforms: linux/amd64,linux/arm64
tags: |
xjasonlyu/tun2socks:dev
ghcr.io/xjasonlyu/tun2socks:dev
- name: Get Version
id: shell
run: |
echo ::set-output name=version::$(git describe --tags --abbrev=0)
- name: Build and Push (nightly)
if: github.ref == 'refs/heads/main'
uses: docker/build-push-action@v2
with:
context: .
push: true
platforms: linux/amd64,linux/arm/v7,linux/arm64
tags: |
xjasonlyu/tun2socks:nightly
ghcr.io/xjasonlyu/tun2socks:nightly
- name: Build and Push (latest)
if: startsWith(github.ref, 'refs/tags/')
uses: docker/build-push-action@v2
with:
context: .
push: true
platforms: linux/amd64,linux/arm64
platforms: linux/amd64,linux/arm/v7,linux/arm64
tags: |
xjasonlyu/tun2socks:latest
xjasonlyu/tun2socks:${{ steps.shell.outputs.version }}
+11 -25
View File
@@ -1,31 +1,31 @@
name: Go
name: Go Static Check
on:
pull_request:
push:
branches:
- dev
tags:
- '*'
tags-ignore:
- '*'
paths-ignore:
- 'docs/**'
- '**.md'
- 'docs/**'
pull_request:
jobs:
build:
name: Build
runs-on: ubuntu-latest
steps:
- name: Setup Go
uses: actions/setup-go@v2
with:
go-version: 1.15.x
- name: Check out code into the Go module directory
uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Setup Go
uses: actions/setup-go@v2
with:
go-version: 1.17.x
- name: Cache go module
uses: actions/cache@v2
with:
@@ -38,19 +38,5 @@ jobs:
run: |
go test ./...
go vet ./...
go get -u honnef.co/go/tools/cmd/staticcheck
go install honnef.co/go/tools/cmd/staticcheck@latest
staticcheck -- $(go list ./...)
- name: Build
if: startsWith(github.ref, 'refs/tags/')
run: make -j releases
- name: Upload Release
uses: softprops/action-gh-release@v1
if: startsWith(github.ref, 'refs/tags/')
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
files: bin/*
draft: true
prerelease: true
+38
View File
@@ -0,0 +1,38 @@
name: Publish Go Releases
on:
push:
tags:
- '*'
paths-ignore:
- '**.md'
- 'docs/**'
- 'docker/**'
jobs:
build:
name: Build
runs-on: ubuntu-latest
steps:
- name: Check out code into the Go module directory
uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Setup Go
uses: actions/setup-go@v2
with:
go-version: 1.17.x
- name: Build
run: make -j releases
- name: Upload Releases
uses: softprops/action-gh-release@v1
if: startsWith(github.ref, 'refs/tags/')
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
files: build/*
draft: true
prerelease: false
+1 -1
View File
@@ -4,7 +4,7 @@
*.dll
*.so
*.dylib
bin/
build/
# IDE
.idea/
+3 -3
View File
@@ -4,9 +4,8 @@ WORKDIR /tun2socks-src
COPY . /tun2socks-src
RUN apk add --no-cache make git \
&& go mod download \
&& make tun2socks \
&& mv ./bin/tun2socks /tun2socks
&& mv ./build/tun2socks /tun2socks
FROM alpine:latest
LABEL org.opencontainers.image.source="https://github.com/xjasonlyu/tun2socks"
@@ -18,12 +17,13 @@ RUN apk add --update --no-cache iptables iproute2 \
&& chmod +x /entrypoint.sh
ENV TUN=tun0
ENV TUN_ADDR=198.18.0.1/15
ENV ADDR=198.18.0.1/15
ENV LOGLEVEL=info
ENV PROXY=direct://
ENV MTU=9000
ENV STATS=
ENV TOKEN=
ENV UDP_TIMEOUT=
ENV EXTRA_COMMANDS=
ENV TUN_INCLUDED_ROUTES=
ENV TUN_EXCLUDED_ROUTES=
+110 -30
View File
@@ -1,71 +1,151 @@
BINDIR = "bin"
NAME = "tun2socks"
BINARY := tun2socks
MODULE := github.com/xjasonlyu/tun2socks
BUILD_FLAGS = "-v"
BUILD_TAGS = ""
BUILD_TIME = $(shell date -u '+%FT%TZ')
BUILD_VERSION = $(shell git describe --tags)
BUILD_DIR := build
BUILD_TAGS :=
BUILD_FLAGS := -v
BUILD_COMMIT := $(shell git rev-parse --short HEAD)
BUILD_VERSION := $(shell git describe --abbrev=0 --tags HEAD)
CGO_ENABLED := 0
GO111MODULE := on
LDFLAGS += -w -s -buildid=
LDFLAGS += -X "github.com/xjasonlyu/tun2socks/constant.Version=$(BUILD_VERSION)"
LDFLAGS += -X "github.com/xjasonlyu/tun2socks/constant.BuildTime=$(BUILD_TIME)" # RFC3339
LDFLAGS += -X "$(MODULE)/constant.Version=$(BUILD_VERSION)"
LDFLAGS += -X "$(MODULE)/constant.GitCommit=$(BUILD_COMMIT)"
GO_BUILD = GO111MODULE=on CGO_ENABLED=0 go build $(BUILD_FLAGS) -ldflags '$(LDFLAGS)' -tags '$(BUILD_TAGS)' -trimpath
GO_BUILD = GO111MODULE=$(GO111MODULE) CGO_ENABLED=$(CGO_ENABLED) \
go build $(BUILD_FLAGS) -ldflags '$(LDFLAGS)' -tags '$(BUILD_TAGS)' -trimpath
PLATFORM_LIST = \
UNIX_ARCH_LIST = \
darwin-amd64 \
darwin-arm64 \
freebsd-386 \
freebsd-amd64 \
freebsd-arm64 \
linux-386 \
linux-amd64 \
linux-arm64 \
linux-armv5 \
linux-armv6 \
linux-armv7 \
linux-mips-softfloat \
linux-mips-hardfloat \
linux-mipsle-softfloat \
linux-mipsle-hardfloat \
linux-mips64 \
linux-mips64le \
linux-ppc64 \
linux-ppc64le \
linux-s390x \
openbsd-386 \
openbsd-amd64 \
openbsd-arm64 \
openbsd-arm64
WINDOWS_ARCH_LIST = \
windows-386 \
windows-amd64 \
windows-arm64 \
windows-arm32v7
all: linux-amd64 darwin-amd64 windows-amd64
tun2socks:
$(GO_BUILD) -o $(BINDIR)/$(NAME)
$(GO_BUILD) -o $(BUILD_DIR)/$(BINARY)
darwin-amd64:
GOARCH=amd64 GOOS=darwin $(GO_BUILD) -o $(BINDIR)/$(NAME)-$@
GOARCH=amd64 GOOS=darwin $(GO_BUILD) -o $(BUILD_DIR)/$(BINARY)-$@
darwin-arm64:
GOARCH=arm64 GOOS=darwin $(GO_BUILD) -o $(BUILD_DIR)/$(BINARY)-$@
freebsd-386:
GOARCH=386 GOOS=freebsd $(GO_BUILD) -o $(BUILD_DIR)/$(BINARY)-$@
freebsd-amd64:
GOARCH=amd64 GOOS=freebsd $(GO_BUILD) -o $(BINDIR)/$(NAME)-$@
GOARCH=amd64 GOOS=freebsd $(GO_BUILD) -o $(BUILD_DIR)/$(BINARY)-$@
freebsd-arm64:
GOARCH=arm64 GOOS=freebsd $(GO_BUILD) -o $(BINDIR)/$(NAME)-$@
GOARCH=arm64 GOOS=freebsd $(GO_BUILD) -o $(BUILD_DIR)/$(BINARY)-$@
linux-386:
GOARCH=386 GOOS=linux $(GO_BUILD) -o $(BUILD_DIR)/$(BINARY)-$@
linux-amd64:
GOARCH=amd64 GOOS=linux $(GO_BUILD) -o $(BINDIR)/$(NAME)-$@
GOARCH=amd64 GOOS=linux $(GO_BUILD) -o $(BUILD_DIR)/$(BINARY)-$@
linux-arm64:
GOARCH=arm64 GOOS=linux $(GO_BUILD) -o $(BINDIR)/$(NAME)-$@
GOARCH=arm64 GOOS=linux $(GO_BUILD) -o $(BUILD_DIR)/$(BINARY)-$@
linux-armv5:
GOARCH=arm GOARM=5 GOOS=linux $(GO_BUILD) -o $(BUILD_DIR)/$(BINARY)-$@
linux-armv6:
GOARCH=arm GOARM=6 GOOS=linux $(GO_BUILD) -o $(BUILD_DIR)/$(BINARY)-$@
linux-armv7:
GOARCH=arm GOARM=7 GOOS=linux $(GO_BUILD) -o $(BUILD_DIR)/$(BINARY)-$@
linux-mips-softfloat:
GOARCH=mips GOMIPS=softfloat GOOS=linux $(GO_BUILD) -o $(BUILD_DIR)/$(BINARY)-$@
linux-mips-hardfloat:
GOARCH=mips GOMIPS=hardfloat GOOS=linux $(GO_BUILD) -o $(BUILD_DIR)/$(BINARY)-$@
linux-mipsle-softfloat:
GOARCH=mipsle GOMIPS=softfloat GOOS=linux $(GO_BUILD) -o $(BUILD_DIR)/$(BINARY)-$@
linux-mipsle-hardfloat:
GOARCH=mipsle GOMIPS=hardfloat GOOS=linux $(GO_BUILD) -o $(BUILD_DIR)/$(BINARY)-$@
linux-mips64:
GOARCH=mips64 GOOS=linux $(GO_BUILD) -o $(BUILD_DIR)/$(BINARY)-$@
linux-mips64le:
GOARCH=mips64le GOOS=linux $(GO_BUILD) -o $(BUILD_DIR)/$(BINARY)-$@
linux-ppc64:
GOARCH=ppc64 GOOS=linux $(GO_BUILD) -o $(BUILD_DIR)/$(BINARY)-$@
linux-ppc64le:
GOARCH=ppc64le GOOS=linux $(GO_BUILD) -o $(BUILD_DIR)/$(BINARY)-$@
linux-s390x:
GOARCH=s390x GOOS=linux $(GO_BUILD) -o $(BUILD_DIR)/$(BINARY)-$@
openbsd-386:
GOARCH=386 GOOS=openbsd $(GO_BUILD) -o $(BUILD_DIR)/$(BINARY)-$@
openbsd-amd64:
GOARCH=amd64 GOOS=openbsd $(GO_BUILD) -o $(BINDIR)/$(NAME)-$@
GOARCH=amd64 GOOS=openbsd $(GO_BUILD) -o $(BUILD_DIR)/$(BINARY)-$@
openbsd-arm64:
GOARCH=arm64 GOOS=openbsd $(GO_BUILD) -o $(BINDIR)/$(NAME)-$@
GOARCH=arm64 GOOS=openbsd $(GO_BUILD) -o $(BUILD_DIR)/$(BINARY)-$@
windows-386:
GOARCH=386 GOOS=windows $(GO_BUILD) -o $(BUILD_DIR)/$(BINARY)-$@.exe
windows-amd64:
GOARCH=amd64 GOOS=windows $(GO_BUILD) -o $(BINDIR)/$(NAME)-$@.exe
GOARCH=amd64 GOOS=windows $(GO_BUILD) -o $(BUILD_DIR)/$(BINARY)-$@.exe
gz_releases=$(addsuffix .gz, $(PLATFORM_LIST))
zip_releases=$(addsuffix .zip, $(WINDOWS_ARCH_LIST))
windows-arm64:
GOARCH=arm64 GOOS=windows $(GO_BUILD) -o $(BUILD_DIR)/$(BINARY)-$@.exe
$(gz_releases): %.gz : %
chmod +x $(BINDIR)/$(NAME)-$(basename $@)
gzip -f -S .gz $(BINDIR)/$(NAME)-$(basename $@)
windows-arm32v7:
GOARCH=arm GOARM=7 GOOS=windows $(GO_BUILD) -o $(BUILD_DIR)/$(BINARY)-$@.exe
$(zip_releases): %.zip : %
zip -m -j $(BINDIR)/$(NAME)-$(basename $@).zip $(BINDIR)/$(NAME)-$(basename $@).exe
unix_releases := $(addsuffix .zip, $(UNIX_ARCH_LIST))
windows_releases := $(addsuffix .zip, $(WINDOWS_ARCH_LIST))
all-arch: $(PLATFORM_LIST) $(WINDOWS_ARCH_LIST)
$(unix_releases): %.zip: %
@zip -qmj $(BUILD_DIR)/$(BINARY)-$(basename $@).zip $(BUILD_DIR)/$(BINARY)-$(basename $@)
releases: $(gz_releases) $(zip_releases)
$(windows_releases): %.zip: %
@zip -qmj $(BUILD_DIR)/$(BINARY)-$(basename $@).zip $(BUILD_DIR)/$(BINARY)-$(basename $@).exe
all-arch: $(UNIX_ARCH_LIST) $(WINDOWS_ARCH_LIST)
releases: $(unix_releases) $(windows_releases)
clean:
rm $(BINDIR)/*
rm -rf $(BUILD_DIR)
+39 -51
View File
@@ -4,72 +4,60 @@
[![Go Version][2]](https://github.com/xjasonlyu/tun2socks/blob/main/go.mod)
[![Go Report][3]](https://goreportcard.com/badge/github.com/xjasonlyu/tun2socks)
[![GitHub License][4]](https://github.com/xjasonlyu/tun2socks/blob/main/LICENSE)
[![Total Lines][5]](https://img.shields.io/tokei/lines/github/xjasonlyu/tun2socks?style=flat-square)
[![Releases][6]](https://github.com/xjasonlyu/tun2socks/releases)
[![Releases][5]](https://github.com/xjasonlyu/tun2socks/releases)
[1]: https://img.shields.io/github/workflow/status/xjasonlyu/tun2socks/Go?style=flat-square
[2]: https://img.shields.io/github/go-mod/go-version/xjasonlyu/tun2socks/main?style=flat-square
[3]: https://goreportcard.com/badge/github.com/xjasonlyu/tun2socks?style=flat-square
[4]: https://img.shields.io/github/license/xjasonlyu/tun2socks?style=flat-square
[5]: https://img.shields.io/tokei/lines/github/xjasonlyu/tun2socks?style=flat-square
[6]: https://img.shields.io/github/v/release/xjasonlyu/tun2socks?include_prereleases&style=flat-square
[5]: https://img.shields.io/github/v/release/xjasonlyu/tun2socks?include_prereleases&style=flat-square
English | [简体中文](README_ZH.md)
# What is tun2socks?
`tun2socks` is an application used to "socksify" TCP/UDP (IPv4 and IPv6) traffic at the network layer. It implements a TUN virtual network interface which accepts all incoming TCP/UDP packets and forwards them through a SOCKS server.
## Features
- ICMP echoing / IPv6 support / Socks5 & SS proxy
- `SO_BINDTODEVICE` & `SO_MARK` option support
- Optimized UDP transmission for game acceleration
- Pure Go implementation, no more CGO required
- Router mode, routing all the traffic in LAN
- TCP/IP stack powered by *[gVisor](https://github.com/google/gvisor)*
- More than *2.5Gbps* throughput (10x faster than [v1](https://github.com/xjasonlyu/tun2socks/tree/v1))
## Requirements
| Target | Minimum | Recommended |
| :----- | :-----: | :---------: |
| System | Linux MacOS Freebsd OpenBSD Windows | Linux or MacOS |
| Memory | >20MB | >128MB |
| CPU | AMD64(x86_64) ARM64 | AMD64 with AES-NI & AVX2 |
- **Network Support**
- Dualstack: `IPv4/IPv6`
- Forwarder: `TCP/UDP`
- Ping Echo: `ICMP`
- **Platform Support**
- Linux
- MacOS
- Windows
- FreeBSD
- OpenBSD
- **Proxy Protocol**
- HTTP
- Socks4
- Socks5
- Shadowsocks
- **Extra Feature**
- Improved stability without CGO
- Optimized UDP transmission for game
- Performed with >2.5Gbps throughput
- TCP/IP stack powered by **[gVisor](https://github.com/google/gvisor)**
## Documentation
Documentations and quick start guides can be found at [Github Wiki](https://github.com/xjasonlyu/tun2socks/wiki).
Docs and quick start guides can be found at [Github Wiki](https://github.com/xjasonlyu/tun2socks/wiki).
## Building from source
## Community
Due to the limitation of gVisor, tun2socks only supports x86_64 and ARM64 for now. Other architectures may become available in the future.
### Environments
Make sure the following dependencies are installed:
- Go 1.15+
### Building
Build and install the `tun2socks` binary:
```shell
make tun2socks
sudo cp ./bin/tun2socks /usr/local/bin
```
Build for all architectures:
```shell
make all-arch
```
Welcome and feel free to ask any questions at [Github Discussions](https://github.com/xjasonlyu/tun2socks/discussions).
## Credits
- [Dreamacro/clash](https://github.com/Dreamacro/clash)
- [google/gvisor](https://github.com/google/gvisor)
- [majek/slirpnetstack](https://github.com/majek/slirpnetstack)
- [WireGuard/wireguard-go](https://git.zx2c4.com/wireguard-go)
- [Dreamacro/clash](https://github.com/Dreamacro/clash) - A rule-based tunnel in Go
- [google/gvisor](https://github.com/google/gvisor) - Application Kernel for Containers
- [wireguard-go](https://git.zx2c4.com/wireguard-go) - Go Implementation of WireGuard
## License
[GPL-3.0](https://github.com/xjasonlyu/tun2socks/blob/main/LICENSE)
[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fxjasonlyu%2Ftun2socks.svg?type=large)](https://app.fossa.com/projects/git%2Bgithub.com%2Fxjasonlyu%2Ftun2socks?ref=badge_large)
## Stargazers over time
[![Stargazers over time](https://starchart.cc/xjasonlyu/tun2socks.svg)](https://starchart.cc/xjasonlyu/tun2socks)
+25 -54
View File
@@ -4,40 +4,34 @@
[![Go Version][2]](https://github.com/xjasonlyu/tun2socks/blob/main/go.mod)
[![Go Report][3]](https://goreportcard.com/badge/github.com/xjasonlyu/tun2socks)
[![GitHub License][4]](https://github.com/xjasonlyu/tun2socks/blob/main/LICENSE)
[![Total Lines][5]](https://img.shields.io/tokei/lines/github/xjasonlyu/tun2socks?style=flat-square)
[![Releases][6]](https://github.com/xjasonlyu/tun2socks/releases)
[![Releases][5]](https://github.com/xjasonlyu/tun2socks/releases)
[1]: https://img.shields.io/github/workflow/status/xjasonlyu/tun2socks/Go?style=flat-square
[2]: https://img.shields.io/github/go-mod/go-version/xjasonlyu/tun2socks/main?style=flat-square
[3]: https://goreportcard.com/badge/github.com/xjasonlyu/tun2socks?style=flat-square
[4]: https://img.shields.io/github/license/xjasonlyu/tun2socks?style=flat-square
[5]: https://img.shields.io/tokei/lines/github/xjasonlyu/tun2socks?style=flat-square
[6]: https://img.shields.io/github/v/release/xjasonlyu/tun2socks?include_prereleases&style=flat-square
[5]: https://img.shields.io/github/v/release/xjasonlyu/tun2socks?include_prereleases&style=flat-square
[English](README.md) | 简体中文
## 什么是 tun2socks
`tun2socks`是一个用来将网络层的`TCP/UDP`(包括`IPv4``IPv6`)流量套接字化的应用。它实现了一个`TUN`虚拟网卡接口,可以把所有到来的`TCP/UDP`包处理并转发给SOCKS服务器。
## 为什么使用 tun2socks
通过在主机上运行`tun2socks`,可以轻松地接管所有的`TCP/UDP`流量,同时提供诸多专业的功能特性,这包括:
- 强制使不支持代理的程序走代理
- 合Clash、V2Ray等代理后端实现全局科学上网
- 合Burp、Charles等工具进行应用层数据的调试
- 合DHCP、CoreDNS等应用部署路由模式代理局域网流量
- 合Clash、V2Ray等工具实现全局代理上网
- 合Burp、Charles等工具进行应用层数据的调试
- 合DHCP、CoreDNS等工具部署路由模式代理局域网流量
## 特性介绍
- ICMP 回应 / IPv6 支持 / Socks5 和 SS 代理支持
- `SO_BINDTODEVICE` & `SO_MARK` 套接字选项支持
- 适用于游戏加速针对UDP流量传输的专门优化
- Go 实现,不再需要 CGO提升了稳定性
- 路由模式,可以用来转发代理局域网内所有流量
- 核心由 *[gVisor](https://github.com/google/gvisor)* 强力驱动的 TCP/IP 网络栈
- 超过 *2.5Gbps* 的带宽吞吐量([v1](https://github.com/xjasonlyu/tun2socks/tree/v1) 版本的10x倍以上)
- **全面支持:** IPv4/IPv6/ICMP/TCP/UDP
- **代理协议:** HTTP/Socks4/Socks5/Shadowsocks
- **游戏加速** 针对UDP传输的优化
- **纯Go实现** 无需CGO,稳定性提升
- **路由模式** 转发代理局域网内所有流量
- **TCP/IP栈:** 由 **[gVisor](https://github.com/google/gvisor)** 强力驱动
- **高性能:** >2.5Gbps 的带宽吞吐量
## 硬件需求
@@ -45,43 +39,15 @@
| :--- | :---: | :---: |
| 系统 | Linux MacOS Freebsd OpenBSD Windows | Linux or MacOS |
| 内存 | >20MB | >128MB |
| 架构 | AMD64(x86_64) ARM64 | AMD64 with AES-NI & AVX2 |
| 架构 | ANY | AMD64 or ARM64 |
## 使用文档
文档以及使用方式,请看 [Github Wiki](https://github.com/xjasonlyu/tun2socks/wiki)。
## 源码编译
## 交流讨论
由于 tun2socks 是基于 gVisor 的 TCP/IP 栈,所以目前只支持 x86_64 和 ARM64 架构。以后其他的架构的支持取决于 gVisor
### 环境依赖
确保安装了以下环境:
- Go 1.15+
### 开始编译
编译以及安装 `tun2socks` 二进制文件:
```shell
make tun2socks
sudo cp ./bin/tun2socks /usr/local/bin
```
编译所有架构的二进制文件:
```shell
make all-arch
```
## 特别感谢
- [Dreamacro/clash](https://github.com/Dreamacro/clash)
- [google/gvisor](https://github.com/google/gvisor)
- [majek/slirpnetstack](https://github.com/majek/slirpnetstack)
- [WireGuard/wireguard-go](https://git.zx2c4.com/wireguard-go)
欢迎来讨论区交流提问,[Github Discussions](https://github.com/xjasonlyu/tun2socks/discussions)
## 注意事项
@@ -89,9 +55,14 @@ make all-arch
2. `tun2socks`只应该专注于将网络层的TCP/UDP流量转发给SOCKS服务器,其他的如DNS(DoH)、DHCP等模块功能应该交由第三方应用实现,所以弃用了DNS模块。
3. 因为是通过用户空间的网络栈接管所有流量并处理转发,在高吞吐时CPU的使用量会剧增,所以CPU的性能直接与可以达到的最大带宽挂钩。
## TODO
## 特别感谢
- [x] Windows 支持
- [x] FreeBSD 支持
- [x] OpenBSD 支持
- [ ] ~~自动路由模式~~
- [Dreamacro/clash](https://github.com/Dreamacro/clash) - A rule-based tunnel in Go
- [google/gvisor](https://github.com/google/gvisor) - Application Kernel for Containers
- [wireguard-go](https://git.zx2c4.com/wireguard-go) - Go Implementation of WireGuard
## License
[GPL-3.0](https://github.com/xjasonlyu/tun2socks/blob/main/LICENSE)
[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fxjasonlyu%2Ftun2socks.svg?type=large)](https://app.fossa.com/projects/git%2Bgithub.com%2Fxjasonlyu%2Ftun2socks?ref=badge_large)
+1 -1
View File
@@ -1,4 +1,4 @@
// +build !linux,!darwin
//go:build !linux && !darwin
package dialer
+1 -1
View File
@@ -1,4 +1,4 @@
// +build !linux
//go:build !linux
package dialer
+2
View File
@@ -3,6 +3,8 @@ package dialer
import "net"
func init() {
// We must use this DialContext to query DNS
// when using net default resolver.
net.DefaultResolver.PreferGo = true
net.DefaultResolver.Dial = DialContext
}
+1 -5
View File
@@ -7,7 +7,7 @@ import (
"net"
"strconv"
"github.com/xjasonlyu/tun2socks/component/socks5"
"github.com/xjasonlyu/tun2socks/transport/socks5"
)
const (
@@ -87,7 +87,3 @@ func (m *Metadata) Network() string {
func (m *Metadata) String() string {
return m.DestinationAddress()
}
func (m *Metadata) Valid() bool {
return m.SrcIP != nil && m.DstIP != nil
}
+5 -3
View File
@@ -1,8 +1,10 @@
package constant
const Name = "tun2socks"
const (
Name = "tun2socks"
)
var (
Version = ""
BuildTime = ""
Version string
GitCommit string
)
+3
View File
@@ -0,0 +1,3 @@
package fd
const Driver = "fd"
+41
View File
@@ -0,0 +1,41 @@
//go:build !windows
package fd
import (
"fmt"
"strconv"
"github.com/xjasonlyu/tun2socks/core/device"
"golang.org/x/sys/unix"
"gvisor.dev/gvisor/pkg/tcpip/stack"
)
type FD struct {
stack.LinkEndpoint
fd int
mtu uint32
}
func Open(name string, mtu uint32) (device.Device, error) {
fd, err := strconv.Atoi(name)
if err != nil {
return nil, fmt.Errorf("cannot open fd: %s", name)
}
return open(fd, mtu)
}
func (f *FD) Type() string {
return Driver
}
func (f *FD) Name() string {
return strconv.Itoa(f.fd)
}
func (f *FD) Close() error {
return unix.Close(f.fd)
}
var _ device.Device = (*FD)(nil)
+11
View File
@@ -0,0 +1,11 @@
package fd
import (
"errors"
"github.com/xjasonlyu/tun2socks/core/device"
)
func Open(name string, mtu uint32) (device.Device, error) {
return nil, errors.New("not supported")
}
+24
View File
@@ -0,0 +1,24 @@
package fd
import (
"fmt"
"github.com/xjasonlyu/tun2socks/core/device"
"gvisor.dev/gvisor/pkg/tcpip/link/fdbased"
)
func open(fd int, mtu uint32) (device.Device, error) {
f := &FD{fd: fd, mtu: mtu}
ep, err := fdbased.New(&fdbased.Options{
MTU: mtu,
FDs: []int{fd},
EthernetHeader: false,
})
if err != nil {
return nil, fmt.Errorf("create endpoint: %w", err)
}
f.LinkEndpoint = ep
return f, nil
}
+23
View File
@@ -0,0 +1,23 @@
//go:build !linux && !windows
package fd
import (
"fmt"
"os"
"github.com/xjasonlyu/tun2socks/core/device"
"github.com/xjasonlyu/tun2socks/core/device/rwbased"
)
func open(fd int, mtu uint32) (device.Device, error) {
f := &FD{fd: fd, mtu: mtu}
ep, err := rwbased.New(os.NewFile(uintptr(fd), f.Name()), mtu)
if err != nil {
return nil, fmt.Errorf("create endpoint: %w", err)
}
f.LinkEndpoint = ep
return f, nil
}
+7 -3
View File
@@ -1,4 +1,4 @@
// Package channel provides the implementation of io.ReadWriter
// Package rwbased provides the implementation of io.ReadWriter
// based data-link layer endpoints.
package rwbased
@@ -90,12 +90,12 @@ func (e *Endpoint) writePacket(pkt *stack.PacketBuffer) tcpip.Error {
}
// WritePacket writes packet back into io.ReadWriter.
func (e *Endpoint) WritePacket(_ stack.RouteInfo, _ *stack.GSO, _ tcpip.NetworkProtocolNumber, pkt *stack.PacketBuffer) tcpip.Error {
func (e *Endpoint) WritePacket(_ stack.RouteInfo, _ tcpip.NetworkProtocolNumber, pkt *stack.PacketBuffer) tcpip.Error {
return e.writePacket(pkt)
}
// WritePackets writes packets back into io.ReadWriter.
func (e *Endpoint) WritePackets(_ stack.RouteInfo, _ *stack.GSO, pkts stack.PacketBufferList, _ tcpip.NetworkProtocolNumber) (int, tcpip.Error) {
func (e *Endpoint) WritePackets(_ stack.RouteInfo, pkts stack.PacketBufferList, _ tcpip.NetworkProtocolNumber) (int, tcpip.Error) {
n := 0
for pkt := pkts.Front(); pkt != nil; pkt = pkt.Next() {
if err := e.writePacket(pkt); err != nil {
@@ -106,6 +106,10 @@ func (e *Endpoint) WritePackets(_ stack.RouteInfo, _ *stack.GSO, pkts stack.Pack
return n, nil
}
func (e *Endpoint) WriteRawPacket(packetBuffer *stack.PacketBuffer) tcpip.Error {
return &tcpip.ErrNotSupported{}
}
// MTU implements stack.LinkEndpoint.MTU.
func (e *Endpoint) MTU() uint32 {
return e.mtu
+33
View File
@@ -0,0 +1,33 @@
//go:build darwin || freebsd || openbsd
package tun
import (
"github.com/xjasonlyu/tun2socks/common/pool"
)
const (
offset = 4 /* 4 bytes TUN_PI */
defaultMTU = 1500
)
func (t *TUN) Read(packet []byte) (n int, err error) {
buf := pool.Get(offset + len(packet))
defer pool.Put(buf)
if n, err = t.nt.Read(buf, offset); err != nil {
return
}
copy(packet, buf[offset:offset+n])
return
}
func (t *TUN) Write(packet []byte) (int, error) {
buf := pool.Get(offset + len(packet))
defer pool.Put(buf)
copy(buf[offset:], packet)
return t.nt.Write(buf[:offset+len(packet)], offset)
}
+15
View File
@@ -0,0 +1,15 @@
package tun
const (
offset = 0
defaultMTU = 0 /* auto */
)
func (t *TUN) Read(packet []byte) (int, error) {
return t.nt.Read(packet, offset)
}
func (t *TUN) Write(packet []byte) (int, error) {
return t.nt.Write(packet, offset)
}
-5
View File
@@ -1,5 +0,0 @@
// +build darwin freebsd openbsd
package tun
const offset = 4 /* 4 bytes TUN_PI */
-3
View File
@@ -1,3 +0,0 @@
package tun
const offset = 0
-15
View File
@@ -1,15 +0,0 @@
package tun
type Option func(*TUN)
func WithName(name string) Option {
return func(t *TUN) {
t.name = name
}
}
func WithMTU(mtu uint32) Option {
return func(t *TUN) {
t.mtu = mtu
}
}
@@ -1,7 +1,8 @@
//go:build linux
package tun
import (
"errors"
"fmt"
"unsafe"
@@ -22,15 +23,11 @@ type TUN struct {
name string
}
func Open(opts ...Option) (device.Device, error) {
t := &TUN{}
for _, opt := range opts {
opt(t)
}
func Open(name string, mtu uint32) (device.Device, error) {
t := &TUN{name: name, mtu: mtu}
if len(t.name) >= unix.IFNAMSIZ {
return nil, errors.New("interface name too long")
return nil, fmt.Errorf("interface name too long: %s", t.name)
}
fd, err := tun.Open(t.name)
@@ -45,11 +42,11 @@ func Open(opts ...Option) (device.Device, error) {
}
}
mtu, err := rawfile.GetMTU(t.name)
_mtu, err := rawfile.GetMTU(t.name)
if err != nil {
return nil, fmt.Errorf("get mtu: %w", err)
}
t.mtu = mtu
t.mtu = _mtu
ep, err := fdbased.New(&fdbased.Options{
MTU: t.mtu,
@@ -100,7 +97,7 @@ func setMTU(name string, n uint32) error {
)
if errno != 0 {
return errors.New("failed to set MTU")
return fmt.Errorf("failed to set MTU: %w", errno)
}
return nil
-78
View File
@@ -1,78 +0,0 @@
// +build !linux
package tun
import (
"fmt"
"github.com/xjasonlyu/tun2socks/common/pool"
"github.com/xjasonlyu/tun2socks/core/device"
"github.com/xjasonlyu/tun2socks/core/device/rwbased"
"golang.zx2c4.com/wireguard/tun"
)
type TUN struct {
*rwbased.Endpoint
nt *tun.NativeTun
mtu uint32
name string
}
func Open(opts ...Option) (device.Device, error) {
t := &TUN{}
for _, opt := range opts {
opt(t)
}
nt, err := tun.CreateTUN(t.name, int(t.mtu))
if err != nil {
return nil, fmt.Errorf("create tun: %w", err)
}
t.nt = nt.(*tun.NativeTun)
mtu, err := nt.MTU()
if err != nil {
return nil, fmt.Errorf("get mtu: %w", err)
}
t.mtu = uint32(mtu)
ep, err := rwbased.New(t, uint32(mtu))
if err != nil {
return nil, fmt.Errorf("create endpoint: %w", err)
}
t.Endpoint = ep
return t, nil
}
func (t *TUN) Read(packet []byte) (n int, err error) {
buf := pool.Get(offset + len(packet))
defer pool.Put(buf)
if n, err = t.nt.Read(buf, offset); err != nil {
return
}
copy(packet, buf[offset:offset+n])
return
}
func (t *TUN) Write(packet []byte) (int, error) {
buf := pool.Get(offset + len(packet))
defer pool.Put(buf)
copy(buf[offset:], packet)
return t.nt.Write(buf[:offset+len(packet)], offset)
}
func (t *TUN) Name() string {
name, _ := t.nt.Name()
return name
}
func (t *TUN) Close() error {
return t.nt.Close()
}
+58
View File
@@ -0,0 +1,58 @@
//go:build !linux
package tun
import (
"fmt"
"github.com/xjasonlyu/tun2socks/core/device"
"github.com/xjasonlyu/tun2socks/core/device/rwbased"
"golang.zx2c4.com/wireguard/tun"
)
type TUN struct {
*rwbased.Endpoint
nt *tun.NativeTun
mtu uint32
name string
}
func Open(name string, mtu uint32) (device.Device, error) {
t := &TUN{name: name, mtu: mtu}
forcedMTU := defaultMTU
if t.mtu > 0 {
forcedMTU = int(t.mtu)
}
nt, err := tun.CreateTUN(t.name, forcedMTU)
if err != nil {
return nil, fmt.Errorf("create tun: %w", err)
}
t.nt = nt.(*tun.NativeTun)
_mtu, err := nt.MTU()
if err != nil {
return nil, fmt.Errorf("get mtu: %w", err)
}
t.mtu = uint32(_mtu)
ep, err := rwbased.New(t, t.mtu)
if err != nil {
return nil, fmt.Errorf("create endpoint: %w", err)
}
t.Endpoint = ep
return t, nil
}
func (t *TUN) Name() string {
name, _ := t.nt.Name()
return name
}
func (t *TUN) Close() error {
return t.nt.Close()
}
+2 -2
View File
@@ -111,10 +111,10 @@ func WithDefaultTTL(ttl uint8) Option {
// WithForwarding sets packet forwarding between NICs for IPv4 & IPv6.
func WithForwarding(v bool) Option {
return func(s *Stack) error {
if err := s.SetForwarding(ipv4.ProtocolNumber, v); err != nil {
if err := s.SetForwardingDefaultAndAllNICs(ipv4.ProtocolNumber, v); err != nil {
return fmt.Errorf("set ipv4 forwarding: %s", err)
}
if err := s.SetForwarding(ipv6.ProtocolNumber, v); err != nil {
if err := s.SetForwardingDefaultAndAllNICs(ipv6.ProtocolNumber, v); err != nil {
return fmt.Errorf("set ipv6 forwarding: %s", err)
}
return nil
+26 -31
View File
@@ -21,7 +21,7 @@ func withUDPHandler() Option {
udpHandlePacket := func(id stack.TransportEndpointID, pkt *stack.PacketBuffer) bool {
// Ref: gVisor pkg/tcpip/transport/udp/endpoint.go HandlePacket
udpHdr := header.UDP(pkt.TransportHeader().View())
if int(udpHdr.Length()) > pkt.Data.Size()+header.UDPMinimumSize {
if int(udpHdr.Length()) > pkt.Data().Size()+header.UDPMinimumSize {
// Malformed packet.
s.Stats().UDP.MalformedPacketsReceived.Increment()
return true
@@ -38,10 +38,10 @@ func withUDPHandler() Option {
packet := &udpPacket{
s: s,
id: &id,
data: pkt.Data().ExtractVV(),
nicID: pkt.NICID,
netHdr: pkt.Network(),
netProto: pkt.NetworkProtocolNumber,
payload: pkt.Data.ToView(),
}
s.handler.AddPacket(packet)
@@ -55,19 +55,17 @@ func withUDPHandler() Option {
type udpPacket struct {
s *Stack
id *stack.TransportEndpointID
data buffer.VectorisedView
nicID tcpip.NICID
netHdr header.Network
netProto tcpip.NetworkProtocolNumber
payload []byte
}
func (p *udpPacket) Data() []byte {
return p.payload
return p.data.ToView()
}
func (p *udpPacket) Drop() {
/* Release */
}
func (p *udpPacket) Drop() {}
func (p *udpPacket) ID() *stack.TransportEndpointID {
return p.id
@@ -88,33 +86,30 @@ func (p *udpPacket) WriteBack(b []byte, addr net.Addr) (int, error) {
return 0, fmt.Errorf("%s", &tcpip.ErrMessageTooLong{})
}
route, err := p.s.FindRoute(p.nicID, p.netHdr.DestinationAddress(), p.netHdr.SourceAddress(), p.netProto, false /* multicastLoop */)
var (
localAddress tcpip.Address
localPort uint16
)
if udpAddr, ok := addr.(*net.UDPAddr); !ok {
localAddress = p.netHdr.DestinationAddress()
localPort = p.id.LocalPort
} else if ipv4 := udpAddr.IP.To4(); ipv4 != nil {
localAddress = tcpip.Address(ipv4)
localPort = uint16(udpAddr.Port)
} else {
localAddress = tcpip.Address(udpAddr.IP)
localPort = uint16(udpAddr.Port)
}
route, err := p.s.FindRoute(p.nicID, localAddress, p.netHdr.SourceAddress(), p.netProto, false /* multicastLoop */)
if err != nil {
return 0, fmt.Errorf("%#v find route: %s", p.id, err)
}
defer route.Release()
data := v.ToVectorisedView()
// if addr is not provided, write back use original dst Addr as src Addr.
if addr == nil {
if err := sendUDP(route, data, p.id.LocalPort, p.id.RemotePort, udpNoChecksum); err != nil {
return 0, fmt.Errorf("%v", err)
}
return data.Size(), nil
}
udpAddr, ok := addr.(*net.UDPAddr)
if !ok {
return 0, fmt.Errorf("type %T is not a valid udp address", addr)
}
if ipv4 := udpAddr.IP.To4(); ipv4 != nil {
route.LocalAddress = tcpip.Address(ipv4)
} else {
route.LocalAddress = tcpip.Address(udpAddr.IP)
}
if err := sendUDP(route, data, uint16(udpAddr.Port), p.id.RemotePort, udpNoChecksum); err != nil {
if err = sendUDP(route, data, localPort, p.id.RemotePort, udpNoChecksum); err != nil {
return 0, fmt.Errorf("%v", err)
}
return data.Size(), nil
@@ -144,7 +139,7 @@ func sendUDP(r *stack.Route, data buffer.VectorisedView, localPort, remotePort u
// transmitter skipped the checksum generation (RFC768).
// On IPv6, UDP checksum is not optional (RFC2460 Section 8.1).
if r.RequiresTXTransportChecksum() &&
(!noChecksum || r.NetProto == header.IPv6ProtocolNumber) {
(!noChecksum || r.NetProto() == header.IPv6ProtocolNumber) {
xsum := r.PseudoHeaderChecksum(udp.ProtocolNumber, length)
for _, v := range data.Views() {
xsum = header.Checksum(v, xsum)
@@ -154,7 +149,7 @@ func sendUDP(r *stack.Route, data buffer.VectorisedView, localPort, remotePort u
ttl := r.DefaultTTL()
if err := r.WritePacket(nil /* gso */, stack.NetworkHeaderParams{
if err := r.WritePacket(stack.NetworkHeaderParams{
Protocol: udp.ProtocolNumber,
TTL: ttl,
TOS: 0, /* default */
@@ -177,7 +172,7 @@ func verifyChecksum(hdr header.UDP, pkt *stack.PacketBuffer) bool {
(hdr.Checksum() != 0 || pkt.NetworkProtocolNumber == header.IPv6ProtocolNumber) {
netHdr := pkt.Network()
xsum := header.PseudoHeaderChecksum(udp.ProtocolNumber, netHdr.DestinationAddress(), netHdr.SourceAddress(), hdr.Length())
for _, v := range pkt.Data.Views() {
for _, v := range pkt.Data().Views() {
xsum = header.Checksum(v, xsum)
}
return hdr.CalculateChecksum(xsum) == 0xffff
-43
View File
@@ -1,43 +0,0 @@
version: '2.4'
services:
tun2socks:
image: ghcr.io/xjasonlyu/tun2socks:latest
cap_add:
- NET_ADMIN
devices:
- '/dev/net/tun:/dev/net/tun'
environment:
- GODEBUG=madvdontneed=1
- LOGLEVEL=
- TUN=
- ETH=
- TUN_ADDR=
- TUN_MASK=
- PROXY=
- STATS=
- TOKEN=
- MTU=
- EXTRA_COMMANDS=
- TUN_INCLUDED_ROUTES=
- TUN_EXCLUDED_ROUTES=
networks:
switch:
ipv4_address: 172.20.1.2
sysctls:
- net.ipv4.ip_forward=1
- net.ipv4.conf.all.rp_filter=0
restart: unless-stopped
container_name: tun2socks
networks:
switch:
name: switch
ipam:
driver: default
config:
- subnet: '172.20.1.0/25'
gateway: 172.20.1.1
driver: macvlan
driver_opts:
parent: eth0
+34 -28
View File
@@ -1,32 +1,40 @@
#!/bin/sh
TUN="${TUN:-tun0}"
TUN_ADDR="${TUN_ADDR:-198.18.0.1/15}"
ADDR="${ADDR:-198.18.0.1/15}"
LOGLEVEL="${LOGLEVEL:-info}"
TABLE="${TABLE:-0x2d5}"
FWMARK="${FWMARK:-0x2d5}"
# default values
TABLE="${TABLE:-0x22b}"
FWMARK="${FWMARK:-0x22b}"
CLONE_MAIN="${CLONE_MAIN:-1}"
create_tun() {
# create tun device
ip tuntap add mode tun dev "$TUN"
ip addr add "$TUN_ADDR" dev "$TUN"
ip addr add "$ADDR" dev "$TUN"
ip link set dev "$TUN" up
}
create_table() {
if [ "$CLONE_MAIN" -ne 0 ]; then
# clone main route table
ip route show table main |
while read -r route; do
ip route add ${route%linkdown*} table "$TABLE"
done
# replace default route
ip route replace default dev "$TUN" table "$TABLE"
else
# just add default route
ip route add default dev "$TUN" table "$TABLE"
fi
}
config_route() {
# clone main route
ip route show table main |
while read -r route; do
ip route add ${route%linkdown*} table "$TABLE"
done
# replace default route
ip route replace default dev "$TUN" table "$TABLE"
# policy routing
ip rule add not fwmark "$FWMARK" table "$TABLE"
ip rule add fwmark "$FWMARK" to "$TUN_ADDR" prohibit
ip rule add fwmark "$FWMARK" to "$ADDR" prohibit
# add tun included routes
for addr in $(echo "$TUN_INCLUDED_ROUTES" | tr ',' '\n'); do
@@ -39,16 +47,10 @@ config_route() {
done
}
disable_rp_filter() {
for path in /proc/sys/net/ipv4/conf/*; do
echo 0 > "$path/rp_filter"
done
}
main() {
create_tun
create_table
config_route
disable_rp_filter
# execute extra commands
if [ -n "$EXTRA_COMMANDS" ]; then
@@ -56,22 +58,26 @@ main() {
fi
if [ -n "$MTU" ]; then
ARGS="--mtu $MTU"
ARGS="-mtu $MTU"
fi
if [ -n "$STATS" ]; then
ARGS="$ARGS --stats $STATS"
ARGS="$ARGS -stats $STATS"
fi
if [ -n "$TOKEN" ]; then
ARGS="$ARGS --token $TOKEN"
ARGS="$ARGS -token $TOKEN"
fi
if [ -n "$UDP_TIMEOUT" ]; then
ARGS="$ARGS -udp-timeout $UDP_TIMEOUT"
fi
exec tun2socks \
--loglevel "$LOGLEVEL" \
--fwmark "$FWMARK" \
--device "$TUN" \
--proxy "$PROXY" \
-loglevel "$LOGLEVEL" \
-fwmark "$FWMARK" \
-device "$TUN" \
-proxy "$PROXY" \
$ARGS
}
-15
View File
@@ -1,15 +0,0 @@
#!/bin/sh
# Create the necessary file structure for /dev/net/tun
if [ ! -c /dev/net/tun ]; then
if [ ! -d /dev/net ]; then
mkdir -m 755 /dev/net
fi
mknod /dev/net/tun c 10 200
chmod 0755 /dev/net/tun
fi
# Load the tun module if not already loaded
if ( ! (lsmod | grep -q "^tun\s")); then
insmod /lib/modules/tun.ko
fi
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 30 KiB

+20 -10
View File
@@ -10,6 +10,7 @@ import (
"github.com/xjasonlyu/tun2socks/log"
"github.com/xjasonlyu/tun2socks/proxy"
"github.com/xjasonlyu/tun2socks/stats"
"github.com/xjasonlyu/tun2socks/tunnel"
)
var _engine = &engine{}
@@ -30,15 +31,16 @@ func Insert(k *Key) {
}
type Key struct {
MTU uint32
Mark int
Proxy string
Stats string
Token string
Device string
LogLevel string
Interface string
Version bool
MTU int
Mark int
UDPTimeout int
Proxy string
Stats string
Token string
Device string
LogLevel string
Interface string
Version bool
}
type engine struct {
@@ -64,6 +66,7 @@ func (e *engine) start() error {
e.setMark,
e.setInterface,
e.setStats,
e.setUDPTimeout,
e.setProxy,
e.setDevice,
e.setStack,
@@ -123,6 +126,13 @@ func (e *engine) setStats() error {
return nil
}
func (e *engine) setUDPTimeout() error {
if e.UDPTimeout > 0 {
tunnel.SetUDPTimeout(e.UDPTimeout)
}
return nil
}
func (e *engine) setProxy() (err error) {
if e.Proxy == "" {
return errors.New("empty proxy")
@@ -138,7 +148,7 @@ func (e *engine) setDevice() (err error) {
return errors.New("empty device")
}
e.device, err = parseDevice(e.Device, e.MTU)
e.device, err = parseDevice(e.Device, uint32(e.MTU))
return
}
+35 -9
View File
@@ -7,6 +7,7 @@ import (
"strings"
"github.com/xjasonlyu/tun2socks/core/device"
"github.com/xjasonlyu/tun2socks/core/device/fd"
"github.com/xjasonlyu/tun2socks/core/device/tun"
"github.com/xjasonlyu/tun2socks/proxy"
"github.com/xjasonlyu/tun2socks/proxy/proto"
@@ -14,7 +15,7 @@ import (
func parseDevice(s string, mtu uint32) (device.Device, error) {
if !strings.Contains(s, "://") {
s = tun.Driver + "://" + s /* default driver */
s = fmt.Sprintf("%s://%s", tun.Driver /* default driver */, s)
}
u, err := url.Parse(s)
@@ -26,8 +27,10 @@ func parseDevice(s string, mtu uint32) (device.Device, error) {
driver := strings.ToLower(u.Scheme)
switch driver {
case fd.Driver:
return fd.Open(name, mtu)
case tun.Driver:
return tun.Open(tun.WithName(name), tun.WithMTU(mtu))
return tun.Open(name, mtu)
default:
return nil, fmt.Errorf("unsupported driver: %s", driver)
}
@@ -35,7 +38,7 @@ func parseDevice(s string, mtu uint32) (device.Device, error) {
func parseProxy(s string) (proxy.Proxy, error) {
if !strings.Contains(s, "://") {
s = proto.Socks5.String() + "://" + s /* default protocol */
s = fmt.Sprintf("%s://%s", proto.Socks5 /* default protocol */, s)
}
u, err := url.Parse(s)
@@ -48,8 +51,14 @@ func parseProxy(s string) (proxy.Proxy, error) {
switch protocol {
case proto.Direct.String():
return proxy.NewDirect(), nil
case proto.Reject.String():
return proxy.NewReject(), nil
case proto.HTTP.String():
return proxy.NewHTTP(parseHTTP(u))
case proto.Socks4.String():
return proxy.NewSocks4(parseSocks4(u))
case proto.Socks5.String():
return proxy.NewSocks5(parseSocks(u))
return proxy.NewSocks5(parseSocks5(u))
case proto.Shadowsocks.String():
return proxy.NewShadowsocks(parseShadowsocks(u))
default:
@@ -57,13 +66,28 @@ func parseProxy(s string) (proxy.Proxy, error) {
}
}
func parseSocks(u *url.URL) (address, username, password string) {
address = u.Host
username = u.User.Username()
func parseHTTP(u *url.URL) (address, username, password string) {
address, username = u.Host, u.User.Username()
password, _ = u.User.Password()
return
}
func parseSocks4(u *url.URL) (address, username string) {
address, username = u.Host, u.User.Username()
return
}
func parseSocks5(u *url.URL) (address, username, password string) {
address, username = u.Host, u.User.Username()
password, _ = u.User.Password()
// Socks5 over UDS
if address == "" {
address = u.Path
}
return
}
func parseShadowsocks(u *url.URL) (address, method, password, obfsMode, obfsHost string) {
address = u.Host
@@ -73,8 +97,10 @@ func parseShadowsocks(u *url.URL) (address, method, password, obfsMode, obfsHost
} else {
data, _ := base64.RawURLEncoding.DecodeString(u.User.String())
userInfo := strings.SplitN(string(data), ":", 2)
method = userInfo[0]
password = userInfo[1]
if len(userInfo) == 2 {
method = userInfo[0]
password = userInfo[1]
}
}
rawQuery, _ := url.QueryUnescape(u.RawQuery)
+3 -3
View File
@@ -5,7 +5,7 @@ import (
"runtime"
"strings"
"github.com/xjasonlyu/tun2socks/constant"
V "github.com/xjasonlyu/tun2socks/constant"
)
func showVersion() {
@@ -14,9 +14,9 @@ func showVersion() {
}
func versionString() string {
return fmt.Sprintf("%s %s\n", constant.Name, strings.TrimPrefix(constant.Version, "v"))
return fmt.Sprintf("%s-%s\n", V.Name, strings.TrimPrefix(V.Version, "v"))
}
func releaseString() string {
return fmt.Sprintf("%s/%s, %s, %s\n", runtime.GOOS, runtime.GOARCH, runtime.Version(), constant.BuildTime)
return fmt.Sprintf("%s/%s, %s, %s\n", runtime.GOOS, runtime.GOARCH, runtime.Version(), V.GitCommit)
}
+20 -14
View File
@@ -1,22 +1,28 @@
module github.com/xjasonlyu/tun2socks
go 1.15
go 1.17
require (
github.com/Dreamacro/go-shadowsocks2 v0.1.6
github.com/Dreamacro/go-shadowsocks2 v0.1.7
github.com/go-chi/chi v4.1.2+incompatible
github.com/go-chi/cors v1.1.1
github.com/go-chi/cors v1.2.0
github.com/go-chi/render v1.0.1
github.com/gofrs/uuid v4.0.0+incompatible
github.com/gofrs/uuid v4.1.0+incompatible
github.com/gorilla/websocket v1.4.2
github.com/sirupsen/logrus v1.7.0
github.com/spf13/pflag v1.0.5
github.com/stretchr/testify v1.5.1
go.uber.org/atomic v1.7.0
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad // indirect
golang.org/x/net v0.0.0-20210119194325-5f4716e94777 // indirect
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c
golang.org/x/time v0.0.0-20201208040808-7e3f01d25324
golang.zx2c4.com/wireguard v0.0.20201118
gvisor.dev/gvisor v0.0.0-20210207054208-21036aed5e58
github.com/sirupsen/logrus v1.8.1
github.com/stretchr/testify v1.7.0
go.uber.org/atomic v1.9.0
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 // indirect
golang.org/x/net v0.0.0-20211029224645-99673261e6eb // indirect
golang.org/x/sys v0.0.0-20211031064116-611d5d643895
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac
golang.zx2c4.com/wireguard v0.0.0-20211030003956-52704c4b9288
gvisor.dev/gvisor v0.0.0-20211029210705-806fa5c3235c
)
require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/google/btree v1.0.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect
)
+31 -627
View File
@@ -1,647 +1,51 @@
bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8=
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
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.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY=
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/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/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=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI=
github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0=
github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA=
github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0=
github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0=
github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc=
github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk=
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/Dreamacro/go-shadowsocks2 v0.1.6 h1:PysSf9sLT3Qn8jhlin5v7Rk68gOQG4K5BZFY1nxLGxI=
github.com/Dreamacro/go-shadowsocks2 v0.1.6/go.mod h1:LSXCjyHesPY3pLjhwff1mQX72ItcBT/N2xNC685cYeU=
github.com/Microsoft/go-winio v0.4.16-0.20201130162521-d1ffc52c7331/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0=
github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0=
github.com/Microsoft/hcsshim v0.8.14/go.mod h1:NtVKoYxQuTLx6gEq0L96c9Ju4JbRJ4nY2ow3VK6a9Lg=
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
github.com/cenkalti/backoff v1.1.1-0.20190506075156-2146c9339422/go.mod h1:b6Nc7NRH5C4aCISLry0tLnTjcuTEvoiqcWDdsU0sOGM=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
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/cilium/ebpf v0.0.0-20200110133405-4032b1d8aae3/go.mod h1:MA5e5Lr8slmEg9bt0VpxxWqJlO4iwu3FBdHUzV7wQVg=
github.com/cilium/ebpf v0.2.0/go.mod h1:To2CFviqOWL/M0gIMsvSMlqe7em/l1ALkX1PyjrX2Qs=
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/containerd/cgroups v0.0.0-20200531161412-0dbf7f05ba59/go.mod h1:pA0z1pT8KYB3TCXK/ocprsh7MAkoW8bZVzPdih9snmM=
github.com/containerd/cgroups v0.0.0-20201119153540-4cbc285b3327/go.mod h1:ZJeTFisyysqgcCdecO57Dj79RfL0LNeGiFUqLYQRYLE=
github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw=
github.com/containerd/console v0.0.0-20191206165004-02ecf6a7291e/go.mod h1:8Pf4gM6VEbTNRIT26AyyU7hxdQU3MvAvxVI0sc00XBE=
github.com/containerd/console v1.0.1/go.mod h1:XUsP6YE/mKtz6bxc+I8UiKKTP04qjQL4qcS3XoQ5xkw=
github.com/containerd/containerd v1.3.2/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
github.com/containerd/containerd v1.3.9/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
github.com/containerd/continuity v0.0.0-20201208142359-180525291bb7/go.mod h1:kR3BEg7bDFaEddKm54WSmrol1fKWDU1nKYkgrcgZT7Y=
github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI=
github.com/containerd/fifo v0.0.0-20191213151349-ff969a566b00/go.mod h1:jPQ2IAeZRCYxpS/Cm1495vGFww6ecHmMk1YJH2Q5ln0=
github.com/containerd/go-runc v0.0.0-20180907222934-5a6d9f37cfa3/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0=
github.com/containerd/go-runc v0.0.0-20200220073739-7016d3ce2328/go.mod h1:PpyHrqVs8FTi9vpyHwPwiNEGaACDxT/N/pLcvMSRA9g=
github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o=
github.com/containerd/ttrpc v1.0.2/go.mod h1:UAxOpgT9ziI0gJrmKvgcZivgxOp8iFPSk8httJEt98Y=
github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd/go.mod h1:Cm3kwCdlkCfMSHURc+r6fwoGH6/F1hH3S4sg0rLFWPc=
github.com/containerd/typeurl v0.0.0-20200205145503-b45ef1f1f737/go.mod h1:TB1hUtrpaiO88KEK56ijojHS1+NeF0izUACaJW2mdXg=
github.com/coreos/go-systemd/v22 v22.0.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk=
github.com/coreos/go-systemd/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/cpuguy83/go-md2man/v2 v2.0.0 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM=
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/davecgh/go-spew v0.0.0-20151105211317-5215b55f46b2/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/Dreamacro/go-shadowsocks2 v0.1.7 h1:8CtbE1HoPPMfrQZGXmlluq6dO2lL31W6WRRE8fabc4Q=
github.com/Dreamacro/go-shadowsocks2 v0.1.7/go.mod h1:8p5G4cAj5ZlXwUR+Ww63gfSikr8kvw8uw3TDwLAJpUc=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
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/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/docker v1.4.2-0.20191028175130-9e7d5ac5ea55/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/go-connections v0.3.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA=
github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/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/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-chi/chi v4.1.2+incompatible h1:fGFk2Gmi/YKXk0OmGfBh0WgmN3XB8lVnEyNz34tQRec=
github.com/go-chi/chi v4.1.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ=
github.com/go-chi/cors v1.1.1 h1:eHuqxsIw89iXcWnWUN8R72JMibABJTN/4IOYI5WERvw=
github.com/go-chi/cors v1.1.1/go.mod h1:K2Yje0VW/SJzxiyMYu6iPQYa7hMjQX2i/F491VChg1I=
github.com/go-chi/cors v1.2.0 h1:tV1g1XENQ8ku4Bq3K9ub2AtgG+p16SmzeMSGTwrOKdE=
github.com/go-chi/cors v1.2.0/go.mod h1:sSbTewc+6wYHBBCW7ytsFSn836hqM7JxpglAy2Vzc58=
github.com/go-chi/render v1.0.1 h1:4/5tis2cKaNdnv9zFLfXzcquC9HbeZgCnxGnKrltBS8=
github.com/go-chi/render v1.0.1/go.mod h1:pq4Rr7HbnsdaeHagklXub+p6Wd16Af5l9koip1OvJns=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0=
github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg=
github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc=
github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I=
github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/gofrs/flock v0.6.1-0.20180915234121-886344bea079/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
github.com/gofrs/uuid v4.0.0+incompatible h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPhW6m+TnJw=
github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
github.com/gogo/googleapis v1.4.0/go.mod h1:5YRNX2z1oM5gXdAkurHa942MDgEJyk02w4OecKY87+c=
github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
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/protobuf v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.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=
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0 h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo=
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.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-github/v32 v32.1.0/go.mod h1:rIEpZD9CTDQwDK9GDrtMTycQNA4JU3qBsCizh3q2WCI=
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
github.com/google/gofuzz v1.0.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/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-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210115211752-39141e76b647/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/subcommands v1.0.2-0.20190508160503-636abe8753b8/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk=
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
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/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.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8=
github.com/gofrs/uuid v4.1.0+incompatible h1:sIa2eCvUTwgjbqXrPLfNwUf9S3i3mpH1O1atV+iL/Wk=
github.com/gofrs/uuid v4.1.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4=
github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA=
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/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
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/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/json-iterator/go v0.0.0-20180612202835-f2b4162afba3/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
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/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
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.2/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/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/pty v1.1.4-0.20190131011033-7dc38fb350b1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mattbaird/jsonpatch v0.0.0-20171005235357-81af80346b1a/go.mod h1:M1qoD/MqPgTZIk0EWKB38wE28ACRfVcn+cU08jyArI0=
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-20180320133207-05fbef0ca5da/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
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/mohae/deepcopy v0.0.0-20170308212314-bb9b5e7adda9/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
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.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
github.com/opencontainers/runtime-spec v1.0.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
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/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20190522114515-bc1a522cf7b1/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
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/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM=
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
github.com/spf13/cobra v0.0.2-0.20171109065643-2da4a54c5cee/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.1-0.20171106142849-4c012f6dcd95/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/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v0.0.0-20151208002404-e3a8ff8ce365/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
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=
github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
github.com/urfave/cli v1.22.2 h1:gsqYFH8bb9ekPA12kRo0hfjngWQjkJPlN9R0N78BoUo=
github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
github.com/vishvananda/netlink v1.0.1-0.20190930145447-2ec5bdc52b86/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk=
github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
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=
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.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4=
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
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-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201117144127-c1f2f97bffc9/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad h1:DN0cp81fZ3njFcrLCytUHRSUkqBjfTo4Tx9RJTWs0EY=
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
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=
golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
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/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=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
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/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=
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
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/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/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-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=
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-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-20191004110552-13f9640d40b9/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=
golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
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-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 h1:VvcQYSHwXgi7W+TpUR6A9g6Up98WAHf3f/ulnJ62IyA=
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201031054903-ff519b6c9102 h1:42cLlJJdEh+ySyeUUbEQ5bsTiq8voBeTuweGVkY6Puw=
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-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210119194325-5f4716e94777 h1:003p0dJM77cxMSyCPFphvZf/Y5/NXf5fzg6ufd1/Oew=
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
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/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/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 h1:qwRHBd0NqMbJxfbotnDhm2ByMI1Shq4Y6oRJo21SGJA=
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9 h1:SQFwaSi55rU7vdNs9Yr0Z324VNlrF+0wMqRXT4St8ck=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/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=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
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-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-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 h1:YyJpGZS1sBuBCzLAR1VEpK193GlqGZbnPFnPV/5Rsb4=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
golang.org/x/crypto v0.0.0-20210317152858-513c2a44f670/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 h1:7I4JAnoQBe7ZtJcBaYHi5UtiO8tQHbUSXxL+pnGRANg=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20211029224645-99673261e6eb h1:pirldcYWx7rx7kE5r+9WsOXPXK0+WH5+uZ7uPmJ44uM=
golang.org/x/net v0.0.0-20211029224645-99673261e6eb/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
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-20191210023423-ac6580df4449/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200120151820-655fe14d7479/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
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-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-20200916030750-2334cc1a136f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201117222635-ba5294a509c7/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-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c h1:VwygUrnw9jn88c4u8GD3rZQbqrP/tgas88tPUbBxQrk=
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/sys v0.0.0-20211031064116-611d5d643895 h1:iaNpwpnrgL5jzWS0vCNnfa8HqzxveCFpFx3uC/X4Tps=
golang.org/x/sys v0.0.0-20211031064116-611d5d643895/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
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 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.4 h1:0YWbFKbhXG/wIiuHDSKpS0Iy7FSA+u45VtBMfQcFTTc=
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
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 h1:/5xXl8Y5W96D+TtHSlonuFqGHIWVuyCkGJLwGh9JJFs=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20201208040808-7e3f01d25324 h1:Hir2P/De0WpUhtrKGGjvSb2YxUgyZ7EFOSLIcSSpiwE=
golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac h1:7zkz7BUtwNFFqcowJ+RIgu2MaV/MapERkDIy+mwPyjs=
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
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-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=
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
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-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-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
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/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.zx2c4.com/wireguard v0.0.20201118 h1:QL8y2C7uO8T6z1GY+UX/hSeWiYEBurQkXjOTRFtCvXU=
golang.zx2c4.com/wireguard v0.0.20201118/go.mod h1:Dz+cq5bnrai9EpgYj4GDof/+qaGzbRWbeaAOs1bUYa0=
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=
google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
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/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/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
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=
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200117163144-32f20d992d24/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
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-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-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
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.23.1/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.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8=
google.golang.org/grpc v1.36.0-dev.0.20210122012134-2c42474aca0c/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
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=
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
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.25.1-0.20201020201750-d3470999428b/go.mod h1:hFxJC2f0epmp1elRCiEGJTKAWbwxZ2nvqZdHl3FQXCY=
golang.zx2c4.com/wireguard v0.0.0-20211030003956-52704c4b9288 h1:v3PAPzkDfgUxCCHa2ygoesDpj490YbYB4Q3ZuE6lFKk=
golang.zx2c4.com/wireguard v0.0.0-20211030003956-52704c4b9288/go.mod h1:RTjaYEQboNk7+2qfPGBotaMEh/5HIvmPZ6DIe10lTqI=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
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/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
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.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
gvisor.dev/gvisor v0.0.0-20210207054208-21036aed5e58 h1:mGt9tyR+QR3vwST1urdmz4fFupFUKInN2RZeiwC88Mo=
gvisor.dev/gvisor v0.0.0-20210207054208-21036aed5e58/go.mod h1:bGHhdxWoqL+3AwdMfePr6TWTcvHO33egRmxDPAQFdJE=
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=
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
honnef.co/go/tools v0.1.1/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las=
k8s.io/api v0.16.13/go.mod h1:QWu8UWSTiuQZMMeYjwLs6ILu5O74qKSJ0c+4vrchDxs=
k8s.io/apimachinery v0.16.13/go.mod h1:4HMHS3mDHtVttspuuhrJ1GGr/0S9B6iWYWZ57KnnZqQ=
k8s.io/apimachinery v0.16.14-rc.0/go.mod h1:4HMHS3mDHtVttspuuhrJ1GGr/0S9B6iWYWZ57KnnZqQ=
k8s.io/client-go v0.16.13/go.mod h1:UKvVT4cajC2iN7DCjLgT0KVY/cbY6DGdUCyRiIfws5M=
k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I=
k8s.io/kube-openapi v0.0.0-20200410163147-594e756bea31/go.mod h1:1TqjTSzOxsLGIKfj0lK8EeCP7K1iUG65v09OM0/WG5E=
k8s.io/utils v0.0.0-20190801114015-581e00157fb1/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
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 v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI=
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
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=
gvisor.dev/gvisor v0.0.0-20211029210705-806fa5c3235c h1:S4L2OVKs48LB9vVbPaiEfRqon+dn0wm3MABd2cyvjkc=
gvisor.dev/gvisor v0.0.0-20211029210705-806fa5c3235c/go.mod h1:btyTBPTxT8AFMvW7yctFJ2nPCEDWZLpmKQEZ0gG+bbQ=
+5 -5
View File
@@ -8,8 +8,8 @@ import (
)
var (
logCh = make(chan interface{})
source = observable.NewObservable(logCh)
_logCh = make(chan interface{})
_source = observable.NewObservable(_logCh)
)
type Event struct {
@@ -24,16 +24,16 @@ func newEvent(level Level, format string, args ...interface{}) *Event {
Time: time.Now(),
Message: fmt.Sprintf(format, args...),
}
logCh <- event /* send all events to logCh */
_logCh <- event /* send all events to logCh */
return event
}
func Subscribe() observable.Subscription {
sub, _ := source.Subscribe()
sub, _ := _source.Subscribe()
return sub
}
func UnSubscribe(sub observable.Subscription) {
source.UnSubscribe(sub)
_source.UnSubscribe(sub)
}
+5 -5
View File
@@ -2,14 +2,14 @@ package log
import (
"os"
"sync/atomic"
"github.com/sirupsen/logrus"
"go.uber.org/atomic"
)
var (
// defaultLevel is package default logging level.
defaultLevel = InfoLevel
// _defaultLevel is package default logging level.
_defaultLevel = atomic.NewUint32(uint32(InfoLevel))
)
func init() {
@@ -18,7 +18,7 @@ func init() {
}
func SetLevel(level Level) {
atomic.StoreUint32((*uint32)(&defaultLevel), uint32(level))
_defaultLevel.Store(uint32(level))
}
func Debugf(format string, args ...interface{}) {
@@ -43,7 +43,7 @@ func Fatalf(format string, args ...interface{}) {
func logf(level Level, format string, args ...interface{}) {
event := newEvent(level, format, args...)
if event.Level > defaultLevel {
if uint32(event.Level) > _defaultLevel.Load() {
return
}
+9 -9
View File
@@ -1,28 +1,28 @@
package main
import (
"flag"
"os"
"os/signal"
"syscall"
"github.com/xjasonlyu/tun2socks/engine"
"github.com/xjasonlyu/tun2socks/log"
flag "github.com/spf13/pflag"
)
var key = new(engine.Key)
func init() {
flag.StringVarP(&key.Device, "device", "d", "", "use this device [driver://]name")
flag.IntVar(&key.Mark, "fwmark", 0, "set firewall MARK (Linux only)")
flag.StringVarP(&key.Interface, "interface", "i", "", "use network INTERFACE (Linux/MacOS only)")
flag.StringVarP(&key.LogLevel, "loglevel", "l", "info", "log level [debug|info|warn|error|silent]")
flag.Uint32VarP(&key.MTU, "mtu", "m", 0, "set device maximum transmission unit (MTU)")
flag.StringVarP(&key.Proxy, "proxy", "p", "", "use this proxy [protocol://]host[:port]")
flag.IntVar(&key.Mark, "fwmark", 0, "Set firewall MARK (Linux only)")
flag.IntVar(&key.MTU, "mtu", 0, "Set device maximum transmission unit (MTU)")
flag.IntVar(&key.UDPTimeout, "udp-timeout", 0, "Set timeout for each UDP session")
flag.BoolVar(&key.Version, "version", false, "Show version information and quit")
flag.StringVar(&key.Device, "device", "", "Use this device [driver://]name")
flag.StringVar(&key.Interface, "interface", "", "Use network INTERFACE (Linux/MacOS only)")
flag.StringVar(&key.LogLevel, "loglevel", "info", "Log level [debug|info|warn|error|silent]")
flag.StringVar(&key.Proxy, "proxy", "", "Use this proxy [protocol://]host[:port]")
flag.StringVar(&key.Stats, "stats", "", "HTTP statistic server listen address")
flag.StringVar(&key.Token, "token", "", "HTTP statistic server auth token")
flag.BoolVarP(&key.Version, "version", "v", false, "show version information and quit")
flag.Parse()
}
-4
View File
@@ -16,10 +16,6 @@ type Base struct {
proto proto.Proto
}
func NewBase(addr string, proto proto.Proto) *Base {
return &Base{addr: addr, proto: proto}
}
func (b *Base) Addr() string {
return b.addr
}
+97
View File
@@ -0,0 +1,97 @@
package proxy
// Ref: https://github.com/Dreamacro/clash/adapter/outbound/http
import (
"bufio"
"context"
"encoding/base64"
"errors"
"fmt"
"io"
"net"
"net/http"
"net/url"
"github.com/xjasonlyu/tun2socks/component/dialer"
M "github.com/xjasonlyu/tun2socks/constant"
"github.com/xjasonlyu/tun2socks/proxy/proto"
)
type HTTP struct {
*Base
user string
pass string
}
func NewHTTP(addr, user, pass string) (*HTTP, error) {
return &HTTP{
Base: &Base{
addr: addr,
proto: proto.HTTP,
},
user: user,
pass: pass,
}, nil
}
func (h *HTTP) DialContext(ctx context.Context, metadata *M.Metadata) (c net.Conn, err error) {
c, err = dialer.DialContext(ctx, "tcp", h.Addr())
if err != nil {
return nil, fmt.Errorf("connect to %s: %w", h.Addr(), err)
}
setKeepAlive(c)
defer safeConnClose(c, err)
err = h.shakeHand(metadata, c)
return
}
func (h *HTTP) shakeHand(metadata *M.Metadata, rw io.ReadWriter) error {
addr := metadata.DestinationAddress()
req := &http.Request{
Method: http.MethodConnect,
URL: &url.URL{
Host: addr,
},
Host: addr,
Header: http.Header{
"Proxy-Connection": []string{"Keep-Alive"},
},
}
if h.user != "" && h.pass != "" {
auth := h.user + ":" + h.pass
req.Header.Add("Proxy-Authorization",
fmt.Sprintf("Basic %s", base64.StdEncoding.EncodeToString([]byte(auth))))
}
if err := req.Write(rw); err != nil {
return err
}
resp, err := http.ReadResponse(bufio.NewReader(rw), req)
if err != nil {
return err
}
if resp.StatusCode == http.StatusOK {
return nil
}
if resp.StatusCode == http.StatusProxyAuthRequired {
return errors.New("HTTP need auth")
}
if resp.StatusCode == http.StatusMethodNotAllowed {
return errors.New("CONNECT method not allowed by proxy")
}
if resp.StatusCode >= http.StatusInternalServerError {
return errors.New(resp.Status)
}
return fmt.Errorf("HTTP connect status code: %d", resp.StatusCode)
}
+12 -3
View File
@@ -4,8 +4,11 @@ import "fmt"
const (
Direct Proto = iota
Shadowsocks
Reject
HTTP
Socks4
Socks5
Shadowsocks
)
type Proto uint8
@@ -14,10 +17,16 @@ func (proto Proto) String() string {
switch proto {
case Direct:
return "direct"
case Shadowsocks:
return "ss"
case Reject:
return "reject"
case HTTP:
return "http"
case Socks4:
return "socks4"
case Socks5:
return "socks5"
case Shadowsocks:
return "ss"
default:
return fmt.Sprintf("proto(%d)", proto)
}
+32
View File
@@ -0,0 +1,32 @@
package proxy
import (
"context"
"errors"
"net"
M "github.com/xjasonlyu/tun2socks/constant"
"github.com/xjasonlyu/tun2socks/proxy/proto"
)
var _ Proxy = (*Reject)(nil)
type Reject struct {
*Base
}
func NewReject() *Reject {
return &Reject{
Base: &Base{
proto: proto.Reject,
},
}
}
func (r *Reject) DialContext(context.Context, *M.Metadata) (net.Conn, error) {
return nil, errors.New("TCP rejected")
}
func (r *Reject) DialUDP(*M.Metadata) (net.PacketConn, error) {
return nil, errors.New("UDP rejected")
}
+2 -6
View File
@@ -8,9 +8,9 @@ import (
"github.com/xjasonlyu/tun2socks/component/dialer"
obfs "github.com/xjasonlyu/tun2socks/component/simple-obfs"
"github.com/xjasonlyu/tun2socks/component/socks5"
M "github.com/xjasonlyu/tun2socks/constant"
"github.com/xjasonlyu/tun2socks/proxy/proto"
"github.com/xjasonlyu/tun2socks/transport/socks5"
"github.com/Dreamacro/go-shadowsocks2/core"
)
@@ -50,11 +50,7 @@ func (ss *Shadowsocks) DialContext(ctx context.Context, metadata *M.Metadata) (c
}
setKeepAlive(c)
defer func() {
if err != nil && c != nil {
c.Close()
}
}()
defer safeConnClose(c, err)
switch ss.obfsMode {
case "tls":
+43
View File
@@ -0,0 +1,43 @@
package proxy
import (
"context"
"fmt"
"net"
"github.com/xjasonlyu/tun2socks/component/dialer"
M "github.com/xjasonlyu/tun2socks/constant"
"github.com/xjasonlyu/tun2socks/proxy/proto"
"github.com/xjasonlyu/tun2socks/transport/socks4"
)
var _ Proxy = (*Socks4)(nil)
type Socks4 struct {
*Base
userID string
}
func NewSocks4(addr, userID string) (*Socks4, error) {
return &Socks4{
Base: &Base{
addr: addr,
proto: proto.Socks4,
},
userID: userID,
}, nil
}
func (ss *Socks4) DialContext(ctx context.Context, metadata *M.Metadata) (c net.Conn, err error) {
c, err = dialer.DialContext(ctx, "tcp", ss.Addr())
if err != nil {
return nil, fmt.Errorf("connect to %s: %w", ss.Addr(), err)
}
setKeepAlive(c)
defer safeConnClose(c, err)
err = socks4.ClientHandshake(c, metadata.DestinationAddress(), socks4.CmdConnect, ss.userID)
return
}
+19 -10
View File
@@ -2,15 +2,15 @@ package proxy
import (
"context"
"errors"
"fmt"
"io"
"io/ioutil"
"net"
"github.com/xjasonlyu/tun2socks/component/dialer"
"github.com/xjasonlyu/tun2socks/component/socks5"
M "github.com/xjasonlyu/tun2socks/constant"
"github.com/xjasonlyu/tun2socks/proxy/proto"
"github.com/xjasonlyu/tun2socks/transport/socks5"
)
var _ Proxy = (*Socks5)(nil)
@@ -20,6 +20,9 @@ type Socks5 struct {
user string
pass string
// unix indicates if socks5 over UDS is enabled.
unix bool
}
func NewSocks5(addr, user, pass string) (*Socks5, error) {
@@ -30,21 +33,23 @@ func NewSocks5(addr, user, pass string) (*Socks5, error) {
},
user: user,
pass: pass,
unix: len(addr) > 0 && addr[0] == '/',
}, nil
}
func (ss *Socks5) DialContext(ctx context.Context, metadata *M.Metadata) (c net.Conn, err error) {
c, err = dialer.DialContext(ctx, "tcp", ss.Addr())
var network = "tcp"
if ss.unix {
network = "unix"
}
c, err = dialer.DialContext(ctx, network, ss.Addr())
if err != nil {
return nil, fmt.Errorf("connect to %s: %w", ss.Addr(), err)
}
setKeepAlive(c)
defer func() {
if err != nil && c != nil {
c.Close()
}
}()
defer safeConnClose(c, err)
var user *socks5.User
if ss.user != "" {
@@ -59,6 +64,10 @@ func (ss *Socks5) DialContext(ctx context.Context, metadata *M.Metadata) (c net.
}
func (ss *Socks5) DialUDP(*M.Metadata) (_ net.PacketConn, err error) {
if ss.unix {
return nil, errors.New("not supported when unix domain socket is enabled")
}
ctx, cancel := context.WithTimeout(context.Background(), tcpConnectTimeout)
defer cancel()
@@ -95,7 +104,7 @@ func (ss *Socks5) DialUDP(*M.Metadata) (_ net.PacketConn, err error) {
addr, err := socks5.ClientHandshake(c, targetAddr, socks5.CmdUDPAssociate, user)
if err != nil {
return nil, fmt.Errorf("client hanshake: %w", err)
return nil, fmt.Errorf("client handshake: %w", err)
}
pc, err := dialer.ListenPacket("udp", "")
@@ -104,7 +113,7 @@ func (ss *Socks5) DialUDP(*M.Metadata) (_ net.PacketConn, err error) {
}
go func() {
io.Copy(ioutil.Discard, c)
io.Copy(io.Discard, c)
c.Close()
// A UDP association terminates when the TCP connection that the UDP
// ASSOCIATE request arrived on terminates. RFC1928
+7
View File
@@ -16,3 +16,10 @@ func setKeepAlive(c net.Conn) {
tcp.SetKeepAlivePeriod(tcpKeepAlivePeriod)
}
}
// safeConnClose closes tcp connection safely.
func safeConnClose(c net.Conn, err error) {
if c != nil && err != nil {
c.Close()
}
}
+1 -1
View File
@@ -31,7 +31,7 @@ func getConnections(w http.ResponseWriter, r *http.Request) {
return
}
conn, err := upgrader.Upgrade(w, r, nil)
conn, err := _upgrader.Upgrade(w, r, nil)
if err != nil {
return
}
+6 -6
View File
@@ -8,7 +8,7 @@ import (
"strings"
"time"
"github.com/xjasonlyu/tun2socks/constant"
V "github.com/xjasonlyu/tun2socks/constant"
"github.com/xjasonlyu/tun2socks/log"
"github.com/xjasonlyu/tun2socks/tunnel/statistic"
@@ -19,7 +19,7 @@ import (
)
var (
upgrader = websocket.Upgrader{
_upgrader = websocket.Upgrader{
CheckOrigin: func(r *http.Request) bool {
return true
},
@@ -60,7 +60,7 @@ func Start(addr, token string) error {
}
func hello(w http.ResponseWriter, r *http.Request) {
render.JSON(w, r, render.M{"hello": constant.Name})
render.JSON(w, r, render.M{"hello": V.Name})
}
func authenticator(token string) func(http.Handler) http.Handler {
@@ -114,7 +114,7 @@ func getLogs(w http.ResponseWriter, r *http.Request) {
var wsConn *websocket.Conn
if websocket.IsWebSocketUpgrade(r) {
wsConn, err = upgrader.Upgrade(w, r, nil)
wsConn, err = _upgrader.Upgrade(w, r, nil)
if err != nil {
return
}
@@ -163,7 +163,7 @@ func traffic(w http.ResponseWriter, r *http.Request) {
var wsConn *websocket.Conn
if websocket.IsWebSocketUpgrade(r) {
var err error
wsConn, err = upgrader.Upgrade(w, r, nil)
wsConn, err = _upgrader.Upgrade(w, r, nil)
if err != nil {
return
}
@@ -203,5 +203,5 @@ func traffic(w http.ResponseWriter, r *http.Request) {
}
func version(w http.ResponseWriter, r *http.Request) {
render.JSON(w, r, render.M{"version": constant.Version})
render.JSON(w, r, render.M{"version": V.Version, "commit": V.GitCommit})
}
+127
View File
@@ -0,0 +1,127 @@
// Package socks4 provides SOCKS4/SOCKS4A client functionalities.
package socks4
import (
"bytes"
"encoding/binary"
"errors"
"io"
"net"
"strconv"
)
const Version = 0x04
type Command = uint8
const (
CmdConnect Command = 0x01
CmdBind Command = 0x02
)
type Code = uint8
const (
RequestGranted Code = 90
RequestRejected Code = 91
RequestIdentdFailed Code = 92
RequestIdentdMismatched Code = 93
)
var (
errVersionMismatched = errors.New("version code mismatched")
errIPv6NotSupported = errors.New("IPv6 not supported")
ErrRequestRejected = errors.New("request rejected or failed")
ErrRequestIdentdFailed = errors.New("request rejected because SOCKS server cannot connect to identd on the client")
ErrRequestIdentdMismatched = errors.New("request rejected because the client program and identd report different user-ids")
ErrRequestUnknownCode = errors.New("request failed with unknown code")
)
func ClientHandshake(rw io.ReadWriter, addr string, command Command, userID string) (err error) {
var (
host string
port uint16
)
if host, port, err = splitHostPort(addr); err != nil {
return err
}
ip := net.ParseIP(host)
if ip == nil /* HOST */ {
ip = net.IPv4(0, 0, 0, 1)
} else if ip.To4() == nil /* IPv6 */ {
return errIPv6NotSupported
}
dstIP := /* [4]byte */ ip.To4()
req := &bytes.Buffer{}
req.WriteByte(Version)
req.WriteByte(command)
binary.Write(req, binary.BigEndian, port)
req.Write(dstIP)
req.WriteString(userID)
req.WriteByte(0) /* NULL */
if isReservedIP(dstIP) /* SOCKS4A */ {
req.WriteString(host)
req.WriteByte(0) /* NULL */
}
if _, err = rw.Write(req.Bytes()); err != nil {
return err
}
var resp [8]byte
if _, err = io.ReadFull(rw, resp[:]); err != nil {
return err
}
if resp[0] != 0x00 {
return errVersionMismatched
}
switch resp[1] {
case RequestGranted:
return nil
case RequestRejected:
return ErrRequestRejected
case RequestIdentdFailed:
return ErrRequestIdentdFailed
case RequestIdentdMismatched:
return ErrRequestIdentdMismatched
default:
return ErrRequestUnknownCode
}
}
// For version 4A, if the client cannot resolve the destination host's
// domain name to find its IP address, it should set the first three bytes
// of DSTIP to NULL and the last byte to a non-zero value. (This corresponds
// to IP address 0.0.0.x, with x nonzero. As decreed by IANA -- The
// Internet Assigned Numbers Authority -- such an address is inadmissible
// as a destination IP address and thus should never occur if the client
// can resolve the domain name.)
func isReservedIP(ip net.IP) bool {
subnet := net.IPNet{
IP: net.IPv4zero,
Mask: net.IPv4Mask(0xff, 0xff, 0xff, 0x00),
}
return !ip.IsUnspecified() && subnet.Contains(ip)
}
func splitHostPort(addr string) (string, uint16, error) {
host, portStr, err := net.SplitHostPort(addr)
if err != nil {
return "", 0, err
}
portInt, err := strconv.ParseUint(portStr, 10, 16)
if err != nil {
return "", 0, err
}
return host, uint16(portInt), nil
}
+152
View File
@@ -0,0 +1,152 @@
SOCKS: A protocol for TCP proxy across firewalls
Ying-Da Lee
Principal Member Technical Staff
NEC Systems Laboratory, CSTC
ylee@syl.dl.nec.com
SOCKS was originally developed by David Koblas and subsequently modified
and extended by me to its current running version -- version 4. It is a
protocol that relays TCP sessions at a firewall host to allow application
users transparent access across the firewall. Because the protocol is
independent of application protocols, it can be (and has been) used for
many different services, such as telnet, ftp, finger, whois, gopher, WWW,
etc. Access control can be applied at the beginning of each TCP session;
thereafter the server simply relays the data between the client and the
application server, incurring minimum processing overhead. Since SOCKS
never has to know anything about the application protocol, it should also
be easy for it to accommodate applications which use encryption to protect
their traffic from nosey snoopers.
Two operations are defined: CONNECT and BIND.
1) CONNECT
The client connects to the SOCKS server and sends a CONNECT request when
it wants to establish a connection to an application server. The client
includes in the request packet the IP address and the port number of the
destination host, and userid, in the following format.
+----+----+----+----+----+----+----+----+----+----+....+----+
| VN | CD | DSTPORT | DSTIP | USERID |NULL|
+----+----+----+----+----+----+----+----+----+----+....+----+
# of bytes: 1 1 2 4 variable 1
VN is the SOCKS protocol version number and should be 4. CD is the
SOCKS command code and should be 1 for CONNECT request. NULL is a byte
of all zero bits.
The SOCKS server checks to see whether such a request should be granted
based on any combination of source IP address, destination IP address,
destination port number, the userid, and information it may obtain by
consulting IDENT, cf. RFC 1413. If the request is granted, the SOCKS
server makes a connection to the specified port of the destination host.
A reply packet is sent to the client when this connection is established,
or when the request is rejected or the operation fails.
+----+----+----+----+----+----+----+----+
| VN | CD | DSTPORT | DSTIP |
+----+----+----+----+----+----+----+----+
# of bytes: 1 1 2 4
VN is the version of the reply code and should be 0. CD is the result
code with one of the following values:
90: request granted
91: request rejected or failed
92: request rejected becasue SOCKS server cannot connect to
identd on the client
93: request rejected because the client program and identd
report different user-ids
The remaining fields are ignored.
The SOCKS server closes its connection immediately after notifying
the client of a failed or rejected request. For a successful request,
the SOCKS server gets ready to relay traffic on both directions. This
enables the client to do I/O on its connection as if it were directly
connected to the application server.
2) BIND
The client connects to the SOCKS server and sends a BIND request when
it wants to prepare for an inbound connection from an application server.
This should only happen after a primary connection to the application
server has been established with a CONNECT. Typically, this is part of
the sequence of actions:
-bind(): obtain a socket
-getsockname(): get the IP address and port number of the socket
-listen(): ready to accept call from the application server
-use the primary connection to inform the application server of
the IP address and the port number that it should connect to.
-accept(): accept a connection from the application server
The purpose of SOCKS BIND operation is to support such a sequence
but using a socket on the SOCKS server rather than on the client.
The client includes in the request packet the IP address of the
application server, the destination port used in the primary connection,
and the userid.
+----+----+----+----+----+----+----+----+----+----+....+----+
| VN | CD | DSTPORT | DSTIP | USERID |NULL|
+----+----+----+----+----+----+----+----+----+----+....+----+
# of bytes: 1 1 2 4 variable 1
VN is again 4 for the SOCKS protocol version number. CD must be 2 to
indicate BIND request.
The SOCKS server uses the client information to decide whether the
request is to be granted. The reply it sends back to the client has
the same format as the reply for CONNECT request, i.e.,
+----+----+----+----+----+----+----+----+
| VN | CD | DSTPORT | DSTIP |
+----+----+----+----+----+----+----+----+
# of bytes: 1 1 2 4
VN is the version of the reply code and should be 0. CD is the result
code with one of the following values:
90: request granted
91: request rejected or failed
92: request rejected becasue SOCKS server cannot connect to
identd on the client
93: request rejected because the client program and identd
report different user-ids.
However, for a granted request (CD is 90), the DSTPORT and DSTIP fields
are meaningful. In that case, the SOCKS server obtains a socket to wait
for an incoming connection and sends the port number and the IP address
of that socket to the client in DSTPORT and DSTIP, respectively. If the
DSTIP in the reply is 0 (the value of constant INADDR_ANY), then the
client should replace it by the IP address of the SOCKS server to which
the cleint is connected. (This happens if the SOCKS server is not a
multi-homed host.) In the typical scenario, these two numbers are
made available to the application client prgram via the result of the
subsequent getsockname() call. The application protocol must provide a
way for these two pieces of information to be sent from the client to
the application server so that it can initiate the connection, which
connects it to the SOCKS server rather than directly to the application
client as it normally would.
The SOCKS server sends a second reply packet to the client when the
anticipated connection from the application server is established.
The SOCKS server checks the IP address of the originating host against
the value of DSTIP specified in the client's BIND request. If a mismatch
is found, the CD field in the second reply is set to 91 and the SOCKS
server closes both connections. If the two match, CD in the second
reply is set to 90 and the SOCKS server gets ready to relay the traffic
on its two connections. From then on the client does I/O on its connection
to the SOCKS server as if it were directly connected to the application
server.
For both CONNECT and BIND operations, the server sets a time limit
(2 minutes in current CSTC implementation) for the establishment of its
connection with the application server. If the connection is still not
establiched when the time limit expires, the server closes its connection
to the client and gives up.
+39
View File
@@ -0,0 +1,39 @@
SOCKS 4A: A Simple Extension to SOCKS 4 Protocol
Ying-Da Lee
yingda@best.com or yingda@esd.sgi.com
Please read SOCKS4.protocol first for an description of the version 4
protocol. This extension is intended to allow the use of SOCKS on hosts
which are not capable of resolving all domain names.
In version 4, the client sends the following packet to the SOCKS server
to request a CONNECT or a BIND operation:
+----+----+----+----+----+----+----+----+----+----+....+----+
| VN | CD | DSTPORT | DSTIP | USERID |NULL|
+----+----+----+----+----+----+----+----+----+----+....+----+
# of bytes: 1 1 2 4 variable 1
VN is the SOCKS protocol version number and should be 4. CD is the
SOCKS command code and should be 1 for CONNECT or 2 for BIND. NULL
is a byte of all zero bits.
For version 4A, if the client cannot resolve the destination host's
domain name to find its IP address, it should set the first three bytes
of DSTIP to NULL and the last byte to a non-zero value. (This corresponds
to IP address 0.0.0.x, with x nonzero. As decreed by IANA -- The
Internet Assigned Numbers Authority -- such an address is inadmissible
as a destination IP address and thus should never occur if the client
can resolve the domain name.) Following the NULL byte terminating
USERID, the client must sends the destination domain name and termiantes
it with another NULL byte. This is used for both CONNECT and BIND requests.
A server using protocol 4A must check the DSTIP in the request packet.
If it represent address 0.0.0.x with nonzero x, the server must read
in the domain name that the client sends in the packet. The server
should resolve the domain name and make connection to the destination
host if it can.
SOCKSified sockd may pass domain names that it cannot resolve to
the next-hop SOCKS server.
@@ -35,6 +35,34 @@ const (
AtypIPv6 Atyp = 0x04
)
// Reply field as defined in RFC 1928 section 6.
type Reply uint8
func (r Reply) String() string {
switch r {
case 0x00:
return "succeeded"
case 0x01:
return "general SOCKS server failure"
case 0x02:
return "connection not allowed by ruleset"
case 0x03:
return "network unreachable"
case 0x04:
return "host unreachable"
case 0x05:
return "connection refused"
case 0x06:
return "TTL expired"
case 0x07:
return "command not supported"
case 0x08:
return "address type not supported"
default:
return "unassigned"
}
}
// MaxAddrLen is the maximum size of SOCKS address in bytes.
const MaxAddrLen = 1 + 1 + 255 + 2
@@ -120,15 +148,16 @@ type User struct {
// ClientHandshake fast-tracks SOCKS initialization to get target address to connect on client side.
func ClientHandshake(rw io.ReadWriter, addr Addr, command Command, user *User) (Addr, error) {
buf := make([]byte, MaxAddrLen)
var err error
var method uint8
if user != nil {
method = 0x02 /* USERNAME/PASSWORD */
} else {
method = 0x00 /* NO AUTHENTICATION REQUIRED */
}
// VER, NMETHODS, METHODS
if user != nil {
_, err = rw.Write([]byte{Version, 0x01 /* NMETHODS */, 0x02 /* USERNAME/PASSWORD */})
} else {
_, err = rw.Write([]byte{Version, 0x01 /* NMETHODS */, 0x00 /* NO AUTHENTICATION REQUIRED */})
}
if err != nil {
if _, err := rw.Write([]byte{Version, 0x01 /* NMETHODS */, method}); err != nil {
return nil, err
}
@@ -184,8 +213,8 @@ func ClientHandshake(rw io.ReadWriter, addr Addr, command Command, user *User) (
return nil, err
}
if buf[1] != 0x00 /* SUCCEEDED */ {
return nil, fmt.Errorf("unsucceed reply: %X", buf[1])
if rep := Reply(buf[1]); rep != 0x00 /* SUCCEEDED */ {
return nil, fmt.Errorf("%#02x: %s", uint8(rep), rep)
}
return ReadAddr(rw, buf)
+1 -9
View File
@@ -3,7 +3,6 @@ package tunnel
import (
"io"
"net"
"strconv"
"sync"
"time"
@@ -34,10 +33,6 @@ func handleTCP(localConn core.TCPConn) {
DstIP: net.IP(id.LocalAddress),
DstPort: id.LocalPort,
}
if !metadata.Valid() {
log.Warnf("[Metadata] not valid: %#v", metadata)
return
}
targetConn, err := proxy.Dial(metadata)
if err != nil {
@@ -49,10 +44,7 @@ func handleTCP(localConn core.TCPConn) {
metadata.MidIP = dialerAddr.IP
metadata.MidPort = uint16(dialerAddr.Port)
} else { /* fallback */
ip, p, _ := net.SplitHostPort(targetConn.LocalAddr().String())
port, _ := strconv.ParseUint(p, 10, 16)
metadata.MidIP = net.ParseIP(ip)
metadata.MidPort = uint16(port)
metadata.MidIP, metadata.MidPort = parseAddr(targetConn.LocalAddr().String())
}
targetConn = newTCPTracker(targetConn, metadata)
+8 -15
View File
@@ -15,9 +15,9 @@ const (
)
var (
tcpQueue = make(chan core.TCPConn) /* unbuffered */
udpQueue = make(chan core.UDPPacket, maxUDPQueueSize)
numUDPWorkers = max(runtime.NumCPU(), 4 /* at least 4 workers */)
_tcpQueue = make(chan core.TCPConn) /* unbuffered */
_udpQueue = make(chan core.UDPPacket, maxUDPQueueSize)
_numUDPWorkers = max(runtime.NumCPU(), 4 /* at least 4 workers */)
)
func init() {
@@ -26,29 +26,22 @@ func init() {
// Add adds tcpConn to tcpQueue.
func Add(conn core.TCPConn) {
tcpQueue <- conn
_tcpQueue <- conn
}
// AddPacket adds udpPacket to udpQueue.
func AddPacket(packet core.UDPPacket) {
select {
case udpQueue <- packet:
case _udpQueue <- packet:
default:
log.Warnf("queue is currently full, packet will be dropped")
packet.Drop()
}
}
func max(a, b int) int {
if a > b {
return a
}
return b
}
func process() {
for i := 0; i < numUDPWorkers; i++ {
queue := udpQueue
for i := 0; i < _numUDPWorkers; i++ {
queue := _udpQueue
go func() {
for packet := range queue {
handleUDP(packet)
@@ -56,7 +49,7 @@ func process() {
}()
}
for conn := range tcpQueue {
for conn := range _tcpQueue {
go handleTCP(conn)
}
}
+22 -25
View File
@@ -4,7 +4,6 @@ import (
"errors"
"net"
"os"
"strconv"
"time"
"github.com/xjasonlyu/tun2socks/common/pool"
@@ -16,15 +15,19 @@ import (
"github.com/xjasonlyu/tun2socks/tunnel/statistic"
)
const (
udpSessionTimeout = 30 * time.Second
var (
// _natTable uses source udp packet information
// as key to store destination udp packetConn.
_natTable = nat.NewTable()
// _udpSessionTimeout is the default timeout for
// each UDP session.
_udpSessionTimeout = 60 * time.Second
)
var (
// natTable uses source udp packet information
// as key to store destination udp packetConn.
natTable = nat.NewTable()
)
func SetUDPTimeout(v int) {
_udpSessionTimeout = time.Duration(v) * time.Second
}
func newUDPTracker(conn net.PacketConn, metadata *M.Metadata) net.PacketConn {
return statistic.NewUDPTracker(conn, metadata, statistic.DefaultManager)
@@ -39,18 +42,14 @@ func handleUDP(packet core.UDPPacket) {
DstIP: net.IP(id.LocalAddress),
DstPort: id.LocalPort,
}
if !metadata.Valid() {
log.Warnf("[Metadata] not valid: %#v", metadata)
return
}
generateNATKey := func(m *M.Metadata) string {
return m.SourceAddress() /* Full Cone NAT Key */
return m.SourceAddress() /* as Full Cone NAT Key */
}
key := generateNATKey(metadata)
handle := func(drop bool) bool {
pc := natTable.Get(key)
pc := _natTable.Get(key)
if pc != nil {
handleUDPToRemote(packet, pc, metadata /* as net.Addr */, drop)
return true
@@ -63,7 +62,7 @@ func handleUDP(packet core.UDPPacket) {
}
lockKey := key + "-lock"
cond, loaded := natTable.GetOrCreateLock(lockKey)
cond, loaded := _natTable.GetOrCreateLock(lockKey)
go func() {
if loaded {
cond.L.Lock()
@@ -74,7 +73,7 @@ func handleUDP(packet core.UDPPacket) {
}
defer func() {
natTable.Delete(lockKey)
_natTable.Delete(lockKey)
cond.Broadcast()
}()
@@ -88,10 +87,7 @@ func handleUDP(packet core.UDPPacket) {
metadata.MidIP = dialerAddr.IP
metadata.MidPort = uint16(dialerAddr.Port)
} else { /* fallback */
ip, p, _ := net.SplitHostPort(pc.LocalAddr().String())
port, _ := strconv.ParseUint(p, 10, 16)
metadata.MidIP = net.ParseIP(ip)
metadata.MidPort = uint16(port)
metadata.MidIP, metadata.MidPort = parseAddr(pc.LocalAddr().String())
}
pc = newUDPTracker(pc, metadata)
@@ -99,12 +95,12 @@ func handleUDP(packet core.UDPPacket) {
go func() {
defer pc.Close()
defer packet.Drop()
defer natTable.Delete(key)
defer _natTable.Delete(key)
handleUDPToLocal(packet, pc, udpSessionTimeout)
handleUDPToLocal(packet, pc)
}()
natTable.Set(key, pc)
_natTable.Set(key, pc)
handle(false /* drop */)
}()
}
@@ -119,16 +115,17 @@ func handleUDPToRemote(packet core.UDPPacket, pc net.PacketConn, remote net.Addr
if _, err := pc.WriteTo(packet.Data() /* data */, remote); err != nil {
log.Warnf("[UDP] write to %s error: %v", remote, err)
}
pc.SetReadDeadline(time.Now().Add(_udpSessionTimeout)) /* reset timeout */
log.Infof("[UDP] %s --> %s", packet.RemoteAddr(), remote)
}
func handleUDPToLocal(packet core.UDPPacket, pc net.PacketConn, timeout time.Duration) {
func handleUDPToLocal(packet core.UDPPacket, pc net.PacketConn) {
buf := pool.Get(pool.MaxSegmentSize)
defer pool.Put(buf)
for /* just loop */ {
pc.SetReadDeadline(time.Now().Add(timeout))
pc.SetReadDeadline(time.Now().Add(_udpSessionTimeout))
n, from, err := pc.ReadFrom(buf)
if err != nil {
if !errors.Is(err, os.ErrDeadlineExceeded) /* ignore i/o timeout */ {
+20
View File
@@ -0,0 +1,20 @@
package tunnel
import (
"net"
"strconv"
)
func max(a, b int) int {
if a > b {
return a
}
return b
}
// parseAddr parses address to IP and port.
func parseAddr(addr string) (net.IP, uint16) {
host, portStr, _ := net.SplitHostPort(addr)
portInt, _ := strconv.ParseUint(portStr, 10, 16)
return net.ParseIP(host), uint16(portInt)
}