Compare commits

...
355 Commits
Author SHA1 Message Date
Jason LyuandGitHub ec85410144 Chore(stale): add exempt-pr-labels (#438) 2024-12-21 04:12:05 +08:00
43f0ba892f Chore(deps): Bump golang.org/x/crypto from 0.29.0 to 0.31.0 (#434)
Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.29.0 to 0.31.0.
- [Commits](https://github.com/golang/crypto/compare/v0.29.0...v0.31.0)

---
updated-dependencies:
- dependency-name: golang.org/x/crypto
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-11 21:53:43 -05:00
寻觅andGitHub e5009398d5 Feature: add Loong64 arch (#427) 2024-11-12 07:29:06 -05:00
Jason LyuandGitHub 54ef0500d3 Chore: bump go mods (#426) 2024-11-11 04:15:24 +08:00
b65d23180c Feature: set open FD offset for iOS (#418)
Co-authored-by: Jason Lyu <xjasonlyu@gmail.com>
2024-10-13 03:51:27 +08:00
Jason LyuandGitHub a821cc483c Chore: bump go mods (#413) 2024-09-30 04:44:55 +08:00
Jason LyuandGitHub 56786517dc Refactor: bufferpool new function (#407) 2024-09-23 02:39:36 +08:00
Jason LyuandGitHub 428f82694a Chore: add README credits (#408) 2024-09-23 02:39:24 +08:00
Jason LyuandGitHub bf745d0e0e Chore: update .dockerignore (#401) 2024-09-02 06:06:38 +08:00
Jason LyuandGitHub 391d3d9f89 Refactor(pool): use generic buffer/pool (#399) 2024-09-02 05:57:22 +08:00
Jason LyuandGitHub fc4c5c4c55 Refactor(pool): move to internal (#398) 2024-09-01 04:23:25 +08:00
Jason LyuandGitHub 978803cdf8 Refactor(socks): replace net.IP with netip.Addr (#397) 2024-09-01 04:04:01 +08:00
Jason LyuandGitHub bd37a1a4c6 Refactor(metadata): replace net.IP with netip.Addr (#396) 2024-09-01 02:57:09 +08:00
Jason LyuandGitHub 1f09b4d42d Refactor(core): replace net.IP with netip.Addr (#395) 2024-08-31 12:00:38 +08:00
Jason LyuandGitHub fd98f65994 Refactor(tunnel): modularize tunnel pkg (#393) 2024-08-31 11:31:18 +08:00
Jason LyuandGitHub 71c45ef87e Chore(mod): bump to go1.23 (#394) 2024-08-31 11:21:07 +08:00
Jason LyuandGitHub 601601a1dc Refactor(log): use go.uber.org/zap (#389) 2024-08-29 06:56:35 +08:00
Jason LyuandGitHub c8c08cfeea Chore: adjust markdown layout (#388) 2024-08-21 05:27:56 +08:00
Jason LyuandGitHub 776e6470d3 Feature(actions): add testing (#378) 2024-08-21 05:27:20 +08:00
Jason LyuandGitHub 66fafd224e Chore: update README (#387)
* remove Chinese README
2024-08-21 02:14:22 +08:00
Jason LyuandGitHub e083dafcf5 Chore(.gitignore): use github template (#381) 2024-07-22 08:53:29 +08:00
Jason LyuandGitHub 24b8cdd96b Refactor(debug): simplify version string (#380) 2024-07-22 08:34:24 +08:00
Jason LyuandGitHub dd791e50c1 Feature: bump gVisor to latest version (#376) 2024-07-20 11:31:44 +08:00
Jason LyuandGitHub 7555425ab8 Chore: update golangci-lint settings (#377)
* remove staticcheck config
2024-07-16 10:32:59 +08:00
Jason LyuandGitHub 592517a00d Chore(actions): update versions (#375) 2024-07-16 06:22:25 +08:00
63f71e0b84 Chore(deps): Bump github.com/gorilla/schema from 1.3.0 to 1.4.1 (#370)
Bumps [github.com/gorilla/schema](https://github.com/gorilla/schema) from 1.3.0 to 1.4.1.
- [Release notes](https://github.com/gorilla/schema/releases)
- [Commits](https://github.com/gorilla/schema/compare/v1.3.0...v1.4.1)

---
updated-dependencies:
- dependency-name: github.com/gorilla/schema
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-12 05:19:58 +08:00
Jason LyuandGitHub 488e5b223c Chore(actions): update versions (#362) 2024-05-13 02:34:37 +08:00
Jason LyuandGitHub 0d819e1aec Fix: codeql autobuild error (#355) 2024-04-07 02:53:17 +08:00
Jason LyuandGitHub 60a63db500 Chore: bump dependency (#354)
* gVisor: `v0.0.0-20240215211334-a66ecfdd829a` => `v0.0.0-20240405191320-0878b34101b5`
2024-04-07 02:33:43 +08:00
Yawning AngelandGitHub 8c7c9085c2 Fix: socks5 usernames and passwords can BOTH be up to 255 bytes (#343) 2024-02-28 10:27:14 +08:00
Jason LyuandGitHub 8653c18875 Fix: safely split command strings (#340) 2024-02-20 05:41:58 +08:00
Jason LyuandGitHub 7b1d73d86e Chore: bump to go1.22 (#337)
* Chore: update go mods
* Chore: bump to go1.22
* Chore: fix lint trigger
2024-02-16 06:47:17 +08:00
Nicolai MooreandGitHub a49ce339b7 Fix: call SetSendBufferSize when setting send buffer size option (#336) 2024-02-07 10:18:53 +08:00
Jason LyuandGitHub 2334083cf9 Chore: update CodeQL (#332) 2024-01-28 07:21:33 +08:00
Jason LyuandGitHub 01d4ac4864 Chore: update go mods (#331) 2024-01-28 07:10:26 +08:00
Jason LyuandGitHub c8f8cb5caf Chore(release/go): use version from go.mod (#317) 2023-11-14 06:21:26 +08:00
Jason LyuandGitHub e5bfa13a3f Chore: update go mod (#316)
* bump gvisor to `v0.0.0-20231113203814-cdee0abd0280`
2023-11-14 06:00:15 +08:00
ctyandGitHub e86b3b7dc5 Perf(SOCKS5): optimize memory footprint with authentication (#315) 2023-11-13 06:28:42 +08:00
Jason LyuandGitHub 010765138c Chore: update README (#314)
* Remove deleted repositories
2023-11-03 23:09:12 +08:00
Jason LyuandGitHub f8bddb162e Improve(proxy/ss): allow explicit none cipher mode (#312) 2023-10-25 09:36:02 +08:00
Jason LyuandGitHub 2d80a4ba3b Chore(actions/docker): use github variables (#311) 2023-10-25 00:21:43 +08:00
Jason LyuandGitHub 00a5f18ebd Feature(proxy): support gost relay protocol (#310) 2023-10-24 10:55:33 +08:00
Jason LyuandGitHub 47913b549f Fix: defer func for safeConnClose (#309) 2023-10-24 09:13:36 +08:00
Jason LyuandGitHub 2283f82bbc Refactor: direct proxy parsing (#308) 2023-10-24 04:44:17 +08:00
Jason LyuandGitHub cbf620b2f8 Improve: use embedded go-shadowsocks2 (#306)
* Improve: use embedded go-shadowsocks2
* Chore: update go mod
2023-10-23 02:52:26 +08:00
Jason LyuandGitHub 68da4d9997 Chore: update go mod (#303) 2023-09-29 04:56:49 +08:00
Jason LyuandGitHub 78086193fb Fix: bump versions for actions (#302) 2023-09-29 04:46:13 +08:00
Jason LyuandGitHub 631fa59182 Feature: persistent wintun with GUID option (#301)
Fixes: #300
2023-09-29 04:36:29 +08:00
Jason LyuandGitHub f448baa2ae Chore: use errors.ErrUnsupported (#294) 2023-09-05 01:51:03 +08:00
Jason LyuandGitHub b470006fb6 Chore: bump to go1.21 (#292) 2023-08-29 01:30:11 +08:00
Jason LyuandGitHub 73ea4358cb Docker: add options for multicast groups (#290) 2023-08-28 07:04:22 +08:00
Jason LyuandGitHub 19ba20ffc0 Improve(actions): add concurrency groups (#289) 2023-08-28 03:57:16 +08:00
Jason LyuandGitHub f1b7b4745b Chore: bump go mods (#288) 2023-08-28 03:48:38 +08:00
90f77548ed Feature: add support for multicast (#245)
* add support for multicast (#243)

* adjust setup

---------

Co-authored-by: xjasonlyu <xjasonlyu@gmail.com>
2023-08-28 03:40:49 +08:00
xjasonlyu fffcbbea10 Chore: set up sponsor button 2023-08-27 14:14:27 -04:00
xjasonlyu f588b4c731 Chore: star chart with dark theme supported 2023-08-06 13:44:24 +08:00
Jason LyuandGitHub 71efe6c7cf Chore: do not mark stale for help wanted issues (#280) 2023-07-27 10:21:20 +08:00
xjasonlyu 2067a3129e Chore: update badge links 2023-07-20 15:01:18 +08:00
yushengandGitHub 8309fddef3 Feature: fdbased open fd with offset (#272) 2023-06-30 13:18:53 +08:00
xjasonlyu 2b494a7517 Fix: HTTP proxy basic auth error (#266) 2023-06-20 14:40:54 +08:00
xjasonlyu 7ab86fd9b0 Chore: use renamed buffer pkg 2023-06-05 14:54:58 +08:00
xjasonlyu 4868427efb Chore: update go modules 2023-06-05 14:54:29 +08:00
xjasonlyu 673a942fb3 Improve: set mtu with unix ioctl 2023-05-30 17:40:46 +08:00
xjasonlyu 44ad654d72 Fix: revert to classic TUN creation (#254) 2023-05-30 17:40:45 +08:00
xjasonlyu 46c04db29f Fix: tun issue with virtio_net_hdr (#254) 2023-05-26 16:23:01 +08:00
xjasonlyu 07a6a9f096 Chore: bump gVisor version 2023-05-26 14:45:37 +08:00
xjasonlyu cd6b118e63 Refactor: relocate simple-obfs pkg 2023-05-20 15:10:06 +08:00
xjasonlyu 9838f57e0d Refactor: relocate dialer pkg 2023-05-20 14:53:08 +08:00
xjasonlyu 9dfea44f48 Refactor: remove nat pkg 2023-05-20 14:37:49 +08:00
xjasonlyu 860cf31256 Fix: relocate unused const 2023-05-20 14:37:02 +08:00
xjasonlyu 8e20770bec Refactor: optimize http proxy 2023-05-20 14:32:16 +08:00
xjasonlyu 3320ba46e4 Fix: update tcpip.Address api 2023-05-18 21:38:29 +08:00
xjasonlyu 38bfbb2c3f Chore: update go mod 2023-05-18 21:16:44 +08:00
xjasonlyu 6c07927bba Chore: remove ref annotations 2023-05-18 21:15:04 +08:00
xjasonlyu 2813b4c581 Chore: move files to .github 2023-05-17 22:19:57 +08:00
Jason LyuandGitHub db7c3fd7d2 Chore: create CODE_OF_CONDUCT.md (#259) 2023-05-17 22:16:38 +08:00
Jason LyuandGitHub 4fc5c03e35 Chore: create SECURITY.md (#258) 2023-05-17 22:02:30 +08:00
Vladislav FursovandGitHub 3cbbf3068a Fix(socks5): panic with unassigned reply code (#255) 2023-05-17 10:06:56 +08:00
Jason LyuandGitHub 8da083b28e Chore: nolint in tun_wireguard_unix.go (#253) 2023-05-15 15:05:46 +08:00
xjasonlyu dc6eb815da CI(linter): enable new linters 2023-05-11 10:58:19 +08:00
Jason LyuandGitHub 3b54548914 CI: update golangci-lint config (#251) 2023-05-11 10:51:55 +08:00
SolynandGitHub d061f1c040 Feature: support setting log output (#248)
Signed-off-by: yusheng <yusheng@tencent.com>
2023-05-06 20:49:49 +08:00
xjasonlyu 8e8ccdab89 Chore: use Star History 2023-04-25 15:25:48 +08:00
xjasonlyu 9cbc99e8f5 Chore: bump golang.org/x/sys to v0.7.0 2023-04-06 12:54:12 +08:00
xjasonlyu 2dbd2caaa9 Fix: netstats JSON response 2023-04-03 19:59:37 +08:00
2d0bd1d219 Improve: tunnel/tcp pipe (#219)
Co-authored-by: xjasonlyu <xjasonlyu@gmail.com>
2023-04-03 19:15:24 +08:00
xjasonlyu 61a9d26815 Minor: UDP unidirectionalPacketStream 2023-04-03 19:13:03 +08:00
xjasonlyu 4cc02c822c Minor: improve tunnel/udp 2023-04-03 18:43:02 +08:00
xjasonlyu 20499c6432 Revert: cli tcp-wait-timeout option
This reverts commit 2c51a65685.
2023-04-03 17:57:13 +08:00
xjasonlyu ad522ebb35 Chore: minor renames 2023-04-03 17:43:19 +08:00
xjasonlyu 06d8bee2af Ignore: (*gonet.TCPConn).RemoteAddr() warning 2023-04-03 13:52:28 +08:00
xjasonlyu b809f89411 Revert: udp-rlybuf option
As a low-level networking tool, tun2socks should be able to handle UDP packets of all possible sizes. This reverts commit fb9ca95909.
2023-04-03 12:24:07 +08:00
xjasonlyu b8ff1859c1 Chore: update go mods 2023-04-02 20:20:56 +08:00
xjasonlyu 89c37dc156 Improve: deprecate isIgnorable
All errors should be returned by copyBuffer and handled by higher level functions.
2023-04-02 16:43:55 +08:00
xjasonlyu 1b8e063485 Fix: log message typo 2023-03-30 18:11:08 +08:00
xjasonlyu 195290884c Fix: potential crash by bad UDP address (#238) 2023-03-30 14:11:43 +08:00
xjasonlyu 3b343600e7 Chore: core loglevel to debug 2023-03-29 23:19:08 +08:00
2c51a65685 Feature: cli tcp-wait-timeout option (#156)
Co-authored-by: xjasonlyu <xjasonlyu@gmail.com>
2023-03-29 17:41:01 +08:00
xjasonlyu fb9ca95909 Feature: add udp-rlybuf option
* Default UDP relay buffer size: 16KiB
2023-03-29 16:56:03 +08:00
xjasonlyu 1e99f2d580 Chore: debug level log 2023-03-28 18:04:46 +08:00
xjasonlyu ce15b1b2c2 Improve: with default tracker 2023-03-28 18:00:05 +08:00
xjasonlyu c036db2e23 Chore: rm unused code 2023-03-27 19:11:56 +08:00
007c97fe67 Feature: support pre&post-up exec (#233)
* Add tun pre/post script
* Improve: pre & post tun

---------

Co-authored-by: xjasonlyu <xjasonlyu@gmail.com>
2023-03-27 13:26:39 +08:00
xjasonlyu 7327f2c784 Improve: with gvisor internal log 2023-03-27 13:21:10 +08:00
xjasonlyu 66860d3de8 Improve: enhance error handling 2023-03-27 00:43:39 +08:00
xjasonlyu c61d7b5a20 Chore: error is ignorable 2023-03-26 23:07:13 +08:00
xjasonlyu 680feede3b Improve: add tun io lock 2023-03-26 22:56:01 +08:00
xjasonlyu 22b15f6fab Improve: redirect stack log 2023-03-26 22:48:28 +08:00
xjasonlyu f7b4f75ed4 Fix: align with wireguard io 2023-03-26 22:10:21 +08:00
xjasonlyu 29feac8cd4 Chore: bump go mods 2023-03-26 14:40:39 +08:00
xjasonlyu 6cfc25309e Fix: rand linter
`math/rand.Read` has been deprecated since Go 1.20
2023-02-21 15:06:05 +08:00
xjasonlyu 1f63b239c3 Chore: update linter 2023-02-21 14:55:01 +08:00
xjasonlyu 041bc510ea Chore: bump go modules 2023-02-21 14:05:25 +08:00
xjasonlyu 51d8a27289 Chore: bump gvisor
v0.0.0-20230219185229-4f1045309c43
2023-02-21 14:03:17 +08:00
xjasonlyu 5ffb0186bf Improve: do not stale labeled issues 2023-02-12 14:04:35 +08:00
xjasonlyu 8a2e5cebeb Fix: deprecate rand.Seed 2023-02-06 15:39:37 +08:00
xjasonlyu 846d3d87a7 Chore: bump go.mod to 1.20 2023-02-06 15:39:15 +08:00
xjasonlyu b491e17bfa Chore: add v2 to prefix 2023-02-06 15:38:46 +08:00
xjasonlyu fbe4c22347 Revert: undo crypto/rand
This reverts commit 4a8bf64cb1.
2023-02-06 15:31:05 +08:00
xjasonlyu 4a8bf64cb1 Improve: use crypto/rand 2023-02-04 14:26:41 +08:00
xjasonlyu 059f661862 Chore: bump to go1.20 2023-02-04 13:52:29 +08:00
xjasonlyu ab05092671 Chore: update go mod 2023-02-04 13:52:19 +08:00
xjasonlyu 6809e7f835 Chore: bump gVisor 2023-01-22 13:27:11 +08:00
xjasonlyu bbdc9113d7 Chore: update go mod 2023-01-13 13:40:20 +08:00
xjasonlyu 30608f4925 Chore: bump gVisor 2023-01-01 15:55:12 +08:00
xjasonlyu 39b1406ffa Chore: update mods 2022-12-17 16:57:57 +08:00
xjasonlyu a1edb1c1bb Chore: update workflows 2022-12-17 16:53:30 +08:00
xjasonlyu ad014648ef Fix: build badges 2022-12-16 16:54:54 +08:00
xjasonlyu fa3317a94c Chore: bump go mods 2022-12-01 15:57:08 +08:00
xjasonlyu 8d3c28a516 Feature: support mark on FreeBSD & OpenBSD 2022-12-01 15:46:49 +08:00
LanceLiandGitHub 35f6888c30 Feature: support bind interface on windows (#192) 2022-11-26 23:10:23 +08:00
xjasonlyu 3cbc74b1cf Chore: update gvisor 2022-11-08 15:21:45 +08:00
xjasonlyu 24a53467f6 Chore: deprecate set-output command 2022-10-15 15:33:20 +08:00
xjasonlyu 702ba81ccd Chore: update workflows 2022-10-14 23:26:59 +08:00
xjasonlyu 7fce6e9544 Fix: PacketBufferPtr.IsNil 2022-10-14 22:54:12 +08:00
xjasonlyu 553c2f7a17 Chore: bump modules 2022-10-14 22:36:41 +08:00
xjasonlyu ccfb3a47f6 Fix: make build work
This commit may be reverted if gVisor updates its fdbased pkg.
2022-09-25 16:31:15 +08:00
xjasonlyu 0177157c69 Chore: deprecate openbsd-386 2022-09-25 16:23:47 +08:00
xjasonlyu 82546cd2c5 Chore: with unix build constraint 2022-09-25 15:49:39 +08:00
xjasonlyu 9895b3e048 Chore: update go mod 2022-09-25 15:08:23 +08:00
xjasonlyu 39b50f2bfb Chore: update go mod 2022-09-18 19:31:29 +08:00
xjasonlyu c45470650b Chore: reorder imports 2022-08-07 00:25:59 +08:00
xjasonlyu cb6408a17a Fix: update to bufferv2 2022-08-07 00:05:11 +08:00
xjasonlyu 77bd119d34 Chore: update go mod 2022-08-07 00:04:03 +08:00
xjasonlyu 595896dfc7 Chore: bump to go1.19 2022-08-06 23:51:15 +08:00
xjasonlyu 55a8d038d6 Improve: ignore tcp errors 2022-07-15 21:08:11 +08:00
xjasonlyu e31ffce0e6 Fix: adjust endpoint change 2022-07-15 20:59:37 +08:00
xjasonlyu 267cc6d1a9 Chore: update go mod 2022-07-15 20:17:27 +08:00
xjasonlyu 31468620e7 Chore: update badge logo 2022-06-01 00:10:41 +08:00
xjasonlyu 1536735456 Chore: disable blank issues 2022-05-24 15:30:51 +08:00
xjasonlyu b329f23a4e Chore: auth with GITHUB_TOKEN 2022-05-21 16:27:52 +08:00
xjasonlyu 1ecd587857 Fix(udp): ignore EOF 2022-04-26 16:06:01 +08:00
xjasonlyu 6076fd9a69 Chore(netstats): just render.JSON 2022-04-21 23:30:54 +08:00
xjasonlyu 3926f86613 Feature(docker): add tzdata 2022-04-07 10:56:24 +08:00
xjasonlyu 77e8ad4810 Chore: update modules 2022-04-06 23:33:47 +08:00
xjasonlyu a8e8a2dc4c Fix(tunnel/udp): NAT source verification (#112) 2022-04-06 23:21:18 +08:00
xjasonlyu f2cfa15945 Chore(tunnel): minify log message 2022-04-06 17:26:02 +08:00
xjasonlyu 764657d657 Chore: ignore io timeout 2022-04-06 16:07:59 +08:00
xjasonlyu d65d3b08d0 Change: use default tcp buffer size 2022-04-06 15:48:51 +08:00
xjasonlyu c35f28b3a3 Improve(restapi/netstats): JSON encoding 2022-04-06 15:23:02 +08:00
xjasonlyu 23a6e28768 Chore(core): format request ID 2022-04-05 23:40:57 +08:00
xjasonlyu 102b46e9f6 Refactor(tunnel): udp packet relay 2022-04-05 23:14:16 +08:00
xjasonlyu ab728bd8cc Chore(tunnel): log tcp error 2022-04-05 23:13:38 +08:00
xjasonlyu 4aea88c36e Chore(core): print TransportEndpointID 2022-04-04 22:32:50 +08:00
xjasonlyu e4801c3989 Fix(restapi): debug missing mountpoints 2022-04-04 22:05:47 +08:00
xjasonlyu fd8223e4d0 Fix(docker): sh out of range warning 2022-04-04 21:15:06 +08:00
xjasonlyu 883915ab2c Chore: update README 2022-04-04 17:14:03 +08:00
xjasonlyu 4ca3c90b8c Chore: update modules 2022-04-04 17:06:11 +08:00
xjasonlyu 2e758d1960 Chore(core/tcp): add a comment 2022-04-04 17:06:06 +08:00
xjasonlyu 9797cb31c0 Refactor: return metadata.Addr only 2022-04-03 23:16:36 +08:00
xjasonlyu 8f97bda4f5 Chore: amend log messages 2022-04-03 22:31:59 +08:00
xjasonlyu 6a53c52167 Chore: add udp-timeout constraint 2022-04-03 22:09:41 +08:00
xjasonlyu 992e716216 Improve: use interface index for macos 2022-04-02 16:08:55 +08:00
xjasonlyu 289ea82829 Feature(docker): add tcp options env 2022-04-02 15:15:06 +08:00
xjasonlyu a0d31261b9 Chore: remove redundant alias 2022-04-02 15:06:30 +08:00
xjasonlyu 31e19a0690 Change: udp timeout = time.Duration 2022-04-02 15:05:47 +08:00
xjasonlyu 596056676c Chore: rename to netstack 2022-04-02 00:23:49 +08:00
xjasonlyu bff32beb73 Chore: add/update modules 2022-04-02 00:03:28 +08:00
xjasonlyu 551e2c345c Feature: cli tcp options 2022-04-01 23:40:17 +08:00
xjasonlyu dc2c555865 Fix: correctly apply recv buffer size 2022-04-01 22:34:44 +08:00
xjasonlyu 81c2d6963b Chore: reorder const and func 2022-04-01 22:26:05 +08:00
xjasonlyu b7c3c9001b Chore: add benchmark.png 2022-04-01 22:10:09 +08:00
xjasonlyu 9f239d146b Chore: separate send/recv buffer 2022-04-01 21:48:17 +08:00
xjasonlyu 3c326c01ed Change: disable tcp recv buffer auto-tuning by default 2022-04-01 21:11:33 +08:00
xjasonlyu 21eb99a37e Fix: should apply default option firstly 2022-04-01 14:28:12 +08:00
xjasonlyu e0b0a1e94b Chore(core): amend message 2022-03-31 23:56:06 +08:00
xjasonlyu 096117dda1 Chore: minor declaration 2022-03-31 23:12:11 +08:00
xjasonlyu 21232703af Chore(core): use config.PrintFunc 2022-03-31 17:48:52 +08:00
xjasonlyu ccf53dcb88 Chore: use mirror.Tunnel 2022-03-31 17:28:12 +08:00
xjasonlyu 8d3f8d7631 Fix: potential panic on windows (#110)
This is only a temporary solution.
2022-03-31 15:11:34 +08:00
xjasonlyu 9f7989a9d0 Fix: import missing 2022-03-31 14:06:56 +08:00
xjasonlyu b5f61c0999 Fix(core): race cond when init 2022-03-31 00:04:12 +08:00
xjasonlyu e6fc4adccd Feature(restapi): add netstats 2022-03-30 23:38:31 +08:00
xjasonlyu abdbaa6b83 Refactor(engine): remove struct 2022-03-30 23:09:50 +08:00
xjasonlyu cba7e19d22 Chore(restapi): minor adjustment 2022-03-30 17:56:18 +08:00
xjasonlyu 2aea811072 Chore: with engine 2022-03-29 19:42:44 +08:00
xjasonlyu b166ed5e66 Refactor: stats -> restapi 2022-03-29 19:25:45 +08:00
xjasonlyu e6911cb6fb Chore: remove config example 2022-03-29 18:45:38 +08:00
xjasonlyu 3999c5d66b Refactor(core): with error callback 2022-03-29 17:19:54 +08:00
xjasonlyu 0a9f7f123c Chore: use tcpip.Error 2022-03-29 16:18:52 +08:00
xjasonlyu ba7a7ddc95 Chore(core/adapter): rename to TransportHandler 2022-03-29 15:26:00 +08:00
xjasonlyu 20fe2e4cd8 Chore: minor rename 2022-03-29 14:12:25 +08:00
xjasonlyu 201e79ac71 Fix: nil options panic 2022-03-29 13:39:18 +08:00
xjasonlyu a4bedf6080 Refactor: new dialer impl 2022-03-29 13:39:18 +08:00
xjasonlyu 42d6c96b6b Fix: wrong wait logic 2022-03-29 13:39:18 +08:00
xjasonlyu 9d7dacbea1 Chore(core/device): tun constants 2022-03-29 13:39:18 +08:00
xjasonlyu 0e8b16f9a1 Fix: decrease packet reference (#106)
ref: https://github.com/google/gvisor/commit/f375784d83852b1e3ff20cc9de0648b3c0cf8525
2022-03-29 13:39:18 +08:00
xjasonlyu c2af4c0c7c Fix: wait for device to close 2022-03-29 13:39:18 +08:00
xjasonlyu ba0a4acbda Refactor: core.CreateStackWithOptions 2022-03-29 13:39:18 +08:00
xjasonlyu 898e648cb5 Chore: close stack when stop 2022-03-29 13:39:18 +08:00
xjasonlyu 620d5ac834 Chore: put log in engine 2022-03-29 13:39:18 +08:00
xjasonlyu 7df522a91f Revert: GOAMD64v1 as default (#104)
GOAMD64=v3 will not run on older x86 processors that don't support AVX2.
2022-03-29 13:39:18 +08:00
xjasonlyu 376a1eac2c Fix: early stopped engine (#105) 2022-03-29 13:39:18 +08:00
xjasonlyu 584c9c7805 Chore: explicit resolver 2022-03-29 13:39:18 +08:00
xjasonlyu c6ca52326a Refactor: main.go 2022-03-29 13:39:18 +08:00
xjasonlyu ae07fbdb68 Chore: delete common/automaxprocs 2022-03-29 13:39:18 +08:00
xjasonlyu 531125ee1f Chore: minor refactor 2022-03-29 13:39:18 +08:00
xjasonlyu 7ac97016fe Chore: move all to version 2022-03-29 13:39:18 +08:00
xjasonlyu d3fc3abbb7 Migration: go 1.18 2022-03-29 13:38:50 +08:00
xjasonlyu 8bb8423e50 Chore: fix lint 2022-03-26 15:06:42 +08:00
xjasonlyu 82fd2f91c0 Chore: update action workflows 2022-03-26 14:49:57 +08:00
xjasonlyu 7bbae5549d Chore: adjust Dockerfile 2022-03-26 14:34:26 +08:00
xjasonlyu c68dd0771e Chore: make tcpKeepaliveCount explicit 2022-02-13 14:57:31 +08:00
xjasonlyu 5679d15442 Fix: nil addr panic (#99) 2022-02-12 21:16:43 +08:00
xjasonlyu 4be2734b19 Chore: make internal/version 2022-02-09 17:29:10 +08:00
xjasonlyu 283008536b Feature: more fields in stats version 2022-02-09 17:25:55 +08:00
xjasonlyu 2f21e10be6 Feature: show debug in version 2022-02-09 17:21:20 +08:00
xjasonlyu 8d2170832c Chore(engine): improve log message 2022-02-09 16:49:54 +08:00
xjasonlyu 211831b3e6 Fix(iobased): exit outboundLoop to prevent goroutine leak 2022-02-08 20:17:30 +08:00
xjasonlyu 6a8bc0fd79 Chore(socks5): revise handshake error message 2022-02-08 18:55:03 +08:00
xjasonlyu 9d8251ac43 Fix: google/gvisor@f33d034fec (google/gvisor#7125) 2022-02-08 14:38:24 +08:00
xjasonlyu bf35298289 Fix: suppress panic when wintun.dll not found 2022-02-07 17:31:28 +08:00
xjasonlyu b5794661b5 Chore: update go modules 2022-02-06 21:39:56 +08:00
xjasonlyu dc2794ae1e Improve(statistic): use google/uuid 2022-02-06 21:02:49 +08:00
xjasonlyu 6cfbf4d0e6 Chore: add TODOs 2022-02-06 20:41:49 +08:00
xjasonlyu edec658cd0 Refactor: use core/adapter 2022-02-06 20:26:09 +08:00
xjasonlyu 93a5ff5d86 Improve(stack): add TCP recovery option 2022-02-06 20:17:45 +08:00
xjasonlyu 1b38ce2d25 Improve(socks5): unify addr parsing 2022-02-06 19:48:12 +08:00
xjasonlyu cc56100f15 Chore(metadata): add TCPAddr method 2022-02-05 20:14:05 +08:00
xjasonlyu 575a2a66ac Chore(socks5): add rfc annotation 2022-02-05 19:16:57 +08:00
xjasonlyu d552de237f Fix: reset timeout in udp tunnel 2022-02-05 16:59:23 +08:00
xjasonlyu 6603c1f334 Refactor: improve metadata structure 2022-02-05 16:51:17 +08:00
xjasonlyu dd0cde04b4 Refactor: optimize UDP module
Symmetric NAT support for now.
2022-02-05 15:49:03 +08:00
xjasonlyu 14c663c40e Improve: Makefile debug target 2022-02-03 21:45:16 +08:00
xjasonlyu 6547625688 Fix: UDP packet buffer leak (#82) 2022-02-02 21:29:27 +08:00
xjasonlyu bdf85afa3e Chore: use versionize 2022-02-02 20:29:43 +08:00
xjasonlyu c85cf60a45 Improve: reduce bytes copy 2022-02-02 19:48:38 +08:00
xjasonlyu 47e74ed8c2 Fix: release packet buffer (#82) 2022-02-02 17:17:59 +08:00
xjasonlyu e36c2eb226 Improve: use *channel.Endpoint for underlying I/O 2022-02-02 17:17:43 +08:00
xjasonlyu b28349235f Chore(stack): update opts.go 2022-02-01 20:34:43 +08:00
xjasonlyu faed47da40 Chore: fix lint 2022-02-01 17:30:34 +08:00
xjasonlyu 13b5cc71d7 Improve(stack): specify NIC options 2022-02-01 17:19:51 +08:00
xjasonlyu d415ed35d7 Improve(iobased): impl stack.GSOEndpoint 2022-02-01 17:18:17 +08:00
xjasonlyu cd5b9e8954 Chore: rename to fdbased 2022-02-01 17:17:09 +08:00
xjasonlyu c2ec509cfa Fix(core): update gVisor (#82, #95) 2022-02-01 17:16:39 +08:00
xjasonlyu b581c2e877 Style(workflows): auto reformat 2022-02-01 15:47:10 +08:00
xjasonlyu 5d81f455bd Chore(stack): update comments 2022-02-01 13:18:25 +08:00
xjasonlyu 7e268cfc7a Chore: update issue template 2022-01-31 23:18:32 +08:00
xjasonlyu 3480680806 Chore: chmod -x .go files 2022-01-31 18:32:11 +08:00
xjasonlyu fd000c6617 Refactor: standalone metadata module 2022-01-31 16:03:10 +08:00
xjasonlyu 830c231c43 Refactor: standalone version module 2022-01-31 16:00:17 +08:00
xjasonlyu 0e5dafd36b Chore(docker): re-tag to dev 2022-01-31 14:26:31 +08:00
xjasonlyu 40dfe8807a Chore(iobased): use MTU() 2022-01-29 21:00:43 +08:00
xjasonlyu e3007f0498 Chore: import with newline 2022-01-29 21:00:19 +08:00
xjasonlyu e23837aa6d Style: use gofumpt for fmt 2022-01-29 17:26:24 +08:00
xjasonlyu 1d229ac859 Chore: update workflows 2022-01-29 17:06:01 +08:00
Jason LyuandGitHub 300401ad76 Chore: create codeql-analysis.yml 2022-01-29 17:04:54 +08:00
xjasonlyu e3b57bb8d8 Chore: update issue template 2022-01-29 16:56:03 +08:00
xjasonlyu f114b435d3 Chore: issue template config 2022-01-29 16:34:00 +08:00
xjasonlyu b394b09790 Chore: adjust entrypoint.sh 2022-01-29 14:09:59 +08:00
xjasonlyu 59f682dfab Chore: rename to iobased 2022-01-28 21:10:10 +08:00
xjasonlyu 3b82a085d7 Chore: rename to config.yml 2022-01-28 19:59:32 +08:00
xjasonlyu 4b4b01a507 Improve: use bytes.Buffer pool 2022-01-28 15:30:23 +08:00
xjasonlyu 1bbb51b332 Chore: use automaxprocs 2022-01-28 15:01:04 +08:00
xjasonlyu 2a2420f89d Fix: revert module
Temporarily revert to previous gVisor version due to unstable bugs.
2022-01-20 15:07:42 +08:00
xjasonlyu 95f6464174 Chore: impl interface 2022-01-19 19:52:45 +08:00
xjasonlyu 3fa0820552 Chore: go mod update 2022-01-19 19:52:03 +08:00
Fan LinandGitHub c068fbd626 Fix: set major version to v2 (#88) 2022-01-03 16:06:18 +08:00
xjasonlyu 9370983c63 Chore: upgrade go-chi/chi to v5 2021-12-24 11:31:55 +08:00
xjasonlyu 5fe7c9a5bb Chore: update README_ZH 2021-12-23 20:01:50 +08:00
xjasonlyu c1ba254957 Improve: add pprof debug 2021-12-08 17:00:28 +08:00
xjasonlyu 4ffe32fd89 Improve: add default mtu for fd device 2021-12-08 16:27:45 +08:00
xjasonlyu 8e00168914 Chore: regular module updating 2021-12-08 12:32:23 +08:00
xjasonlyu 0d51d2db54 Chore: update go modules 2021-11-27 13:36:13 +08:00
xjasonlyu cf557f0eb1 Fix: control should return error 2021-11-27 13:27:44 +08:00
xjasonlyu 6bb44f9eb1 Change: use nop for reject 2021-11-27 13:15:01 +08:00
Jason LyuandGitHub 40824d8350 Update issue templates 2021-11-22 11:09:06 +08:00
xjasonlyu 5ee4c676a1 Feature: YAML config support 2021-11-10 13:38:20 +08:00
xjasonlyu 733c4cb779 Chore: grammar correction 2021-11-08 21:11:35 +08:00
xjasonlyu af55e8517c Chore: rename to SerializeSocksAddr 2021-11-08 21:06:24 +08:00
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
149 changed files with 5464 additions and 3002 deletions
+5 -3
View File
@@ -1,6 +1,8 @@
.github
.github/
.gitignore
.golangci.yaml
# Other
build/*
docs/*
docs/
build/
tests/
+128
View File
@@ -0,0 +1,128 @@
# Contributor Covenant Code of Conduct
## Our Pledge
We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, religion, or sexual identity
and orientation.
We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.
## Our Standards
Examples of behavior that contributes to a positive environment for our
community include:
* Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes,
and learning from the experience
* Focusing on what is best not just for us as individuals, but for the
overall community
Examples of unacceptable behavior include:
* The use of sexualized language or imagery, and sexual attention or
advances of any kind
* Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or email
address, without their explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Enforcement Responsibilities
Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.
Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.
## Scope
This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
xjasonlyu@gmail.com.
All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the
reporter of any incident.
## Enforcement Guidelines
Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:
### 1. Correction
**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.
**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.
### 2. Warning
**Community Impact**: A violation through a single incident or series
of actions.
**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or
permanent ban.
### 3. Temporary Ban
**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.
**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.
### 4. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within
the community.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.0, available at
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
Community Impact Guidelines were inspired by [Mozilla's code of conduct
enforcement ladder](https://github.com/mozilla/diversity).
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see the FAQ at
https://www.contributor-covenant.org/faq. Translations are available at
https://www.contributor-covenant.org/translations.
+12
View File
@@ -0,0 +1,12 @@
# These are supported funding model platforms
github: [ xjasonlyu ] # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
patreon: # Replace with a single Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
+55
View File
@@ -0,0 +1,55 @@
name: Bug report
description: Create a report to help us improve
title: "[Bug] "
body:
- type: checkboxes
id: ensure
attributes:
label: Verify steps
description: Please verify that you've followed these steps
options:
- label: Is this something you can **debug and fix**? Send a pull request! Bug fixes and documentation fixes are welcome.
required: true
- label: I have searched on the [issue tracker](……/) for a related issue.
required: true
- type: input
attributes:
label: Version
validations:
required: true
- type: dropdown
id: os
attributes:
label: What OS are you seeing the problem on?
multiple: true
options:
- Windows
- Linux
- macOS
- OpenBSD/FreeBSD
- Other
- type: textarea
attributes:
label: Description
validations:
required: true
- type: textarea
attributes:
label: CLI or Config
description: Paste the command line parameters or configuration below.
- type: textarea
attributes:
render: shell
label: Logs
description: Paste the logs below with the log level set to `DEBUG`.
- type: textarea
attributes:
label: How to Reproduce
description: Steps to reproduce the behavior, if any.
+9
View File
@@ -0,0 +1,9 @@
blank_issues_enabled: false
contact_links:
- name: tun2socks GitHub Wiki
url: https://github.com/xjasonlyu/tun2socks/wiki
about: Please see the wiki for common configurations
- name: tun2socks GitHub Discussions
url: https://github.com/xjasonlyu/tun2socks/discussions
about: Ask questions and get help on GitHub Discussions
@@ -0,0 +1,25 @@
name: Feature request
description: Suggest an idea or improvement
title: "[Feature] "
body:
- type: textarea
id: description
attributes:
label: Description
placeholder: A clear description of the feature or enhancement.
validations:
required: true
- type: textarea
id: related
attributes:
label: Is this feature related to a specific bug?
description: Please include a bug references if yes.
- type: textarea
id: solution
attributes:
label: Do you have a specific solution in mind?
description: >
Please include any details about a solution that you have in mind,
including any alternatives considered.
+29
View File
@@ -0,0 +1,29 @@
# Security Policy
## Supported Versions
| Version | Supported |
|:-------:|:------------------:|
| 2.x | :white_check_mark: |
| 1.x | :x: |
## Reporting a Vulnerability
If you believe you have found a security vulnerability in this repository, please report it to me through coordinated
disclosure.
**Please do not report security vulnerabilities through public GitHub issues, discussions, or pull requests.**
Instead, please email to xjasonlyu[@]gmail.com.
Please include as much of the information listed below as you can to help me better understand and resolve the issue:
* The type of issue (e.g., buffer overflow, payload attack)
* Full paths of source file(s) related to the manifestation of the issue
* The location of the affected source code (tag/branch/commit or direct URL)
* Any special configuration required to reproduce the issue
* Step-by-step instructions to reproduce the issue
* Proof-of-concept or exploit code (if possible)
* Impact of the issue, including how an attacker might exploit the issue
This information will help me triage your report more quickly.
+41
View File
@@ -0,0 +1,41 @@
name: "CodeQL"
concurrency:
group: codeql-${{ github.event_name }}-${{ github.ref }}
cancel-in-progress: true
on:
push:
branches: [ main ]
pull_request:
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
language: [ 'go' ]
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Go
uses: actions/setup-go@v5
with:
check-latest: true
go-version-file: 'go.mod'
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
- name: Autobuild
uses: github/codeql-action/autobuild@v3
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
+35 -32
View File
@@ -1,75 +1,78 @@
name: Publish Docker Image
concurrency:
group: docker-${{ github.event_name }}-${{ github.ref }}
cancel-in-progress: true
on:
push:
branches:
- dev
- 'main'
tags:
- '*'
paths-ignore:
- 'docs/**'
- '**.md'
jobs:
build:
name: Build
docker:
name: Docker
runs-on: ubuntu-latest
steps:
- name: Check out code into the Go module directory
uses: actions/checkout@v2
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up QEMU
uses: docker/setup-qemu-action@v1
uses: docker/setup-qemu-action@v3
with:
platforms: all
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
uses: docker/setup-buildx-action@v3
with:
version: latest
- name: Login to DockerHub
uses: docker/login-action@v1
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Login to GitHub Container Registry
uses: docker/login-action@v1
uses: docker/login-action@v3
with:
registry: ghcr.io
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/arm/v7,linux/arm64
tags: |
xjasonlyu/tun2socks:dev
ghcr.io/xjasonlyu/tun2socks:dev
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Get Version
id: shell
run: |
echo ::set-output name=version::$(git describe --tags --abbrev=0)
echo "version=$(git describe --tags --abbrev=0)" >> $GITHUB_OUTPUT
- name: Build and Push (latest)
if: startsWith(github.ref, 'refs/tags/')
uses: docker/build-push-action@v2
- name: Build and Push (dev)
if: github.ref == 'refs/heads/main'
uses: docker/build-push-action@v6
with:
context: .
push: true
platforms: linux/amd64,linux/arm/v7,linux/arm64
platforms: linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64
tags: |
xjasonlyu/tun2socks:dev
ghcr.io/xjasonlyu/tun2socks:dev
cache-from: type=gha
cache-to: type=gha,mode=max
- name: Build and Push (latest)
if: startsWith(github.ref, 'refs/tags/')
uses: docker/build-push-action@v6
with:
context: .
push: true
platforms: linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64
tags: |
xjasonlyu/tun2socks:latest
xjasonlyu/tun2socks:${{ steps.shell.outputs.version }}
ghcr.io/xjasonlyu/tun2socks:latest
ghcr.io/xjasonlyu/tun2socks:${{ steps.shell.outputs.version }}
cache-from: type=gha
cache-to: type=gha,mode=max
-57
View File
@@ -1,57 +0,0 @@
name: Go
on:
pull_request:
push:
branches:
- dev
tags:
- '*'
paths-ignore:
- 'docs/**'
- 'docker/**'
- '**.md'
jobs:
build:
name: Build
runs-on: ubuntu-latest
steps:
- name: Setup Go
uses: actions/setup-go@v2
with:
go-version: 1.16.x
- name: Check out code into the Go module directory
uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Cache go module
uses: actions/cache@v2
with:
path: ~/go/pkg/mod
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-go-
- name: Get dependencies, run test and static check
run: |
go test ./...
go vet ./...
go get -u honnef.co/go/tools/cmd/staticcheck
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: build/*
draft: true
prerelease: true
+30
View File
@@ -0,0 +1,30 @@
name: Linter
concurrency:
group: linter-${{ github.event_name }}-${{ github.ref }}
cancel-in-progress: true
on:
push:
branches:
- 'main'
pull_request:
jobs:
linter:
name: Linter
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Go
uses: actions/setup-go@v5
with:
check-latest: true
go-version-file: 'go.mod'
- name: golangci-lint
uses: golangci/golangci-lint-action@v6
with:
version: latest
+48
View File
@@ -0,0 +1,48 @@
name: Publish Go Releases
concurrency:
group: release-${{ github.event_name }}-${{ github.ref }}
cancel-in-progress: true
on:
push:
tags:
- '*'
jobs:
release:
name: Release
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup Go
uses: actions/setup-go@v5
with:
check-latest: true
go-version-file: 'go.mod'
- name: Cache go module
uses: actions/cache@v4
with:
path: |
~/go/pkg/mod
~/.cache/go-build
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-go-
- name: Build
if: startsWith(github.ref, 'refs/tags/')
run: make -j releases
- name: Upload Releases
uses: softprops/action-gh-release@v2
if: startsWith(github.ref, 'refs/tags/')
with:
files: build/*
draft: true
prerelease: false
+8 -2
View File
@@ -1,5 +1,10 @@
name: Mark stale issues and pull requests
permissions:
contents: write
issues: write
pull-requests: write
on:
schedule:
- cron: "0 10 * * *"
@@ -8,9 +13,10 @@ jobs:
stale:
runs-on: ubuntu-latest
steps:
- uses: actions/stale@v3
- uses: actions/stale@v9
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
stale-issue-message: 'This issue is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 7 days'
exempt-issue-labels: 'question,bug,enhancement,help wanted'
exempt-pr-labels: 'pending,WIP,help wanted'
days-before-stale: 60
days-before-close: 7
+31
View File
@@ -0,0 +1,31 @@
name: Test
concurrency:
group: test-${{ github.event_name }}-${{ github.ref }}
cancel-in-progress: true
on:
push:
branches:
- 'main'
pull_request:
jobs:
build-test:
name: Build Test
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup Go
uses: actions/setup-go@v5
with:
check-latest: true
go-version-file: 'go.mod'
- name: Run test
run: |
go test ./...
+19 -1
View File
@@ -1,9 +1,27 @@
# Binaries
# If you prefer the allow list template instead of the deny list, see community template:
# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore
#
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib
# Test binary, built with `go test -c`
*.test
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
# Dependency directories (remove the comment below to include it)
# vendor/
# Go workspace file
go.work
go.work.sum
# Build directory
build/
# IDE
+21
View File
@@ -0,0 +1,21 @@
linters:
disable-all: true
enable:
- gci
- gofumpt
- gosimple
- govet
- ineffassign
- misspell
- staticcheck
- unconvert
- unused
- usestdlibvars
linters-settings:
gci:
custom-order: true
sections:
- standard
- default
- prefix(github.com/xjasonlyu/tun2socks)
+12 -9
View File
@@ -1,19 +1,18 @@
FROM golang:alpine AS builder
WORKDIR /tun2socks-src
COPY . /tun2socks-src
WORKDIR /src
COPY . /src
RUN apk add --no-cache make git \
&& make tun2socks \
&& mv ./build/tun2socks /tun2socks
RUN apk add --update --no-cache make git \
&& make tun2socks
FROM alpine:latest
LABEL org.opencontainers.image.source="https://github.com/xjasonlyu/tun2socks"
COPY docker/entrypoint.sh /entrypoint.sh
COPY --from=builder /tun2socks /usr/bin/tun2socks
COPY --from=builder /src/build/tun2socks /usr/bin/tun2socks
RUN apk add --update --no-cache iptables iproute2 \
RUN apk add --update --no-cache iptables iproute2 tzdata \
&& chmod +x /entrypoint.sh
ENV TUN=tun0
@@ -21,8 +20,12 @@ ENV ADDR=198.18.0.1/15
ENV LOGLEVEL=info
ENV PROXY=direct://
ENV MTU=9000
ENV STATS=
ENV TOKEN=
ENV RESTAPI=
ENV UDP_TIMEOUT=
ENV TCP_SNDBUF=
ENV TCP_RCVBUF=
ENV TCP_AUTO_TUNING=
ENV MULTICAST_GROUPS=
ENV EXTRA_COMMANDS=
ENV TUN_INCLUDED_ROUTES=
ENV TUN_EXCLUDED_ROUTES=
+45 -7
View File
@@ -1,5 +1,5 @@
BINARY := tun2socks
MODULE := github.com/xjasonlyu/tun2socks
MODULE := github.com/xjasonlyu/tun2socks/v2
BUILD_DIR := build
BUILD_TAGS :=
@@ -11,19 +11,23 @@ CGO_ENABLED := 0
GO111MODULE := on
LDFLAGS += -w -s -buildid=
LDFLAGS += -X "$(MODULE)/constant.Version=$(BUILD_VERSION)"
LDFLAGS += -X "$(MODULE)/constant.GitCommit=$(BUILD_COMMIT)"
LDFLAGS += -X "$(MODULE)/internal/version.Version=$(BUILD_VERSION)"
LDFLAGS += -X "$(MODULE)/internal/version.GitCommit=$(BUILD_COMMIT)"
GO_BUILD = GO111MODULE=$(GO111MODULE) CGO_ENABLED=$(CGO_ENABLED) \
go build $(BUILD_FLAGS) -ldflags '$(LDFLAGS)' -tags '$(BUILD_TAGS)' -trimpath
UNIX_ARCH_LIST = \
darwin-amd64 \
darwin-amd64-v3 \
darwin-arm64 \
freebsd-386 \
freebsd-amd64 \
freebsd-amd64-v3 \
freebsd-arm64 \
linux-386 \
linux-amd64 \
linux-amd64-v3 \
linux-arm64 \
linux-armv5 \
linux-armv6 \
@@ -37,16 +41,22 @@ UNIX_ARCH_LIST = \
linux-ppc64 \
linux-ppc64le \
linux-s390x \
openbsd-386 \
linux-loong64 \
openbsd-amd64 \
openbsd-amd64-v3 \
openbsd-arm64
WINDOWS_ARCH_LIST = \
windows-386 \
windows-amd64 \
windows-amd64-v3 \
windows-arm64 \
windows-arm32v7
all: linux-amd64 darwin-amd64 windows-amd64
all: linux-amd64 linux-arm64 darwin-amd64 darwin-arm64 windows-amd64
debug: BUILD_TAGS += debug
debug: all
tun2socks:
$(GO_BUILD) -o $(BUILD_DIR)/$(BINARY)
@@ -54,6 +64,9 @@ tun2socks:
darwin-amd64:
GOARCH=amd64 GOOS=darwin $(GO_BUILD) -o $(BUILD_DIR)/$(BINARY)-$@
darwin-amd64-v3:
GOARCH=amd64 GOOS=darwin GOAMD64=v3 $(GO_BUILD) -o $(BUILD_DIR)/$(BINARY)-$@
darwin-arm64:
GOARCH=arm64 GOOS=darwin $(GO_BUILD) -o $(BUILD_DIR)/$(BINARY)-$@
@@ -63,12 +76,21 @@ freebsd-386:
freebsd-amd64:
GOARCH=amd64 GOOS=freebsd $(GO_BUILD) -o $(BUILD_DIR)/$(BINARY)-$@
freebsd-amd64-v3:
GOARCH=amd64 GOOS=freebsd GOAMD64=v3 $(GO_BUILD) -o $(BUILD_DIR)/$(BINARY)-$@
freebsd-arm64:
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 $(BUILD_DIR)/$(BINARY)-$@
linux-amd64-v3:
GOARCH=amd64 GOOS=linux GOAMD64=v3 $(GO_BUILD) -o $(BUILD_DIR)/$(BINARY)-$@
linux-arm64:
GOARCH=arm64 GOOS=linux $(GO_BUILD) -o $(BUILD_DIR)/$(BINARY)-$@
@@ -108,12 +130,15 @@ linux-ppc64le:
linux-s390x:
GOARCH=s390x GOOS=linux $(GO_BUILD) -o $(BUILD_DIR)/$(BINARY)-$@
openbsd-386:
GOARCH=386 GOOS=openbsd $(GO_BUILD) -o $(BUILD_DIR)/$(BINARY)-$@
linux-loong64:
GOARCH=loong64 GOOS=linux $(GO_BUILD) -o $(BUILD_DIR)/$(BINARY)-$@
openbsd-amd64:
GOARCH=amd64 GOOS=openbsd $(GO_BUILD) -o $(BUILD_DIR)/$(BINARY)-$@
openbsd-amd64-v3:
GOARCH=amd64 GOOS=openbsd GOAMD64=v3 $(GO_BUILD) -o $(BUILD_DIR)/$(BINARY)-$@
openbsd-arm64:
GOARCH=arm64 GOOS=openbsd $(GO_BUILD) -o $(BUILD_DIR)/$(BINARY)-$@
@@ -123,6 +148,12 @@ windows-386:
windows-amd64:
GOARCH=amd64 GOOS=windows $(GO_BUILD) -o $(BUILD_DIR)/$(BINARY)-$@.exe
windows-amd64-v3:
GOARCH=amd64 GOOS=windows GOAMD64=v3 $(GO_BUILD) -o $(BUILD_DIR)/$(BINARY)-$@.exe
windows-arm64:
GOARCH=arm64 GOOS=windows $(GO_BUILD) -o $(BUILD_DIR)/$(BINARY)-$@.exe
windows-arm32v7:
GOARCH=arm GOARM=7 GOOS=windows $(GO_BUILD) -o $(BUILD_DIR)/$(BINARY)-$@.exe
@@ -139,5 +170,12 @@ all-arch: $(UNIX_ARCH_LIST) $(WINDOWS_ARCH_LIST)
releases: $(unix_releases) $(windows_releases)
lint:
GOOS=darwin golangci-lint run ./...
GOOS=windows golangci-lint run ./...
GOOS=linux golangci-lint run ./...
GOOS=freebsd golangci-lint run ./...
GOOS=openbsd golangci-lint run ./...
clean:
rm -rf $(BUILD_DIR)
+43 -25
View File
@@ -1,49 +1,67 @@
![tun2socks](docs/logo.png)
![tun2socks](docs/wordmark.png)
[![GitHub Workflow][1]](https://github.com/xjasonlyu/tun2socks/actions)
[![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)
[![Releases][5]](https://github.com/xjasonlyu/tun2socks/releases)
[![Maintainability][4]](https://codeclimate.com/github/xjasonlyu/tun2socks/maintainability)
[![GitHub License][5]](https://github.com/xjasonlyu/tun2socks/blob/main/LICENSE)
[![Docker Pulls][6]](https://hub.docker.com/r/xjasonlyu/tun2socks)
[![Releases][7]](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/github/v/release/xjasonlyu/tun2socks?include_prereleases&style=flat-square
English | [简体中文](README_ZH.md)
[1]: https://img.shields.io/github/actions/workflow/status/xjasonlyu/tun2socks/release.yml?logo=github
[2]: https://img.shields.io/github/go-mod/go-version/xjasonlyu/tun2socks?logo=go
[3]: https://goreportcard.com/badge/github.com/xjasonlyu/tun2socks
[4]: https://api.codeclimate.com/v1/badges/b5b30239174fc6603aca/maintainability
[5]: https://img.shields.io/github/license/xjasonlyu/tun2socks
[6]: https://img.shields.io/docker/pulls/xjasonlyu/tun2socks?logo=docker
[7]: https://img.shields.io/github/v/release/xjasonlyu/tun2socks?logo=smartthings
## Features
- **Fully support:** IPv4/IPv6/ICMP/TCP/UDP
- **Proxy protocol:** Socks5/Shadowsocks
- **Game ready:** optimized UDP transmission
- **Pure Go:** no CGO required, stability improved
- **Router mode:** forwarding packets in LAN
- **TCP/IP stack:** powered by **[gVisor](https://github.com/google/gvisor)**
- **High performance:** >2.5Gbps throughput
- Proxy Everything: Handle all network traffic of any internet programs sent by the device through a proxy.
- Proxy Protocols: HTTP/Socks4/Socks5/Shadowsocks with authentication support for remote connections.
- Run Everywhere: Linux/macOS/Windows/FreeBSD/OpenBSD multi-platform support with specific optimization.
- Gateway Mode: Act as a Layer 3 gateway to handle network traffic from other devices on the same network.
- Full IPv6 Support: All functions work in IPv6, tunnel IPv4 connections through IPv6 proxy and vice versa.
- Network Stack: Powered by the user-space TCP/IP stack from Google container application kernel **[gVisor](https://github.com/google/gvisor)**.
## Requirements
## Benchmarks
| Target | Minimum | Recommended |
| :----- | :-----: | :---------: |
| System | Linux MacOS Freebsd OpenBSD Windows | Linux or MacOS |
| Memory | >20MB | >128MB |
| CPU | ANY | AMD64 or ARM64 |
For all scenarios of usage, tun2socks performs best.
See [benchmarks](https://github.com/xjasonlyu/tun2socks/wiki/Benchmarks) for more details.
![benchmark](docs/benchmark.png)
## Documentation
Documentations and quick start guides can be found at [Github Wiki](https://github.com/xjasonlyu/tun2socks/wiki).
- [Install from Source](https://github.com/xjasonlyu/tun2socks/wiki/Install-from-Source)
- [Quickstart Examples](https://github.com/xjasonlyu/tun2socks/wiki/Examples)
- [Memory Optimization](https://github.com/xjasonlyu/tun2socks/wiki/Memory-Optimization)
Full documentation and technical guides can be found at [Wiki](https://github.com/xjasonlyu/tun2socks/wiki).
## Community
Welcome and feel free to ask any questions at [Discussions](https://github.com/xjasonlyu/tun2socks/discussions).
## Credits
- [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
- [wintun](https://git.zx2c4.com/wintun/) - Layer 3 TUN Driver for Windows
## 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)
## Star History
<a href="https://star-history.com/#xjasonlyu/tun2socks&Date">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=xjasonlyu/tun2socks&type=Date&theme=dark" />
<source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=xjasonlyu/tun2socks&type=Date" />
<img alt="Star History Chart" src="https://api.star-history.com/svg?repos=xjasonlyu/tun2socks&type=Date" />
</picture>
</a>
-64
View File
@@ -1,64 +0,0 @@
![tun2socks](docs/logo.png)
[![GitHub Workflow][1]](https://github.com/xjasonlyu/tun2socks/actions)
[![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)
[![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/github/v/release/xjasonlyu/tun2socks?include_prereleases&style=flat-square
[English](README.md) | 简体中文
## 为什么使用 tun2socks
通过在主机上运行`tun2socks`,可以轻松地接管所有的`TCP/UDP`流量,同时提供诸多专业的功能特性,这包括:
- 强制使不支持代理的程序走代理
- 结合Clash、V2Ray等代理后端实现全局科学上网
- 结合Burp、Charles等工具进行应用层数据的调试
- 结合DHCP、CoreDNS等应用部署路由模式代理局域网流量
## 特性介绍
- **全面支持:** IPv4/IPv6/ICMP/TCP/UDP
- **代理协议:** Socks5/Shadowsocks
- **游戏加速:** 针对UDP传输的优化
- **纯Go实现:** 无需CGO,稳定性提升
- **路由模式:** 转发代理局域网内所有流量
- **TCP/IP栈:** 由 **[gVisor](https://github.com/google/gvisor)** 强力驱动
- **高性能:** >2.5Gbps 的带宽吞吐量
## 硬件需求
| 目标 | 最小 | 建议 |
| :--- | :---: | :---: |
| 系统 | Linux MacOS Freebsd OpenBSD Windows | Linux or MacOS |
| 内存 | >20MB | >128MB |
| 架构 | ANY | AMD64 or ARM64 |
## 使用文档
文档以及使用方式,请看 [Github Wiki](https://github.com/xjasonlyu/tun2socks/wiki)。
## 注意事项
1. 由于采用了纯Go实现,所以这一版本的`tun2socks`在有大量连接时内存消耗通常较多。如果您的需求对内存消耗极为敏感,请继续使用 [v1](https://github.com/xjasonlyu/tun2socks/tree/v1) 版本。
2. `tun2socks`只应该专注于将网络层的TCP/UDP流量转发给SOCKS服务器,其他的如DNS(DoH)、DHCP等模块功能应该交由第三方应用实现,所以弃用了DNS模块。
3. 因为是通过用户空间的网络栈接管所有流量并处理转发,在高吞吐时CPU的使用量会剧增,所以CPU的性能直接与可以达到的最大带宽挂钩。
## 特别感谢
- [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)
+13 -15
View File
@@ -1,30 +1,29 @@
package pool
package allocator
import (
"errors"
"math/bits"
"sync"
)
var _allocator = NewAllocator()
"github.com/xjasonlyu/tun2socks/v2/internal/pool"
)
// Allocator for incoming frames, optimized to prevent overwriting
// after zeroing.
type Allocator struct {
buffers []sync.Pool
buffers []*pool.Pool[[]byte]
}
// NewAllocator initiates a []byte allocator for frames less than
// 65536 bytes, the waste(memory fragmentation) of space allocation
// is guaranteed to be no more than 50%.
func NewAllocator() *Allocator {
// New initiates a []byte allocator for frames less than 65536 bytes,
// the waste(memory fragmentation) of space allocation is guaranteed
// to be no more than 50%.
func New() *Allocator {
alloc := &Allocator{}
alloc.buffers = make([]sync.Pool, 17) // 1B -> 64K
alloc.buffers = make([]*pool.Pool[[]byte], 17) // 1B -> 64K
for k := range alloc.buffers {
i := k
alloc.buffers[k].New = func() interface{} {
alloc.buffers[k] = pool.New(func() []byte {
return make([]byte, 1<<uint32(i))
}
})
}
return alloc
}
@@ -37,10 +36,10 @@ func (alloc *Allocator) Get(size int) []byte {
b := msb(size)
if size == 1<<b {
return alloc.buffers[b].Get().([]byte)[:size]
return alloc.buffers[b].Get()[:size]
}
return alloc.buffers[b+1].Get().([]byte)[:size]
return alloc.buffers[b+1].Get()[:size]
}
// Put returns a []byte to pool for future use,
@@ -51,7 +50,6 @@ func (alloc *Allocator) Put(buf []byte) error {
return errors.New("allocator Put() incorrect buffer size")
}
//lint:ignore SA6002 ignore temporarily
alloc.buffers[b].Put(buf)
return nil
}
+4 -4
View File
@@ -1,4 +1,4 @@
package pool
package allocator
import (
"math/rand"
@@ -8,7 +8,7 @@ import (
)
func TestAllocGet(t *testing.T) {
alloc := NewAllocator()
alloc := New()
assert.Nil(t, alloc.Get(0))
assert.Equal(t, 1, len(alloc.Get(1)))
assert.Equal(t, 2, len(alloc.Get(2)))
@@ -23,7 +23,7 @@ func TestAllocGet(t *testing.T) {
}
func TestAllocPut(t *testing.T) {
alloc := NewAllocator()
alloc := New()
assert.NotNil(t, alloc.Put(nil), "put nil misbehavior")
assert.NotNil(t, alloc.Put(make([]byte, 3)), "put elem:3 []bytes misbehavior")
assert.Nil(t, alloc.Put(make([]byte, 4)), "put elem:4 []bytes misbehavior")
@@ -33,7 +33,7 @@ func TestAllocPut(t *testing.T) {
}
func TestAllocPutThenGet(t *testing.T) {
alloc := NewAllocator()
alloc := New()
data := alloc.Get(4)
_ = alloc.Put(data)
newData := alloc.Get(4)
+8 -3
View File
@@ -1,18 +1,23 @@
// Package pool provides a pool of []byte.
package pool
// Package buffer provides a pool of []byte.
package buffer
// Ref: github.com/Dreamacro/clash/common/pool
import (
"github.com/xjasonlyu/tun2socks/v2/buffer/allocator"
)
const (
// MaxSegmentSize is the largest possible UDP datagram size.
MaxSegmentSize = (1 << 16) - 1
// RelayBufferSize is the default buffer size for TCP relays.
// io.Copy default buffer size is 32 KiB, but the maximum packet
// size of vmess/shadowsocks is about 16 KiB, so define a buffer
// of 20 KiB to reduce the memory of each TCP relay.
RelayBufferSize = 20 << 10
)
var _allocator = allocator.New()
// Get gets a []byte from default allocator with most appropriate cap.
func Get(size int) []byte {
return _allocator.Get(size)
-3
View File
@@ -1,3 +0,0 @@
package observable
type Iterable <-chan interface{}
-67
View File
@@ -1,67 +0,0 @@
package observable
// Ref: github.com/Dreamacro/clash/common/observable
import (
"errors"
"sync"
)
type Observable struct {
iterable Iterable
listener map[Subscription]*Subscriber
mux sync.Mutex
done bool
}
func (o *Observable) process() {
for item := range o.iterable {
o.mux.Lock()
for _, sub := range o.listener {
sub.Emit(item)
}
o.mux.Unlock()
}
o.close()
}
func (o *Observable) close() {
o.mux.Lock()
defer o.mux.Unlock()
o.done = true
for _, sub := range o.listener {
sub.Close()
}
}
func (o *Observable) Subscribe() (Subscription, error) {
o.mux.Lock()
defer o.mux.Unlock()
if o.done {
return nil, errors.New("observable is closed")
}
subscriber := newSubscriber()
o.listener[subscriber.Out()] = subscriber
return subscriber.Out(), nil
}
func (o *Observable) UnSubscribe(sub Subscription) {
o.mux.Lock()
defer o.mux.Unlock()
subscriber, exist := o.listener[sub]
if !exist {
return
}
delete(o.listener, sub)
subscriber.Close()
}
func NewObservable(any Iterable) *Observable {
observable := &Observable{
iterable: any,
listener: map[Subscription]*Subscriber{},
}
go observable.process()
return observable
}
-148
View File
@@ -1,148 +0,0 @@
package observable
import (
"sync"
"testing"
"time"
"github.com/stretchr/testify/assert"
"go.uber.org/atomic"
)
func iterator(item []interface{}) chan interface{} {
ch := make(chan interface{})
go func() {
time.Sleep(100 * time.Millisecond)
for _, elm := range item {
ch <- elm
}
close(ch)
}()
return ch
}
func TestObservable(t *testing.T) {
iter := iterator([]interface{}{1, 2, 3, 4, 5})
src := NewObservable(iter)
data, err := src.Subscribe()
assert.Nil(t, err)
count := 0
for range data {
count++
}
assert.Equal(t, count, 5)
}
func TestObservable_MultiSubscribe(t *testing.T) {
iter := iterator([]interface{}{1, 2, 3, 4, 5})
src := NewObservable(iter)
ch1, _ := src.Subscribe()
ch2, _ := src.Subscribe()
var count = atomic.NewInt32(0)
var wg sync.WaitGroup
wg.Add(2)
waitCh := func(ch <-chan interface{}) {
for range ch {
count.Inc()
}
wg.Done()
}
go waitCh(ch1)
go waitCh(ch2)
wg.Wait()
assert.Equal(t, int32(10), count.Load())
}
func TestObservable_UnSubscribe(t *testing.T) {
iter := iterator([]interface{}{1, 2, 3, 4, 5})
src := NewObservable(iter)
data, err := src.Subscribe()
assert.Nil(t, err)
src.UnSubscribe(data)
_, open := <-data
assert.False(t, open)
}
func TestObservable_SubscribeClosedSource(t *testing.T) {
iter := iterator([]interface{}{1})
src := NewObservable(iter)
data, _ := src.Subscribe()
<-data
_, closed := src.Subscribe()
assert.NotNil(t, closed)
}
func TestObservable_UnSubscribeWithNotExistSubscription(t *testing.T) {
sub := Subscription(make(chan interface{}))
iter := iterator([]interface{}{1})
src := NewObservable(iter)
src.UnSubscribe(sub)
}
func TestObservable_SubscribeGoroutineLeak(t *testing.T) {
iter := iterator([]interface{}{1, 2, 3, 4, 5})
src := NewObservable(iter)
max := 100
var list []Subscription
for i := 0; i < max; i++ {
ch, _ := src.Subscribe()
list = append(list, ch)
}
var wg sync.WaitGroup
wg.Add(max)
waitCh := func(ch <-chan interface{}) {
for range ch {
}
wg.Done()
}
for _, ch := range list {
go waitCh(ch)
}
wg.Wait()
for _, sub := range list {
_, more := <-sub
assert.False(t, more)
}
if len(list) > 0 {
_, more := <-list[0]
assert.False(t, more)
}
}
func Benchmark_Observable_1000(b *testing.B) {
ch := make(chan interface{})
o := NewObservable(ch)
num := 1000
var subs []Subscription
for i := 0; i < num; i++ {
sub, _ := o.Subscribe()
subs = append(subs, sub)
}
wg := sync.WaitGroup{}
wg.Add(num)
b.ResetTimer()
for _, sub := range subs {
go func(s Subscription) {
for range s {
}
wg.Done()
}(sub)
}
for i := 0; i < b.N; i++ {
ch <- i
}
close(ch)
wg.Wait()
}
-33
View File
@@ -1,33 +0,0 @@
package observable
import (
"sync"
)
type Subscription <-chan interface{}
type Subscriber struct {
buffer chan interface{}
once sync.Once
}
func (s *Subscriber) Emit(item interface{}) {
s.buffer <- item
}
func (s *Subscriber) Out() Subscription {
return s.buffer
}
func (s *Subscriber) Close() {
s.once.Do(func() {
close(s.buffer)
})
}
func newSubscriber() *Subscriber {
sub := &Subscriber{
buffer: make(chan interface{}, 200),
}
return sub
}
-21
View File
@@ -1,21 +0,0 @@
package dialer
import (
"net"
"sync"
)
var _bindOnce sync.Once
// BindToInterface binds dialer to specific interface.
func BindToInterface(name string) error {
i, err := net.InterfaceByName(name)
if err != nil {
return err
}
_bindOnce.Do(func() {
addControl(bindToInterface(i))
})
return nil
}
-26
View File
@@ -1,26 +0,0 @@
package dialer
import (
"net"
"syscall"
"golang.org/x/sys/unix"
)
func bindToInterface(i *net.Interface) controlFunc {
return func(network, address string, c syscall.RawConn) error {
ipStr, _, _ := net.SplitHostPort(address)
if ip := net.ParseIP(ipStr); ip != nil && !ip.IsGlobalUnicast() {
return nil
}
return c.Control(func(fd uintptr) {
switch network {
case "tcp4", "udp4":
unix.SetsockoptInt(int(fd), syscall.IPPROTO_IP, syscall.IP_BOUND_IF, i.Index)
case "tcp6", "udp6":
unix.SetsockoptInt(int(fd), syscall.IPPROTO_IPV6, syscall.IPV6_BOUND_IF, i.Index)
}
})
}
}
-21
View File
@@ -1,21 +0,0 @@
package dialer
import (
"net"
"syscall"
"golang.org/x/sys/unix"
)
func bindToInterface(i *net.Interface) controlFunc {
return func(network, address string, c syscall.RawConn) error {
ipStr, _, _ := net.SplitHostPort(address)
if ip := net.ParseIP(ipStr); ip != nil && !ip.IsGlobalUnicast() {
return nil
}
return c.Control(func(fd uintptr) {
unix.BindToDevice(int(fd), i.Name)
})
}
}
-15
View File
@@ -1,15 +0,0 @@
// +build !linux,!darwin
package dialer
import (
"errors"
"net"
"syscall"
)
func bindToInterface(_ *net.Interface) controlFunc {
return func(string, string, syscall.RawConn) error {
return errors.New("unsupported platform")
}
}
-37
View File
@@ -1,37 +0,0 @@
package dialer
import (
"errors"
"net"
"syscall"
)
type controlFunc func(string, string, syscall.RawConn) error
var (
_controlPool = make([]controlFunc, 0, 2)
)
func addControl(f controlFunc) {
_controlPool = append(_controlPool, f)
}
func setControl(i interface{}) {
control := func(address, network string, c syscall.RawConn) error {
for _, f := range _controlPool {
if err := f(address, network, c); err != nil {
return err
}
}
return nil
}
switch v := i.(type) {
case *net.Dialer:
v.Control = control
case *net.ListenConfig:
v.Control = control
default:
panic(errors.New("wrong type"))
}
}
-22
View File
@@ -1,22 +0,0 @@
package dialer
import (
"context"
"net"
)
func Dial(network, address string) (net.Conn, error) {
return DialContext(context.Background(), network, address)
}
func DialContext(ctx context.Context, network, address string) (net.Conn, error) {
d := &net.Dialer{}
setControl(d)
return d.DialContext(ctx, network, address)
}
func ListenPacket(network, address string) (net.PacketConn, error) {
lc := &net.ListenConfig{}
setControl(lc)
return lc.ListenPacket(context.Background(), network, address)
}
-14
View File
@@ -1,14 +0,0 @@
package dialer
import (
"sync"
)
var _setOnce sync.Once
// SetMark sets the mark for each packet sent through this dialer(socket).
func SetMark(i int) {
_setOnce.Do(func() {
addControl(setMark(i))
})
}
-15
View File
@@ -1,15 +0,0 @@
package dialer
import (
"syscall"
"golang.org/x/sys/unix"
)
func setMark(i int) controlFunc {
return func(_, _ string, c syscall.RawConn) error {
return c.Control(func(fd uintptr) {
unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_MARK, i)
})
}
}
-14
View File
@@ -1,14 +0,0 @@
// +build !linux
package dialer
import (
"errors"
"syscall"
)
func setMark(_ int) controlFunc {
return func(string, string, syscall.RawConn) error {
return errors.New("fwmark: linux only")
}
}
-31
View File
@@ -1,31 +0,0 @@
/*
Package nat provides simple NAT table implements.
* Normal (Full Cone) NAT
A full cone NAT is one where all requests from the same internal IP address
and port are mapped to the same external IP address and port. Furthermore,
any external host can send a packet to the internal host, by sending a packet
to the mapped external address.
* Restricted Cone NAT
A restricted cone NAT is one where all requests from the same internal IP
address and port are mapped to the same external IP address and port.
Unlike a full cone NAT, an external host (with IP address X) can send a
packet to the internal host only if the internal host had previously sent
a packet to IP address X.
* Port Restricted Cone NAT
A port restricted cone NAT is like a restricted cone NAT, but the restriction
includes port numbers. Specifically, an external host can send a packet, with
source IP address X and source port P, to the internal host only if the internal
host had previously sent a packet to IP address X and port P.
* Symmetric NAT
A symmetric NAT is one where all requests from the same internal IP address
and port, to a specific destination IP address and port, are mapped to the
same external IP address and port. If the same host sends a packet with the
same source address and port, but to a different destination, a different mapping
is used. Furthermore, only the external host that receives a packet can send a
UDP packet back to the internal host.
*/
package nat
-35
View File
@@ -1,35 +0,0 @@
package nat
import (
"net"
"sync"
)
type Table struct {
mapping sync.Map
}
func (t *Table) Set(key string, pc net.PacketConn) {
t.mapping.Store(key, pc)
}
func (t *Table) Get(key string) net.PacketConn {
item, exist := t.mapping.Load(key)
if !exist {
return nil
}
return item.(net.PacketConn)
}
func (t *Table) GetOrCreateLock(key string) (*sync.Cond, bool) {
item, loaded := t.mapping.LoadOrStore(key, sync.NewCond(&sync.Mutex{}))
return item.(*sync.Cond), loaded
}
func (t *Table) Delete(key string) {
t.mapping.Delete(key)
}
func NewTable() *Table {
return &Table{}
}
-89
View File
@@ -1,89 +0,0 @@
package constant
import (
"bytes"
"encoding/binary"
"fmt"
"net"
"strconv"
"github.com/xjasonlyu/tun2socks/component/socks5"
)
const (
TCP Network = iota
UDP
)
type Network uint8
func (n Network) String() string {
switch n {
case TCP:
return "tcp"
case UDP:
return "udp"
default:
return fmt.Sprintf("network(%d)", n)
}
}
func (n Network) MarshalText() ([]byte, error) {
return []byte(n.String()), nil
}
// Metadata implements the net.Addr interface.
type Metadata struct {
Net Network `json:"network"`
SrcIP net.IP `json:"sourceIP"`
MidIP net.IP `json:"dialerIP"`
DstIP net.IP `json:"destinationIP"`
SrcPort uint16 `json:"sourcePort"`
MidPort uint16 `json:"dialerPort"`
DstPort uint16 `json:"destinationPort"`
}
func (m *Metadata) DestinationAddress() string {
return net.JoinHostPort(m.DstIP.String(), strconv.FormatUint(uint64(m.DstPort), 10))
}
func (m *Metadata) SourceAddress() string {
return net.JoinHostPort(m.SrcIP.String(), strconv.FormatUint(uint64(m.SrcPort), 10))
}
func (m *Metadata) UDPAddr() *net.UDPAddr {
if m.Net != UDP || m.DstIP == nil {
return nil
}
return &net.UDPAddr{
IP: m.DstIP,
Port: int(m.DstPort),
}
}
func (m *Metadata) SerializesSocksAddr() socks5.Addr {
var (
buf [][]byte
port [2]byte
)
binary.BigEndian.PutUint16(port[:], m.DstPort)
if m.DstIP.To4() != nil /* IPv4 */ {
aType := socks5.AtypIPv4
buf = [][]byte{{aType}, m.DstIP.To4(), port[:]}
} else /* IPv6 */ {
aType := socks5.AtypIPv6
buf = [][]byte{{aType}, m.DstIP.To16(), port[:]}
}
return bytes.Join(buf, nil)
}
func (m *Metadata) Network() string {
return m.Net.String()
}
// String returns destination address of this metadata.
// Also for implementing net.Addr interface.
func (m *Metadata) String() string {
return m.DestinationAddress()
}
-10
View File
@@ -1,10 +0,0 @@
package constant
const (
Name = "tun2socks"
)
var (
Version string
GitCommit string
)
-34
View File
@@ -1,34 +0,0 @@
package core
import (
"net"
"gvisor.dev/gvisor/pkg/tcpip/stack"
)
type TCPConn interface {
net.Conn
ID() *stack.TransportEndpointID
}
type UDPPacket interface {
// Data get the payload of UDP Packet.
Data() []byte
// Drop call after packet is used, could release resources in this function.
Drop()
// ID returns the transport endpoint id of packet.
ID() *stack.TransportEndpointID
// LocalAddr returns the source IP/Port of packet.
LocalAddr() net.Addr
// RemoteAddr returns the destination IP/Port of packet.
RemoteAddr() net.Addr
// WriteBack writes the payload with source IP/Port equals addr
// - variable source IP/Port is important to STUN
// - if addr is not provided, WriteBack will write out UDP packet with SourceIP/Port equals to original Target.
WriteBack([]byte, net.Addr) (int, error)
}
+24
View File
@@ -0,0 +1,24 @@
package adapter
import (
"net"
"gvisor.dev/gvisor/pkg/tcpip/stack"
)
// TCPConn implements the net.Conn interface.
type TCPConn interface {
net.Conn
// ID returns the transport endpoint id of TCPConn.
ID() *stack.TransportEndpointID
}
// UDPConn implements net.Conn and net.PacketConn.
type UDPConn interface {
net.Conn
net.PacketConn
// ID returns the transport endpoint id of UDPConn.
ID() *stack.TransportEndpointID
}
+8
View File
@@ -0,0 +1,8 @@
package adapter
// TransportHandler is a TCP/UDP connection handler that implements
// HandleTCP and HandleUDP methods.
type TransportHandler interface {
HandleTCP(TCPConn)
HandleUDP(UDPConn)
}
Executable → Regular
-3
View File
@@ -9,9 +9,6 @@ import (
type Device interface {
stack.LinkEndpoint
// Close stops and closes the device.
Close() error
// Name returns the current name of the device.
Name() string
+3
View File
@@ -0,0 +1,3 @@
package fdbased
const Driver = "fd"
+48
View File
@@ -0,0 +1,48 @@
//go:build unix
package fdbased
import (
"fmt"
"strconv"
"golang.org/x/sys/unix"
"gvisor.dev/gvisor/pkg/tcpip/stack"
"github.com/xjasonlyu/tun2socks/v2/core/device"
)
const defaultMTU = 1500
type FD struct {
stack.LinkEndpoint
fd int
mtu uint32
}
func Open(name string, mtu uint32, offset int) (device.Device, error) {
fd, err := strconv.Atoi(name)
if err != nil {
return nil, fmt.Errorf("cannot open fd: %s", name)
}
if mtu == 0 {
mtu = defaultMTU
}
return open(fd, mtu, offset)
}
func (f *FD) Type() string {
return Driver
}
func (f *FD) Name() string {
return strconv.Itoa(f.fd)
}
func (f *FD) Close() {
defer f.LinkEndpoint.Close()
_ = unix.Close(f.fd)
}
var _ device.Device = (*FD)(nil)
+11
View File
@@ -0,0 +1,11 @@
package fdbased
import (
"errors"
"github.com/xjasonlyu/tun2socks/v2/core/device"
)
func Open(name string, mtu uint32, offset int) (device.Device, error) {
return nil, errors.ErrUnsupported
}
+26
View File
@@ -0,0 +1,26 @@
package fdbased
import (
"fmt"
"gvisor.dev/gvisor/pkg/tcpip/link/fdbased"
"github.com/xjasonlyu/tun2socks/v2/core/device"
)
func open(fd int, mtu uint32, offset int) (device.Device, error) {
f := &FD{fd: fd, mtu: mtu}
ep, err := fdbased.New(&fdbased.Options{
FDs: []int{fd},
MTU: mtu,
// TUN only, ignore ethernet header.
EthernetHeader: false,
})
if err != nil {
return nil, fmt.Errorf("create endpoint: %w", err)
}
f.LinkEndpoint = ep
return f, nil
}
+22
View File
@@ -0,0 +1,22 @@
//go:build unix && !linux
package fdbased
import (
"fmt"
"os"
"github.com/xjasonlyu/tun2socks/v2/core/device"
"github.com/xjasonlyu/tun2socks/v2/core/device/iobased"
)
func open(fd int, mtu uint32, offset int) (device.Device, error) {
f := &FD{fd: fd, mtu: mtu}
ep, err := iobased.New(os.NewFile(uintptr(fd), f.Name()), mtu, offset)
if err != nil {
return nil, fmt.Errorf("create endpoint: %w", err)
}
f.LinkEndpoint = ep
return f, nil
}
+153
View File
@@ -0,0 +1,153 @@
// Package iobased provides the implementation of io.ReadWriter
// based data-link layer endpoints.
package iobased
import (
"context"
"errors"
"io"
"sync"
"gvisor.dev/gvisor/pkg/buffer"
"gvisor.dev/gvisor/pkg/tcpip"
"gvisor.dev/gvisor/pkg/tcpip/header"
"gvisor.dev/gvisor/pkg/tcpip/link/channel"
"gvisor.dev/gvisor/pkg/tcpip/stack"
)
const (
// Queue length for outbound packet, arriving for read. Overflow
// causes packet drops.
defaultOutQueueLen = 1 << 10
)
// Endpoint implements the interface of stack.LinkEndpoint from io.ReadWriter.
type Endpoint struct {
*channel.Endpoint
// rw is the io.ReadWriter for reading and writing packets.
rw io.ReadWriter
// mtu (maximum transmission unit) is the maximum size of a packet.
mtu uint32
// offset can be useful when perform TUN device I/O with TUN_PI enabled.
offset int
// once is used to perform the init action once when attaching.
once sync.Once
// wg keeps track of running goroutines.
wg sync.WaitGroup
}
// New returns stack.LinkEndpoint(.*Endpoint) and error.
func New(rw io.ReadWriter, mtu uint32, offset int) (*Endpoint, error) {
if mtu == 0 {
return nil, errors.New("MTU size is zero")
}
if rw == nil {
return nil, errors.New("RW interface is nil")
}
if offset < 0 {
return nil, errors.New("offset must be non-negative")
}
return &Endpoint{
Endpoint: channel.New(defaultOutQueueLen, mtu, ""),
rw: rw,
mtu: mtu,
offset: offset,
}, nil
}
// Attach launches the goroutine that reads packets from io.Reader and
// dispatches them via the provided dispatcher.
func (e *Endpoint) Attach(dispatcher stack.NetworkDispatcher) {
e.Endpoint.Attach(dispatcher)
e.once.Do(func() {
ctx, cancel := context.WithCancel(context.Background())
e.wg.Add(2)
go func() {
e.outboundLoop(ctx)
e.wg.Done()
}()
go func() {
e.dispatchLoop(cancel)
e.wg.Done()
}()
})
}
func (e *Endpoint) Wait() {
e.wg.Wait()
}
// dispatchLoop dispatches packets to upper layer.
func (e *Endpoint) dispatchLoop(cancel context.CancelFunc) {
// Call cancel() to ensure (*Endpoint).outboundLoop(context.Context) exits
// gracefully after (*Endpoint).dispatchLoop(context.CancelFunc) returns.
defer cancel()
offset, mtu := e.offset, int(e.mtu)
for {
data := make([]byte, offset+mtu)
n, err := e.rw.Read(data)
if err != nil {
break
}
if n == 0 || n > mtu {
continue
}
if !e.IsAttached() {
continue /* unattached, drop packet */
}
pkt := stack.NewPacketBuffer(stack.PacketBufferOptions{
Payload: buffer.MakeWithData(data[offset : offset+n]),
})
switch header.IPVersion(data[offset:]) {
case header.IPv4Version:
e.InjectInbound(header.IPv4ProtocolNumber, pkt)
case header.IPv6Version:
e.InjectInbound(header.IPv6ProtocolNumber, pkt)
}
pkt.DecRef()
}
}
// outboundLoop reads outbound packets from channel, and then it calls
// writePacket to send those packets back to lower layer.
func (e *Endpoint) outboundLoop(ctx context.Context) {
for {
pkt := e.ReadContext(ctx)
if pkt == nil {
break
}
e.writePacket(pkt)
}
}
// writePacket writes outbound packets to the io.Writer.
func (e *Endpoint) writePacket(pkt *stack.PacketBuffer) tcpip.Error {
defer pkt.DecRef()
buf := pkt.ToBuffer()
defer buf.Release()
if e.offset != 0 {
v := buffer.NewViewWithData(make([]byte, e.offset))
_ = buf.Prepend(v)
}
if _, err := e.rw.Write(buf.Flatten()); err != nil {
return &tcpip.ErrInvalidEndpointState{}
}
return nil
}
-140
View File
@@ -1,140 +0,0 @@
// Package channel provides the implementation of io.ReadWriter
// based data-link layer endpoints.
package rwbased
import (
"errors"
"io"
"gvisor.dev/gvisor/pkg/tcpip"
"gvisor.dev/gvisor/pkg/tcpip/buffer"
"gvisor.dev/gvisor/pkg/tcpip/header"
"gvisor.dev/gvisor/pkg/tcpip/stack"
)
var _ stack.LinkEndpoint = (*Endpoint)(nil)
// Endpoint implements the interface of stack.LinkEndpoint from io.ReadWriter.
type Endpoint struct {
// rw is the io.ReadWriter for reading and writing packets.
rw io.ReadWriter
// mtu (maximum transmission unit) is the maximum size of a packet.
mtu uint32
dispatcher stack.NetworkDispatcher
}
// New returns stack.LinkEndpoint(.*Endpoint) and error.
func New(rw io.ReadWriter, mtu uint32) (*Endpoint, error) {
if mtu == 0 {
return nil, errors.New("MTU size is zero")
}
if rw == nil {
return nil, errors.New("RW interface is nil")
}
return &Endpoint{
rw: rw,
mtu: mtu,
}, nil
}
// Attach launches the goroutine that reads packets from io.ReadWriter and
// dispatches them via the provided dispatcher.
func (e *Endpoint) Attach(dispatcher stack.NetworkDispatcher) {
go e.dispatchLoop()
e.dispatcher = dispatcher
}
// IsAttached implements stack.LinkEndpoint.IsAttached.
func (e *Endpoint) IsAttached() bool {
return e.dispatcher != nil
}
// dispatchLoop dispatches packets to upper layer.
func (e *Endpoint) dispatchLoop() {
for {
packet := make([]byte, e.mtu)
n, err := e.rw.Read(packet)
if err != nil {
break
}
if !e.IsAttached() {
continue
}
pkb := stack.NewPacketBuffer(stack.PacketBufferOptions{
Data: buffer.NewVectorisedView(n, []buffer.View{buffer.NewViewFromBytes(packet)}),
})
switch header.IPVersion(packet) {
case header.IPv4Version:
e.dispatcher.DeliverNetworkPacket("", "", header.IPv4ProtocolNumber, pkb)
case header.IPv6Version:
e.dispatcher.DeliverNetworkPacket("", "", header.IPv6ProtocolNumber, pkb)
}
}
}
func (e *Endpoint) writePacket(pkt *stack.PacketBuffer) tcpip.Error {
vView := buffer.NewVectorisedView(pkt.Size(), pkt.Views())
if _, err := e.rw.Write(vView.ToView()); err != nil {
return &tcpip.ErrInvalidEndpointState{}
}
return nil
}
// WritePacket writes packet back into io.ReadWriter.
func (e *Endpoint) WritePacket(_ stack.RouteInfo, _ *stack.GSO, _ 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) {
n := 0
for pkt := pkts.Front(); pkt != nil; pkt = pkt.Next() {
if err := e.writePacket(pkt); err != nil {
break
}
n++
}
return n, nil
}
// MTU implements stack.LinkEndpoint.MTU.
func (e *Endpoint) MTU() uint32 {
return e.mtu
}
// Capabilities implements stack.LinkEndpoint.Capabilities.
func (e *Endpoint) Capabilities() stack.LinkEndpointCapabilities {
return stack.CapabilityNone
}
// MaxHeaderLength returns the maximum size of the link layer header. Given it
// doesn't have a header, it just returns 0.
func (*Endpoint) MaxHeaderLength() uint16 {
return 0
}
// LinkAddress returns the link address of this endpoint.
func (*Endpoint) LinkAddress() tcpip.LinkAddress {
return ""
}
// ARPHardwareType implements stack.LinkEndpoint.ARPHardwareType.
func (*Endpoint) ARPHardwareType() header.ARPHardwareType {
return header.ARPHardwareNone
}
// AddHeader implements stack.LinkEndpoint.AddHeader.
func (e *Endpoint) AddHeader(tcpip.LinkAddress, tcpip.LinkAddress, tcpip.NetworkProtocolNumber, *stack.PacketBuffer) {
}
// Wait implements stack.LinkEndpoint.Wait.
func (e *Endpoint) Wait() {}
-29
View File
@@ -1,29 +0,0 @@
// +build darwin freebsd linux,!amd64,!arm64 openbsd
package tun
import (
"github.com/xjasonlyu/tun2socks/common/pool"
)
const offset = 4 /* 4 bytes TUN_PI */
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)
}
-11
View File
@@ -1,11 +0,0 @@
package tun
const offset = 0
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)
}
-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
}
}
Executable → Regular
+1 -1
View File
@@ -2,7 +2,7 @@
package tun
import (
"github.com/xjasonlyu/tun2socks/core/device"
"github.com/xjasonlyu/tun2socks/v2/core/device"
)
const Driver = "tun"
+29 -35
View File
@@ -1,19 +1,17 @@
// +build linux
// +build amd64 arm64
//go:build linux
package tun
import (
"fmt"
"unsafe"
"github.com/xjasonlyu/tun2socks/core/device"
"golang.org/x/sys/unix"
"gvisor.dev/gvisor/pkg/rawfile"
"gvisor.dev/gvisor/pkg/tcpip/link/fdbased"
"gvisor.dev/gvisor/pkg/tcpip/link/rawfile"
"gvisor.dev/gvisor/pkg/tcpip/link/tun"
"gvisor.dev/gvisor/pkg/tcpip/stack"
"github.com/xjasonlyu/tun2socks/v2/core/device"
)
type TUN struct {
@@ -24,12 +22,8 @@ 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, fmt.Errorf("interface name too long: %s", t.name)
@@ -47,17 +41,28 @@ 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,
FDs: []int{fd},
// TUN only
MTU: t.mtu,
// TUN only, ignore ethernet header.
EthernetHeader: false,
// SYS_READV support only for TUN fd.
PacketDispatchMode: fdbased.Readv,
// TAP/TUN fd's are not sockets and using the WritePackets calls results
// in errors as it always defaults to using SendMMsg which is not supported
// for tap/tun device fds.
//
// This CL changes WritePackets to gracefully degrade to using writev instead
// of sendmmsg if the underlying fd is not a socket.
//
// Fixed: https://github.com/google/gvisor/commit/f33d034fecd7723a1e560ccc62aeeba328454fd0
MaxSyscallHeaderBytes: 0x00,
})
if err != nil {
return nil, fmt.Errorf("create endpoint: %w", err)
@@ -71,8 +76,9 @@ func (t *TUN) Name() string {
return t.name
}
func (t *TUN) Close() error {
return unix.Close(t.fd)
func (t *TUN) Close() {
defer t.LinkEndpoint.Close()
_ = unix.Close(t.fd)
}
func setMTU(name string, n uint32) error {
@@ -88,22 +94,10 @@ func setMTU(name string, n uint32) error {
defer unix.Close(fd)
const ifReqSize = unix.IFNAMSIZ + 64
// do ioctl call
var ifr [ifReqSize]byte
copy(ifr[:], name)
*(*uint32)(unsafe.Pointer(&ifr[unix.IFNAMSIZ])) = n
_, _, errno := unix.Syscall(
unix.SYS_IOCTL,
uintptr(fd),
uintptr(unix.SIOCSIFMTU),
uintptr(unsafe.Pointer(&ifr[0])),
)
if errno != 0 {
return fmt.Errorf("failed to set MTU: %w", errno)
ifr, err := unix.NewIfreq(name)
if err != nil {
return err
}
return nil
ifr.SetUint32(n)
return unix.IoctlIfreq(fd, unix.SIOCSIFMTU, ifr)
}
Executable → Regular
+56 -18
View File
@@ -1,44 +1,66 @@
// +build !linux !amd64,!arm64
//go:build !linux
package tun
import (
"fmt"
"github.com/xjasonlyu/tun2socks/core/device"
"github.com/xjasonlyu/tun2socks/core/device/rwbased"
"sync"
"golang.zx2c4.com/wireguard/tun"
"github.com/xjasonlyu/tun2socks/v2/core/device"
"github.com/xjasonlyu/tun2socks/v2/core/device/iobased"
)
type TUN struct {
*rwbased.Endpoint
*iobased.Endpoint
nt *tun.NativeTun
mtu uint32
name string
nt *tun.NativeTun
mtu uint32
name string
offset int
rSizes []int
rBuffs [][]byte
wBuffs [][]byte
rMutex sync.Mutex
wMutex sync.Mutex
}
func Open(opts ...Option) (device.Device, error) {
t := &TUN{}
func Open(name string, mtu uint32) (_ device.Device, err error) {
defer func() {
if r := recover(); r != nil {
err = fmt.Errorf("open tun: %v", r)
}
}()
for _, opt := range opts {
opt(t)
t := &TUN{
name: name,
mtu: mtu,
offset: offset,
rSizes: make([]int, 1),
rBuffs: make([][]byte, 1),
wBuffs: make([][]byte, 1),
}
nt, err := tun.CreateTUN(t.name, int(t.mtu))
forcedMTU := defaultMTU
if t.mtu > 0 {
forcedMTU = int(t.mtu)
}
nt, err := createTUN(t.name, forcedMTU)
if err != nil {
return nil, fmt.Errorf("create tun: %w", err)
}
t.nt = nt.(*tun.NativeTun)
mtu, err := nt.MTU()
tunMTU, err := nt.MTU()
if err != nil {
return nil, fmt.Errorf("get mtu: %w", err)
}
t.mtu = uint32(mtu)
t.mtu = uint32(tunMTU)
ep, err := rwbased.New(t, uint32(mtu))
ep, err := iobased.New(t, t.mtu, offset)
if err != nil {
return nil, fmt.Errorf("create endpoint: %w", err)
}
@@ -47,11 +69,27 @@ func Open(opts ...Option) (device.Device, error) {
return t, nil
}
func (t *TUN) Read(packet []byte) (int, error) {
t.rMutex.Lock()
defer t.rMutex.Unlock()
t.rBuffs[0] = packet
_, err := t.nt.Read(t.rBuffs, t.rSizes, t.offset)
return t.rSizes[0], err
}
func (t *TUN) Write(packet []byte) (int, error) {
t.wMutex.Lock()
defer t.wMutex.Unlock()
t.wBuffs[0] = packet
return t.nt.Write(t.wBuffs, t.offset)
}
func (t *TUN) Name() string {
name, _ := t.nt.Name()
return name
}
func (t *TUN) Close() error {
return t.nt.Close()
func (t *TUN) Close() {
defer t.Endpoint.Close()
_ = t.nt.Close()
}
+16
View File
@@ -0,0 +1,16 @@
//go:build unix && !linux
package tun
import (
"golang.zx2c4.com/wireguard/tun"
)
const (
offset = 4 /* 4 bytes TUN_PI */
defaultMTU = 1500
)
func createTUN(name string, mtu int) (tun.Device, error) {
return tun.CreateTUN(name, mtu)
}
+14
View File
@@ -0,0 +1,14 @@
package tun
import (
"golang.zx2c4.com/wireguard/tun"
)
const (
offset = 0
defaultMTU = 0 /* auto */
)
func createTUN(name string, mtu int) (tun.Device, error) {
return tun.CreateTUN(name, mtu)
}
-6
View File
@@ -1,6 +0,0 @@
package core
type Handler interface {
Add(TCPConn)
AddPacket(UDPPacket)
}
+119
View File
@@ -0,0 +1,119 @@
package core
import (
"fmt"
"net/netip"
"gvisor.dev/gvisor/pkg/tcpip"
"gvisor.dev/gvisor/pkg/tcpip/network/ipv4"
"gvisor.dev/gvisor/pkg/tcpip/network/ipv6"
"gvisor.dev/gvisor/pkg/tcpip/stack"
"github.com/xjasonlyu/tun2socks/v2/core/option"
)
const (
// nicPromiscuousModeEnabled is the value used by stack to enable
// or disable NIC's promiscuous mode.
nicPromiscuousModeEnabled = true
// nicSpoofingEnabled is the value used by stack to enable or disable
// NIC's spoofing.
nicSpoofingEnabled = true
)
// withCreatingNIC creates NIC for stack.
func withCreatingNIC(nicID tcpip.NICID, ep stack.LinkEndpoint) option.Option {
return func(s *stack.Stack) error {
if err := s.CreateNICWithOptions(nicID, ep,
stack.NICOptions{
Disabled: false,
// If no queueing discipline was specified
// provide a stub implementation that just
// delegates to the lower link endpoint.
QDisc: nil,
}); err != nil {
return fmt.Errorf("create NIC: %s", err)
}
return nil
}
}
// withPromiscuousMode sets promiscuous mode in the given NICs.
func withPromiscuousMode(nicID tcpip.NICID, v bool) option.Option {
return func(s *stack.Stack) error {
if err := s.SetPromiscuousMode(nicID, v); err != nil {
return fmt.Errorf("set promiscuous mode: %s", err)
}
return nil
}
}
// withSpoofing sets address spoofing in the given NICs, allowing
// endpoints to bind to any address in the NIC.
func withSpoofing(nicID tcpip.NICID, v bool) option.Option {
return func(s *stack.Stack) error {
if err := s.SetSpoofing(nicID, v); err != nil {
return fmt.Errorf("set spoofing: %s", err)
}
return nil
}
}
// withMulticastGroups adds a NIC to the given multicast groups.
func withMulticastGroups(nicID tcpip.NICID, multicastGroups []netip.Addr) option.Option {
return func(s *stack.Stack) error {
if len(multicastGroups) == 0 {
return nil
}
// The default NIC of tun2socks is working on Spoofing mode. When the UDP Endpoint
// tries to use a non-local address to connect, the network stack will
// generate a temporary addressState to build the route, which can be primary
// but is ephemeral. Nevertheless, when the UDP Endpoint tries to use a
// multicast address to connect, the network stack will select an available
// primary addressState to build the route. However, when tun2socks is in the
// just-initialized or idle state, there will be no available primary addressState,
// and the connect operation will fail. Therefore, we need to add permanent addresses,
// e.g. 10.0.0.1/8 and fd00:1/8, to the default NIC, which are only used to build
// routes for multicast response and do not affect other connections.
//
// In fact, for multicast, the sender normally does not expect a response.
// So, the ep.net.Connect is unnecessary. If we implement a custom UDP Forwarder
// and ForwarderRequest in the future, we can remove these code.
s.AddProtocolAddress(
nicID,
tcpip.ProtocolAddress{
Protocol: ipv4.ProtocolNumber,
AddressWithPrefix: tcpip.AddressWithPrefix{
Address: tcpip.AddrFrom4([4]byte{0x0a, 0, 0, 0x01}),
PrefixLen: 8,
},
},
stack.AddressProperties{PEB: stack.CanBePrimaryEndpoint},
)
s.AddProtocolAddress(
nicID,
tcpip.ProtocolAddress{
Protocol: ipv6.ProtocolNumber,
AddressWithPrefix: tcpip.AddressWithPrefix{
Address: tcpip.AddrFrom16([16]byte{0xfd, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x01}),
PrefixLen: 8,
},
},
stack.AddressProperties{PEB: stack.CanBePrimaryEndpoint},
)
for _, multicastGroup := range multicastGroups {
var err tcpip.Error
switch {
case multicastGroup.Is4():
err = s.JoinGroup(ipv4.ProtocolNumber, nicID, tcpip.AddrFrom4(multicastGroup.As4()))
case multicastGroup.Is6():
err = s.JoinGroup(ipv6.ProtocolNumber, nicID, tcpip.AddrFrom16(multicastGroup.As16()))
}
if err != nil {
return fmt.Errorf("join multicast group: %s", err)
}
}
return nil
}
}
+95 -36
View File
@@ -1,4 +1,4 @@
package stack
package option
import (
"fmt"
@@ -7,23 +7,18 @@ import (
"gvisor.dev/gvisor/pkg/tcpip"
"gvisor.dev/gvisor/pkg/tcpip/network/ipv4"
"gvisor.dev/gvisor/pkg/tcpip/network/ipv6"
"gvisor.dev/gvisor/pkg/tcpip/stack"
"gvisor.dev/gvisor/pkg/tcpip/transport/tcp"
)
const (
// maxBufferSize is the maximum permitted size of a send/receive buffer.
maxBufferSize = 4 << 20 // 4 MiB
// minBufferSize is the smallest size of a receive or send buffer.
minBufferSize = 4 << 10 // 4 KiB
// defaultBufferSize is the default size of the send/recv buffer for
// a transport endpoint.
defaultBufferSize = 212 << 10 // 212 KiB
// defaultTimeToLive specifies the default TTL used by stack.
defaultTimeToLive uint8 = 64
// ipForwardingEnabled is the value used by stack to enable packet
// forwarding between NICs.
ipForwardingEnabled = true
// icmpBurst is the default number of ICMP messages that can be sent in
// a single burst.
icmpBurst = 50
@@ -32,10 +27,6 @@ const (
// by this rate limiter.
icmpLimit rate.Limit = 1000
// ipForwardingEnabled is the value used by stack to enable packet
// forwarding between NICs.
ipForwardingEnabled = true
// tcpCongestionControl is the congestion control algorithm used by
// stack. ccReno is the default option in gVisor stack.
tcpCongestionControlAlgorithm = "reno" // "reno" or "cubic"
@@ -46,18 +37,35 @@ const (
// tcpModerateReceiveBufferEnabled is the value used by stack to
// enable or disable tcp receive buffer auto-tuning option.
tcpModerateReceiveBufferEnabled = true
tcpModerateReceiveBufferEnabled = false
// tcpSACKEnabled is the value used by stack to enable or disable
// tcp selective ACK.
tcpSACKEnabled = true
// tcpRecovery is the loss detection algorithm used by TCP.
tcpRecovery = tcpip.TCPRACKLossDetection
// tcpMinBufferSize is the smallest size of a send/recv buffer.
tcpMinBufferSize = tcp.MinBufferSize
// tcpMaxBufferSize is the maximum permitted size of a send/recv buffer.
tcpMaxBufferSize = tcp.MaxBufferSize
// tcpDefaultBufferSize is the default size of the send buffer for
// a transport endpoint.
tcpDefaultSendBufferSize = tcp.DefaultSendBufferSize
// tcpDefaultReceiveBufferSize is the default size of the receive buffer
// for a transport endpoint.
tcpDefaultReceiveBufferSize = tcp.DefaultReceiveBufferSize
)
type Option func(*Stack) error
type Option func(*stack.Stack) error
// WithDefault sets all default values for stack.
func WithDefault() Option {
return func(s *Stack) error {
return func(s *stack.Stack) error {
opts := []Option{
WithDefaultTTL(defaultTimeToLive),
WithForwarding(ipForwardingEnabled),
@@ -69,8 +77,9 @@ func WithDefault() Option {
// Too large buffers thrash cache, so there is little point
// in too large buffers.
//
// Ref: https://github.com/majek/slirpnetstack/blob/master/stack.go
WithTCPBufferSizeRange(minBufferSize, defaultBufferSize, maxBufferSize),
// Ref: https://github.com/cloudflare/slirpnetstack/blob/master/stack.go
WithTCPSendBufferSizeRange(tcpMinBufferSize, tcpDefaultSendBufferSize, tcpMaxBufferSize),
WithTCPReceiveBufferSizeRange(tcpMinBufferSize, tcpDefaultReceiveBufferSize, tcpMaxBufferSize),
WithTCPCongestionControl(tcpCongestionControlAlgorithm),
WithTCPDelay(tcpDelayEnabled),
@@ -82,6 +91,17 @@ func WithDefault() Option {
// TCP selective ACK Option, see:
// https://tools.ietf.org/html/rfc2018
WithTCPSACKEnabled(tcpSACKEnabled),
// TCPRACKLossDetection: indicates RACK is used for loss detection and
// recovery.
//
// TCPRACKStaticReoWnd: indicates the reordering window should not be
// adjusted when DSACK is received.
//
// TCPRACKNoDupTh: indicates RACK should not consider the classic three
// duplicate acknowledgements rule to mark the segments as lost. This
// is used when reordering is not detected.
WithTCPRecovery(tcpRecovery),
}
for _, opt := range opts {
@@ -96,7 +116,7 @@ func WithDefault() Option {
// WithDefaultTTL sets the default TTL used by stack.
func WithDefaultTTL(ttl uint8) Option {
return func(s *Stack) error {
return func(s *stack.Stack) error {
opt := tcpip.DefaultTTLOption(ttl)
if err := s.SetNetworkProtocolOption(ipv4.ProtocolNumber, &opt); err != nil {
return fmt.Errorf("set ipv4 default TTL: %s", err)
@@ -110,11 +130,11 @@ 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 {
return func(s *stack.Stack) error {
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
@@ -124,7 +144,7 @@ func WithForwarding(v bool) Option {
// WithICMPBurst sets the number of ICMP messages that can be sent
// in a single burst.
func WithICMPBurst(burst int) Option {
return func(s *Stack) error {
return func(s *stack.Stack) error {
s.SetICMPBurst(burst)
return nil
}
@@ -133,19 +153,26 @@ func WithICMPBurst(burst int) Option {
// WithICMPLimit sets the maximum number of ICMP messages permitted
// by rate limiter.
func WithICMPLimit(limit rate.Limit) Option {
return func(s *Stack) error {
return func(s *stack.Stack) error {
s.SetICMPLimit(limit)
return nil
}
}
// WithTCPBufferSizeRange sets the receive and send buffer size range for TCP.
func WithTCPBufferSizeRange(a, b, c int) Option {
return func(s *Stack) error {
rcvOpt := tcpip.TCPReceiveBufferSizeRangeOption{Min: a, Default: b, Max: c}
if err := s.SetTransportProtocolOption(tcp.ProtocolNumber, &rcvOpt); err != nil {
return fmt.Errorf("set TCP receive buffer size range: %s", err)
// WithTCPSendBufferSize sets default the send buffer size for TCP.
func WithTCPSendBufferSize(size int) Option {
return func(s *stack.Stack) error {
sndOpt := tcpip.TCPSendBufferSizeRangeOption{Min: tcpMinBufferSize, Default: size, Max: tcpMaxBufferSize}
if err := s.SetTransportProtocolOption(tcp.ProtocolNumber, &sndOpt); err != nil {
return fmt.Errorf("set TCP send buffer size range: %s", err)
}
return nil
}
}
// WithTCPSendBufferSizeRange sets the send buffer size range for TCP.
func WithTCPSendBufferSizeRange(a, b, c int) Option {
return func(s *stack.Stack) error {
sndOpt := tcpip.TCPSendBufferSizeRangeOption{Min: a, Default: b, Max: c}
if err := s.SetTransportProtocolOption(tcp.ProtocolNumber, &sndOpt); err != nil {
return fmt.Errorf("set TCP send buffer size range: %s", err)
@@ -154,9 +181,31 @@ func WithTCPBufferSizeRange(a, b, c int) Option {
}
}
// WithTCPReceiveBufferSize sets the default receive buffer size for TCP.
func WithTCPReceiveBufferSize(size int) Option {
return func(s *stack.Stack) error {
rcvOpt := tcpip.TCPReceiveBufferSizeRangeOption{Min: tcpMinBufferSize, Default: size, Max: tcpMaxBufferSize}
if err := s.SetTransportProtocolOption(tcp.ProtocolNumber, &rcvOpt); err != nil {
return fmt.Errorf("set TCP receive buffer size range: %s", err)
}
return nil
}
}
// WithTCPReceiveBufferSizeRange sets the receive buffer size range for TCP.
func WithTCPReceiveBufferSizeRange(a, b, c int) Option {
return func(s *stack.Stack) error {
rcvOpt := tcpip.TCPReceiveBufferSizeRangeOption{Min: a, Default: b, Max: c}
if err := s.SetTransportProtocolOption(tcp.ProtocolNumber, &rcvOpt); err != nil {
return fmt.Errorf("set TCP receive buffer size range: %s", err)
}
return nil
}
}
// WithTCPCongestionControl sets the current congestion control algorithm.
func WithTCPCongestionControl(cc string) Option {
return func(s *Stack) error {
return func(s *stack.Stack) error {
opt := tcpip.CongestionControlOption(cc)
if err := s.SetTransportProtocolOption(tcp.ProtocolNumber, &opt); err != nil {
return fmt.Errorf("set TCP congestion control algorithm: %s", err)
@@ -167,7 +216,7 @@ func WithTCPCongestionControl(cc string) Option {
// WithTCPDelay enables or disables Nagle's algorithm in TCP.
func WithTCPDelay(v bool) Option {
return func(s *Stack) error {
return func(s *stack.Stack) error {
opt := tcpip.TCPDelayEnabled(v)
if err := s.SetTransportProtocolOption(tcp.ProtocolNumber, &opt); err != nil {
return fmt.Errorf("set TCP delay: %s", err)
@@ -178,7 +227,7 @@ func WithTCPDelay(v bool) Option {
// WithTCPModerateReceiveBuffer sets receive buffer moderation for TCP.
func WithTCPModerateReceiveBuffer(v bool) Option {
return func(s *Stack) error {
return func(s *stack.Stack) error {
opt := tcpip.TCPModerateReceiveBufferOption(v)
if err := s.SetTransportProtocolOption(tcp.ProtocolNumber, &opt); err != nil {
return fmt.Errorf("set TCP moderate receive buffer: %s", err)
@@ -189,7 +238,7 @@ func WithTCPModerateReceiveBuffer(v bool) Option {
// WithTCPSACKEnabled sets the SACK option for TCP.
func WithTCPSACKEnabled(v bool) Option {
return func(s *Stack) error {
return func(s *stack.Stack) error {
opt := tcpip.TCPSACKEnabled(v)
if err := s.SetTransportProtocolOption(tcp.ProtocolNumber, &opt); err != nil {
return fmt.Errorf("set TCP SACK: %s", err)
@@ -197,3 +246,13 @@ func WithTCPSACKEnabled(v bool) Option {
return nil
}
}
// WithTCPRecovery sets the recovery option for TCP.
func WithTCPRecovery(v tcpip.TCPRecovery) Option {
return func(s *stack.Stack) error {
if err := s.SetTransportProtocolOption(tcp.ProtocolNumber, &v); err != nil {
return fmt.Errorf("set TCP Recovery: %s", err)
}
return nil
}
}
+8 -7
View File
@@ -1,22 +1,23 @@
package stack
package core
import (
"gvisor.dev/gvisor/pkg/tcpip"
"gvisor.dev/gvisor/pkg/tcpip/header"
"gvisor.dev/gvisor/pkg/tcpip/stack"
"github.com/xjasonlyu/tun2socks/v2/core/option"
)
func withICMPHandler() Option {
return func(s *Stack) error {
// Add default route table for IPv4 and IPv6.
// This will handle all incoming ICMP packets.
func withRouteTable(nicID tcpip.NICID) option.Option {
return func(s *stack.Stack) error {
s.SetRouteTable([]tcpip.Route{
{
Destination: header.IPv4EmptySubnet,
NIC: s.nicID,
NIC: nicID,
},
{
Destination: header.IPv6EmptySubnet,
NIC: s.nicID,
NIC: nicID,
},
})
return nil
+107
View File
@@ -0,0 +1,107 @@
package core
import (
"net/netip"
"gvisor.dev/gvisor/pkg/tcpip/network/ipv4"
"gvisor.dev/gvisor/pkg/tcpip/network/ipv6"
"gvisor.dev/gvisor/pkg/tcpip/stack"
"gvisor.dev/gvisor/pkg/tcpip/transport/icmp"
"gvisor.dev/gvisor/pkg/tcpip/transport/tcp"
"gvisor.dev/gvisor/pkg/tcpip/transport/udp"
"github.com/xjasonlyu/tun2socks/v2/core/adapter"
"github.com/xjasonlyu/tun2socks/v2/core/option"
)
// Config is the configuration to create *stack.Stack.
type Config struct {
// LinkEndpoints is the interface implemented by
// data link layer protocols.
LinkEndpoint stack.LinkEndpoint
// TransportHandler is the handler used by internal
// stack to set transport handlers.
TransportHandler adapter.TransportHandler
// MulticastGroups is used by internal stack to add
// nic to given groups.
MulticastGroups []netip.Addr
// Options are supplement options to apply settings
// for the internal stack.
Options []option.Option
}
// CreateStack creates *stack.Stack with given config.
func CreateStack(cfg *Config) (*stack.Stack, error) {
opts := []option.Option{option.WithDefault()}
if len(opts) > 0 {
opts = append(opts, cfg.Options...)
}
s := stack.New(stack.Options{
NetworkProtocols: []stack.NetworkProtocolFactory{
ipv4.NewProtocol,
ipv6.NewProtocol,
},
TransportProtocols: []stack.TransportProtocolFactory{
tcp.NewProtocol,
udp.NewProtocol,
icmp.NewProtocol4,
icmp.NewProtocol6,
},
})
// Generate unique NIC id.
nicID := s.NextNICID()
opts = append(opts,
// Important: We must initiate transport protocol handlers
// before creating NIC, otherwise NIC would dispatch packets
// to stack and cause race condition.
// Initiate transport protocol (TCP/UDP) with given handler.
withTCPHandler(cfg.TransportHandler.HandleTCP),
withUDPHandler(cfg.TransportHandler.HandleUDP),
// Create stack NIC and then bind link endpoint to it.
withCreatingNIC(nicID, cfg.LinkEndpoint),
// In the past we did s.AddAddressRange to assign 0.0.0.0/0
// onto the interface. We need that to be able to terminate
// all the incoming connections - to any ip. AddressRange API
// has been removed and the suggested workaround is to use
// Promiscuous mode. https://github.com/google/gvisor/issues/3876
//
// Ref: https://github.com/cloudflare/slirpnetstack/blob/master/stack.go
withPromiscuousMode(nicID, nicPromiscuousModeEnabled),
// Enable spoofing if a stack may send packets from unowned
// addresses. This change required changes to some netgophers
// since previously, promiscuous mode was enough to let the
// netstack respond to all incoming packets regardless of the
// packet's destination address. Now that a stack.Route is not
// held for each incoming packet, finding a route may fail with
// local addresses we don't own but accepted packets for while
// in promiscuous mode. Since we also want to be able to send
// from any address (in response the received promiscuous mode
// packets), we need to enable spoofing.
//
// Ref: https://github.com/google/gvisor/commit/8c0701462a84ff77e602f1626aec49479c308127
withSpoofing(nicID, nicSpoofingEnabled),
// Add default route table for IPv4 and IPv6. This will handle
// all incoming ICMP packets.
withRouteTable(nicID),
// Add default NIC to the given multicast groups.
withMulticastGroups(nicID, cfg.MulticastGroups),
)
for _, opt := range opts {
if err := opt(s); err != nil {
return nil, err
}
}
return s, nil
}
-52
View File
@@ -1,52 +0,0 @@
package stack
import (
"fmt"
"gvisor.dev/gvisor/pkg/tcpip"
"gvisor.dev/gvisor/pkg/tcpip/stack"
)
const (
// defaultNICID is the ID of default NIC used by DefaultStack.
defaultNICID tcpip.NICID = 0x01
// nicPromiscuousModeEnabled is the value used by stack to enable
// or disable NIC's promiscuous mode.
nicPromiscuousModeEnabled = true
// nicSpoofingEnabled is the value used by stack to enable or disable
// NIC's spoofing.
nicSpoofingEnabled = true
)
// withCreatingNIC creates NIC for stack.
func withCreatingNIC(ep stack.LinkEndpoint) Option {
return func(s *Stack) error {
if err := s.CreateNIC(s.nicID, ep); err != nil {
return fmt.Errorf("create NIC: %s", err)
}
return nil
}
}
// withPromiscuousMode sets promiscuous mode in the given NIC.
func withPromiscuousMode(v bool) Option {
return func(s *Stack) error {
if err := s.SetPromiscuousMode(s.nicID, v); err != nil {
return fmt.Errorf("set promiscuous mode: %s", err)
}
return nil
}
}
// withSpoofing sets address spoofing in the given NIC, allowing
// endpoints to bind to any address in the NIC.
func withSpoofing(v bool) Option {
return func(s *Stack) error {
if err := s.SetSpoofing(s.nicID, v); err != nil {
return fmt.Errorf("set spoofing: %s", err)
}
return nil
}
}
-82
View File
@@ -1,82 +0,0 @@
// Package stack provides a thin wrapper around a gVisor's stack.
package stack
import (
"github.com/xjasonlyu/tun2socks/core"
"gvisor.dev/gvisor/pkg/tcpip"
"gvisor.dev/gvisor/pkg/tcpip/network/ipv4"
"gvisor.dev/gvisor/pkg/tcpip/network/ipv6"
"gvisor.dev/gvisor/pkg/tcpip/stack"
"gvisor.dev/gvisor/pkg/tcpip/transport/icmp"
"gvisor.dev/gvisor/pkg/tcpip/transport/tcp"
"gvisor.dev/gvisor/pkg/tcpip/transport/udp"
)
type Stack struct {
*stack.Stack
handler core.Handler
nicID tcpip.NICID
}
// New allocates a new *Stack with given options.
func New(ep stack.LinkEndpoint, handler core.Handler, opts ...Option) (*Stack, error) {
s := &Stack{
Stack: stack.New(stack.Options{
NetworkProtocols: []stack.NetworkProtocolFactory{
ipv4.NewProtocol,
ipv6.NewProtocol,
},
TransportProtocols: []stack.TransportProtocolFactory{
tcp.NewProtocol,
udp.NewProtocol,
icmp.NewProtocol4,
icmp.NewProtocol6,
},
}),
handler: handler,
nicID: defaultNICID,
}
opts = append(opts,
// Important: We must initiate transport protocol handlers
// before creating NIC, otherwise NIC would dispatch packets
// to stack and cause race condition.
withICMPHandler(), withTCPHandler(), withUDPHandler(),
// Create stack NIC and then bind link endpoint.
withCreatingNIC(ep),
// In past we did s.AddAddressRange to assign 0.0.0.0/0 onto
// the interface. We need that to be able to terminate all the
// incoming connections - to any ip. AddressRange API has been
// removed and the suggested workaround is to use Promiscuous
// mode. https://github.com/google/gvisor/issues/3876
//
// Ref: https://github.com/majek/slirpnetstack/blob/master/stack.go
withPromiscuousMode(nicPromiscuousModeEnabled),
// Enable spoofing if a stack may send packets from unowned addresses.
// This change required changes to some netgophers since previously,
// promiscuous mode was enough to let the netstack respond to all
// incoming packets regardless of the packet's destination address. Now
// that a stack.Route is not held for each incoming packet, finding a route
// may fail with local addresses we don't own but accepted packets for
// while in promiscuous mode. Since we also want to be able to send from
// any address (in response the received promiscuous mode packets), we need
// to enable spoofing.
//
// Ref: https://github.com/google/gvisor/commit/8c0701462a84ff77e602f1626aec49479c308127
withSpoofing(nicSpoofingEnabled),
)
for _, opt := range opts {
if err := opt(s); err != nil {
return nil, err
}
}
return s, nil
}
-83
View File
@@ -1,83 +0,0 @@
package stack
import (
"fmt"
"net"
"time"
"gvisor.dev/gvisor/pkg/tcpip"
"gvisor.dev/gvisor/pkg/tcpip/adapters/gonet"
"gvisor.dev/gvisor/pkg/tcpip/stack"
"gvisor.dev/gvisor/pkg/tcpip/transport/tcp"
"gvisor.dev/gvisor/pkg/waiter"
)
const (
// defaultWndSize if set to zero, the default
// receive window buffer size is used instead.
defaultWndSize = 0
// maxConnAttempts specifies the maximum number
// of in-flight tcp connection attempts.
maxConnAttempts = 2 << 10
// tcpKeepaliveIdle specifies the time a connection
// must remain idle before the first TCP keepalive
// packet is sent. Once this time is reached,
// tcpKeepaliveInterval option is used instead.
tcpKeepaliveIdle = 60 * time.Second
// tcpKeepaliveInterval specifies the interval
// time between sending TCP keepalive packets.
tcpKeepaliveInterval = 30 * time.Second
)
func withTCPHandler() Option {
return func(s *Stack) error {
tcpForwarder := tcp.NewForwarder(s.Stack, defaultWndSize, maxConnAttempts, func(r *tcp.ForwarderRequest) {
var wq waiter.Queue
id := r.ID()
ep, err := r.CreateEndpoint(&wq)
if err != nil {
// prevent potential half-open TCP connection leak.
r.Complete(true)
return
}
r.Complete(false)
setKeepalive(ep)
conn := &tcpConn{
Conn: gonet.NewTCPConn(&wq, ep),
id: &id,
}
s.handler.Add(conn)
})
s.SetTransportProtocolHandler(tcp.ProtocolNumber, tcpForwarder.HandlePacket)
return nil
}
}
func setKeepalive(ep tcpip.Endpoint) error {
ep.SocketOptions().SetKeepAlive(true)
idle := tcpip.KeepaliveIdleOption(tcpKeepaliveIdle)
if err := ep.SetSockOpt(&idle); err != nil {
return fmt.Errorf("set keepalive idle: %s", err)
}
interval := tcpip.KeepaliveIntervalOption(tcpKeepaliveInterval)
if err := ep.SetSockOpt(&interval); err != nil {
return fmt.Errorf("set keepalive interval: %s", err)
}
return nil
}
type tcpConn struct {
net.Conn
id *stack.TransportEndpointID
}
func (c *tcpConn) ID() *stack.TransportEndpointID {
return c.id
}
-184
View File
@@ -1,184 +0,0 @@
package stack
import (
"fmt"
"net"
"gvisor.dev/gvisor/pkg/tcpip"
"gvisor.dev/gvisor/pkg/tcpip/buffer"
"gvisor.dev/gvisor/pkg/tcpip/header"
"gvisor.dev/gvisor/pkg/tcpip/stack"
"gvisor.dev/gvisor/pkg/tcpip/transport/udp"
)
const (
// udpNoChecksum disables UDP checksum.
udpNoChecksum = true
)
func withUDPHandler() Option {
return func(s *Stack) error {
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 {
// Malformed packet.
s.Stats().UDP.MalformedPacketsReceived.Increment()
return true
}
if !verifyChecksum(udpHdr, pkt) {
// Checksum error.
s.Stats().UDP.ChecksumErrors.Increment()
return true
}
s.Stats().UDP.PacketsReceived.Increment()
packet := &udpPacket{
s: s,
id: &id,
nicID: pkt.NICID,
netHdr: pkt.Network(),
netProto: pkt.NetworkProtocolNumber,
payload: pkt.Data.ToView(),
}
s.handler.AddPacket(packet)
return true
}
s.SetTransportProtocolHandler(udp.ProtocolNumber, udpHandlePacket)
return nil
}
}
type udpPacket struct {
s *Stack
id *stack.TransportEndpointID
nicID tcpip.NICID
netHdr header.Network
netProto tcpip.NetworkProtocolNumber
payload []byte
}
func (p *udpPacket) Data() []byte {
return p.payload
}
func (p *udpPacket) Drop() {}
func (p *udpPacket) ID() *stack.TransportEndpointID {
return p.id
}
func (p *udpPacket) LocalAddr() net.Addr {
return &net.UDPAddr{IP: net.IP(p.id.LocalAddress), Port: int(p.id.LocalPort)}
}
func (p *udpPacket) RemoteAddr() net.Addr {
return &net.UDPAddr{IP: net.IP(p.id.RemoteAddress), Port: int(p.id.RemotePort)}
}
func (p *udpPacket) WriteBack(b []byte, addr net.Addr) (int, error) {
v := buffer.View(b)
if len(v) > header.UDPMaximumPacketSize {
// Payload can't possibly fit in a packet.
return 0, fmt.Errorf("%s", &tcpip.ErrMessageTooLong{})
}
route, err := p.s.FindRoute(p.nicID, p.netHdr.DestinationAddress(), 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 {
return 0, fmt.Errorf("%v", err)
}
return data.Size(), nil
}
// sendUDP sends a UDP segment via the provided network endpoint and under the
// provided identity.
func sendUDP(r *stack.Route, data buffer.VectorisedView, localPort, remotePort uint16, noChecksum bool) tcpip.Error {
pkt := stack.NewPacketBuffer(stack.PacketBufferOptions{
ReserveHeaderBytes: header.UDPMinimumSize + int(r.MaxHeaderLength()),
Data: data,
})
// Initialize the UDP header.
udpHdr := header.UDP(pkt.TransportHeader().Push(header.UDPMinimumSize))
pkt.TransportProtocolNumber = udp.ProtocolNumber
length := uint16(pkt.Size())
udpHdr.Encode(&header.UDPFields{
SrcPort: localPort,
DstPort: remotePort,
Length: length,
})
// Set the checksum field unless TX checksum offload is enabled.
// On IPv4, UDP checksum is optional, and a zero value indicates the
// 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) {
xsum := r.PseudoHeaderChecksum(udp.ProtocolNumber, length)
for _, v := range data.Views() {
xsum = header.Checksum(v, xsum)
}
udpHdr.SetChecksum(^udpHdr.CalculateChecksum(xsum))
}
ttl := r.DefaultTTL()
if err := r.WritePacket(nil /* gso */, stack.NetworkHeaderParams{
Protocol: udp.ProtocolNumber,
TTL: ttl,
TOS: 0, /* default */
}, pkt); err != nil {
r.Stats().UDP.PacketSendErrors.Increment()
return err
}
// Track count of packets sent.
r.Stats().UDP.PacketsSent.Increment()
return nil
}
// verifyChecksum verifies the checksum unless RX checksum offload is enabled.
// On IPv4, UDP checksum is optional, and a zero value means the transmitter
// omitted the checksum generation (RFC768).
// On IPv6, UDP checksum is not optional (RFC2460 Section 8.1).
func verifyChecksum(hdr header.UDP, pkt *stack.PacketBuffer) bool {
if !pkt.RXTransportChecksumValidated &&
(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() {
xsum = header.Checksum(v, xsum)
}
return hdr.CalculateChecksum(xsum) == 0xffff
}
return true
}
+122
View File
@@ -0,0 +1,122 @@
package core
import (
"time"
glog "gvisor.dev/gvisor/pkg/log"
"gvisor.dev/gvisor/pkg/tcpip"
"gvisor.dev/gvisor/pkg/tcpip/adapters/gonet"
"gvisor.dev/gvisor/pkg/tcpip/header"
"gvisor.dev/gvisor/pkg/tcpip/stack"
"gvisor.dev/gvisor/pkg/tcpip/transport/tcp"
"gvisor.dev/gvisor/pkg/waiter"
"github.com/xjasonlyu/tun2socks/v2/core/adapter"
"github.com/xjasonlyu/tun2socks/v2/core/option"
)
const (
// defaultWndSize if set to zero, the default
// receive window buffer size is used instead.
defaultWndSize = 0
// maxConnAttempts specifies the maximum number
// of in-flight tcp connection attempts.
maxConnAttempts = 2 << 10
// tcpKeepaliveCount is the maximum number of
// TCP keep-alive probes to send before giving up
// and killing the connection if no response is
// obtained from the other end.
tcpKeepaliveCount = 9
// tcpKeepaliveIdle specifies the time a connection
// must remain idle before the first TCP keepalive
// packet is sent. Once this time is reached,
// tcpKeepaliveInterval option is used instead.
tcpKeepaliveIdle = 60 * time.Second
// tcpKeepaliveInterval specifies the interval
// time between sending TCP keepalive packets.
tcpKeepaliveInterval = 30 * time.Second
)
func withTCPHandler(handle func(adapter.TCPConn)) option.Option {
return func(s *stack.Stack) error {
tcpForwarder := tcp.NewForwarder(s, defaultWndSize, maxConnAttempts, func(r *tcp.ForwarderRequest) {
var (
wq waiter.Queue
ep tcpip.Endpoint
err tcpip.Error
id = r.ID()
)
defer func() {
if err != nil {
glog.Debugf("forward tcp request: %s:%d->%s:%d: %s",
id.RemoteAddress, id.RemotePort, id.LocalAddress, id.LocalPort, err)
}
}()
// Perform a TCP three-way handshake.
ep, err = r.CreateEndpoint(&wq)
if err != nil {
// RST: prevent potential half-open TCP connection leak.
r.Complete(true)
return
}
defer r.Complete(false)
err = setSocketOptions(s, ep)
conn := &tcpConn{
TCPConn: gonet.NewTCPConn(&wq, ep),
id: id,
}
handle(conn)
})
s.SetTransportProtocolHandler(tcp.ProtocolNumber, tcpForwarder.HandlePacket)
return nil
}
}
func setSocketOptions(s *stack.Stack, ep tcpip.Endpoint) tcpip.Error {
{ /* TCP keepalive options */
ep.SocketOptions().SetKeepAlive(true)
idle := tcpip.KeepaliveIdleOption(tcpKeepaliveIdle)
if err := ep.SetSockOpt(&idle); err != nil {
return err
}
interval := tcpip.KeepaliveIntervalOption(tcpKeepaliveInterval)
if err := ep.SetSockOpt(&interval); err != nil {
return err
}
if err := ep.SetSockOptInt(tcpip.KeepaliveCountOption, tcpKeepaliveCount); err != nil {
return err
}
}
{ /* TCP recv/send buffer size */
var ss tcpip.TCPSendBufferSizeRangeOption
if err := s.TransportProtocolOption(header.TCPProtocolNumber, &ss); err == nil {
ep.SocketOptions().SetSendBufferSize(int64(ss.Default), false)
}
var rs tcpip.TCPReceiveBufferSizeRangeOption
if err := s.TransportProtocolOption(header.TCPProtocolNumber, &rs); err == nil {
ep.SocketOptions().SetReceiveBufferSize(int64(rs.Default), false)
}
}
return nil
}
type tcpConn struct {
*gonet.TCPConn
id stack.TransportEndpointID
}
func (c *tcpConn) ID() *stack.TransportEndpointID {
return &c.id
}
+46
View File
@@ -0,0 +1,46 @@
package core
import (
glog "gvisor.dev/gvisor/pkg/log"
"gvisor.dev/gvisor/pkg/tcpip/adapters/gonet"
"gvisor.dev/gvisor/pkg/tcpip/stack"
"gvisor.dev/gvisor/pkg/tcpip/transport/udp"
"gvisor.dev/gvisor/pkg/waiter"
"github.com/xjasonlyu/tun2socks/v2/core/adapter"
"github.com/xjasonlyu/tun2socks/v2/core/option"
)
func withUDPHandler(handle func(adapter.UDPConn)) option.Option {
return func(s *stack.Stack) error {
udpForwarder := udp.NewForwarder(s, func(r *udp.ForwarderRequest) {
var (
wq waiter.Queue
id = r.ID()
)
ep, err := r.CreateEndpoint(&wq)
if err != nil {
glog.Debugf("forward udp request: %s:%d->%s:%d: %s",
id.RemoteAddress, id.RemotePort, id.LocalAddress, id.LocalPort, err)
return
}
conn := &udpConn{
UDPConn: gonet.NewUDPConn(&wq, ep),
id: id,
}
handle(conn)
})
s.SetTransportProtocolHandler(udp.ProtocolNumber, udpForwarder.HandlePacket)
return nil
}
}
type udpConn struct {
*gonet.UDPConn
id stack.TransportEndpointID
}
func (c *udpConn) ID() *stack.TransportEndpointID {
return &c.id
}
+66
View File
@@ -0,0 +1,66 @@
package dialer
import (
"context"
"net"
"syscall"
"go.uber.org/atomic"
)
var (
DefaultInterfaceName = atomic.NewString("")
DefaultInterfaceIndex = atomic.NewInt32(0)
DefaultRoutingMark = atomic.NewInt32(0)
)
type Options struct {
// InterfaceName is the name of interface/device to bind.
// If a socket is bound to an interface, only packets received
// from that particular interface are processed by the socket.
InterfaceName string
// InterfaceIndex is the index of interface/device to bind.
// It is almost the same as InterfaceName except it uses the
// index of the interface instead of the name.
InterfaceIndex int
// RoutingMark is the mark for each packet sent through this
// socket. Changing the mark can be used for mark-based routing
// without netfilter or for packet filtering.
RoutingMark int
}
func DialContext(ctx context.Context, network, address string) (net.Conn, error) {
return DialContextWithOptions(ctx, network, address, &Options{
InterfaceName: DefaultInterfaceName.Load(),
InterfaceIndex: int(DefaultInterfaceIndex.Load()),
RoutingMark: int(DefaultRoutingMark.Load()),
})
}
func DialContextWithOptions(ctx context.Context, network, address string, opts *Options) (net.Conn, error) {
d := &net.Dialer{
Control: func(network, address string, c syscall.RawConn) error {
return setSocketOptions(network, address, c, opts)
},
}
return d.DialContext(ctx, network, address)
}
func ListenPacket(network, address string) (net.PacketConn, error) {
return ListenPacketWithOptions(network, address, &Options{
InterfaceName: DefaultInterfaceName.Load(),
InterfaceIndex: int(DefaultInterfaceIndex.Load()),
RoutingMark: int(DefaultRoutingMark.Load()),
})
}
func ListenPacketWithOptions(network, address string, opts *Options) (net.PacketConn, error) {
lc := &net.ListenConfig{
Control: func(network, address string, c syscall.RawConn) error {
return setSocketOptions(network, address, c, opts)
},
}
return lc.ListenPacket(context.Background(), network, address)
}
+19
View File
@@ -0,0 +1,19 @@
package dialer
func isTCPSocket(network string) bool {
switch network {
case "tcp", "tcp4", "tcp6":
return true
default:
return false
}
}
func isUDPSocket(network string) bool {
switch network {
case "udp", "udp4", "udp6":
return true
default:
return false
}
}
+45
View File
@@ -0,0 +1,45 @@
package dialer
import (
"net"
"syscall"
"golang.org/x/sys/unix"
)
func setSocketOptions(network, address string, c syscall.RawConn, opts *Options) (err error) {
if opts == nil || !isTCPSocket(network) && !isUDPSocket(network) {
return
}
var innerErr error
err = c.Control(func(fd uintptr) {
host, _, _ := net.SplitHostPort(address)
if ip := net.ParseIP(host); ip != nil && !ip.IsGlobalUnicast() {
return
}
if opts.InterfaceIndex == 0 && opts.InterfaceName != "" {
if iface, err := net.InterfaceByName(opts.InterfaceName); err == nil {
opts.InterfaceIndex = iface.Index
}
}
if opts.InterfaceIndex != 0 {
switch network {
case "tcp4", "udp4":
innerErr = unix.SetsockoptInt(int(fd), syscall.IPPROTO_IP, syscall.IP_BOUND_IF, opts.InterfaceIndex)
case "tcp6", "udp6":
innerErr = unix.SetsockoptInt(int(fd), syscall.IPPROTO_IPV6, syscall.IPV6_BOUND_IF, opts.InterfaceIndex)
}
if innerErr != nil {
return
}
}
})
if innerErr != nil {
err = innerErr
}
return
}
+33
View File
@@ -0,0 +1,33 @@
package dialer
import (
"net"
"syscall"
"golang.org/x/sys/unix"
)
func setSocketOptions(network, address string, c syscall.RawConn, opts *Options) (err error) {
if opts == nil || !isTCPSocket(network) && !isUDPSocket(network) {
return
}
var innerErr error
err = c.Control(func(fd uintptr) {
host, _, _ := net.SplitHostPort(address)
if ip := net.ParseIP(host); ip != nil && !ip.IsGlobalUnicast() {
return
}
if opts.RoutingMark != 0 {
if innerErr = unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_USER_COOKIE, opts.RoutingMark); innerErr != nil {
return
}
}
})
if innerErr != nil {
err = innerErr
}
return
}
+44
View File
@@ -0,0 +1,44 @@
package dialer
import (
"net"
"syscall"
"golang.org/x/sys/unix"
)
func setSocketOptions(network, address string, c syscall.RawConn, opts *Options) (err error) {
if opts == nil || !isTCPSocket(network) && !isUDPSocket(network) {
return
}
var innerErr error
err = c.Control(func(fd uintptr) {
host, _, _ := net.SplitHostPort(address)
if ip := net.ParseIP(host); ip != nil && !ip.IsGlobalUnicast() {
return
}
if opts.InterfaceName == "" && opts.InterfaceIndex != 0 {
if iface, err := net.InterfaceByIndex(opts.InterfaceIndex); err == nil {
opts.InterfaceName = iface.Name
}
}
if opts.InterfaceName != "" {
if innerErr = unix.BindToDevice(int(fd), opts.InterfaceName); innerErr != nil {
return
}
}
if opts.RoutingMark != 0 {
if innerErr = unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_MARK, opts.RoutingMark); innerErr != nil {
return
}
}
})
if innerErr != nil {
err = innerErr
}
return
}
+33
View File
@@ -0,0 +1,33 @@
package dialer
import (
"net"
"syscall"
"golang.org/x/sys/unix"
)
func setSocketOptions(network, address string, c syscall.RawConn, opts *Options) (err error) {
if opts == nil || !isTCPSocket(network) && !isUDPSocket(network) {
return
}
var innerErr error
err = c.Control(func(fd uintptr) {
host, _, _ := net.SplitHostPort(address)
if ip := net.ParseIP(host); ip != nil && !ip.IsGlobalUnicast() {
return
}
if opts.RoutingMark != 0 {
if innerErr = unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_RTABLE, opts.RoutingMark); innerErr != nil {
return
}
}
})
if innerErr != nil {
err = innerErr
}
return
}
+9
View File
@@ -0,0 +1,9 @@
//go:build !unix && !windows
package dialer
import "syscall"
func setSocketOptions(network, address string, c syscall.RawConn, opts *Options) error {
return nil
}
+68
View File
@@ -0,0 +1,68 @@
package dialer
import (
"encoding/binary"
"net"
"syscall"
"unsafe"
"golang.org/x/sys/windows"
)
const (
IP_UNICAST_IF = 31
IPV6_UNICAST_IF = 31
)
func setSocketOptions(network, address string, c syscall.RawConn, opts *Options) (err error) {
if opts == nil || !isTCPSocket(network) && !isUDPSocket(network) {
return
}
var innerErr error
err = c.Control(func(fd uintptr) {
host, _, _ := net.SplitHostPort(address)
ip := net.ParseIP(host)
if ip != nil && !ip.IsGlobalUnicast() {
return
}
if opts.InterfaceIndex == 0 && opts.InterfaceName != "" {
if iface, err := net.InterfaceByName(opts.InterfaceName); err == nil {
opts.InterfaceIndex = iface.Index
}
}
if opts.InterfaceIndex != 0 {
switch network {
case "tcp4", "udp4":
innerErr = bindSocketToInterface4(windows.Handle(fd), uint32(opts.InterfaceIndex))
case "tcp6", "udp6":
innerErr = bindSocketToInterface6(windows.Handle(fd), uint32(opts.InterfaceIndex))
if network == "udp6" && ip == nil {
// The underlying IP net maybe IPv4 even if the `network` param is `udp6`,
// so we should bind socket to interface4 at the same time.
innerErr = bindSocketToInterface4(windows.Handle(fd), uint32(opts.InterfaceIndex))
}
}
}
})
if innerErr != nil {
err = innerErr
}
return
}
func bindSocketToInterface4(handle windows.Handle, index uint32) error {
// For IPv4, this parameter must be an interface index in network byte order.
// Ref: https://learn.microsoft.com/en-us/windows/win32/winsock/ipproto-ip-socket-options
var bytes [4]byte
binary.BigEndian.PutUint32(bytes[:], index)
index = *(*uint32)(unsafe.Pointer(&bytes[0]))
return windows.SetsockoptInt(handle, windows.IPPROTO_IP, IP_UNICAST_IF, int(index))
}
func bindSocketToInterface6(handle windows.Handle, index uint32) error {
return windows.SetsockoptInt(handle, windows.IPPROTO_IPV6, IPV6_UNICAST_IF, int(index))
}
+7 -3
View File
@@ -1,10 +1,14 @@
package dialer
package dns
import "net"
import (
"net"
"github.com/xjasonlyu/tun2socks/v2/dialer"
)
func init() {
// We must use this DialContext to query DNS
// when using net default resolver.
net.DefaultResolver.PreferGo = true
net.DefaultResolver.Dial = DialContext
net.DefaultResolver.Dial = dialer.DialContext
}
+27 -11
View File
@@ -47,7 +47,7 @@ config_route() {
done
}
main() {
run() {
create_tun
create_table
config_route
@@ -58,23 +58,39 @@ main() {
fi
if [ -n "$MTU" ]; then
ARGS="-mtu $MTU"
ARGS="--mtu $MTU"
fi
if [ -n "$STATS" ]; then
ARGS="$ARGS -stats $STATS"
if [ -n "$RESTAPI" ]; then
ARGS="$ARGS --restapi $RESTAPI"
fi
if [ -n "$TOKEN" ]; then
ARGS="$ARGS -token $TOKEN"
if [ -n "$UDP_TIMEOUT" ]; then
ARGS="$ARGS --udp-timeout $UDP_TIMEOUT"
fi
if [ -n "$TCP_SNDBUF" ]; then
ARGS="$ARGS --tcp-sndbuf $TCP_SNDBUF"
fi
if [ -n "$TCP_RCVBUF" ]; then
ARGS="$ARGS --tcp-rcvbuf $TCP_RCVBUF"
fi
if [ "$TCP_AUTO_TUNING" = 1 ]; then
ARGS="$ARGS --tcp-auto-tuning"
fi
if [ -n "$MULTICAST_GROUPS" ]; then
ARGS="$ARGS --multicast-groups $MULTICAST_GROUPS"
fi
exec tun2socks \
-loglevel "$LOGLEVEL" \
-fwmark "$FWMARK" \
-device "$TUN" \
-proxy "$PROXY" \
--loglevel "$LOGLEVEL" \
--fwmark "$FWMARK" \
--device "$TUN" \
--proxy "$PROXY" \
$ARGS
}
main || exit 1
run || exit 1
Binary file not shown.

After

Width:  |  Height:  |  Size: 122 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 84 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 109 KiB

Executable → Regular
+181 -97
View File
@@ -2,157 +2,241 @@ package engine
import (
"errors"
"os"
"net"
"net/netip"
"os/exec"
"sync"
"time"
"github.com/xjasonlyu/tun2socks/component/dialer"
"github.com/xjasonlyu/tun2socks/core/device"
"github.com/xjasonlyu/tun2socks/core/stack"
"github.com/xjasonlyu/tun2socks/log"
"github.com/xjasonlyu/tun2socks/proxy"
"github.com/xjasonlyu/tun2socks/stats"
"github.com/docker/go-units"
"github.com/google/shlex"
"gvisor.dev/gvisor/pkg/tcpip"
"gvisor.dev/gvisor/pkg/tcpip/stack"
"github.com/xjasonlyu/tun2socks/v2/core"
"github.com/xjasonlyu/tun2socks/v2/core/device"
"github.com/xjasonlyu/tun2socks/v2/core/option"
"github.com/xjasonlyu/tun2socks/v2/dialer"
"github.com/xjasonlyu/tun2socks/v2/log"
"github.com/xjasonlyu/tun2socks/v2/proxy"
"github.com/xjasonlyu/tun2socks/v2/restapi"
"github.com/xjasonlyu/tun2socks/v2/tunnel"
)
var _engine = &engine{}
var (
_engineMu sync.Mutex
// _defaultKey holds the default key for the engine.
_defaultKey *Key
// _defaultProxy holds the default proxy for the engine.
_defaultProxy proxy.Proxy
// _defaultDevice holds the default device for the engine.
_defaultDevice device.Device
// _defaultStack holds the default stack for the engine.
_defaultStack *stack.Stack
)
// Start starts the default engine up.
func Start() error {
return _engine.start()
func Start() {
if err := start(); err != nil {
log.Fatalf("[ENGINE] failed to start: %v", err)
}
}
// Stop shuts the default engine down.
func Stop() error {
return _engine.stop()
func Stop() {
if err := stop(); err != nil {
log.Fatalf("[ENGINE] failed to stop: %v", err)
}
}
// Insert loads *Key to the default engine.
func Insert(k *Key) {
_engine.insert(k)
_engineMu.Lock()
_defaultKey = k
_engineMu.Unlock()
}
type Key struct {
MTU int
Mark int
Proxy string
Stats string
Token string
Device string
LogLevel string
Interface string
Version bool
}
type engine struct {
*Key
stack *stack.Stack
proxy proxy.Proxy
device device.Device
}
func (e *engine) start() error {
if e.Key == nil {
func start() error {
_engineMu.Lock()
if _defaultKey == nil {
return errors.New("empty key")
}
if e.Version {
showVersion()
os.Exit(0)
}
for _, f := range []func() error{
e.setLogLevel,
e.setMark,
e.setInterface,
e.setStats,
e.setProxy,
e.setDevice,
e.setStack,
for _, f := range []func(*Key) error{
general,
restAPI,
netstack,
} {
if err := f(); err != nil {
if err := f(_defaultKey); err != nil {
return err
}
}
_engineMu.Unlock()
return nil
}
func (e *engine) stop() error {
if e.device != nil {
return e.device.Close()
func stop() (err error) {
_engineMu.Lock()
if _defaultDevice != nil {
_defaultDevice.Close()
}
if _defaultStack != nil {
_defaultStack.Close()
_defaultStack.Wait()
}
_engineMu.Unlock()
return nil
}
func (e *engine) insert(k *Key) {
e.Key = k
}
func (e *engine) setLogLevel() error {
level, err := log.ParseLevel(e.LogLevel)
func execCommand(cmd string) error {
parts, err := shlex.Split(cmd)
if err != nil {
return err
}
log.SetLevel(level)
return nil
}
func (e *engine) setMark() error {
if e.Mark != 0 {
dialer.SetMark(e.Mark)
log.Infof("[DIALER] set fwmark: %#x", e.Mark)
if len(parts) == 0 {
return errors.New("empty command")
}
return nil
_, err = exec.Command(parts[0], parts[1:]...).Output()
return err
}
func (e *engine) setInterface() error {
if e.Interface != "" {
if err := dialer.BindToInterface(e.Interface); err != nil {
func general(k *Key) error {
level, err := log.ParseLevel(k.LogLevel)
if err != nil {
return err
}
log.SetLogger(log.Must(log.NewLeveled(level)))
if k.Interface != "" {
iface, err := net.InterfaceByName(k.Interface)
if err != nil {
return err
}
log.Infof("[DIALER] use interface: %s", e.Interface)
dialer.DefaultInterfaceName.Store(iface.Name)
dialer.DefaultInterfaceIndex.Store(int32(iface.Index))
log.Infof("[DIALER] bind to interface: %s", k.Interface)
}
if k.Mark != 0 {
dialer.DefaultRoutingMark.Store(int32(k.Mark))
log.Infof("[DIALER] set fwmark: %#x", k.Mark)
}
if k.UDPTimeout > 0 {
if k.UDPTimeout < time.Second {
return errors.New("invalid udp timeout value")
}
tunnel.T().SetUDPTimeout(k.UDPTimeout)
}
return nil
}
func (e *engine) setStats() error {
if e.Stats != "" {
func restAPI(k *Key) error {
if k.RestAPI != "" {
u, err := parseRestAPI(k.RestAPI)
if err != nil {
return err
}
host, token := u.Host, u.User.String()
restapi.SetStatsFunc(func() tcpip.Stats {
_engineMu.Lock()
defer _engineMu.Unlock()
// default stack is not initialized.
if _defaultStack == nil {
return tcpip.Stats{}
}
return _defaultStack.Stats()
})
go func() {
_ = stats.Start(e.Stats, e.Token)
if err := restapi.Start(host, token); err != nil {
log.Errorf("[RESTAPI] failed to start: %v", err)
}
}()
log.Infof("[STATS] serve at: http://%s", e.Stats)
log.Infof("[RESTAPI] serve at: %s", u)
}
return nil
}
func (e *engine) setProxy() (err error) {
if e.Proxy == "" {
func netstack(k *Key) (err error) {
if k.Proxy == "" {
return errors.New("empty proxy")
}
e.proxy, err = parseProxy(e.Proxy)
proxy.SetDialer(e.proxy)
return
}
func (e *engine) setDevice() (err error) {
if e.Device == "" {
if k.Device == "" {
return errors.New("empty device")
}
e.device, err = parseDevice(e.Device, uint32(e.MTU))
return
}
if k.TUNPreUp != "" {
log.Infof("[TUN] pre-execute command: `%s`", k.TUNPreUp)
if preUpErr := execCommand(k.TUNPreUp); preUpErr != nil {
log.Errorf("[TUN] failed to pre-execute: %s: %v", k.TUNPreUp, preUpErr)
}
}
func (e *engine) setStack() (err error) {
defer func() {
if err == nil {
log.Infof(
"[STACK] %s://%s <-> %s://%s",
e.device.Type(), e.device.Name(),
e.proxy.Proto(), e.proxy.Addr(),
)
if k.TUNPostUp == "" || err != nil {
return
}
log.Infof("[TUN] post-execute command: `%s`", k.TUNPostUp)
if postUpErr := execCommand(k.TUNPostUp); postUpErr != nil {
log.Errorf("[TUN] failed to post-execute: %s: %v", k.TUNPostUp, postUpErr)
}
}()
e.stack, err = stack.New(e.device, &fakeTunnel{}, stack.WithDefault())
return
if _defaultProxy, err = parseProxy(k.Proxy); err != nil {
return
}
tunnel.T().SetDialer(_defaultProxy)
if _defaultDevice, err = parseDevice(k.Device, uint32(k.MTU)); err != nil {
return
}
var multicastGroups []netip.Addr
if multicastGroups, err = parseMulticastGroups(k.MulticastGroups); err != nil {
return err
}
var opts []option.Option
if k.TCPModerateReceiveBuffer {
opts = append(opts, option.WithTCPModerateReceiveBuffer(true))
}
if k.TCPSendBufferSize != "" {
size, err := units.RAMInBytes(k.TCPSendBufferSize)
if err != nil {
return err
}
opts = append(opts, option.WithTCPSendBufferSize(int(size)))
}
if k.TCPReceiveBufferSize != "" {
size, err := units.RAMInBytes(k.TCPReceiveBufferSize)
if err != nil {
return err
}
opts = append(opts, option.WithTCPReceiveBufferSize(int(size)))
}
if _defaultStack, err = core.CreateStack(&core.Config{
LinkEndpoint: _defaultDevice,
TransportHandler: tunnel.T(),
MulticastGroups: multicastGroups,
Options: opts,
}); err != nil {
return
}
log.Infof(
"[STACK] %s://%s <-> %s://%s",
_defaultDevice.Type(), _defaultDevice.Name(),
_defaultProxy.Proto(), _defaultProxy.Addr(),
)
return nil
}
+20
View File
@@ -0,0 +1,20 @@
package engine
import "time"
type Key struct {
MTU int `yaml:"mtu"`
Mark int `yaml:"fwmark"`
Proxy string `yaml:"proxy"`
RestAPI string `yaml:"restapi"`
Device string `yaml:"device"`
LogLevel string `yaml:"loglevel"`
Interface string `yaml:"interface"`
TCPModerateReceiveBuffer bool `yaml:"tcp-moderate-receive-buffer"`
TCPSendBufferSize string `yaml:"tcp-send-buffer-size"`
TCPReceiveBufferSize string `yaml:"tcp-receive-buffer-size"`
MulticastGroups string `yaml:"multicast-groups"`
TUNPreUp string `yaml:"tun-pre-up"`
TUNPostUp string `yaml:"tun-post-up"`
UDPTimeout time.Duration `yaml:"udp-timeout"`
}
+128 -22
View File
@@ -3,18 +3,51 @@ package engine
import (
"encoding/base64"
"fmt"
"net"
"net/netip"
"net/url"
"runtime"
"strings"
"github.com/xjasonlyu/tun2socks/core/device"
"github.com/xjasonlyu/tun2socks/core/device/tun"
"github.com/xjasonlyu/tun2socks/proxy"
"github.com/xjasonlyu/tun2socks/proxy/proto"
"github.com/gorilla/schema"
"github.com/xjasonlyu/tun2socks/v2/core/device"
"github.com/xjasonlyu/tun2socks/v2/core/device/fdbased"
"github.com/xjasonlyu/tun2socks/v2/core/device/tun"
"github.com/xjasonlyu/tun2socks/v2/proxy"
"github.com/xjasonlyu/tun2socks/v2/proxy/proto"
)
func parseDevice(s string, mtu uint32) (device.Device, error) {
func parseRestAPI(s string) (*url.URL, error) {
if !strings.Contains(s, "://") {
s = tun.Driver + "://" + s /* default driver */
s = fmt.Sprintf("%s://%s", "http", s)
}
u, err := url.Parse(s)
if err != nil {
return nil, err
}
addr, err := net.ResolveTCPAddr("tcp", u.Host)
if err != nil {
return nil, err
}
if addr.IP == nil {
addr.IP = net.IPv4zero /* default: 0.0.0.0 */
}
u.Host = addr.String()
switch u.Scheme {
case "http":
return u, nil
default:
return nil, fmt.Errorf("unsupported scheme: %s", u.Scheme)
}
}
func parseDevice(s string, mtu uint32) (device.Device, error) {
if !strings.Contains(s, "://") {
s = fmt.Sprintf("%s://%s", tun.Driver /* default driver */, s)
}
u, err := url.Parse(s)
@@ -22,20 +55,31 @@ func parseDevice(s string, mtu uint32) (device.Device, error) {
return nil, err
}
name := u.Host
driver := strings.ToLower(u.Scheme)
switch driver {
case fdbased.Driver:
return parseFD(u, mtu)
case tun.Driver:
return tun.Open(tun.WithName(name), tun.WithMTU(mtu))
return parseTUN(u, mtu)
default:
return nil, fmt.Errorf("unsupported driver: %s", driver)
}
}
func parseFD(u *url.URL, mtu uint32) (device.Device, error) {
offset := 0
// fd offset in ios
// https://stackoverflow.com/questions/69260852/ios-network-extension-packet-parsing/69487795#69487795
if runtime.GOOS == "ios" {
offset = 4
}
return fdbased.Open(u.Host, mtu, offset)
}
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,33 +92,64 @@ 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 parseHTTP(u)
case proto.Socks4.String():
return parseSocks4(u)
case proto.Socks5.String():
return proxy.NewSocks5(parseSocks(u))
return parseSocks5(u)
case proto.Shadowsocks.String():
return proxy.NewShadowsocks(parseShadowsocks(u))
return parseShadowsocks(u)
case proto.Relay.String():
return parseRelay(u)
default:
return nil, fmt.Errorf("unsupported protocol: %s", protocol)
}
}
func parseSocks(u *url.URL) (address, username, password string) {
address = u.Host
username = u.User.Username()
password, _ = u.User.Password()
return
func parseHTTP(u *url.URL) (proxy.Proxy, error) {
address, username := u.Host, u.User.Username()
password, _ := u.User.Password()
return proxy.NewHTTP(address, username, password)
}
func parseShadowsocks(u *url.URL) (address, method, password, obfsMode, obfsHost string) {
address = u.Host
func parseSocks4(u *url.URL) (proxy.Proxy, error) {
address, userID := u.Host, u.User.Username()
return proxy.NewSocks4(address, userID)
}
if pass, set := u.User.Password(); set {
func parseSocks5(u *url.URL) (proxy.Proxy, error) {
address, username := u.Host, u.User.Username()
password, _ := u.User.Password()
// Socks5 over UDS
if address == "" {
address = u.Path
}
return proxy.NewSocks5(address, username, password)
}
func parseShadowsocks(u *url.URL) (proxy.Proxy, error) {
var (
address = u.Host
method, password string
obfsMode, obfsHost string
)
if ss := u.User.String(); ss == "" {
method = "dummy" // none cipher mode
} else if pass, set := u.User.Password(); set {
method = u.User.Username()
password = pass
} else {
data, _ := base64.RawURLEncoding.DecodeString(u.User.String())
data, _ := base64.RawURLEncoding.DecodeString(ss)
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)
@@ -94,5 +169,36 @@ func parseShadowsocks(u *url.URL) (address, method, password, obfsMode, obfsHost
}
}
return proxy.NewShadowsocks(address, method, password, obfsMode, obfsHost)
}
func parseRelay(u *url.URL) (proxy.Proxy, error) {
address, username := u.Host, u.User.Username()
password, _ := u.User.Password()
opts := struct {
NoDelay bool
}{}
if err := schema.NewDecoder().Decode(&opts, u.Query()); err != nil {
return nil, err
}
return proxy.NewRelay(address, username, password, opts.NoDelay)
}
func parseMulticastGroups(s string) (multicastGroups []netip.Addr, _ error) {
for _, ip := range strings.Split(s, ",") {
if ip = strings.TrimSpace(ip); ip == "" {
continue
}
addr, err := netip.ParseAddr(ip)
if err != nil {
return nil, err
}
if !addr.IsMulticast() {
return nil, fmt.Errorf("invalid multicast IP: %s", addr)
}
multicastGroups = append(multicastGroups, addr)
}
return
}
+14
View File
@@ -0,0 +1,14 @@
//go:build unix
package engine
import (
"net/url"
"github.com/xjasonlyu/tun2socks/v2/core/device"
"github.com/xjasonlyu/tun2socks/v2/core/device/tun"
)
func parseTUN(u *url.URL, mtu uint32) (device.Device, error) {
return tun.Open(u.Host, mtu)
}
+34
View File
@@ -0,0 +1,34 @@
package engine
import (
"net/url"
"github.com/gorilla/schema"
"golang.org/x/sys/windows"
wun "golang.zx2c4.com/wireguard/tun"
"github.com/xjasonlyu/tun2socks/v2/core/device"
"github.com/xjasonlyu/tun2socks/v2/core/device/tun"
"github.com/xjasonlyu/tun2socks/v2/internal/version"
)
func init() {
wun.WintunTunnelType = version.Name
}
func parseTUN(u *url.URL, mtu uint32) (device.Device, error) {
opts := struct {
GUID string
}{}
if err := schema.NewDecoder().Decode(&opts, u.Query()); err != nil {
return nil, err
}
if opts.GUID != "" {
guid, err := windows.GUIDFromString(opts.GUID)
if err != nil {
return nil, err
}
wun.WintunStaticRequestedGUID = &guid
}
return tun.Open(u.Host, mtu)
}
-18
View File
@@ -1,18 +0,0 @@
package engine
import (
"github.com/xjasonlyu/tun2socks/core"
"github.com/xjasonlyu/tun2socks/tunnel"
)
var _ core.Handler = (*fakeTunnel)(nil)
type fakeTunnel struct{}
func (*fakeTunnel) Add(conn core.TCPConn) {
tunnel.Add(conn)
}
func (*fakeTunnel) AddPacket(packet core.UDPPacket) {
tunnel.AddPacket(packet)
}
-22
View File
@@ -1,22 +0,0 @@
package engine
import (
"fmt"
"runtime"
"strings"
V "github.com/xjasonlyu/tun2socks/constant"
)
func showVersion() {
fmt.Print(versionString())
fmt.Print(releaseString())
}
func versionString() string {
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(), V.GitCommit)
}
+30 -18
View File
@@ -1,23 +1,35 @@
module github.com/xjasonlyu/tun2socks
module github.com/xjasonlyu/tun2socks/v2
go 1.16
go 1.23.1
require (
github.com/Dreamacro/go-shadowsocks2 v0.1.6
github.com/go-chi/chi v4.1.2+incompatible
github.com/go-chi/cors v1.1.1
github.com/go-chi/render v1.0.1
github.com/gofrs/uuid v4.0.0+incompatible
github.com/gorilla/websocket v1.4.2
github.com/magefile/mage v1.11.0 // indirect
github.com/sirupsen/logrus v1.7.1
github.com/stretchr/testify v1.7.0
go.uber.org/atomic v1.7.0
golang.org/x/net v0.0.0-20210119194325-5f4716e94777 // indirect
golang.org/x/sys v0.0.0-20210216224549-f992740a1bac
golang.org/x/time v0.0.0-20201208040808-7e3f01d25324
golang.zx2c4.com/wireguard v0.0.0-20210216200525-4e439ea10e32
gvisor.dev/gvisor v0.0.0-20210213011838-e7ae604b523e
github.com/docker/go-units v0.5.0
github.com/go-chi/chi/v5 v5.1.0
github.com/go-chi/cors v1.2.1
github.com/go-chi/render v1.0.3
github.com/go-gost/relay v0.5.0
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510
github.com/google/uuid v1.6.0
github.com/gorilla/schema v1.4.1
github.com/gorilla/websocket v1.5.3
github.com/stretchr/testify v1.9.0
go.uber.org/atomic v1.11.0
go.uber.org/automaxprocs v1.6.0
go.uber.org/zap v1.27.0
golang.org/x/crypto v0.31.0
golang.org/x/sys v0.28.0
golang.org/x/time v0.8.0
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173
gopkg.in/yaml.v3 v3.0.1
gvisor.dev/gvisor v0.0.0-20241108012608-5901531b85ba
)
replace gvisor.dev/gvisor => github.com/xjasonlyu/gvisor v0.0.0-20210217091018-5497a9345bcd
require (
github.com/ajg/form v1.5.1 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/google/btree v1.1.3 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
golang.org/x/net v0.31.0 // indirect
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect
)
+54 -621
View File
@@ -1,630 +1,63 @@
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-20210208174643-50096c924a4e/go.mod h1:EXlVlkqNba9rJe3j7w3Xa924itAMLgZH4UD/Q4PExuQ=
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/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
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/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU=
github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY=
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/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/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/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/go-chi/chi/v5 v5.1.0 h1:acVI1TYaD+hhedDJ3r54HyA6sExp3HfXq7QWEEY/xMw=
github.com/go-chi/chi/v5 v5.1.0/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
github.com/go-chi/cors v1.2.1 h1:xEC8UT3Rlp2QuWNEr4Fs/c2EAGVKBwy/1vHx3bppil4=
github.com/go-chi/cors v1.2.1/go.mod h1:sSbTewc+6wYHBBCW7ytsFSn836hqM7JxpglAy2Vzc58=
github.com/go-chi/render v1.0.3 h1:AsXqd2a1/INaIfUSKq3G5uA8weYx20FOsM7uSoCyyt4=
github.com/go-chi/render v1.0.3/go.mod h1:/gr3hVkmYR0YlEy3LxCuVRFzEu9Ruok+gFqbIofjao0=
github.com/go-gost/relay v0.5.0 h1:JG1tgy/KWiVXS0ukuVXvbM0kbYuJTWxYpJ5JwzsCf/c=
github.com/go-gost/relay v0.5.0/go.mod h1:lcX+23LCQ3khIeASBo+tJ/WbwXFO32/N5YN6ucuYTG8=
github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg=
github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/schema v1.4.1 h1:jUg5hUjCSDZpNGLuXQOgIWGdlgrIdYvgQ0wZtdK1M3E=
github.com/gorilla/schema v1.4.1/go.mod h1:Dg5SSm5PV60mhF2NFaTV1xuYYj8tV8NOPRo4FggUMnM=
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
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/magefile/mage v1.10.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A=
github.com/magefile/mage v1.11.0 h1:C/55Ywp9BpgVVclD3lRnSYCwXTYxmSppIgLeDYlNuls=
github.com/magefile/mage v1.11.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A=
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/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
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/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
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.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/sirupsen/logrus v1.7.1 h1:rsizeFmZP+GYwyb4V6t6qpG7ZNWzA2bvgW/yC2xHCcg=
github.com/sirupsen/logrus v1.7.1/go.mod h1:4GuYW9TZmE769R5STWrRakJc4UqQ3+QQ95fyz7ENv1A=
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/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/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/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
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/xjasonlyu/gvisor v0.0.0-20210217091018-5497a9345bcd h1:tXPm4IklE8uuAyXkfpr0Js6gc34WUK9RfB8mKWYkeio=
github.com/xjasonlyu/gvisor v0.0.0-20210217091018-5497a9345bcd/go.mod h1:TMDExUbPoyZXybG8K1+vm5ElIxI5qXUM5fwK7vI8YIg=
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/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/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
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/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/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/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
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/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-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-20210105210732-16f7687f5001/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210216224549-f992740a1bac h1:9glrpwtNjBYgRpb67AZJKHfzj1stG/8BL5H7In2oTC4=
golang.org/x/sys v0.0.0-20210216224549-f992740a1bac/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
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/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20201208040808-7e3f01d25324 h1:Hir2P/De0WpUhtrKGGjvSb2YxUgyZ7EFOSLIcSSpiwE=
golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/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.0-20210216200525-4e439ea10e32 h1:b9GuQq7q23DkzDMMlnL1Dfj6zCzYF34ZOg3A8wUwHPs=
golang.zx2c4.com/wireguard v0.0.0-20210216200525-4e439ea10e32/go.mod h1:LofpIKqPJNvHiwKXuzsBshJCTe7IgRAz3iizquljFDk=
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.20210208035533-9280052d3665/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=
github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g=
github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs=
go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwEFJ8r8=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
golang.org/x/net v0.31.0 h1:68CPQngjLL0r2AlUKiSxtQFKvzRVbnzLwMUn5SzcLHo=
golang.org/x/net v0.31.0/go.mod h1:P4fl1q7dY2hnZFxEk4pPSkDHF+QqjitcnDjUQyMM+pM=
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/time v0.8.0 h1:9i3RxcPv3PZnitoVGMPDKZSq1xW1gK1Xy3ArNOGZfEg=
golang.org/x/time v0.8.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 h1:B82qJJgjvYKsXS9jeunTOisW56dUokqW/FOteYJJ/yg=
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2/go.mod h1:deeaetjYA+DHMHg+sMSMI58GrEteJUUzzw7en6TJQcI=
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173 h1:/jFs0duh4rdb8uIfPMv78iAJGcPKDeqAFnaLBropIC4=
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173/go.mod h1:tkCQ4FQXmpAgYVh++1cq16/dH4QJtmvpRv19DWGAHSA=
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/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
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=
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
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.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gvisor.dev/gvisor v0.0.0-20241108012608-5901531b85ba h1:ZXzGZ6Md+Vspe9x45C6QlpCdpwYC6nHFtWIfZzTqB0k=
gvisor.dev/gvisor v0.0.0-20241108012608-5901531b85ba/go.mod h1:5DMfjtclAbTIjbXqO1qCe2K5GKKxWz2JHvCChuTcJEM=
+38
View File
@@ -0,0 +1,38 @@
// Package pool provides internal pool utilities.
package pool
import (
"sync"
)
// A Pool is a generic wrapper around [sync.Pool] to provide strongly-typed
// object pooling.
//
// Note that SA6002 (ref: https://staticcheck.io/docs/checks/#SA6002) will
// not be detected, so all internal pool use must take care to only store
// pointer types.
type Pool[T any] struct {
pool sync.Pool
}
// New returns a new [Pool] for T, and will use fn to construct new Ts when
// the pool is empty.
func New[T any](fn func() T) *Pool[T] {
return &Pool[T]{
pool: sync.Pool{
New: func() any {
return fn()
},
},
}
}
// Get gets a T from the pool, or creates a new one if the pool is empty.
func (p *Pool[T]) Get() T {
return p.pool.Get().(T)
}
// Put returns x into the pool.
func (p *Pool[T]) Put(x T) {
p.pool.Put(x)
}
+85
View File
@@ -0,0 +1,85 @@
package pool
import (
"runtime/debug"
"sync"
"testing"
"github.com/stretchr/testify/require"
)
type pooledValue[T any] struct {
value T
}
func TestNew(t *testing.T) {
// Disable GC to avoid the victim cache during the test.
defer debug.SetGCPercent(debug.SetGCPercent(-1))
p := New(func() *pooledValue[string] {
return &pooledValue[string]{
value: "new",
}
})
// Probabilistically, 75% of sync.Pool.Put calls will succeed when -race
// is enabled (see ref below); attempt to make this quasi-deterministic by
// brute force (i.e., put significantly more objects in the pool than we
// will need for the test) in order to avoid testing without race enabled.
//
// ref: https://cs.opensource.google/go/go/+/refs/tags/go1.20.2:src/sync/pool.go;l=100-103
for i := 0; i < 1_000; i++ {
p.Put(&pooledValue[string]{
value: t.Name(),
})
}
// Ensure that we always get the expected value. Note that this must only
// run a fraction of the number of times that Put is called above.
for i := 0; i < 10; i++ {
func() {
x := p.Get()
defer p.Put(x)
require.Equal(t, t.Name(), x.value)
}()
}
// Depool all objects that might be in the pool to ensure that it's empty.
for i := 0; i < 1_000; i++ {
p.Get()
}
// Now that the pool is empty, it should use the value specified in the
// underlying sync.Pool.New func.
require.Equal(t, "new", p.Get().value)
}
func TestNew_Race(t *testing.T) {
p := New(func() *pooledValue[int] {
return &pooledValue[int]{
value: -1,
}
})
var wg sync.WaitGroup
defer wg.Wait()
// Run a number of goroutines that read and write pool object fields to
// tease out races.
for i := 0; i < 1_000; i++ {
i := i
wg.Add(1)
go func() {
defer wg.Done()
x := p.Get()
defer p.Put(x)
// Must both read and write the field.
if n := x.value; n >= -1 {
x.value = i
}
}()
}
}
+11
View File
@@ -0,0 +1,11 @@
package version
import (
"runtime/debug"
)
// Info returns project dependencies as []*debug.Module.
func Info() []*debug.Module {
bi, _ := debug.ReadBuildInfo()
return bi.Deps
}
+27
View File
@@ -0,0 +1,27 @@
package version
import (
"fmt"
"runtime"
"strings"
)
const Name = "tun2socks"
var (
// Version can be set at link time by executing
// the command: `git describe --abbrev=0 --tags HEAD`
Version string
// GitCommit can be set at link time by executing
// the command: `git rev-parse --short HEAD`
GitCommit string
)
func String() string {
return fmt.Sprintf("%s-%s", Name, strings.TrimPrefix(Version, "v"))
}
func BuildString() string {
return fmt.Sprintf("%s/%s, %s, %s", runtime.GOOS, runtime.GOARCH, runtime.Version(), GitCommit)
}
+2
View File
@@ -0,0 +1,2 @@
// Package log is a thin wrapper based on "go.uber.org/zap".
package log
+37
View File
@@ -0,0 +1,37 @@
package log
import (
"runtime"
"strings"
"time"
glog "gvisor.dev/gvisor/pkg/log"
)
var _globalE = &emitter{}
func init() {
glog.SetTarget(_globalE)
}
type emitter struct {
logger *SugaredLogger
}
func (e *emitter) setLogger(logger *SugaredLogger) {
e.logger = logger.WithOptions(pkgCallerSkip)
}
func (e *emitter) logf(level glog.Level, format string, args ...any) {
e.logger.Logf(1-Level(level), "[STACK] "+format, args...)
}
func (e *emitter) Emit(depth int, level glog.Level, _ time.Time, format string, args ...any) {
if _, file, line, ok := runtime.Caller(depth + 1); ok {
// Ignore: gvisor.dev/gvisor/pkg/tcpip/adapters/gonet/gonet.go:457
if line == 457 && strings.HasSuffix(file, "gonet/gonet.go") {
return
}
}
e.logf(level, format, args...)
}
-39
View File
@@ -1,39 +0,0 @@
package log
import (
"fmt"
"time"
"github.com/xjasonlyu/tun2socks/common/observable"
)
var (
_logCh = make(chan interface{})
_source = observable.NewObservable(_logCh)
)
type Event struct {
Level Level `json:"level"`
Message string `json:"msg"`
Time time.Time `json:"time"`
}
func newEvent(level Level, format string, args ...interface{}) *Event {
event := &Event{
Level: level,
Time: time.Now(),
Message: fmt.Sprintf(format, args...),
}
_logCh <- event /* send all events to logCh */
return event
}
func Subscribe() observable.Subscription {
sub, _ := _source.Subscribe()
return sub
}
func UnSubscribe(sub observable.Subscription) {
_source.UnSubscribe(sub)
}
Executable → Regular
+18 -59
View File
@@ -1,72 +1,31 @@
package log
import (
"encoding/json"
"fmt"
"strings"
"go.uber.org/zap/zapcore"
)
type Level uint32
// Level is an alias for zapcore.Level.
type Level = zapcore.Level
// Levels are aliases for Level.
const (
SilentLevel Level = iota
ErrorLevel
WarnLevel
InfoLevel
DebugLevel
DebugLevel = zapcore.DebugLevel
InfoLevel = zapcore.InfoLevel
WarnLevel = zapcore.WarnLevel
ErrorLevel = zapcore.ErrorLevel
DPanicLevel = zapcore.DPanicLevel
PanicLevel = zapcore.PanicLevel
FatalLevel = zapcore.FatalLevel
InvalidLevel = zapcore.InvalidLevel
SilentLevel = InvalidLevel + 1
)
// UnmarshalJSON deserialize Level with json
func (level *Level) UnmarshalJSON(data []byte) error {
var lvl string
if err := json.Unmarshal(data, &lvl); err != nil {
return err
}
l, err := ParseLevel(lvl)
if err != nil {
return err
}
*level = l
return nil
}
// MarshalJSON serialize Level with json
func (level Level) MarshalJSON() ([]byte, error) {
return json.Marshal(level.String())
}
func (level Level) String() string {
switch level {
case DebugLevel:
return "debug"
case InfoLevel:
return "info"
case WarnLevel:
return "warning"
case ErrorLevel:
return "error"
case SilentLevel:
return "silent"
default:
return fmt.Sprintf("not a valid level %d", level)
}
}
func ParseLevel(lvl string) (Level, error) {
switch strings.ToLower(lvl) {
case "silent":
// ParseLevel is a thin wrapper for zapcore.ParseLevel.
func ParseLevel(text string) (Level, error) {
switch text {
case "silent", "SILENT":
return SilentLevel, nil
case "error":
return ErrorLevel, nil
case "warn":
return WarnLevel, nil
case "info":
return InfoLevel, nil
case "debug":
return DebugLevel, nil
default:
return Level(0), fmt.Errorf("not a valid logrus Level: %q", lvl)
return zapcore.ParseLevel(text)
}
}

Some files were not shown because too many files have changed in this diff Show More