mirror of
https://github.com/go-gost/gost.git
synced 2026-10-08 20:15:46 +00:00
Compare commits
82
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d3283d6278 | ||
|
|
4b3e711adb | ||
|
|
258d9f5b26 | ||
|
|
5d9d33f368 | ||
|
|
fec33e62ea | ||
|
|
2f0da6993b | ||
|
|
39cb9c65d9 | ||
|
|
4ef4448249 | ||
|
|
1151ecd2a4 | ||
|
|
df3533b4ef | ||
|
|
2400e29fe0 | ||
|
|
41bb4cdbb0 | ||
|
|
4a192bc1b3 | ||
|
|
f17b2d2e96 | ||
|
|
e771534920 | ||
|
|
68c311a7d1 | ||
|
|
1c9974340b | ||
|
|
09c12b013c | ||
|
|
b86d7ee06d | ||
|
|
8274b62672 | ||
|
|
7f924fdeb6 | ||
|
|
5d797eac43 | ||
|
|
2c29028a3b | ||
|
|
e8071d9b65 | ||
|
|
50cf4edd1f | ||
|
|
3d5f0f93fd | ||
|
|
aa754f8515 | ||
|
|
a7f4d3e63e | ||
|
|
180214a124 | ||
|
|
baa6f0cea0 | ||
|
|
ca0de58757 | ||
|
|
5acccebe7b | ||
|
|
850bb1379f | ||
|
|
9e404471a6 | ||
|
|
166317a7d0 | ||
|
|
77d9e3798c | ||
|
|
5cbba69ae2 | ||
|
|
8a8cbdd9e1 | ||
|
|
fb5f57fa80 | ||
|
|
5603af2fcf | ||
|
|
8ae4e43fc3 | ||
|
|
96b3b7e962 | ||
|
|
85de11ae46 | ||
|
|
3a409fea42 | ||
|
|
1c65aae3a9 | ||
|
|
84255850b6 | ||
|
|
54e0091c38 | ||
|
|
605c43ca08 | ||
|
|
3418dd0f00 | ||
|
|
21463c0e9b | ||
|
|
11077eaa75 | ||
|
|
9cd94cb68b | ||
|
|
37ef13655d | ||
|
|
961646fb46 | ||
|
|
666846d352 | ||
|
|
c70521ddab | ||
|
|
7c91dfb56f | ||
|
|
4b88c240f8 | ||
|
|
1b31c80d2c | ||
|
|
810f9f4d8f | ||
|
|
5fe56cb63f | ||
|
|
733655625a | ||
|
|
670a118c6d | ||
|
|
cb0d81f938 | ||
|
|
7b5913123f | ||
|
|
bb7fb31e3d | ||
|
|
7fd8720f38 | ||
|
|
815341dbfa | ||
|
|
2864480296 | ||
|
|
0a41b70ef4 | ||
|
|
20e7528b25 | ||
|
|
2e40afe535 | ||
|
|
42f72adde0 | ||
|
|
a2d62d1753 | ||
|
|
749d802a12 | ||
|
|
695c720d26 | ||
|
|
c282e69ffd | ||
|
|
eae153d481 | ||
|
|
a7fddd1d7c | ||
|
|
5c5af49b0e | ||
|
|
bfc1f8472c | ||
|
|
4007e80811 |
+3
-1
@@ -34,4 +34,6 @@ _testmain.go
|
|||||||
cmd/gost/gost
|
cmd/gost/gost
|
||||||
snap
|
snap
|
||||||
|
|
||||||
*.pem
|
*.pem
|
||||||
|
*.yaml
|
||||||
|
*.txt
|
||||||
+4
-1
@@ -1,4 +1,4 @@
|
|||||||
FROM --platform=$BUILDPLATFORM golang:1.18rc1-alpine as builder
|
FROM --platform=$BUILDPLATFORM golang:1.19-alpine as builder
|
||||||
|
|
||||||
# Convert TARGETPLATFORM to GOARCH format
|
# Convert TARGETPLATFORM to GOARCH format
|
||||||
# https://github.com/tonistiigi/xx
|
# https://github.com/tonistiigi/xx
|
||||||
@@ -18,6 +18,9 @@ RUN cd cmd/gost && go env && go build
|
|||||||
|
|
||||||
FROM alpine:latest
|
FROM alpine:latest
|
||||||
|
|
||||||
|
# add iptables for tun/tap
|
||||||
|
RUN apk add --no-cache iptables
|
||||||
|
|
||||||
WORKDIR /bin/
|
WORKDIR /bin/
|
||||||
|
|
||||||
COPY --from=builder /src/cmd/gost/gost .
|
COPY --from=builder /src/cmd/gost/gost .
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ PLATFORM_LIST = \
|
|||||||
darwin-arm64 \
|
darwin-arm64 \
|
||||||
linux-386 \
|
linux-386 \
|
||||||
linux-amd64 \
|
linux-amd64 \
|
||||||
|
linux-amd64v3 \
|
||||||
linux-armv5 \
|
linux-armv5 \
|
||||||
linux-armv6 \
|
linux-armv6 \
|
||||||
linux-armv7 \
|
linux-armv7 \
|
||||||
@@ -20,12 +21,15 @@ PLATFORM_LIST = \
|
|||||||
linux-mips64 \
|
linux-mips64 \
|
||||||
linux-mips64le \
|
linux-mips64le \
|
||||||
linux-s390x \
|
linux-s390x \
|
||||||
|
linux-riscv64 \
|
||||||
freebsd-386 \
|
freebsd-386 \
|
||||||
freebsd-amd64
|
freebsd-amd64
|
||||||
|
|
||||||
WINDOWS_ARCH_LIST = \
|
WINDOWS_ARCH_LIST = \
|
||||||
windows-386 \
|
windows-386 \
|
||||||
windows-amd64
|
windows-amd64 \
|
||||||
|
windows-amd64v3 \
|
||||||
|
windows-arm64
|
||||||
|
|
||||||
all: linux-amd64 darwin-amd64 darwin-arm64 windows-amd64 # Most used
|
all: linux-amd64 darwin-amd64 darwin-arm64 windows-amd64 # Most used
|
||||||
|
|
||||||
@@ -41,6 +45,9 @@ linux-386:
|
|||||||
linux-amd64:
|
linux-amd64:
|
||||||
GOARCH=amd64 GOOS=linux $(GOBUILD) -o $(BINDIR)/$(NAME)-$@ $(GOFILES)
|
GOARCH=amd64 GOOS=linux $(GOBUILD) -o $(BINDIR)/$(NAME)-$@ $(GOFILES)
|
||||||
|
|
||||||
|
linux-amd64v3:
|
||||||
|
GOARCH=amd64 GOOS=linux GOAMD64=v3 $(GOBUILD) -o $(BINDIR)/$(NAME)-$@ $(GOFILES)
|
||||||
|
|
||||||
linux-armv5:
|
linux-armv5:
|
||||||
GOARCH=arm GOOS=linux GOARM=5 $(GOBUILD) -o $(BINDIR)/$(NAME)-$@ $(GOFILES)
|
GOARCH=arm GOOS=linux GOARM=5 $(GOBUILD) -o $(BINDIR)/$(NAME)-$@ $(GOFILES)
|
||||||
|
|
||||||
@@ -74,6 +81,9 @@ linux-mips64le:
|
|||||||
linux-s390x:
|
linux-s390x:
|
||||||
GOARCH=s390x GOOS=linux $(GOBUILD) -o $(BINDIR)/$(NAME)-$@ $(GOFILES)
|
GOARCH=s390x GOOS=linux $(GOBUILD) -o $(BINDIR)/$(NAME)-$@ $(GOFILES)
|
||||||
|
|
||||||
|
linux-riscv64:
|
||||||
|
GOARCH=riscv64 GOOS=linux $(GOBUILD) -o $(BINDIR)/$(NAME)-$@ $(GOFILES)
|
||||||
|
|
||||||
freebsd-386:
|
freebsd-386:
|
||||||
GOARCH=386 GOOS=freebsd $(GOBUILD) -o $(BINDIR)/$(NAME)-$@ $(GOFILES)
|
GOARCH=386 GOOS=freebsd $(GOBUILD) -o $(BINDIR)/$(NAME)-$@ $(GOFILES)
|
||||||
|
|
||||||
@@ -86,6 +96,12 @@ windows-386:
|
|||||||
windows-amd64:
|
windows-amd64:
|
||||||
GOARCH=amd64 GOOS=windows $(GOBUILD) -o $(BINDIR)/$(NAME)-$@.exe $(GOFILES)
|
GOARCH=amd64 GOOS=windows $(GOBUILD) -o $(BINDIR)/$(NAME)-$@.exe $(GOFILES)
|
||||||
|
|
||||||
|
windows-amd64v3:
|
||||||
|
GOARCH=amd64 GOOS=windows GOAMD64=v3 $(GOBUILD) -o $(BINDIR)/$(NAME)-$@.exe $(GOFILES)
|
||||||
|
|
||||||
|
windows-arm64:
|
||||||
|
GOARCH=arm64 GOOS=windows $(GOBUILD) -o $(BINDIR)/$(NAME)-$@.exe $(GOFILES)
|
||||||
|
|
||||||
gz_releases=$(addsuffix .gz, $(PLATFORM_LIST))
|
gz_releases=$(addsuffix .gz, $(PLATFORM_LIST))
|
||||||
zip_releases=$(addsuffix .zip, $(WINDOWS_ARCH_LIST))
|
zip_releases=$(addsuffix .zip, $(WINDOWS_ARCH_LIST))
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,57 @@
|
|||||||
gost 3.0
|
# GO Simple Tunnel
|
||||||
======
|
|
||||||
|
|
||||||
WORK IN PROGRESS...
|
### GO语言实现的安全隧道
|
||||||
|
|
||||||
|
[English README](README_en.md)
|
||||||
|
|
||||||
|
## 功能特性
|
||||||
|
|
||||||
|
- [x] [多端口监听](https://gost.run/getting-started/quick-start/)
|
||||||
|
- [x] [多级转发链](https://gost.run/concepts/chain/)
|
||||||
|
- [x] [多协议支持](https://gost.run/tutorials/protocols/overview/)
|
||||||
|
- [x] [TCP/UDP端口转发](https://gost.run/tutorials/port-forwarding/)
|
||||||
|
- [x] [TCP/UDP透明代理](https://gost.run/tutorials/redirect/)
|
||||||
|
- [x] DNS[解析](https://gost.run/concepts/resolver/)和[代理](https://gost.run/tutorials/dns/)
|
||||||
|
- [x] [TUN/TAP设备](https://gost.run/tutorials/tuntap/)
|
||||||
|
- [x] [反向代理](https://gost.run/tutorials/reverse-proxy/)
|
||||||
|
- [x] [负载均衡](https://gost.run/concepts/selector/)
|
||||||
|
- [x] [路由控制](https://gost.run/concepts/bypass/)
|
||||||
|
- [x] [限速限流](https://gost.run/concepts/limiter/)
|
||||||
|
- [x] [准入控制](https://gost.run/concepts/admission/)
|
||||||
|
- [x] [动态配置](https://gost.run/tutorials/api/config/)
|
||||||
|
- [x] [Prometheus监控指标](https://gost.run/tutorials/metrics/)
|
||||||
|
- [x] [Web API](https://gost.run/tutorials/api/overview/)
|
||||||
|
- [ ] Web UI
|
||||||
|
|
||||||
|
Wiki站点:[https://gost.run](https://gost.run)
|
||||||
|
|
||||||
|
Telegram讨论群:[https://t.me/gogost](https://t.me/gogost)
|
||||||
|
|
||||||
|
Google讨论组:[https://groups.google.com/d/forum/go-gost](https://groups.google.com/d/forum/go-gost)
|
||||||
|
|
||||||
|
旧版入口:[v2.gost.run](https://v2.gost.run)
|
||||||
|
|
||||||
|
## 下载安装
|
||||||
|
|
||||||
|
|
||||||
|
### 二进制文件
|
||||||
|
|
||||||
|
[https://github.com/go-gost/gost/releases](https://github.com/go-gost/gost/releases)
|
||||||
|
|
||||||
|
### 源码编译
|
||||||
|
|
||||||
|
```
|
||||||
|
git clone https://github.com/go-gost/gost.git
|
||||||
|
cd gost/cmd/gost
|
||||||
|
go build
|
||||||
|
```
|
||||||
|
|
||||||
|
### Docker
|
||||||
|
|
||||||
|
```
|
||||||
|
docker run --rm gogost/gost -V
|
||||||
|
```
|
||||||
|
|
||||||
|
### Shadowsocks Android插件
|
||||||
|
|
||||||
|
[xausky/ShadowsocksGostPlugin](https://github.com/xausky/ShadowsocksGostPlugin)
|
||||||
|
|||||||
@@ -0,0 +1,55 @@
|
|||||||
|
# GO Simple Tunnel
|
||||||
|
|
||||||
|
### A simple security tunnel written in golang
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- [x] [Listening on multiple ports](https://gost.run/en/getting-started/quick-start/)
|
||||||
|
- [x] [Multi-level forwarding chain](https://gost.run/en/concepts/chain/)
|
||||||
|
- [x] Rich protocol
|
||||||
|
- [x] [TCP/UDP port forwarding](https://gost.run/en/tutorials/port-forwarding/)
|
||||||
|
- [x] [TCP/UDP transparent proxy](https://gost.run/en/tutorials/redirect/)
|
||||||
|
- [x] DNS [resolver](https://gost.run/en/concepts/resolver/) and [proxy](https://gost.run/en/tutorials/dns/)
|
||||||
|
- [x] [TUN/TAP device](https://gost.run/en/tutorials/tuntap/)
|
||||||
|
- [x] [Reverse Proxy](https://gost.run/en/tutorials/reverse-proxy/)
|
||||||
|
- [x] [Load balancing](https://gost.run/en/concepts/selector/)
|
||||||
|
- [x] [Routing control](https://gost.run/en/concepts/bypass/)
|
||||||
|
- [x] [Bandwidth/Rate Limiter](https://gost.run/en/concepts/limiter/)
|
||||||
|
- [x] [Admission control](https://gost.run/en/concepts/limiter/)
|
||||||
|
- [x] [Dynamic configuration](https://gost.run/en/tutorials/api/config/)
|
||||||
|
- [x] [Prometheus metrics](https://gost.run/en/tutorials/metrics/)
|
||||||
|
- [x] [Web API](https://gost.run/en/tutorials/api/overview/)
|
||||||
|
- [ ] Web UI
|
||||||
|
|
||||||
|
Wiki: [https://gost.run](https://gost.run/en/)
|
||||||
|
|
||||||
|
Telegram: [https://t.me/gogost](https://t.me/gogost)
|
||||||
|
|
||||||
|
Google group: [https://groups.google.com/d/forum/go-gost](https://groups.google.com/d/forum/go-gost)
|
||||||
|
|
||||||
|
Legacy version: [v2.gost.run](https://v2.gost.run/en/)
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
|
||||||
|
### Binary files
|
||||||
|
|
||||||
|
[https://github.com/go-gost/gost/releases](https://github.com/go-gost/gost/releases)
|
||||||
|
|
||||||
|
### From source
|
||||||
|
|
||||||
|
```
|
||||||
|
git clone https://github.com/go-gost/gost.git
|
||||||
|
cd gost/cmd/gost
|
||||||
|
go build
|
||||||
|
```
|
||||||
|
|
||||||
|
### Docker
|
||||||
|
|
||||||
|
```
|
||||||
|
docker run --rm gogost/gost -V
|
||||||
|
```
|
||||||
|
|
||||||
|
### Shadowsocks Android
|
||||||
|
|
||||||
|
[xausky/ShadowsocksGostPlugin](https://github.com/xausky/ShadowsocksGostPlugin)
|
||||||
+192
-110
@@ -6,13 +6,16 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/go-gost/gost/pkg/config"
|
mdutil "github.com/go-gost/core/metadata/util"
|
||||||
"github.com/go-gost/gost/pkg/metadata"
|
"github.com/go-gost/x/config"
|
||||||
metrics "github.com/go-gost/gost/pkg/metrics/service"
|
"github.com/go-gost/x/limiter/conn"
|
||||||
"github.com/go-gost/gost/pkg/registry"
|
"github.com/go-gost/x/limiter/traffic"
|
||||||
|
mdx "github.com/go-gost/x/metadata"
|
||||||
|
"github.com/go-gost/x/registry"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -31,31 +34,13 @@ func (l *stringList) Set(value string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func buildConfigFromCmd(services, nodes stringList) (*config.Config, error) {
|
func buildConfigFromCmd(services, nodes stringList) (*config.Config, error) {
|
||||||
|
namePrefix := ""
|
||||||
cfg := &config.Config{}
|
cfg := &config.Config{}
|
||||||
|
|
||||||
if v := os.Getenv("GOST_PROFILING"); v != "" {
|
|
||||||
cfg.Profiling = &config.ProfilingConfig{
|
|
||||||
Addr: v,
|
|
||||||
Enable: true,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if v := os.Getenv("GOST_METRICS"); v != "" {
|
|
||||||
cfg.Metrics = &config.MetricsConfig{
|
|
||||||
Addr: v,
|
|
||||||
Path: metrics.DefaultPath,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if v := os.Getenv("GOST_LOGGING_LEVEL"); v != "" {
|
|
||||||
cfg.Log = &config.LogConfig{
|
|
||||||
Level: v,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var chain *config.ChainConfig
|
var chain *config.ChainConfig
|
||||||
if len(nodes) > 0 {
|
if len(nodes) > 0 {
|
||||||
chain = &config.ChainConfig{
|
chain = &config.ChainConfig{
|
||||||
Name: "chain-0",
|
Name: fmt.Sprintf("%schain-0", namePrefix),
|
||||||
}
|
}
|
||||||
cfg.Chains = append(cfg.Chains, chain)
|
cfg.Chains = append(cfg.Chains, chain)
|
||||||
}
|
}
|
||||||
@@ -70,7 +55,7 @@ func buildConfigFromCmd(services, nodes stringList) (*config.Config, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
nodeConfig.Name = "node-0"
|
nodeConfig.Name = fmt.Sprintf("%snode-0", namePrefix)
|
||||||
|
|
||||||
var nodes []*config.NodeConfig
|
var nodes []*config.NodeConfig
|
||||||
for _, host := range strings.Split(nodeConfig.Addr, ",") {
|
for _, host := range strings.Split(nodeConfig.Addr, ",") {
|
||||||
@@ -79,25 +64,26 @@ func buildConfigFromCmd(services, nodes stringList) (*config.Config, error) {
|
|||||||
}
|
}
|
||||||
nodeCfg := &config.NodeConfig{}
|
nodeCfg := &config.NodeConfig{}
|
||||||
*nodeCfg = *nodeConfig
|
*nodeCfg = *nodeConfig
|
||||||
nodeCfg.Name = fmt.Sprintf("node-%d", len(nodes))
|
nodeCfg.Name = fmt.Sprintf("%snode-%d", namePrefix, len(nodes))
|
||||||
nodeCfg.Addr = host
|
nodeCfg.Addr = host
|
||||||
nodes = append(nodes, nodeCfg)
|
nodes = append(nodes, nodeCfg)
|
||||||
}
|
}
|
||||||
|
|
||||||
md := metadata.MapMetadata(nodeConfig.Connector.Metadata)
|
mc := nodeConfig.Connector.Metadata
|
||||||
|
md := mdx.NewMetadata(mc)
|
||||||
|
|
||||||
hopConfig := &config.HopConfig{
|
hopConfig := &config.HopConfig{
|
||||||
Name: fmt.Sprintf("hop-%d", i),
|
Name: fmt.Sprintf("%shop-%d", namePrefix, i),
|
||||||
Selector: parseSelector(md),
|
Selector: parseSelector(mc),
|
||||||
Nodes: nodes,
|
Nodes: nodes,
|
||||||
}
|
}
|
||||||
|
|
||||||
if v := metadata.GetString(md, "bypass"); v != "" {
|
if v := mdutil.GetString(md, "bypass"); v != "" {
|
||||||
bypassCfg := &config.BypassConfig{
|
bypassCfg := &config.BypassConfig{
|
||||||
Name: fmt.Sprintf("bypass-%d", len(cfg.Bypasses)),
|
Name: fmt.Sprintf("%sbypass-%d", namePrefix, len(cfg.Bypasses)),
|
||||||
}
|
}
|
||||||
if v[0] == '~' {
|
if v[0] == '~' {
|
||||||
bypassCfg.Reverse = true
|
bypassCfg.Whitelist = true
|
||||||
v = v[1:]
|
v = v[1:]
|
||||||
}
|
}
|
||||||
for _, s := range strings.Split(v, ",") {
|
for _, s := range strings.Split(v, ",") {
|
||||||
@@ -108,11 +94,11 @@ func buildConfigFromCmd(services, nodes stringList) (*config.Config, error) {
|
|||||||
}
|
}
|
||||||
hopConfig.Bypass = bypassCfg.Name
|
hopConfig.Bypass = bypassCfg.Name
|
||||||
cfg.Bypasses = append(cfg.Bypasses, bypassCfg)
|
cfg.Bypasses = append(cfg.Bypasses, bypassCfg)
|
||||||
md.Del("bypass")
|
delete(mc, "bypass")
|
||||||
}
|
}
|
||||||
if v := metadata.GetString(md, "resolver"); v != "" {
|
if v := mdutil.GetString(md, "resolver"); v != "" {
|
||||||
resolverCfg := &config.ResolverConfig{
|
resolverCfg := &config.ResolverConfig{
|
||||||
Name: fmt.Sprintf("resolver-%d", len(cfg.Resolvers)),
|
Name: fmt.Sprintf("%sresolver-%d", namePrefix, len(cfg.Resolvers)),
|
||||||
}
|
}
|
||||||
for _, rs := range strings.Split(v, ",") {
|
for _, rs := range strings.Split(v, ",") {
|
||||||
if rs == "" {
|
if rs == "" {
|
||||||
@@ -127,11 +113,11 @@ func buildConfigFromCmd(services, nodes stringList) (*config.Config, error) {
|
|||||||
}
|
}
|
||||||
hopConfig.Resolver = resolverCfg.Name
|
hopConfig.Resolver = resolverCfg.Name
|
||||||
cfg.Resolvers = append(cfg.Resolvers, resolverCfg)
|
cfg.Resolvers = append(cfg.Resolvers, resolverCfg)
|
||||||
md.Del("resolver")
|
delete(mc, "resolver")
|
||||||
}
|
}
|
||||||
if v := metadata.GetString(md, "hosts"); v != "" {
|
if v := mdutil.GetString(md, "hosts"); v != "" {
|
||||||
hostsCfg := &config.HostsConfig{
|
hostsCfg := &config.HostsConfig{
|
||||||
Name: fmt.Sprintf("hosts-%d", len(cfg.Hosts)),
|
Name: fmt.Sprintf("%shosts-%d", namePrefix, len(cfg.Hosts)),
|
||||||
}
|
}
|
||||||
for _, s := range strings.Split(v, ",") {
|
for _, s := range strings.Split(v, ",") {
|
||||||
ss := strings.SplitN(s, ":", 2)
|
ss := strings.SplitN(s, ":", 2)
|
||||||
@@ -148,12 +134,18 @@ func buildConfigFromCmd(services, nodes stringList) (*config.Config, error) {
|
|||||||
}
|
}
|
||||||
hopConfig.Hosts = hostsCfg.Name
|
hopConfig.Hosts = hostsCfg.Name
|
||||||
cfg.Hosts = append(cfg.Hosts, hostsCfg)
|
cfg.Hosts = append(cfg.Hosts, hostsCfg)
|
||||||
md.Del("hosts")
|
delete(mc, "hosts")
|
||||||
}
|
}
|
||||||
|
|
||||||
if v := metadata.GetString(md, "interface"); v != "" {
|
if v := mdutil.GetString(md, "interface"); v != "" {
|
||||||
hopConfig.Interface = v
|
hopConfig.Interface = v
|
||||||
md.Del("interface")
|
delete(mc, "interface")
|
||||||
|
}
|
||||||
|
if v := mdutil.GetInt(md, "so_mark"); v > 0 {
|
||||||
|
hopConfig.SockOpts = &config.SockOptsConfig{
|
||||||
|
Mark: v,
|
||||||
|
}
|
||||||
|
delete(mc, "so_mark")
|
||||||
}
|
}
|
||||||
|
|
||||||
chain.Hops = append(chain.Hops, hopConfig)
|
chain.Hops = append(chain.Hops, hopConfig)
|
||||||
@@ -169,7 +161,7 @@ func buildConfigFromCmd(services, nodes stringList) (*config.Config, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
service.Name = fmt.Sprintf("service-%d", i)
|
service.Name = fmt.Sprintf("%sservice-%d", namePrefix, i)
|
||||||
if chain != nil {
|
if chain != nil {
|
||||||
if service.Listener.Type == "rtcp" || service.Listener.Type == "rudp" {
|
if service.Listener.Type == "rtcp" || service.Listener.Type == "rudp" {
|
||||||
service.Listener.Chain = chain.Name
|
service.Listener.Chain = chain.Name
|
||||||
@@ -179,17 +171,18 @@ func buildConfigFromCmd(services, nodes stringList) (*config.Config, error) {
|
|||||||
}
|
}
|
||||||
cfg.Services = append(cfg.Services, service)
|
cfg.Services = append(cfg.Services, service)
|
||||||
|
|
||||||
md := metadata.MapMetadata(service.Handler.Metadata)
|
mh := service.Handler.Metadata
|
||||||
if v := metadata.GetInt(md, "retries"); v > 0 {
|
md := mdx.NewMetadata(mh)
|
||||||
|
if v := mdutil.GetInt(md, "retries"); v > 0 {
|
||||||
service.Handler.Retries = v
|
service.Handler.Retries = v
|
||||||
md.Del("retries")
|
delete(mh, "retries")
|
||||||
}
|
}
|
||||||
if v := metadata.GetString(md, "admission"); v != "" {
|
if v := mdutil.GetString(md, "admission"); v != "" {
|
||||||
admCfg := &config.AdmissionConfig{
|
admCfg := &config.AdmissionConfig{
|
||||||
Name: fmt.Sprintf("admission-%d", len(cfg.Admissions)),
|
Name: fmt.Sprintf("%sadmission-%d", namePrefix, len(cfg.Admissions)),
|
||||||
}
|
}
|
||||||
if v[0] == '~' {
|
if v[0] == '~' {
|
||||||
admCfg.Reverse = true
|
admCfg.Whitelist = true
|
||||||
v = v[1:]
|
v = v[1:]
|
||||||
}
|
}
|
||||||
for _, s := range strings.Split(v, ",") {
|
for _, s := range strings.Split(v, ",") {
|
||||||
@@ -200,14 +193,14 @@ func buildConfigFromCmd(services, nodes stringList) (*config.Config, error) {
|
|||||||
}
|
}
|
||||||
service.Admission = admCfg.Name
|
service.Admission = admCfg.Name
|
||||||
cfg.Admissions = append(cfg.Admissions, admCfg)
|
cfg.Admissions = append(cfg.Admissions, admCfg)
|
||||||
md.Del("admission")
|
delete(mh, "admission")
|
||||||
}
|
}
|
||||||
if v := metadata.GetString(md, "bypass"); v != "" {
|
if v := mdutil.GetString(md, "bypass"); v != "" {
|
||||||
bypassCfg := &config.BypassConfig{
|
bypassCfg := &config.BypassConfig{
|
||||||
Name: fmt.Sprintf("bypass-%d", len(cfg.Bypasses)),
|
Name: fmt.Sprintf("%sbypass-%d", namePrefix, len(cfg.Bypasses)),
|
||||||
}
|
}
|
||||||
if v[0] == '~' {
|
if v[0] == '~' {
|
||||||
bypassCfg.Reverse = true
|
bypassCfg.Whitelist = true
|
||||||
v = v[1:]
|
v = v[1:]
|
||||||
}
|
}
|
||||||
for _, s := range strings.Split(v, ",") {
|
for _, s := range strings.Split(v, ",") {
|
||||||
@@ -218,11 +211,11 @@ func buildConfigFromCmd(services, nodes stringList) (*config.Config, error) {
|
|||||||
}
|
}
|
||||||
service.Bypass = bypassCfg.Name
|
service.Bypass = bypassCfg.Name
|
||||||
cfg.Bypasses = append(cfg.Bypasses, bypassCfg)
|
cfg.Bypasses = append(cfg.Bypasses, bypassCfg)
|
||||||
md.Del("bypass")
|
delete(mh, "bypass")
|
||||||
}
|
}
|
||||||
if v := metadata.GetString(md, "resolver"); v != "" {
|
if v := mdutil.GetString(md, "resolver"); v != "" {
|
||||||
resolverCfg := &config.ResolverConfig{
|
resolverCfg := &config.ResolverConfig{
|
||||||
Name: fmt.Sprintf("resolver-%d", len(cfg.Resolvers)),
|
Name: fmt.Sprintf("%sresolver-%d", namePrefix, len(cfg.Resolvers)),
|
||||||
}
|
}
|
||||||
for _, rs := range strings.Split(v, ",") {
|
for _, rs := range strings.Split(v, ",") {
|
||||||
if rs == "" {
|
if rs == "" {
|
||||||
@@ -231,17 +224,18 @@ func buildConfigFromCmd(services, nodes stringList) (*config.Config, error) {
|
|||||||
resolverCfg.Nameservers = append(
|
resolverCfg.Nameservers = append(
|
||||||
resolverCfg.Nameservers,
|
resolverCfg.Nameservers,
|
||||||
&config.NameserverConfig{
|
&config.NameserverConfig{
|
||||||
Addr: rs,
|
Addr: rs,
|
||||||
|
Prefer: mdutil.GetString(md, "prefer"),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
service.Resolver = resolverCfg.Name
|
service.Resolver = resolverCfg.Name
|
||||||
cfg.Resolvers = append(cfg.Resolvers, resolverCfg)
|
cfg.Resolvers = append(cfg.Resolvers, resolverCfg)
|
||||||
md.Del("resolver")
|
delete(mh, "resolver")
|
||||||
}
|
}
|
||||||
if v := metadata.GetString(md, "hosts"); v != "" {
|
if v := mdutil.GetString(md, "hosts"); v != "" {
|
||||||
hostsCfg := &config.HostsConfig{
|
hostsCfg := &config.HostsConfig{
|
||||||
Name: fmt.Sprintf("hosts-%d", len(cfg.Hosts)),
|
Name: fmt.Sprintf("%shosts-%d", namePrefix, len(cfg.Hosts)),
|
||||||
}
|
}
|
||||||
for _, s := range strings.Split(v, ",") {
|
for _, s := range strings.Split(v, ",") {
|
||||||
ss := strings.SplitN(s, ":", 2)
|
ss := strings.SplitN(s, ":", 2)
|
||||||
@@ -258,7 +252,51 @@ func buildConfigFromCmd(services, nodes stringList) (*config.Config, error) {
|
|||||||
}
|
}
|
||||||
service.Hosts = hostsCfg.Name
|
service.Hosts = hostsCfg.Name
|
||||||
cfg.Hosts = append(cfg.Hosts, hostsCfg)
|
cfg.Hosts = append(cfg.Hosts, hostsCfg)
|
||||||
md.Del("hosts")
|
delete(mh, "hosts")
|
||||||
|
}
|
||||||
|
|
||||||
|
in := mdutil.GetString(md, "limiter.in")
|
||||||
|
out := mdutil.GetString(md, "limiter.out")
|
||||||
|
cin := mdutil.GetString(md, "limiter.conn.in")
|
||||||
|
cout := mdutil.GetString(md, "limiter.conn.out")
|
||||||
|
if in != "" || cin != "" || out != "" || cout != "" {
|
||||||
|
limiter := &config.LimiterConfig{
|
||||||
|
Name: fmt.Sprintf("%slimiter-%d", namePrefix, len(cfg.Limiters)),
|
||||||
|
}
|
||||||
|
if in != "" || out != "" {
|
||||||
|
limiter.Limits = append(limiter.Limits,
|
||||||
|
fmt.Sprintf("%s %s %s", traffic.GlobalLimitKey, in, out))
|
||||||
|
}
|
||||||
|
if cin != "" || cout != "" {
|
||||||
|
limiter.Limits = append(limiter.Limits,
|
||||||
|
fmt.Sprintf("%s %s %s", traffic.ConnLimitKey, cin, cout))
|
||||||
|
}
|
||||||
|
service.Limiter = limiter.Name
|
||||||
|
cfg.Limiters = append(cfg.Limiters, limiter)
|
||||||
|
delete(mh, "limiter.in")
|
||||||
|
delete(mh, "limiter.out")
|
||||||
|
delete(mh, "limiter.conn.in")
|
||||||
|
delete(mh, "limiter.conn.out")
|
||||||
|
}
|
||||||
|
|
||||||
|
if climit := mdutil.GetInt(md, "climiter"); climit > 0 {
|
||||||
|
limiter := &config.LimiterConfig{
|
||||||
|
Name: fmt.Sprintf("%sclimiter-%d", namePrefix, len(cfg.CLimiters)),
|
||||||
|
Limits: []string{fmt.Sprintf("%s %d", conn.GlobalLimitKey, climit)},
|
||||||
|
}
|
||||||
|
service.CLimiter = limiter.Name
|
||||||
|
cfg.CLimiters = append(cfg.CLimiters, limiter)
|
||||||
|
delete(mh, "climiter")
|
||||||
|
}
|
||||||
|
|
||||||
|
if rlimit := mdutil.GetFloat(md, "rlimiter"); rlimit > 0 {
|
||||||
|
limiter := &config.LimiterConfig{
|
||||||
|
Name: fmt.Sprintf("%srlimiter-%d", namePrefix, len(cfg.RLimiters)),
|
||||||
|
Limits: []string{fmt.Sprintf("%s %s", conn.GlobalLimitKey, strconv.FormatFloat(rlimit, 'f', -1, 64))},
|
||||||
|
}
|
||||||
|
service.RLimiter = limiter.Name
|
||||||
|
cfg.RLimiters = append(cfg.RLimiters, limiter)
|
||||||
|
delete(mh, "rlimiter")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -266,6 +304,11 @@ func buildConfigFromCmd(services, nodes stringList) (*config.Config, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func buildServiceConfig(url *url.URL) (*config.ServiceConfig, error) {
|
func buildServiceConfig(url *url.URL) (*config.ServiceConfig, error) {
|
||||||
|
namePrefix := ""
|
||||||
|
if v := os.Getenv("_GOST_ID"); v != "" {
|
||||||
|
namePrefix = fmt.Sprintf("go-%s@", v)
|
||||||
|
}
|
||||||
|
|
||||||
var handler, listener string
|
var handler, listener string
|
||||||
schemes := strings.Split(url.Scheme, "+")
|
schemes := strings.Split(url.Scheme, "+")
|
||||||
if len(schemes) == 1 {
|
if len(schemes) == 1 {
|
||||||
@@ -294,12 +337,20 @@ func buildServiceConfig(url *url.URL) (*config.ServiceConfig, error) {
|
|||||||
// forward mode
|
// forward mode
|
||||||
if remotes := strings.Trim(url.EscapedPath(), "/"); remotes != "" {
|
if remotes := strings.Trim(url.EscapedPath(), "/"); remotes != "" {
|
||||||
svc.Forwarder = &config.ForwarderConfig{
|
svc.Forwarder = &config.ForwarderConfig{
|
||||||
Targets: strings.Split(remotes, ","),
|
// Targets: strings.Split(remotes, ","),
|
||||||
|
}
|
||||||
|
for i, addr := range strings.Split(remotes, ",") {
|
||||||
|
svc.Forwarder.Nodes = append(svc.Forwarder.Nodes,
|
||||||
|
&config.ForwardNodeConfig{
|
||||||
|
Name: fmt.Sprintf("%starget-%d", namePrefix, i),
|
||||||
|
Addr: addr,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
if handler != "relay" {
|
if handler != "relay" {
|
||||||
if listener == "tcp" || listener == "udp" ||
|
if listener == "tcp" || listener == "udp" ||
|
||||||
listener == "rtcp" || listener == "rudp" ||
|
listener == "rtcp" || listener == "rudp" ||
|
||||||
listener == "tun" || listener == "tap" {
|
listener == "tun" || listener == "tap" ||
|
||||||
|
listener == "dns" {
|
||||||
handler = listener
|
handler = listener
|
||||||
} else {
|
} else {
|
||||||
handler = "forward"
|
handler = "forward"
|
||||||
@@ -315,62 +366,72 @@ func buildServiceConfig(url *url.URL) (*config.ServiceConfig, error) {
|
|||||||
auth.Password, _ = url.User.Password()
|
auth.Password, _ = url.User.Password()
|
||||||
}
|
}
|
||||||
|
|
||||||
md := metadata.MapMetadata{}
|
m := map[string]any{}
|
||||||
for k, v := range url.Query() {
|
for k, v := range url.Query() {
|
||||||
if len(v) > 0 {
|
if len(v) > 0 {
|
||||||
md[k] = v[0]
|
m[k] = v[0]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
md := mdx.NewMetadata(m)
|
||||||
|
|
||||||
if sa := metadata.GetString(md, "auth"); sa != "" {
|
if sa := mdutil.GetString(md, "auth"); sa != "" {
|
||||||
au, err := parseAuthFromCmd(sa)
|
au, err := parseAuthFromCmd(sa)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
auth = au
|
auth = au
|
||||||
}
|
}
|
||||||
md.Del("auth")
|
delete(m, "auth")
|
||||||
|
|
||||||
tlsConfig := &config.TLSConfig{
|
tlsConfig := &config.TLSConfig{
|
||||||
CertFile: metadata.GetString(md, "certFile"),
|
CertFile: mdutil.GetString(md, "certFile"),
|
||||||
KeyFile: metadata.GetString(md, "keyFile"),
|
KeyFile: mdutil.GetString(md, "keyFile"),
|
||||||
CAFile: metadata.GetString(md, "caFile"),
|
CAFile: mdutil.GetString(md, "caFile"),
|
||||||
}
|
}
|
||||||
md.Del("certFile")
|
if tlsConfig.CertFile == "" {
|
||||||
md.Del("keyFile")
|
tlsConfig.CertFile = mdutil.GetString(md, "cert")
|
||||||
md.Del("caFile")
|
}
|
||||||
|
if tlsConfig.KeyFile == "" {
|
||||||
|
tlsConfig.KeyFile = mdutil.GetString(md, "key")
|
||||||
|
}
|
||||||
|
if tlsConfig.CAFile == "" {
|
||||||
|
tlsConfig.CAFile = mdutil.GetString(md, "ca")
|
||||||
|
}
|
||||||
|
|
||||||
|
delete(m, "certFile")
|
||||||
|
delete(m, "cert")
|
||||||
|
delete(m, "keyFile")
|
||||||
|
delete(m, "key")
|
||||||
|
delete(m, "caFile")
|
||||||
|
delete(m, "ca")
|
||||||
|
|
||||||
if tlsConfig.CertFile == "" {
|
if tlsConfig.CertFile == "" {
|
||||||
tlsConfig = nil
|
tlsConfig = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if v := metadata.GetString(md, "dns"); v != "" {
|
if v := mdutil.GetString(md, "dns"); v != "" {
|
||||||
md.Set("dns", strings.Split(v, ","))
|
md.Set("dns", strings.Split(v, ","))
|
||||||
}
|
}
|
||||||
if v := metadata.GetString(md, "interface"); v != "" {
|
|
||||||
svc.Interface = v
|
|
||||||
md.Del("interface")
|
|
||||||
}
|
|
||||||
|
|
||||||
if svc.Forwarder != nil {
|
if svc.Forwarder != nil {
|
||||||
svc.Forwarder.Selector = parseSelector(md)
|
svc.Forwarder.Selector = parseSelector(m)
|
||||||
}
|
}
|
||||||
|
|
||||||
svc.Handler = &config.HandlerConfig{
|
svc.Handler = &config.HandlerConfig{
|
||||||
Type: handler,
|
Type: handler,
|
||||||
Auth: auth,
|
Auth: auth,
|
||||||
Metadata: md,
|
Metadata: m,
|
||||||
}
|
}
|
||||||
svc.Listener = &config.ListenerConfig{
|
svc.Listener = &config.ListenerConfig{
|
||||||
Type: listener,
|
Type: listener,
|
||||||
TLS: tlsConfig,
|
TLS: tlsConfig,
|
||||||
Metadata: md,
|
Metadata: m,
|
||||||
}
|
}
|
||||||
|
|
||||||
if svc.Handler.Type == "sshd" {
|
svc.Metadata = m
|
||||||
|
|
||||||
|
if svc.Listener.Type == "ssh" || svc.Listener.Type == "sshd" {
|
||||||
svc.Handler.Auth = nil
|
svc.Handler.Auth = nil
|
||||||
}
|
|
||||||
if svc.Listener.Type == "sshd" {
|
|
||||||
svc.Listener.Auth = auth
|
svc.Listener.Auth = auth
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -411,37 +472,51 @@ func buildNodeConfig(url *url.URL) (*config.NodeConfig, error) {
|
|||||||
auth.Password, _ = url.User.Password()
|
auth.Password, _ = url.User.Password()
|
||||||
}
|
}
|
||||||
|
|
||||||
md := metadata.MapMetadata{}
|
m := map[string]any{}
|
||||||
for k, v := range url.Query() {
|
for k, v := range url.Query() {
|
||||||
if len(v) > 0 {
|
if len(v) > 0 {
|
||||||
md[k] = v[0]
|
m[k] = v[0]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
md := mdx.NewMetadata(m)
|
||||||
|
|
||||||
if sauth := metadata.GetString(md, "auth"); sauth != "" && auth == nil {
|
if sauth := mdutil.GetString(md, "auth"); sauth != "" && auth == nil {
|
||||||
au, err := parseAuthFromCmd(sauth)
|
au, err := parseAuthFromCmd(sauth)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
auth = au
|
auth = au
|
||||||
}
|
}
|
||||||
md.Del("auth")
|
delete(m, "auth")
|
||||||
|
|
||||||
tlsConfig := &config.TLSConfig{
|
tlsConfig := &config.TLSConfig{
|
||||||
CertFile: metadata.GetString(md, "certFile"),
|
CertFile: mdutil.GetString(md, "certFile"),
|
||||||
KeyFile: metadata.GetString(md, "keyFile"),
|
KeyFile: mdutil.GetString(md, "keyFile"),
|
||||||
CAFile: metadata.GetString(md, "caFile"),
|
CAFile: mdutil.GetString(md, "caFile"),
|
||||||
Secure: metadata.GetBool(md, "secure"),
|
Secure: mdutil.GetBool(md, "secure"),
|
||||||
ServerName: metadata.GetString(md, "serverName"),
|
ServerName: mdutil.GetString(md, "serverName"),
|
||||||
}
|
}
|
||||||
if tlsConfig.ServerName == "" {
|
if tlsConfig.ServerName == "" {
|
||||||
tlsConfig.ServerName = url.Hostname()
|
tlsConfig.ServerName = url.Hostname()
|
||||||
}
|
}
|
||||||
md.Del("certFile")
|
if tlsConfig.CertFile == "" {
|
||||||
md.Del("keyFile")
|
tlsConfig.CertFile = mdutil.GetString(md, "cert")
|
||||||
md.Del("caFile")
|
}
|
||||||
md.Del("secure")
|
if tlsConfig.KeyFile == "" {
|
||||||
md.Del("serverName")
|
tlsConfig.KeyFile = mdutil.GetString(md, "key")
|
||||||
|
}
|
||||||
|
if tlsConfig.CAFile == "" {
|
||||||
|
tlsConfig.CAFile = mdutil.GetString(md, "ca")
|
||||||
|
}
|
||||||
|
|
||||||
|
delete(m, "certFile")
|
||||||
|
delete(m, "cert")
|
||||||
|
delete(m, "keyFile")
|
||||||
|
delete(m, "key")
|
||||||
|
delete(m, "caFile")
|
||||||
|
delete(m, "ca")
|
||||||
|
delete(m, "secure")
|
||||||
|
delete(m, "serverName")
|
||||||
|
|
||||||
if !tlsConfig.Secure && tlsConfig.CertFile == "" && tlsConfig.CAFile == "" {
|
if !tlsConfig.Secure && tlsConfig.CertFile == "" && tlsConfig.CAFile == "" {
|
||||||
tlsConfig = nil
|
tlsConfig = nil
|
||||||
@@ -450,18 +525,16 @@ func buildNodeConfig(url *url.URL) (*config.NodeConfig, error) {
|
|||||||
node.Connector = &config.ConnectorConfig{
|
node.Connector = &config.ConnectorConfig{
|
||||||
Type: connector,
|
Type: connector,
|
||||||
Auth: auth,
|
Auth: auth,
|
||||||
Metadata: md,
|
Metadata: m,
|
||||||
}
|
}
|
||||||
node.Dialer = &config.DialerConfig{
|
node.Dialer = &config.DialerConfig{
|
||||||
Type: dialer,
|
Type: dialer,
|
||||||
TLS: tlsConfig,
|
TLS: tlsConfig,
|
||||||
Metadata: md,
|
Metadata: m,
|
||||||
}
|
}
|
||||||
|
|
||||||
if node.Connector.Type == "sshd" {
|
if node.Dialer.Type == "ssh" || node.Dialer.Type == "sshd" {
|
||||||
node.Connector.Auth = nil
|
node.Connector.Auth = nil
|
||||||
}
|
|
||||||
if node.Dialer.Type == "sshd" {
|
|
||||||
node.Dialer.Auth = auth
|
node.Dialer.Auth = auth
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -508,10 +581,17 @@ func parseAuthFromCmd(sa string) (*config.AuthConfig, error) {
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseSelector(md metadata.MapMetadata) *config.SelectorConfig {
|
func parseSelector(m map[string]any) *config.SelectorConfig {
|
||||||
strategy := metadata.GetString(md, "strategy")
|
md := mdx.NewMetadata(m)
|
||||||
maxFails := metadata.GetInt(md, "maxFails")
|
strategy := mdutil.GetString(md, "strategy")
|
||||||
failTimeout := metadata.GetDuration(md, "failTimeout")
|
maxFails := mdutil.GetInt(md, "maxFails")
|
||||||
|
if maxFails == 0 {
|
||||||
|
maxFails = mdutil.GetInt(md, "max_fails")
|
||||||
|
}
|
||||||
|
failTimeout := mdutil.GetDuration(md, "failTimeout")
|
||||||
|
if failTimeout == 0 {
|
||||||
|
failTimeout = mdutil.GetDuration(md, "fail_timeout")
|
||||||
|
}
|
||||||
if strategy == "" && maxFails <= 0 && failTimeout <= 0 {
|
if strategy == "" && maxFails <= 0 && failTimeout <= 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -522,12 +602,14 @@ func parseSelector(md metadata.MapMetadata) *config.SelectorConfig {
|
|||||||
maxFails = 1
|
maxFails = 1
|
||||||
}
|
}
|
||||||
if failTimeout <= 0 {
|
if failTimeout <= 0 {
|
||||||
failTimeout = time.Second
|
failTimeout = 30 * time.Second
|
||||||
}
|
}
|
||||||
|
|
||||||
md.Del("strategy")
|
delete(m, "strategy")
|
||||||
md.Del("maxFails")
|
delete(m, "maxFails")
|
||||||
md.Del("failTimeout")
|
delete(m, "max_fails")
|
||||||
|
delete(m, "failTimeout")
|
||||||
|
delete(m, "fail_timeout")
|
||||||
|
|
||||||
return &config.SelectorConfig{
|
return &config.SelectorConfig{
|
||||||
Strategy: strategy,
|
Strategy: strategy,
|
||||||
|
|||||||
+72
-17
@@ -3,14 +3,17 @@ package main
|
|||||||
import (
|
import (
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
"github.com/go-gost/gost/pkg/api"
|
"github.com/go-gost/core/logger"
|
||||||
"github.com/go-gost/gost/pkg/config"
|
"github.com/go-gost/core/service"
|
||||||
"github.com/go-gost/gost/pkg/config/parsing"
|
"github.com/go-gost/x/api"
|
||||||
"github.com/go-gost/gost/pkg/logger"
|
"github.com/go-gost/x/config"
|
||||||
metrics "github.com/go-gost/gost/pkg/metrics/service"
|
"github.com/go-gost/x/config/parsing"
|
||||||
"github.com/go-gost/gost/pkg/registry"
|
xlogger "github.com/go-gost/x/logger"
|
||||||
"github.com/go-gost/gost/pkg/service"
|
metrics "github.com/go-gost/x/metrics/service"
|
||||||
|
"github.com/go-gost/x/registry"
|
||||||
|
"gopkg.in/natefinch/lumberjack.v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
func buildService(cfg *config.Config) (services []service.Service) {
|
func buildService(cfg *config.Config) (services []service.Service) {
|
||||||
@@ -62,6 +65,46 @@ func buildService(cfg *config.Config) (services []service.Service) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for _, recorderCfg := range cfg.Recorders {
|
||||||
|
if h := parsing.ParseRecorder(recorderCfg); h != nil {
|
||||||
|
if err := registry.RecorderRegistry().Register(recorderCfg.Name, h); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, limiterCfg := range cfg.Limiters {
|
||||||
|
if h := parsing.ParseTrafficLimiter(limiterCfg); h != nil {
|
||||||
|
if err := registry.TrafficLimiterRegistry().Register(limiterCfg.Name, h); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, limiterCfg := range cfg.CLimiters {
|
||||||
|
if h := parsing.ParseConnLimiter(limiterCfg); h != nil {
|
||||||
|
if err := registry.ConnLimiterRegistry().Register(limiterCfg.Name, h); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, limiterCfg := range cfg.RLimiters {
|
||||||
|
if h := parsing.ParseRateLimiter(limiterCfg); h != nil {
|
||||||
|
if err := registry.RateLimiterRegistry().Register(limiterCfg.Name, h); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, hopCfg := range cfg.Hops {
|
||||||
|
hop, err := parsing.ParseHop(hopCfg)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
if hop != nil {
|
||||||
|
if err := registry.HopRegistry().Register(hopCfg.Name, hop); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
for _, chainCfg := range cfg.Chains {
|
for _, chainCfg := range cfg.Chains {
|
||||||
c, err := parsing.ParseChain(chainCfg)
|
c, err := parsing.ParseChain(chainCfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -94,30 +137,42 @@ func logFromConfig(cfg *config.LogConfig) logger.Logger {
|
|||||||
if cfg == nil {
|
if cfg == nil {
|
||||||
cfg = &config.LogConfig{}
|
cfg = &config.LogConfig{}
|
||||||
}
|
}
|
||||||
opts := []logger.LoggerOption{
|
opts := []xlogger.LoggerOption{
|
||||||
logger.FormatLoggerOption(logger.LogFormat(cfg.Format)),
|
xlogger.FormatLoggerOption(logger.LogFormat(cfg.Format)),
|
||||||
logger.LevelLoggerOption(logger.LogLevel(cfg.Level)),
|
xlogger.LevelLoggerOption(logger.LogLevel(cfg.Level)),
|
||||||
}
|
}
|
||||||
|
|
||||||
var out io.Writer = os.Stderr
|
var out io.Writer = os.Stderr
|
||||||
switch cfg.Output {
|
switch cfg.Output {
|
||||||
case "none", "null":
|
case "none", "null":
|
||||||
return logger.Nop()
|
return xlogger.Nop()
|
||||||
case "stdout":
|
case "stdout":
|
||||||
out = os.Stdout
|
out = os.Stdout
|
||||||
case "stderr", "":
|
case "stderr", "":
|
||||||
out = os.Stderr
|
out = os.Stderr
|
||||||
default:
|
default:
|
||||||
f, err := os.OpenFile(cfg.Output, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
|
if cfg.Rotation != nil {
|
||||||
if err != nil {
|
out = &lumberjack.Logger{
|
||||||
log.Warnf("log", err)
|
Filename: cfg.Output,
|
||||||
|
MaxSize: cfg.Rotation.MaxSize,
|
||||||
|
MaxAge: cfg.Rotation.MaxAge,
|
||||||
|
MaxBackups: cfg.Rotation.MaxBackups,
|
||||||
|
LocalTime: cfg.Rotation.LocalTime,
|
||||||
|
Compress: cfg.Rotation.Compress,
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
out = f
|
os.MkdirAll(filepath.Dir(cfg.Output), 0755)
|
||||||
|
f, err := os.OpenFile(cfg.Output, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
|
||||||
|
if err != nil {
|
||||||
|
log.Warn(err)
|
||||||
|
} else {
|
||||||
|
out = f
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
opts = append(opts, logger.OutputLoggerOption(out))
|
opts = append(opts, xlogger.OutputLoggerOption(out))
|
||||||
|
|
||||||
return logger.NewLogger(opts...)
|
return xlogger.NewLogger(opts...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildAPIService(cfg *config.APIConfig) (service.Service, error) {
|
func buildAPIService(cfg *config.APIConfig) (service.Service, error) {
|
||||||
|
|||||||
+188
-43
@@ -1,20 +1,29 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
_ "net/http/pprof"
|
_ "net/http/pprof"
|
||||||
"os"
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"os/signal"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
"syscall"
|
||||||
|
|
||||||
"github.com/go-gost/gost/pkg/config"
|
"github.com/go-gost/core/logger"
|
||||||
"github.com/go-gost/gost/pkg/logger"
|
"github.com/go-gost/x/config"
|
||||||
metrics "github.com/go-gost/gost/pkg/metrics/service"
|
"github.com/go-gost/x/config/parsing"
|
||||||
|
xlogger "github.com/go-gost/x/logger"
|
||||||
|
xmetrics "github.com/go-gost/x/metrics"
|
||||||
|
"github.com/go-gost/x/registry"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
log = logger.Default()
|
log logger.Logger
|
||||||
|
|
||||||
cfgFile string
|
cfgFile string
|
||||||
outputFormat string
|
outputFormat string
|
||||||
@@ -25,12 +34,52 @@ var (
|
|||||||
metricsAddr string
|
metricsAddr string
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
args := strings.Join(os.Args[1:], " ")
|
||||||
|
|
||||||
|
if strings.Contains(args, " -- ") {
|
||||||
|
var (
|
||||||
|
wg sync.WaitGroup
|
||||||
|
ret int
|
||||||
|
)
|
||||||
|
|
||||||
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
for wid, wargs := range strings.Split(" "+args+" ", " -- ") {
|
||||||
|
wg.Add(1)
|
||||||
|
go func(wid int, wargs string) {
|
||||||
|
defer wg.Done()
|
||||||
|
defer cancel()
|
||||||
|
worker(wid, strings.Split(wargs, " "), &ctx, &ret)
|
||||||
|
}(wid, strings.TrimSpace(wargs))
|
||||||
|
}
|
||||||
|
|
||||||
|
wg.Wait()
|
||||||
|
|
||||||
|
os.Exit(ret)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func worker(id int, args []string, ctx *context.Context, ret *int) {
|
||||||
|
cmd := exec.CommandContext(*ctx, os.Args[0], args...)
|
||||||
|
|
||||||
|
cmd.Stdout = os.Stdout
|
||||||
|
cmd.Stderr = os.Stderr
|
||||||
|
cmd.Env = append(os.Environ(), fmt.Sprintf("_GOST_ID=%d", id))
|
||||||
|
|
||||||
|
cmd.Run()
|
||||||
|
if cmd.ProcessState.Exited() {
|
||||||
|
*ret = cmd.ProcessState.ExitCode()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
var printVersion bool
|
var printVersion bool
|
||||||
|
|
||||||
flag.Var(&services, "L", "service list")
|
flag.Var(&services, "L", "service list")
|
||||||
flag.Var(&nodes, "F", "chain node list")
|
flag.Var(&nodes, "F", "chain node list")
|
||||||
flag.StringVar(&cfgFile, "C", "", "configure file")
|
flag.StringVar(&cfgFile, "C", "", "configuration file")
|
||||||
flag.BoolVar(&printVersion, "V", false, "print version")
|
flag.BoolVar(&printVersion, "V", false, "print version")
|
||||||
flag.StringVar(&outputFormat, "O", "", "output format, one of yaml|json format")
|
flag.StringVar(&outputFormat, "O", "", "output format, one of yaml|json format")
|
||||||
flag.BoolVar(&debug, "D", false, "debug mode")
|
flag.BoolVar(&debug, "D", false, "debug mode")
|
||||||
@@ -43,40 +92,70 @@ func init() {
|
|||||||
version, runtime.Version(), runtime.GOOS, runtime.GOARCH)
|
version, runtime.Version(), runtime.GOOS, runtime.GOARCH)
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log = xlogger.NewLogger()
|
||||||
|
logger.SetDefault(log)
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
cfg := &config.Config{}
|
cfg := &config.Config{}
|
||||||
var err error
|
if cfgFile != "" {
|
||||||
if len(services) > 0 || apiAddr != "" {
|
if err := cfg.ReadFile(cfgFile); err != nil {
|
||||||
cfg, err = buildConfigFromCmd(services, nodes)
|
log.Fatal(err)
|
||||||
if debug && cfg != nil {
|
|
||||||
if cfg.Log == nil {
|
|
||||||
cfg.Log = &config.LogConfig{}
|
|
||||||
}
|
|
||||||
cfg.Log.Level = string(logger.DebugLevel)
|
|
||||||
}
|
|
||||||
if apiAddr != "" {
|
|
||||||
cfg.API = &config.APIConfig{
|
|
||||||
Addr: apiAddr,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if metricsAddr != "" {
|
|
||||||
cfg.Metrics = &config.MetricsConfig{
|
|
||||||
Addr: metricsAddr,
|
|
||||||
Path: metrics.DefaultPath,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if cfgFile != "" {
|
|
||||||
err = cfg.ReadFile(cfgFile)
|
|
||||||
} else {
|
|
||||||
err = cfg.Load()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cmdCfg, err := buildConfigFromCmd(services, nodes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
cfg = mergeConfig(cfg, cmdCfg)
|
||||||
|
|
||||||
|
if len(cfg.Services) == 0 && apiAddr == "" {
|
||||||
|
if err := cfg.Load(); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if v := os.Getenv("GOST_PROFILING"); v != "" {
|
||||||
|
cfg.Profiling = &config.ProfilingConfig{
|
||||||
|
Addr: v,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if v := os.Getenv("GOST_METRICS"); v != "" {
|
||||||
|
cfg.Metrics = &config.MetricsConfig{
|
||||||
|
Addr: v,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if v := os.Getenv("GOST_LOGGER_LEVEL"); v != "" {
|
||||||
|
cfg.Log = &config.LogConfig{
|
||||||
|
Level: v,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if v := os.Getenv("GOST_API"); v != "" {
|
||||||
|
cfg.API = &config.APIConfig{
|
||||||
|
Addr: v,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if debug {
|
||||||
|
if cfg.Log == nil {
|
||||||
|
cfg.Log = &config.LogConfig{}
|
||||||
|
}
|
||||||
|
cfg.Log.Level = string(logger.DebugLevel)
|
||||||
|
}
|
||||||
|
if apiAddr != "" {
|
||||||
|
cfg.API = &config.APIConfig{
|
||||||
|
Addr: apiAddr,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if metricsAddr != "" {
|
||||||
|
cfg.Metrics = &config.MetricsConfig{
|
||||||
|
Addr: metricsAddr,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
log = logFromConfig(cfg.Log)
|
log = logFromConfig(cfg.Log)
|
||||||
|
|
||||||
@@ -89,7 +168,7 @@ func main() {
|
|||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
if cfg.Profiling != nil && cfg.Profiling.Enable {
|
if cfg.Profiling != nil {
|
||||||
go func() {
|
go func() {
|
||||||
addr := cfg.Profiling.Addr
|
addr := cfg.Profiling.Addr
|
||||||
if addr == "" {
|
if addr == "" {
|
||||||
@@ -114,26 +193,92 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if cfg.Metrics != nil {
|
if cfg.Metrics != nil {
|
||||||
s, err := buildMetricsService(cfg.Metrics)
|
xmetrics.Init(xmetrics.NewMetrics())
|
||||||
if err != nil {
|
if cfg.Metrics.Addr != "" {
|
||||||
log.Fatal(err)
|
s, err := buildMetricsService(cfg.Metrics)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
go func() {
|
||||||
|
defer s.Close()
|
||||||
|
log.Info("metrics service on ", s.Addr())
|
||||||
|
log.Fatal(s.Serve())
|
||||||
|
}()
|
||||||
}
|
}
|
||||||
defer s.Close()
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
log.Info("metrics service on ", s.Addr())
|
|
||||||
log.Fatal(s.Serve())
|
|
||||||
}()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
buildDefaultTLSConfig(cfg.TLS)
|
parsing.BuildDefaultTLSConfig(cfg.TLS)
|
||||||
|
|
||||||
services := buildService(cfg)
|
services := buildService(cfg)
|
||||||
for _, svc := range services {
|
for _, svc := range services {
|
||||||
go svc.Serve()
|
svc := svc
|
||||||
|
go func() {
|
||||||
|
svc.Serve()
|
||||||
|
// svc.Close()
|
||||||
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
config.SetGlobal(cfg)
|
config.SetGlobal(cfg)
|
||||||
|
|
||||||
select {}
|
sigs := make(chan os.Signal, 1)
|
||||||
|
signal.Notify(sigs, os.Interrupt, syscall.SIGTERM, syscall.SIGINT, syscall.SIGHUP)
|
||||||
|
|
||||||
|
for sig := range sigs {
|
||||||
|
switch sig {
|
||||||
|
case syscall.SIGHUP:
|
||||||
|
return
|
||||||
|
default:
|
||||||
|
for name, srv := range registry.ServiceRegistry().GetAll() {
|
||||||
|
srv.Close()
|
||||||
|
log.Debugf("service %s shutdown", name)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func mergeConfig(cfg1, cfg2 *config.Config) *config.Config {
|
||||||
|
if cfg1 == nil {
|
||||||
|
return cfg2
|
||||||
|
}
|
||||||
|
if cfg2 == nil {
|
||||||
|
return cfg1
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg := &config.Config{
|
||||||
|
Services: append(cfg1.Services, cfg2.Services...),
|
||||||
|
Chains: append(cfg1.Chains, cfg2.Chains...),
|
||||||
|
Hops: append(cfg1.Hops, cfg2.Hops...),
|
||||||
|
Authers: append(cfg1.Authers, cfg2.Authers...),
|
||||||
|
Admissions: append(cfg1.Admissions, cfg2.Admissions...),
|
||||||
|
Bypasses: append(cfg1.Bypasses, cfg2.Bypasses...),
|
||||||
|
Resolvers: append(cfg1.Resolvers, cfg2.Resolvers...),
|
||||||
|
Hosts: append(cfg1.Hosts, cfg2.Hosts...),
|
||||||
|
Recorders: append(cfg1.Recorders, cfg2.Recorders...),
|
||||||
|
Limiters: append(cfg1.Limiters, cfg2.Limiters...),
|
||||||
|
CLimiters: append(cfg1.CLimiters, cfg2.CLimiters...),
|
||||||
|
RLimiters: append(cfg1.RLimiters, cfg2.RLimiters...),
|
||||||
|
TLS: cfg1.TLS,
|
||||||
|
Log: cfg1.Log,
|
||||||
|
API: cfg1.API,
|
||||||
|
Metrics: cfg1.Metrics,
|
||||||
|
Profiling: cfg1.Profiling,
|
||||||
|
}
|
||||||
|
if cfg2.TLS != nil {
|
||||||
|
cfg.TLS = cfg2.TLS
|
||||||
|
}
|
||||||
|
if cfg2.Log != nil {
|
||||||
|
cfg.Log = cfg2.Log
|
||||||
|
}
|
||||||
|
if cfg2.API != nil {
|
||||||
|
cfg.API = cfg2.API
|
||||||
|
}
|
||||||
|
if cfg2.Metrics != nil {
|
||||||
|
cfg.Metrics = cfg2.Metrics
|
||||||
|
}
|
||||||
|
if cfg2.Profiling != nil {
|
||||||
|
cfg.Profiling = cfg2.Profiling
|
||||||
|
}
|
||||||
|
|
||||||
|
return cfg
|
||||||
}
|
}
|
||||||
|
|||||||
+78
-70
@@ -2,80 +2,88 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
// Register connectors
|
// Register connectors
|
||||||
_ "github.com/go-gost/gost/pkg/connector/forward"
|
_ "github.com/go-gost/x/connector/direct"
|
||||||
_ "github.com/go-gost/gost/pkg/connector/http"
|
_ "github.com/go-gost/x/connector/forward"
|
||||||
_ "github.com/go-gost/gost/pkg/connector/http2"
|
_ "github.com/go-gost/x/connector/http"
|
||||||
_ "github.com/go-gost/gost/pkg/connector/relay"
|
_ "github.com/go-gost/x/connector/http2"
|
||||||
_ "github.com/go-gost/gost/pkg/connector/sni"
|
_ "github.com/go-gost/x/connector/relay"
|
||||||
_ "github.com/go-gost/gost/pkg/connector/socks/v4"
|
_ "github.com/go-gost/x/connector/sni"
|
||||||
_ "github.com/go-gost/gost/pkg/connector/socks/v5"
|
_ "github.com/go-gost/x/connector/socks/v4"
|
||||||
_ "github.com/go-gost/gost/pkg/connector/ss"
|
_ "github.com/go-gost/x/connector/socks/v5"
|
||||||
_ "github.com/go-gost/gost/pkg/connector/ss/udp"
|
_ "github.com/go-gost/x/connector/ss"
|
||||||
_ "github.com/go-gost/gost/pkg/connector/sshd"
|
_ "github.com/go-gost/x/connector/ss/udp"
|
||||||
|
_ "github.com/go-gost/x/connector/sshd"
|
||||||
|
|
||||||
// Register dialers
|
// Register dialers
|
||||||
_ "github.com/go-gost/gost/pkg/dialer/ftcp"
|
_ "github.com/go-gost/x/dialer/direct"
|
||||||
_ "github.com/go-gost/gost/pkg/dialer/grpc"
|
_ "github.com/go-gost/x/dialer/dtls"
|
||||||
_ "github.com/go-gost/gost/pkg/dialer/http2"
|
_ "github.com/go-gost/x/dialer/ftcp"
|
||||||
_ "github.com/go-gost/gost/pkg/dialer/http2/h2"
|
_ "github.com/go-gost/x/dialer/grpc"
|
||||||
_ "github.com/go-gost/gost/pkg/dialer/http3"
|
_ "github.com/go-gost/x/dialer/http2"
|
||||||
_ "github.com/go-gost/gost/pkg/dialer/icmp"
|
_ "github.com/go-gost/x/dialer/http2/h2"
|
||||||
_ "github.com/go-gost/gost/pkg/dialer/kcp"
|
_ "github.com/go-gost/x/dialer/http3"
|
||||||
_ "github.com/go-gost/gost/pkg/dialer/obfs/http"
|
_ "github.com/go-gost/x/dialer/icmp"
|
||||||
_ "github.com/go-gost/gost/pkg/dialer/obfs/tls"
|
_ "github.com/go-gost/x/dialer/kcp"
|
||||||
_ "github.com/go-gost/gost/pkg/dialer/pht"
|
_ "github.com/go-gost/x/dialer/mtls"
|
||||||
_ "github.com/go-gost/gost/pkg/dialer/quic"
|
_ "github.com/go-gost/x/dialer/mws"
|
||||||
_ "github.com/go-gost/gost/pkg/dialer/ssh"
|
_ "github.com/go-gost/x/dialer/obfs/http"
|
||||||
_ "github.com/go-gost/gost/pkg/dialer/sshd"
|
_ "github.com/go-gost/x/dialer/obfs/tls"
|
||||||
_ "github.com/go-gost/gost/pkg/dialer/tcp"
|
_ "github.com/go-gost/x/dialer/pht"
|
||||||
_ "github.com/go-gost/gost/pkg/dialer/tls"
|
_ "github.com/go-gost/x/dialer/quic"
|
||||||
_ "github.com/go-gost/gost/pkg/dialer/tls/mux"
|
_ "github.com/go-gost/x/dialer/ssh"
|
||||||
_ "github.com/go-gost/gost/pkg/dialer/udp"
|
_ "github.com/go-gost/x/dialer/sshd"
|
||||||
_ "github.com/go-gost/gost/pkg/dialer/ws"
|
_ "github.com/go-gost/x/dialer/tcp"
|
||||||
_ "github.com/go-gost/gost/pkg/dialer/ws/mux"
|
_ "github.com/go-gost/x/dialer/tls"
|
||||||
|
_ "github.com/go-gost/x/dialer/udp"
|
||||||
|
_ "github.com/go-gost/x/dialer/ws"
|
||||||
|
|
||||||
// Register handlers
|
// Register handlers
|
||||||
_ "github.com/go-gost/gost/pkg/handler/auto"
|
_ "github.com/go-gost/x/handler/auto"
|
||||||
_ "github.com/go-gost/gost/pkg/handler/dns"
|
_ "github.com/go-gost/x/handler/dns"
|
||||||
_ "github.com/go-gost/gost/pkg/handler/forward/local"
|
_ "github.com/go-gost/x/handler/forward/local"
|
||||||
_ "github.com/go-gost/gost/pkg/handler/forward/remote"
|
_ "github.com/go-gost/x/handler/forward/remote"
|
||||||
_ "github.com/go-gost/gost/pkg/handler/http"
|
_ "github.com/go-gost/x/handler/http"
|
||||||
_ "github.com/go-gost/gost/pkg/handler/http2"
|
_ "github.com/go-gost/x/handler/http2"
|
||||||
_ "github.com/go-gost/gost/pkg/handler/redirect"
|
_ "github.com/go-gost/x/handler/http3"
|
||||||
_ "github.com/go-gost/gost/pkg/handler/relay"
|
_ "github.com/go-gost/x/handler/redirect/tcp"
|
||||||
_ "github.com/go-gost/gost/pkg/handler/sni"
|
_ "github.com/go-gost/x/handler/redirect/udp"
|
||||||
_ "github.com/go-gost/gost/pkg/handler/socks/v4"
|
_ "github.com/go-gost/x/handler/relay"
|
||||||
_ "github.com/go-gost/gost/pkg/handler/socks/v5"
|
_ "github.com/go-gost/x/handler/sni"
|
||||||
_ "github.com/go-gost/gost/pkg/handler/ss"
|
_ "github.com/go-gost/x/handler/socks/v4"
|
||||||
_ "github.com/go-gost/gost/pkg/handler/ss/udp"
|
_ "github.com/go-gost/x/handler/socks/v5"
|
||||||
_ "github.com/go-gost/gost/pkg/handler/sshd"
|
_ "github.com/go-gost/x/handler/ss"
|
||||||
_ "github.com/go-gost/gost/pkg/handler/tap"
|
_ "github.com/go-gost/x/handler/ss/udp"
|
||||||
_ "github.com/go-gost/gost/pkg/handler/tun"
|
_ "github.com/go-gost/x/handler/sshd"
|
||||||
|
_ "github.com/go-gost/x/handler/tap"
|
||||||
|
_ "github.com/go-gost/x/handler/tun"
|
||||||
|
|
||||||
// Register listeners
|
// Register listeners
|
||||||
_ "github.com/go-gost/gost/pkg/listener/dns"
|
_ "github.com/go-gost/x/listener/dns"
|
||||||
_ "github.com/go-gost/gost/pkg/listener/ftcp"
|
_ "github.com/go-gost/x/listener/dtls"
|
||||||
_ "github.com/go-gost/gost/pkg/listener/grpc"
|
_ "github.com/go-gost/x/listener/ftcp"
|
||||||
_ "github.com/go-gost/gost/pkg/listener/http2"
|
_ "github.com/go-gost/x/listener/grpc"
|
||||||
_ "github.com/go-gost/gost/pkg/listener/http2/h2"
|
_ "github.com/go-gost/x/listener/http2"
|
||||||
_ "github.com/go-gost/gost/pkg/listener/http3"
|
_ "github.com/go-gost/x/listener/http2/h2"
|
||||||
_ "github.com/go-gost/gost/pkg/listener/icmp"
|
_ "github.com/go-gost/x/listener/http3"
|
||||||
_ "github.com/go-gost/gost/pkg/listener/kcp"
|
_ "github.com/go-gost/x/listener/http3/h3"
|
||||||
_ "github.com/go-gost/gost/pkg/listener/obfs/http"
|
_ "github.com/go-gost/x/listener/icmp"
|
||||||
_ "github.com/go-gost/gost/pkg/listener/obfs/tls"
|
_ "github.com/go-gost/x/listener/kcp"
|
||||||
_ "github.com/go-gost/gost/pkg/listener/pht"
|
_ "github.com/go-gost/x/listener/mtls"
|
||||||
_ "github.com/go-gost/gost/pkg/listener/quic"
|
_ "github.com/go-gost/x/listener/mws"
|
||||||
_ "github.com/go-gost/gost/pkg/listener/redirect/udp"
|
_ "github.com/go-gost/x/listener/obfs/http"
|
||||||
_ "github.com/go-gost/gost/pkg/listener/rtcp"
|
_ "github.com/go-gost/x/listener/obfs/tls"
|
||||||
_ "github.com/go-gost/gost/pkg/listener/rudp"
|
_ "github.com/go-gost/x/listener/pht"
|
||||||
_ "github.com/go-gost/gost/pkg/listener/ssh"
|
_ "github.com/go-gost/x/listener/quic"
|
||||||
_ "github.com/go-gost/gost/pkg/listener/sshd"
|
_ "github.com/go-gost/x/listener/redirect/tcp"
|
||||||
_ "github.com/go-gost/gost/pkg/listener/tap"
|
_ "github.com/go-gost/x/listener/redirect/udp"
|
||||||
_ "github.com/go-gost/gost/pkg/listener/tcp"
|
_ "github.com/go-gost/x/listener/rtcp"
|
||||||
_ "github.com/go-gost/gost/pkg/listener/tls"
|
_ "github.com/go-gost/x/listener/rudp"
|
||||||
_ "github.com/go-gost/gost/pkg/listener/tls/mux"
|
_ "github.com/go-gost/x/listener/ssh"
|
||||||
_ "github.com/go-gost/gost/pkg/listener/tun"
|
_ "github.com/go-gost/x/listener/sshd"
|
||||||
_ "github.com/go-gost/gost/pkg/listener/udp"
|
_ "github.com/go-gost/x/listener/tap"
|
||||||
_ "github.com/go-gost/gost/pkg/listener/ws"
|
_ "github.com/go-gost/x/listener/tcp"
|
||||||
_ "github.com/go-gost/gost/pkg/listener/ws/mux"
|
_ "github.com/go-gost/x/listener/tls"
|
||||||
|
_ "github.com/go-gost/x/listener/tun"
|
||||||
|
_ "github.com/go-gost/x/listener/udp"
|
||||||
|
_ "github.com/go-gost/x/listener/ws"
|
||||||
)
|
)
|
||||||
|
|||||||
-107
@@ -1,107 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/rand"
|
|
||||||
"crypto/rsa"
|
|
||||||
"crypto/tls"
|
|
||||||
"crypto/x509"
|
|
||||||
"crypto/x509/pkix"
|
|
||||||
"encoding/pem"
|
|
||||||
"math/big"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
tls_util "github.com/go-gost/gost/pkg/common/util/tls"
|
|
||||||
"github.com/go-gost/gost/pkg/config"
|
|
||||||
)
|
|
||||||
|
|
||||||
func buildDefaultTLSConfig(cfg *config.TLSConfig) {
|
|
||||||
if cfg == nil {
|
|
||||||
cfg = &config.TLSConfig{
|
|
||||||
CertFile: "cert.pem",
|
|
||||||
KeyFile: "key.pem",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tlsConfig, err := loadConfig(cfg.CertFile, cfg.KeyFile)
|
|
||||||
if err != nil {
|
|
||||||
// generate random self-signed certificate.
|
|
||||||
cert, err := genCertificate()
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
tlsConfig = &tls.Config{
|
|
||||||
Certificates: []tls.Certificate{cert},
|
|
||||||
}
|
|
||||||
log.Warn("load TLS certificate files failed, use random generated certificate")
|
|
||||||
} else {
|
|
||||||
log.Info("load TLS certificate files OK")
|
|
||||||
}
|
|
||||||
tls_util.DefaultConfig = tlsConfig
|
|
||||||
}
|
|
||||||
|
|
||||||
func loadConfig(certFile, keyFile string) (*tls.Config, error) {
|
|
||||||
cert, err := tls.LoadX509KeyPair(certFile, keyFile)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
cfg := &tls.Config{
|
|
||||||
Certificates: []tls.Certificate{cert},
|
|
||||||
}
|
|
||||||
|
|
||||||
return cfg, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func genCertificate() (cert tls.Certificate, err error) {
|
|
||||||
rawCert, rawKey, err := generateKeyPair()
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
return tls.X509KeyPair(rawCert, rawKey)
|
|
||||||
}
|
|
||||||
|
|
||||||
func generateKeyPair() (rawCert, rawKey []byte, err error) {
|
|
||||||
// Create private key and self-signed certificate
|
|
||||||
// Adapted from https://golang.org/src/crypto/tls/generate_cert.go
|
|
||||||
|
|
||||||
priv, err := rsa.GenerateKey(rand.Reader, 2048)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
validFor := time.Hour * 24 * 365 * 10 // ten years
|
|
||||||
notBefore := time.Now()
|
|
||||||
notAfter := notBefore.Add(validFor)
|
|
||||||
serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
|
|
||||||
serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
template := x509.Certificate{
|
|
||||||
SerialNumber: serialNumber,
|
|
||||||
Subject: pkix.Name{
|
|
||||||
Organization: []string{"gost"},
|
|
||||||
},
|
|
||||||
NotBefore: notBefore,
|
|
||||||
NotAfter: notAfter,
|
|
||||||
|
|
||||||
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
|
|
||||||
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
|
|
||||||
BasicConstraintsValid: true,
|
|
||||||
}
|
|
||||||
|
|
||||||
template.DNSNames = append(template.DNSNames, "gost.run")
|
|
||||||
derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
rawCert = pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
|
|
||||||
privBytes, err := x509.MarshalPKCS8PrivateKey(priv)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
rawKey = pem.EncodeToMemory(&pem.Block{Type: "PRIVATE KEY", Bytes: privBytes})
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
const (
|
const (
|
||||||
version = "3.0.0-alpha.3"
|
version = "3.0.0-rc.2"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -2,92 +2,107 @@ module github.com/go-gost/gost
|
|||||||
|
|
||||||
go 1.18
|
go 1.18
|
||||||
|
|
||||||
|
replace github.com/templexxx/cpu v0.0.7 => github.com/templexxx/cpu v0.0.10-0.20211111114238-98168dcec14a
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/LiamHaworth/go-tproxy v0.0.0-20190726054950-ef7efd7f24ed
|
github.com/go-gost/core v0.0.0-20221221101823-36ed0eae2dec
|
||||||
github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d
|
github.com/go-gost/x v0.0.0-20221222094430-fb29d5c80e89
|
||||||
github.com/docker/libcontainer v2.2.1+incompatible
|
gopkg.in/natefinch/lumberjack.v2 v2.0.0
|
||||||
github.com/gin-contrib/cors v1.3.1
|
|
||||||
github.com/gin-gonic/gin v1.7.7
|
|
||||||
github.com/go-gost/gosocks4 v0.0.1
|
|
||||||
github.com/go-gost/gosocks5 v0.3.1-0.20211109033403-d894d75b7f09
|
|
||||||
github.com/go-gost/relay v0.1.1-0.20211123134818-8ef7fd81ffd7
|
|
||||||
github.com/go-gost/tls-dissector v0.0.2-0.20211125135007-2b5d5bd9c07e
|
|
||||||
github.com/gobwas/glob v0.2.3
|
|
||||||
github.com/golang/snappy v0.0.3
|
|
||||||
github.com/gorilla/websocket v1.4.2
|
|
||||||
github.com/lucas-clemente/quic-go v0.25.0
|
|
||||||
github.com/miekg/dns v1.1.45
|
|
||||||
github.com/milosgajdos/tenus v0.0.3
|
|
||||||
github.com/prometheus/client_golang v1.12.1
|
|
||||||
github.com/rs/xid v1.3.0
|
|
||||||
github.com/shadowsocks/go-shadowsocks2 v0.1.4
|
|
||||||
github.com/shadowsocks/shadowsocks-go v0.0.0-20200409064450-3e585ff90601
|
|
||||||
github.com/sirupsen/logrus v1.8.1
|
|
||||||
github.com/songgao/water v0.0.0-20200317203138-2b4b6d7c09d8
|
|
||||||
github.com/spf13/viper v1.9.0
|
|
||||||
github.com/xtaci/kcp-go/v5 v5.6.1
|
|
||||||
github.com/xtaci/smux v1.5.16
|
|
||||||
github.com/xtaci/tcpraw v1.2.25
|
|
||||||
golang.org/x/crypto v0.0.0-20220214200702-86341886e292
|
|
||||||
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd
|
|
||||||
golang.org/x/sys v0.0.0-20220224120231-95c6836cb0e7
|
|
||||||
google.golang.org/grpc v1.44.0
|
|
||||||
google.golang.org/protobuf v1.27.1
|
|
||||||
gopkg.in/yaml.v2 v2.4.0
|
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da // indirect
|
github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da // indirect
|
||||||
|
github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 // indirect
|
||||||
|
github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d // indirect
|
||||||
github.com/beorn7/perks v1.0.1 // indirect
|
github.com/beorn7/perks v1.0.1 // indirect
|
||||||
github.com/cespare/xxhash/v2 v2.1.2 // indirect
|
github.com/cespare/xxhash/v2 v2.1.2 // indirect
|
||||||
github.com/cheekybits/genny v1.0.0 // indirect
|
|
||||||
github.com/coreos/go-iptables v0.5.0 // indirect
|
github.com/coreos/go-iptables v0.5.0 // indirect
|
||||||
github.com/fsnotify/fsnotify v1.5.1 // indirect
|
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
||||||
|
github.com/fsnotify/fsnotify v1.5.4 // indirect
|
||||||
|
github.com/gin-contrib/cors v1.3.1 // indirect
|
||||||
github.com/gin-contrib/sse v0.1.0 // indirect
|
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||||
github.com/go-playground/locales v0.13.0 // indirect
|
github.com/gin-gonic/gin v1.7.7 // indirect
|
||||||
github.com/go-playground/universal-translator v0.17.0 // indirect
|
github.com/go-gost/gosocks4 v0.0.1 // indirect
|
||||||
github.com/go-playground/validator/v10 v10.4.1 // indirect
|
github.com/go-gost/gosocks5 v0.3.1-0.20211109033403-d894d75b7f09 // indirect
|
||||||
|
github.com/go-gost/relay v0.1.1-0.20211123134818-8ef7fd81ffd7 // indirect
|
||||||
|
github.com/go-gost/tls-dissector v0.0.2-0.20220408131628-aac992c27451 // indirect
|
||||||
|
github.com/go-playground/locales v0.14.0 // indirect
|
||||||
|
github.com/go-playground/universal-translator v0.18.0 // indirect
|
||||||
|
github.com/go-playground/validator/v10 v10.10.1 // indirect
|
||||||
|
github.com/go-redis/redis/v8 v8.11.5 // indirect
|
||||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect
|
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect
|
||||||
|
github.com/gobwas/glob v0.2.3 // indirect
|
||||||
|
github.com/golang/mock v1.6.0 // indirect
|
||||||
github.com/golang/protobuf v1.5.2 // indirect
|
github.com/golang/protobuf v1.5.2 // indirect
|
||||||
|
github.com/golang/snappy v0.0.4 // indirect
|
||||||
github.com/google/gopacket v1.1.19 // indirect
|
github.com/google/gopacket v1.1.19 // indirect
|
||||||
|
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 // indirect
|
||||||
|
github.com/gorilla/websocket v1.5.0 // indirect
|
||||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||||
github.com/json-iterator/go v1.1.12 // indirect
|
github.com/json-iterator/go v1.1.12 // indirect
|
||||||
github.com/klauspost/cpuid v1.3.1 // indirect
|
github.com/klauspost/cpuid v1.3.1 // indirect
|
||||||
github.com/klauspost/reedsolomon v1.9.9 // indirect
|
github.com/klauspost/reedsolomon v1.9.9 // indirect
|
||||||
github.com/leodido/go-urn v1.2.0 // indirect
|
github.com/leodido/go-urn v1.2.1 // indirect
|
||||||
github.com/magiconair/properties v1.8.5 // indirect
|
github.com/lucas-clemente/quic-go v0.30.0 // indirect
|
||||||
github.com/marten-seemann/qpack v0.2.1 // indirect
|
github.com/magiconair/properties v1.8.6 // indirect
|
||||||
github.com/marten-seemann/qtls-go1-16 v0.1.4 // indirect
|
github.com/marten-seemann/qpack v0.3.0 // indirect
|
||||||
github.com/marten-seemann/qtls-go1-17 v0.1.0 // indirect
|
github.com/marten-seemann/qtls-go1-18 v0.1.3 // indirect
|
||||||
github.com/marten-seemann/qtls-go1-18 v0.1.0-beta.1 // indirect
|
github.com/marten-seemann/qtls-go1-19 v0.1.1 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.12 // indirect
|
github.com/mattn/go-isatty v0.0.14 // indirect
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect
|
github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect
|
||||||
github.com/mitchellh/mapstructure v1.4.2 // indirect
|
github.com/miekg/dns v1.1.50 // indirect
|
||||||
|
github.com/mitchellh/mapstructure v1.4.3 // indirect
|
||||||
github.com/mmcloughlin/avo v0.0.0-20200803215136-443f81d77104 // indirect
|
github.com/mmcloughlin/avo v0.0.0-20200803215136-443f81d77104 // indirect
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||||
github.com/nxadm/tail v1.4.8 // indirect
|
github.com/onsi/ginkgo/v2 v2.2.0 // indirect
|
||||||
github.com/onsi/ginkgo v1.16.5 // indirect
|
github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
|
||||||
github.com/pelletier/go-toml v1.9.4 // indirect
|
github.com/pelletier/go-toml v1.9.4 // indirect
|
||||||
|
github.com/pion/dtls/v2 v2.1.5 // indirect
|
||||||
|
github.com/pion/logging v0.2.2 // indirect
|
||||||
|
github.com/pion/transport v0.14.1 // indirect
|
||||||
|
github.com/pion/udp v0.1.1 // indirect
|
||||||
|
github.com/pires/go-proxyproto v0.6.2 // indirect
|
||||||
github.com/pkg/errors v0.9.1 // indirect
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
|
github.com/prometheus/client_golang v1.12.1 // indirect
|
||||||
github.com/prometheus/client_model v0.2.0 // indirect
|
github.com/prometheus/client_model v0.2.0 // indirect
|
||||||
github.com/prometheus/common v0.32.1 // indirect
|
github.com/prometheus/common v0.32.1 // indirect
|
||||||
github.com/prometheus/procfs v0.7.3 // indirect
|
github.com/prometheus/procfs v0.7.3 // indirect
|
||||||
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 // indirect
|
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 // indirect
|
||||||
github.com/spf13/afero v1.6.0 // indirect
|
github.com/rs/xid v1.3.0 // indirect
|
||||||
|
github.com/shadowsocks/go-shadowsocks2 v0.1.5 // indirect
|
||||||
|
github.com/shadowsocks/shadowsocks-go v0.0.0-20200409064450-3e585ff90601 // indirect
|
||||||
|
github.com/sirupsen/logrus v1.8.1 // indirect
|
||||||
|
github.com/songgao/water v0.0.0-20200317203138-2b4b6d7c09d8 // indirect
|
||||||
|
github.com/spf13/afero v1.8.2 // indirect
|
||||||
github.com/spf13/cast v1.4.1 // indirect
|
github.com/spf13/cast v1.4.1 // indirect
|
||||||
github.com/spf13/jwalterweatherman v1.1.0 // indirect
|
github.com/spf13/jwalterweatherman v1.1.0 // indirect
|
||||||
github.com/spf13/pflag v1.0.5 // indirect
|
github.com/spf13/pflag v1.0.5 // indirect
|
||||||
|
github.com/spf13/viper v1.10.1 // indirect
|
||||||
github.com/subosito/gotenv v1.2.0 // indirect
|
github.com/subosito/gotenv v1.2.0 // indirect
|
||||||
github.com/templexxx/cpu v0.0.7 // indirect
|
github.com/templexxx/cpu v0.0.7 // indirect
|
||||||
github.com/templexxx/xorsimd v0.4.1 // indirect
|
github.com/templexxx/xorsimd v0.4.1 // indirect
|
||||||
github.com/tjfoc/gmsm v1.3.2 // indirect
|
github.com/tjfoc/gmsm v1.3.2 // indirect
|
||||||
github.com/ugorji/go/codec v1.1.7 // indirect
|
github.com/ugorji/go/codec v1.2.7 // indirect
|
||||||
golang.org/x/mod v0.5.1 // indirect
|
github.com/vishvananda/netlink v1.1.0 // indirect
|
||||||
golang.org/x/text v0.3.7 // indirect
|
github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df // indirect
|
||||||
golang.org/x/tools v0.1.9 // indirect
|
github.com/xtaci/kcp-go/v5 v5.6.1 // indirect
|
||||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
|
github.com/xtaci/smux v1.5.16 // indirect
|
||||||
|
github.com/xtaci/tcpraw v1.2.25 // indirect
|
||||||
|
github.com/yl2chen/cidranger v1.0.2 // indirect
|
||||||
|
golang.org/x/crypto v0.3.0 // indirect
|
||||||
|
golang.org/x/exp v0.0.0-20220827204233-334a2380cb91 // indirect
|
||||||
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
|
||||||
|
golang.org/x/net v0.2.0 // indirect
|
||||||
|
golang.org/x/sys v0.2.0 // indirect
|
||||||
|
golang.org/x/text v0.4.0 // indirect
|
||||||
|
golang.org/x/time v0.2.0 // indirect
|
||||||
|
golang.org/x/tools v0.1.12 // indirect
|
||||||
|
golang.zx2c4.com/wintun v0.0.0-20211104114900-415007cec224 // indirect
|
||||||
|
golang.zx2c4.com/wireguard v0.0.0-20220703234212-c31a7b1ab478 // indirect
|
||||||
google.golang.org/genproto v0.0.0-20220126215142-9970aeb2e350 // indirect
|
google.golang.org/genproto v0.0.0-20220126215142-9970aeb2e350 // indirect
|
||||||
gopkg.in/ini.v1 v1.63.2 // indirect
|
google.golang.org/grpc v1.51.0 // indirect
|
||||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
|
google.golang.org/protobuf v1.28.1 // indirect
|
||||||
|
gopkg.in/ini.v1 v1.66.4 // indirect
|
||||||
|
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||||
cloud.google.com/go v0.31.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.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||||
cloud.google.com/go v0.37.0/go.mod h1:TS1dMSSfndXH133OKGwekG838Om/cQT0BUHV3HcBgoo=
|
|
||||||
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
|
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.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
|
||||||
cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
|
cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
|
||||||
|
cloud.google.com/go v0.44.3/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
|
||||||
cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
|
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.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
|
||||||
cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
|
cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
|
||||||
@@ -17,14 +16,7 @@ cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOY
|
|||||||
cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
|
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.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI=
|
||||||
cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk=
|
cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk=
|
||||||
cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg=
|
cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY=
|
||||||
cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8=
|
|
||||||
cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0=
|
|
||||||
cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY=
|
|
||||||
cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM=
|
|
||||||
cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY=
|
|
||||||
cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ=
|
|
||||||
cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI=
|
|
||||||
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
|
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.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.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
|
||||||
@@ -33,7 +25,6 @@ cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4g
|
|||||||
cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
|
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.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/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
|
||||||
cloud.google.com/go/firestore v1.6.0/go.mod h1:afJwI0vaXwAG54kI7A//lP/lSPDkQORQuMkv56TxEPU=
|
|
||||||
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
|
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.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.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
|
||||||
@@ -43,16 +34,11 @@ cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0Zeo
|
|||||||
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
|
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.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
|
||||||
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
|
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
|
||||||
dmitri.shuralyov.com/app/changes v0.0.0-20180602232624-0a106ad413e3/go.mod h1:Yl+fi1br7+Rr3LqpNJf1/uxUdtRUV+Tnj0o93V2B9MU=
|
cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo=
|
||||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||||
dmitri.shuralyov.com/html/belt v0.0.0-20180602232347-f7d459c86be0/go.mod h1:JLBrvjyP0v+ecvNYvCpyZgu5/xkfAUhi6wJj28eUfSU=
|
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
||||||
dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1:a1inKt/atXimZ4Mv927x+r7UpyzRUf4emIoiiSC2TN4=
|
|
||||||
dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU=
|
|
||||||
git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg=
|
|
||||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
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/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||||
github.com/LiamHaworth/go-tproxy v0.0.0-20190726054950-ef7efd7f24ed h1:eqa6queieK8SvoszxCu0WwH7lSVeL4/N/f1JwOMw1G4=
|
|
||||||
github.com/LiamHaworth/go-tproxy v0.0.0-20190726054950-ef7efd7f24ed/go.mod h1:rA52xkgZwql9LRZXWb2arHEFP6qSR48KY2xOfWzEciQ=
|
|
||||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||||
github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da h1:KjTM2ks9d14ZYCvmHS9iAKVt9AyzRSqNU1qabPih5BY=
|
github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da h1:KjTM2ks9d14ZYCvmHS9iAKVt9AyzRSqNU1qabPih5BY=
|
||||||
github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da/go.mod h1:eHEWzANqSiWQsof+nXEI9bUVUyV6F53Fp89EuCh2EAA=
|
github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da/go.mod h1:eHEWzANqSiWQsof+nXEI9bUVUyV6F53Fp89EuCh2EAA=
|
||||||
@@ -61,28 +47,20 @@ github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuy
|
|||||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||||
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||||
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
|
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
|
||||||
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
|
github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 h1:s6gZFSlWYmbqAuRjVTiNNhvNRfY2Wxp9nhfyel4rklc=
|
||||||
|
github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE=
|
||||||
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
|
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
|
||||||
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
|
|
||||||
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
|
|
||||||
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
|
|
||||||
github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
|
|
||||||
github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d h1:Byv0BzEl3/e6D5CLfI0j/7hiIEtvGVFPCZ7Ei2oq8iQ=
|
github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d h1:Byv0BzEl3/e6D5CLfI0j/7hiIEtvGVFPCZ7Ei2oq8iQ=
|
||||||
github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
|
github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
|
||||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||||
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
|
|
||||||
github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g=
|
|
||||||
github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s=
|
|
||||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||||
github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
|
github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
|
||||||
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||||
github.com/cheekybits/genny v1.0.0 h1:uGGa4nei+j20rOSeDeP5Of12XVm7TGUd4dJA9RDitfE=
|
|
||||||
github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ=
|
|
||||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
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/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/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||||
@@ -90,39 +68,24 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk
|
|||||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||||
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||||
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||||
github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI=
|
|
||||||
github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||||
github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
|
||||||
github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
|
||||||
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
|
||||||
github.com/coreos/go-iptables v0.5.0 h1:mw6SAibtHKZcNzAsOxjoHIG0gy5YFHhypWSSNc6EjbQ=
|
github.com/coreos/go-iptables v0.5.0 h1:mw6SAibtHKZcNzAsOxjoHIG0gy5YFHhypWSSNc6EjbQ=
|
||||||
github.com/coreos/go-iptables v0.5.0/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU=
|
github.com/coreos/go-iptables v0.5.0/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU=
|
||||||
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||||
github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
|
||||||
github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
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/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/docker/libcontainer v2.2.1+incompatible h1:++SbbkCw+X8vAd4j2gOCzZ2Nn7s2xFALTf7LZKmM1/0=
|
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
|
||||||
github.com/docker/libcontainer v2.2.1+incompatible/go.mod h1:osvj61pYsqhNCMLGX31xr7klUBhHb/ZBuXS0o1Fvwbw=
|
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
|
||||||
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
|
||||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/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.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.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po=
|
||||||
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
|
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
|
||||||
github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
|
|
||||||
github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
|
github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
|
||||||
github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
|
|
||||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI=
|
||||||
github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
|
github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU=
|
||||||
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
|
|
||||||
github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY=
|
|
||||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
|
||||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
|
||||||
github.com/fsnotify/fsnotify v1.5.1 h1:mZcQUHVQUQWoPXXtuf9yuEXKudkV2sx1E06UadKWpgI=
|
|
||||||
github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU=
|
|
||||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||||
github.com/gin-contrib/cors v1.3.1 h1:doAsuITavI4IOcd0Y19U4B+O0dNWihRyX//nn4sEmgA=
|
github.com/gin-contrib/cors v1.3.1 h1:doAsuITavI4IOcd0Y19U4B+O0dNWihRyX//nn4sEmgA=
|
||||||
github.com/gin-contrib/cors v1.3.1/go.mod h1:jjEJ4268OPZUcU7k9Pm653S7lXUGcqMADzFA61xsmDk=
|
github.com/gin-contrib/cors v1.3.1/go.mod h1:jjEJ4268OPZUcU7k9Pm653S7lXUGcqMADzFA61xsmDk=
|
||||||
@@ -131,19 +94,21 @@ github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm
|
|||||||
github.com/gin-gonic/gin v1.5.0/go.mod h1:Nd6IXA8m5kNZdNEHMBd93KT+mdY3+bewLgRvmCsR2Do=
|
github.com/gin-gonic/gin v1.5.0/go.mod h1:Nd6IXA8m5kNZdNEHMBd93KT+mdY3+bewLgRvmCsR2Do=
|
||||||
github.com/gin-gonic/gin v1.7.7 h1:3DoBmSbJbZAWqXJC3SLjAPfutPJJRN1U5pALB7EeTTs=
|
github.com/gin-gonic/gin v1.7.7 h1:3DoBmSbJbZAWqXJC3SLjAPfutPJJRN1U5pALB7EeTTs=
|
||||||
github.com/gin-gonic/gin v1.7.7/go.mod h1:axIBovoeJpVj8S3BwE0uPMTeReE4+AfFtqpqaZ1qq1U=
|
github.com/gin-gonic/gin v1.7.7/go.mod h1:axIBovoeJpVj8S3BwE0uPMTeReE4+AfFtqpqaZ1qq1U=
|
||||||
github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
|
|
||||||
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
|
|
||||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
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-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-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||||
|
github.com/go-gost/core v0.0.0-20221221101823-36ed0eae2dec h1:QxAIPNaXlWpqCVYFjkRjw9EIJte3qI+J94Kh213TdaI=
|
||||||
|
github.com/go-gost/core v0.0.0-20221221101823-36ed0eae2dec/go.mod h1:R08B7BVdhWsYHX8s7wkEBpeKqc4+YFP6bLLFoao0J/A=
|
||||||
github.com/go-gost/gosocks4 v0.0.1 h1:+k1sec8HlELuQV7rWftIkmy8UijzUt2I6t+iMPlGB2s=
|
github.com/go-gost/gosocks4 v0.0.1 h1:+k1sec8HlELuQV7rWftIkmy8UijzUt2I6t+iMPlGB2s=
|
||||||
github.com/go-gost/gosocks4 v0.0.1/go.mod h1:3B6L47HbU/qugDg4JnoFPHgJXE43Inz8Bah1QaN9qCc=
|
github.com/go-gost/gosocks4 v0.0.1/go.mod h1:3B6L47HbU/qugDg4JnoFPHgJXE43Inz8Bah1QaN9qCc=
|
||||||
github.com/go-gost/gosocks5 v0.3.1-0.20211109033403-d894d75b7f09 h1:A95M6UWcfZgOuJkQ7QLfG0Hs5peWIUSysCDNz4pfe04=
|
github.com/go-gost/gosocks5 v0.3.1-0.20211109033403-d894d75b7f09 h1:A95M6UWcfZgOuJkQ7QLfG0Hs5peWIUSysCDNz4pfe04=
|
||||||
github.com/go-gost/gosocks5 v0.3.1-0.20211109033403-d894d75b7f09/go.mod h1:1G6I7HP7VFVxveGkoK8mnprnJqSqJjdcASKsdUn4Pp4=
|
github.com/go-gost/gosocks5 v0.3.1-0.20211109033403-d894d75b7f09/go.mod h1:1G6I7HP7VFVxveGkoK8mnprnJqSqJjdcASKsdUn4Pp4=
|
||||||
github.com/go-gost/relay v0.1.1-0.20211123134818-8ef7fd81ffd7 h1:itaaJhQJ19kUXEB4Igb0EbY8m+1Py2AaNNSBds/9gk4=
|
github.com/go-gost/relay v0.1.1-0.20211123134818-8ef7fd81ffd7 h1:itaaJhQJ19kUXEB4Igb0EbY8m+1Py2AaNNSBds/9gk4=
|
||||||
github.com/go-gost/relay v0.1.1-0.20211123134818-8ef7fd81ffd7/go.mod h1:lcX+23LCQ3khIeASBo+tJ/WbwXFO32/N5YN6ucuYTG8=
|
github.com/go-gost/relay v0.1.1-0.20211123134818-8ef7fd81ffd7/go.mod h1:lcX+23LCQ3khIeASBo+tJ/WbwXFO32/N5YN6ucuYTG8=
|
||||||
github.com/go-gost/tls-dissector v0.0.2-0.20211125135007-2b5d5bd9c07e h1:73NGqAs22ey3wJkIYVD/ACEoovuIuOlEzQTEoqrO5+U=
|
github.com/go-gost/tls-dissector v0.0.2-0.20220408131628-aac992c27451 h1:xj8gUZGYO3nb5+6Bjw9+tsFkA9sYynrOvDvvC4uDV2I=
|
||||||
github.com/go-gost/tls-dissector v0.0.2-0.20211125135007-2b5d5bd9c07e/go.mod h1:/9QfdewqmHdaE362Hv5nDaSWLx3pCmtD870d6GaquXs=
|
github.com/go-gost/tls-dissector v0.0.2-0.20220408131628-aac992c27451/go.mod h1:/9QfdewqmHdaE362Hv5nDaSWLx3pCmtD870d6GaquXs=
|
||||||
|
github.com/go-gost/x v0.0.0-20221222094430-fb29d5c80e89 h1:HUrSU0AySPcTla9hiQbO63iao75fx8idHUk431pOgH0=
|
||||||
|
github.com/go-gost/x v0.0.0-20221222094430-fb29d5c80e89/go.mod h1:pIv7SEewg5j86yMxYwLbqKlVCO0BKGHwKxruXj6C/4k=
|
||||||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||||
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||||
github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
|
github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
|
||||||
@@ -153,26 +118,28 @@ github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG
|
|||||||
github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A=
|
github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A=
|
||||||
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||||
github.com/go-playground/locales v0.12.1/go.mod h1:IUMDtCfWo/w/mtMfIE/IG2K+Ey3ygWanZIBtBW0W2TM=
|
github.com/go-playground/locales v0.12.1/go.mod h1:IUMDtCfWo/w/mtMfIE/IG2K+Ey3ygWanZIBtBW0W2TM=
|
||||||
github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q=
|
|
||||||
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
|
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
|
||||||
|
github.com/go-playground/locales v0.14.0 h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb8WugfUU=
|
||||||
|
github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs=
|
||||||
github.com/go-playground/universal-translator v0.16.0/go.mod h1:1AnU7NaIRDWWzGEKwgtJRd2xk99HeFyHw3yid4rvQIY=
|
github.com/go-playground/universal-translator v0.16.0/go.mod h1:1AnU7NaIRDWWzGEKwgtJRd2xk99HeFyHw3yid4rvQIY=
|
||||||
github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no=
|
|
||||||
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
|
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
|
||||||
github.com/go-playground/validator/v10 v10.4.1 h1:pH2c5ADXtd66mxoE0Zm9SUhxE20r7aM3F26W0hOn+GE=
|
github.com/go-playground/universal-translator v0.18.0 h1:82dyy6p4OuJq4/CByFNOn/jYrnRPArHwAcmLoJZxyho=
|
||||||
|
github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA=
|
||||||
github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4=
|
github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4=
|
||||||
|
github.com/go-playground/validator/v10 v10.10.1 h1:uA0+amWMiglNZKZ9FJRKUAe9U3RX91eVn1JYXMWt7ig=
|
||||||
|
github.com/go-playground/validator/v10 v10.10.1/go.mod h1:i+3WkQ1FvaUjjxh1kSvIA4dMGDBiPU55YFDl0WbKdWU=
|
||||||
|
github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI=
|
||||||
|
github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo=
|
||||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I=
|
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I=
|
||||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
|
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
|
||||||
github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=
|
github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=
|
||||||
github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
|
github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
|
||||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
|
||||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
|
||||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||||
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/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-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/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E=
|
|
||||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||||
github.com/golang/mock v1.2.0/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.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
|
||||||
@@ -180,7 +147,6 @@ github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt
|
|||||||
github.com/golang/mock v1.4.1/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.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||||
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
|
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
|
||||||
github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8=
|
|
||||||
github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
|
github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
|
||||||
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
|
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
|
||||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
@@ -198,11 +164,10 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD
|
|||||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||||
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||||
github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM=
|
|
||||||
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
|
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
|
||||||
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||||
github.com/golang/snappy v0.0.3 h1:fHPg5GQYlCeLIPB9BZqMVR5nR9A+IM5zcgeTdjMYmLA=
|
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
|
||||||
github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||||
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
github.com/google/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.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||||
@@ -213,20 +178,15 @@ github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
|||||||
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.1/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.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
|
||||||
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
|
github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
|
||||||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
|
||||||
github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
|
|
||||||
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
|
|
||||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8=
|
github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8=
|
||||||
github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo=
|
github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo=
|
||||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
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.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
||||||
github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
||||||
github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk=
|
|
||||||
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
github.com/google/pprof v0.0.0-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-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-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||||
@@ -236,50 +196,23 @@ github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hf
|
|||||||
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/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-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||||
github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||||
github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||||
github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 h1:yAJXTCF9TqKcTiHJAE8dj7HMvPfh66eeA2JYW7eFpSE=
|
||||||
github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||||
github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
|
||||||
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
|
||||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||||
github.com/google/uuid v1.1.2/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.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY=
|
|
||||||
github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg=
|
|
||||||
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
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/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
||||||
github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0=
|
github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g=
|
||||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
|
||||||
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
|
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||||
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/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw=
|
|
||||||
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
|
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
|
||||||
github.com/hashicorp/consul/api v1.10.1/go.mod h1:XjsvQN+RJGWI2TWy1/kqaE16HrR2J/FWgkYjdZQsX9M=
|
|
||||||
github.com/hashicorp/consul/sdk v0.8.0/go.mod h1:GBvyrGALthsZObzUGsfgHZQDXjg4lOjagTIwIR1vPms=
|
|
||||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
|
||||||
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
|
|
||||||
github.com/hashicorp/go-hclog v0.12.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
|
|
||||||
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
|
|
||||||
github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
|
|
||||||
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
|
|
||||||
github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA=
|
|
||||||
github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8=
|
|
||||||
github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
|
|
||||||
github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
|
|
||||||
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
|
||||||
github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
|
||||||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
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/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||||
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
|
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
|
||||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||||
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
|
|
||||||
github.com/hashicorp/mdns v1.0.1/go.mod h1:4gW7WsVCke5TE7EPeYliwHlRUyBtfCwuFwuMg2DmyNY=
|
|
||||||
github.com/hashicorp/memberlist v0.2.2/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE=
|
|
||||||
github.com/hashicorp/serf v0.9.5/go.mod h1:UWDWwZeL5cuWDJdl0C6wrvrUwEqtQ4ZKBKKENpqIUyk=
|
|
||||||
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-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/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||||
github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU=
|
|
||||||
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
|
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
|
||||||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||||
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||||
@@ -292,7 +225,6 @@ github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1
|
|||||||
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
|
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
|
||||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||||
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
|
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
|
||||||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
|
||||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||||
github.com/klauspost/cpuid v1.2.4/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
|
github.com/klauspost/cpuid v1.2.4/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
|
||||||
github.com/klauspost/cpuid v1.3.1 h1:5JNjFYYQrZeKRJ0734q51WCEEn2huer72Dc7K+R/b6s=
|
github.com/klauspost/cpuid v1.3.1 h1:5JNjFYYQrZeKRJ0734q51WCEEn2huer72Dc7K+R/b6s=
|
||||||
@@ -304,56 +236,37 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxv
|
|||||||
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
|
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
|
||||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||||
github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs=
|
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||||
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
|
||||||
|
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
|
||||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
github.com/kr/pty v1.1.3/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/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
|
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||||
|
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||||
github.com/leodido/go-urn v1.1.0/go.mod h1:+cyI34gQWZcE1eQU7NVgKkkzdXDQHr1dBMtdAPozLkw=
|
github.com/leodido/go-urn v1.1.0/go.mod h1:+cyI34gQWZcE1eQU7NVgKkkzdXDQHr1dBMtdAPozLkw=
|
||||||
github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
|
|
||||||
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
|
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
|
||||||
github.com/lucas-clemente/quic-go v0.25.0 h1:K+X9Gvd7JXsOHtU0N2icZ2Nw3rx82uBej3mP4CLgibc=
|
github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w=
|
||||||
github.com/lucas-clemente/quic-go v0.25.0/go.mod h1:YtzP8bxRVCBlO77yRanE264+fY/T2U9ZlW1AaHOsMOg=
|
github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
|
||||||
github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI=
|
github.com/lucas-clemente/quic-go v0.30.0 h1:nwLW0h8ahVQ5EPTIM7uhl/stHqQDea15oRlYKZmw2O0=
|
||||||
github.com/magiconair/properties v1.8.5 h1:b6kJs+EmPFMYGkow9GiUyCyOvIwYetYJ3fSaWak/Gls=
|
github.com/lucas-clemente/quic-go v0.30.0/go.mod h1:ssOrRsOmdxa768Wr78vnh2B8JozgLsMzG/g+0qEC7uk=
|
||||||
github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
|
github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo=
|
||||||
github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
|
||||||
github.com/marten-seemann/qpack v0.2.1 h1:jvTsT/HpCn2UZJdP+UUB53FfUUgeOyG5K1ns0OJOGVs=
|
github.com/marten-seemann/qpack v0.3.0 h1:UiWstOgT8+znlkDPOg2+3rIuYXJ2CnGDkGUXN6ki6hE=
|
||||||
github.com/marten-seemann/qpack v0.2.1/go.mod h1:F7Gl5L1jIgN1D11ucXefiuJS9UMVP2opoCp2jDKb7wc=
|
github.com/marten-seemann/qpack v0.3.0/go.mod h1:cGfKPBiP4a9EQdxCwEwI/GEeWAsjSekBvx/X8mh58+g=
|
||||||
github.com/marten-seemann/qtls-go1-15 v0.1.4/go.mod h1:GyFwywLKkRt+6mfU99csTEY1joMZz5vmB1WNZH3P81I=
|
github.com/marten-seemann/qtls-go1-18 v0.1.3 h1:R4H2Ks8P6pAtUagjFty2p7BVHn3XiwDAl7TTQf5h7TI=
|
||||||
github.com/marten-seemann/qtls-go1-16 v0.1.4 h1:xbHbOGGhrenVtII6Co8akhLEdrawwB2iHl5yhJRpnco=
|
github.com/marten-seemann/qtls-go1-18 v0.1.3/go.mod h1:mJttiymBAByA49mhlNZZGrH5u1uXYZJ+RW28Py7f4m4=
|
||||||
github.com/marten-seemann/qtls-go1-16 v0.1.4/go.mod h1:gNpI2Ol+lRS3WwSOtIUUtRwZEQMXjYK+dQSBFbethAk=
|
github.com/marten-seemann/qtls-go1-19 v0.1.1 h1:mnbxeq3oEyQxQXwI4ReCgW9DPoPR94sNlqWoDZnjRIE=
|
||||||
github.com/marten-seemann/qtls-go1-17 v0.1.0 h1:P9ggrs5xtwiqXv/FHNwntmuLMNq3KaSIG93AtAZ48xk=
|
github.com/marten-seemann/qtls-go1-19 v0.1.1/go.mod h1:5HTDWtVudo/WFsHKRNuOhWlbdjrfs5JHrYb0wIJqGpI=
|
||||||
github.com/marten-seemann/qtls-go1-17 v0.1.0/go.mod h1:fz4HIxByo+LlWcreM4CZOYNuz3taBQ8rN2X6FqvaWo8=
|
|
||||||
github.com/marten-seemann/qtls-go1-18 v0.1.0-beta.1 h1:EnzzN9fPUkUck/1CuY1FlzBaIYMoiBsdwTNmNGkwUUM=
|
|
||||||
github.com/marten-seemann/qtls-go1-18 v0.1.0-beta.1/go.mod h1:PUhIQk19LoFt2174H4+an8TYvWOGjb/hHwphBeaDHwI=
|
|
||||||
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
|
||||||
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
|
||||||
github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
|
||||||
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
|
||||||
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
|
||||||
github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
|
github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
|
||||||
github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
|
|
||||||
github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
|
|
||||||
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
|
|
||||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||||
|
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
|
||||||
|
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
|
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||||
github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4=
|
github.com/miekg/dns v1.1.50 h1:DQUfb9uc6smULcREF09Uc+/Gd46YWqJd5DbpPE9xkcA=
|
||||||
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
|
github.com/miekg/dns v1.1.50/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME=
|
||||||
github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso=
|
github.com/mitchellh/mapstructure v1.4.3 h1:OVowDSCllw/YjdLkam3/sm7wEtOy59d8ndGgCcyj8cs=
|
||||||
github.com/miekg/dns v1.1.45 h1:g5fRIhm9nx7g8osrAvgb16QJfmyMsyOCb+J7LSv+Qzk=
|
github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||||
github.com/miekg/dns v1.1.45/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME=
|
|
||||||
github.com/milosgajdos/tenus v0.0.3 h1:jmaJzwaY1DUyYVD0lM4U+uvP2kkEg1VahDqRFxIkVBE=
|
|
||||||
github.com/milosgajdos/tenus v0.0.3/go.mod h1:eIjx29vNeDOYWJuCnaHY2r4fq5egetV26ry3on7p8qY=
|
|
||||||
github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI=
|
|
||||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
|
||||||
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
|
|
||||||
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
|
||||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
|
||||||
github.com/mitchellh/mapstructure v1.4.2 h1:6h7AQ0yhTcIsmFmnAwQls75jp2Gzs4iB8W7pjMO+rqo=
|
|
||||||
github.com/mitchellh/mapstructure v1.4.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
|
||||||
github.com/mmcloughlin/avo v0.0.0-20200803215136-443f81d77104 h1:ULR/QWMgcgRiZLUjSSJMU+fW+RDMstRdmnDWj9Q+AsA=
|
github.com/mmcloughlin/avo v0.0.0-20200803215136-443f81d77104 h1:ULR/QWMgcgRiZLUjSSJMU+fW+RDMstRdmnDWj9Q+AsA=
|
||||||
github.com/mmcloughlin/avo v0.0.0-20200803215136-443f81d77104/go.mod h1:wqKykBG2QzQDJEzvRkcS8x6MiSJkF52hXZsXcjaB3ls=
|
github.com/mmcloughlin/avo v0.0.0-20200803215136-443f81d77104/go.mod h1:wqKykBG2QzQDJEzvRkcS8x6MiSJkF52hXZsXcjaB3ls=
|
||||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
@@ -365,36 +278,35 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G
|
|||||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||||
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||||
github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo=
|
|
||||||
github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM=
|
|
||||||
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
|
||||||
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
|
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
|
||||||
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
|
|
||||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
|
||||||
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
|
|
||||||
github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
|
|
||||||
github.com/onsi/ginkgo v1.16.2/go.mod h1:CObGmKUOKaSC0RjmoAK7tKyn4Azo5P2IWuoMnvwxz1E=
|
|
||||||
github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
|
|
||||||
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
|
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
|
||||||
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
|
github.com/onsi/ginkgo/v2 v2.2.0 h1:3ZNA3L1c5FYDFTTxbFeVGGD8jYvjYauHD30YgLxVsNI=
|
||||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
github.com/onsi/ginkgo/v2 v2.2.0/go.mod h1:MEH45j8TBi6u9BMogfbp0stKC5cdGjumZj5Y7AG4VIk=
|
||||||
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
github.com/onsi/gomega v1.20.1 h1:PA/3qinGoukvymdIDV8pii6tiZgC8kbmJO6Z5+b002Q=
|
||||||
github.com/onsi/gomega v1.13.0 h1:7lLHu94wT9Ij0o6EWWclhu0aOh32VxhkwEJvzuWPeak=
|
github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
|
||||||
github.com/onsi/gomega v1.13.0/go.mod h1:lRk9szgn8TxENtWd0Tp4c3wjlRfMTMH27I+3Je41yGY=
|
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
|
||||||
github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8=
|
|
||||||
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
|
||||||
github.com/pelletier/go-toml v1.9.4 h1:tjENF6MfZAg8e4ZmZTeWaWiT2vXtsoO6+iuOjFhECwM=
|
github.com/pelletier/go-toml v1.9.4 h1:tjENF6MfZAg8e4ZmZTeWaWiT2vXtsoO6+iuOjFhECwM=
|
||||||
github.com/pelletier/go-toml v1.9.4/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
|
github.com/pelletier/go-toml v1.9.4/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
|
||||||
|
github.com/pion/dtls/v2 v2.1.5 h1:jlh2vtIyUBShchoTDqpCCqiYCyRFJ/lvf/gQ8TALs+c=
|
||||||
|
github.com/pion/dtls/v2 v2.1.5/go.mod h1:BqCE7xPZbPSubGasRoDFJeTsyJtdD1FanJYL0JGheqY=
|
||||||
|
github.com/pion/logging v0.2.2 h1:M9+AIj/+pxNsDfAT64+MAVgJO0rsyLnoJKCqf//DoeY=
|
||||||
|
github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms=
|
||||||
|
github.com/pion/transport v0.12.2/go.mod h1:N3+vZQD9HlDP5GWkZ85LohxNsDcNgofQmyL6ojX5d8Q=
|
||||||
|
github.com/pion/transport v0.13.0/go.mod h1:yxm9uXpK9bpBBWkITk13cLo1y5/ur5VQpG22ny6EP7g=
|
||||||
|
github.com/pion/transport v0.14.1 h1:XSM6olwW+o8J4SCmOBb/BpwZypkHeyM0PGFCxNQBr40=
|
||||||
|
github.com/pion/transport v0.14.1/go.mod h1:4tGmbk00NeYA3rUa9+n+dzCCoKkcy3YlYb99Jn2fNnI=
|
||||||
|
github.com/pion/udp v0.1.1 h1:8UAPvyqmsxK8oOjloDk4wUt63TzFe9WEJkg5lChlj7o=
|
||||||
|
github.com/pion/udp v0.1.1/go.mod h1:6AFo+CMdKQm7UiA0eUPA8/eVCTx8jBIITLZHc9DWX5M=
|
||||||
|
github.com/pires/go-proxyproto v0.6.2 h1:KAZ7UteSOt6urjme6ZldyFm4wDe/z0ZUP0Yv0Dos0d8=
|
||||||
|
github.com/pires/go-proxyproto v0.6.2/go.mod h1:Odh9VFOZJCf9G8cLW5o435Xf1J95Jw9Gw5rnCjcwzAY=
|
||||||
|
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
||||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI=
|
github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
|
|
||||||
github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s=
|
|
||||||
github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
|
||||||
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||||
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
|
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
|
||||||
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
|
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
|
||||||
@@ -406,13 +318,11 @@ github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:
|
|||||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||||
github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M=
|
github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M=
|
||||||
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||||
github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
|
||||||
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||||
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
|
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
|
||||||
github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc=
|
github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc=
|
||||||
github.com/prometheus/common v0.32.1 h1:hWIdL3N2HoUx3B8j3YN9mWor0qhY/NlEKZEaXxuIRh4=
|
github.com/prometheus/common v0.32.1 h1:hWIdL3N2HoUx3B8j3YN9mWor0qhY/NlEKZEaXxuIRh4=
|
||||||
github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls=
|
github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls=
|
||||||
github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
|
||||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||||
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||||
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
|
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
|
||||||
@@ -423,39 +333,15 @@ github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 h1:f/FNXud6gA3MNr
|
|||||||
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3/go.mod h1:HgjTstvQsPGkxUsCd2KWxErBblirPizecHcpD3ffK+s=
|
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3/go.mod h1:HgjTstvQsPGkxUsCd2KWxErBblirPizecHcpD3ffK+s=
|
||||||
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
|
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
|
||||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||||
|
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
||||||
|
github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8=
|
||||||
|
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
|
||||||
github.com/rs/xid v1.3.0 h1:6NjYksEUlhurdVehpc7S7dk6DAmcKv8V9gG0FsVN2U4=
|
github.com/rs/xid v1.3.0 h1:6NjYksEUlhurdVehpc7S7dk6DAmcKv8V9gG0FsVN2U4=
|
||||||
github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
|
github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
|
||||||
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
|
github.com/shadowsocks/go-shadowsocks2 v0.1.5 h1:PDSQv9y2S85Fl7VBeOMF9StzeXZyK1HakRm86CUbr28=
|
||||||
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
github.com/shadowsocks/go-shadowsocks2 v0.1.5/go.mod h1:AGGpIoek4HRno4xzyFiAtLHkOpcoznZEkAccaI/rplM=
|
||||||
github.com/sagikazarmark/crypt v0.1.0/go.mod h1:B/mN0msZuINBtQ1zZLEQcegFJJf9vnYIR88KRMEuODE=
|
|
||||||
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
|
|
||||||
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
|
|
||||||
github.com/shadowsocks/go-shadowsocks2 v0.1.4 h1:4VzajPL7RwwmImysBSvI+lm/UaegDGQq3hr42dYo3gs=
|
|
||||||
github.com/shadowsocks/go-shadowsocks2 v0.1.4/go.mod h1:AGGpIoek4HRno4xzyFiAtLHkOpcoznZEkAccaI/rplM=
|
|
||||||
github.com/shadowsocks/shadowsocks-go v0.0.0-20200409064450-3e585ff90601 h1:XU9hik0exChEmY92ALW4l9WnDodxLVS9yOSNh2SizaQ=
|
github.com/shadowsocks/shadowsocks-go v0.0.0-20200409064450-3e585ff90601 h1:XU9hik0exChEmY92ALW4l9WnDodxLVS9yOSNh2SizaQ=
|
||||||
github.com/shadowsocks/shadowsocks-go v0.0.0-20200409064450-3e585ff90601/go.mod h1:mttDPaeLm87u74HMrP+n2tugXvIKWcwff/cqSX0lehY=
|
github.com/shadowsocks/shadowsocks-go v0.0.0-20200409064450-3e585ff90601/go.mod h1:mttDPaeLm87u74HMrP+n2tugXvIKWcwff/cqSX0lehY=
|
||||||
github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY=
|
|
||||||
github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48/go.mod h1:5u70Mqkb5O5cxEA8nxTsgrgLehJeAw6Oc4Ab1c/P1HM=
|
|
||||||
github.com/shurcooL/github_flavored_markdown v0.0.0-20181002035957-2122de532470/go.mod h1:2dOwnU2uBioM+SGy2aZoq1f/Sd1l9OkAeAUvjSyvgU0=
|
|
||||||
github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk=
|
|
||||||
github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ=
|
|
||||||
github.com/shurcooL/gofontwoff v0.0.0-20180329035133-29b52fc0a18d/go.mod h1:05UtEgK5zq39gLST6uB0cf3NEHjETfB4Fgr3Gx5R9Vw=
|
|
||||||
github.com/shurcooL/gopherjslib v0.0.0-20160914041154-feb6d3990c2c/go.mod h1:8d3azKNyqcHP1GaQE/c6dDgjkgSx2BZ4IoEi4F1reUI=
|
|
||||||
github.com/shurcooL/highlight_diff v0.0.0-20170515013008-09bb4053de1b/go.mod h1:ZpfEhSmds4ytuByIcDnOLkTHGUI6KNqRNPDLHDk+mUU=
|
|
||||||
github.com/shurcooL/highlight_go v0.0.0-20181028180052-98c3abbbae20/go.mod h1:UDKB5a1T23gOMUJrI+uSuH0VRDStOiUVSjBTRDVBVag=
|
|
||||||
github.com/shurcooL/home v0.0.0-20181020052607-80b7ffcb30f9/go.mod h1:+rgNQw2P9ARFAs37qieuu7ohDNQ3gds9msbT2yn85sg=
|
|
||||||
github.com/shurcooL/htmlg v0.0.0-20170918183704-d01228ac9e50/go.mod h1:zPn1wHpTIePGnXSHpsVPWEktKXHr6+SS6x/IKRb7cpw=
|
|
||||||
github.com/shurcooL/httperror v0.0.0-20170206035902-86b7830d14cc/go.mod h1:aYMfkZ6DWSJPJ6c4Wwz3QtW22G7mf/PEgaB9k/ik5+Y=
|
|
||||||
github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg=
|
|
||||||
github.com/shurcooL/httpgzip v0.0.0-20180522190206-b1c53ac65af9/go.mod h1:919LwcH0M7/W4fcZ0/jy0qGght1GIhqyS/EgWGH2j5Q=
|
|
||||||
github.com/shurcooL/issues v0.0.0-20181008053335-6292fdc1e191/go.mod h1:e2qWDig5bLteJ4fwvDAc2NHzqFEthkqn7aOZAOpj+PQ=
|
|
||||||
github.com/shurcooL/issuesapp v0.0.0-20180602232740-048589ce2241/go.mod h1:NPpHK2TI7iSaM0buivtFUc9offApnI0Alt/K8hcHy0I=
|
|
||||||
github.com/shurcooL/notifications v0.0.0-20181007000457-627ab5aea122/go.mod h1:b5uSkrEVM1jQUspwbixRBhaIjIzL2xazXp6kntxYle0=
|
|
||||||
github.com/shurcooL/octicon v0.0.0-20181028054416-fa4f57f9efb2/go.mod h1:eWdoE5JD4R5UVWDucdOPg1g2fqQRq78IQa9zlOV1vpQ=
|
|
||||||
github.com/shurcooL/reactions v0.0.0-20181006231557-f2e0b4ca5b82/go.mod h1:TCR1lToEk4d2s07G3XGfz2QrgHXg4RJBvjrOozvoWfk=
|
|
||||||
github.com/shurcooL/sanitized_anchor_name v0.0.0-20170918181015-86672fcb3f95/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
|
||||||
github.com/shurcooL/users v0.0.0-20180125191416-49c67e49c537/go.mod h1:QJTqeLYEDaXHZDBsXlPCDqdhQuJkuw4NOtaxYe3xii4=
|
|
||||||
github.com/shurcooL/webdavfs v0.0.0-20170829043945-18c3829fa133/go.mod h1:hKmq5kWdCj2z2KEozexVbfEZIWiTjhE0+UjmZgPqehw=
|
|
||||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||||
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
|
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
|
||||||
@@ -463,19 +349,17 @@ github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE
|
|||||||
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||||
github.com/songgao/water v0.0.0-20200317203138-2b4b6d7c09d8 h1:TG/diQgUe0pntT/2D9tmUCz4VNwm9MfrtPr0SU2qSX8=
|
github.com/songgao/water v0.0.0-20200317203138-2b4b6d7c09d8 h1:TG/diQgUe0pntT/2D9tmUCz4VNwm9MfrtPr0SU2qSX8=
|
||||||
github.com/songgao/water v0.0.0-20200317203138-2b4b6d7c09d8/go.mod h1:P5HUIBuIWKbyjl083/loAegFkfbFNx5i2qEP4CNbm7E=
|
github.com/songgao/water v0.0.0-20200317203138-2b4b6d7c09d8/go.mod h1:P5HUIBuIWKbyjl083/loAegFkfbFNx5i2qEP4CNbm7E=
|
||||||
github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE=
|
|
||||||
github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA=
|
|
||||||
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||||
github.com/spf13/afero v1.6.0 h1:xoax2sJ2DT8S8xA2paPFjDCScCNeWsg75VG0DLRreiY=
|
github.com/spf13/afero v1.8.2 h1:xehSyVa0YnHWsJ49JFljMpg1HX19V6NDZ1fkm1Xznbo=
|
||||||
github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I=
|
github.com/spf13/afero v1.8.2/go.mod h1:CtAatgMJh6bJEIs48Ay/FOnkljP3WeGUG0MC1RfAqwo=
|
||||||
github.com/spf13/cast v1.4.1 h1:s0hze+J0196ZfEMTs80N7UlFt0BDuQ7Q+JDnHiMWKdA=
|
github.com/spf13/cast v1.4.1 h1:s0hze+J0196ZfEMTs80N7UlFt0BDuQ7Q+JDnHiMWKdA=
|
||||||
github.com/spf13/cast v1.4.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
github.com/spf13/cast v1.4.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||||
github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk=
|
github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk=
|
||||||
github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
|
github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
|
||||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||||
github.com/spf13/viper v1.9.0 h1:yR6EXjTp0y0cLN8OZg1CRZmOBdI88UcGkhgyJhu6nZk=
|
github.com/spf13/viper v1.10.1 h1:nuJZuYpG7gTj/XqiUwg8bA0cp1+M2mC3J4g5luUYBKk=
|
||||||
github.com/spf13/viper v1.9.0/go.mod h1:+i6ajR7OX2XaiBkrcZJFK21htRk7eDeLg7+O6bhUPP4=
|
github.com/spf13/viper v1.10.1/go.mod h1:IGlFPqhNAPKRxohIzWpI5QEy4kuI7tcl5WvR+8qy1rU=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
@@ -483,23 +367,27 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV
|
|||||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
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.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
|
||||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
|
github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY=
|
||||||
|
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
|
github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
|
||||||
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
|
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
|
||||||
github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA=
|
|
||||||
github.com/templexxx/cpu v0.0.1/go.mod h1:w7Tb+7qgcAlIyX4NhLuDKt78AHA5SzPmq0Wj6HiEnnk=
|
github.com/templexxx/cpu v0.0.1/go.mod h1:w7Tb+7qgcAlIyX4NhLuDKt78AHA5SzPmq0Wj6HiEnnk=
|
||||||
github.com/templexxx/cpu v0.0.7 h1:pUEZn8JBy/w5yzdYWgx+0m0xL9uk6j4K91C5kOViAzo=
|
github.com/templexxx/cpu v0.0.10-0.20211111114238-98168dcec14a h1:f0GQM8LuKYnXdNLcAg+di6PULSlR5iQtZT3bDwDRiA0=
|
||||||
github.com/templexxx/cpu v0.0.7/go.mod h1:w7Tb+7qgcAlIyX4NhLuDKt78AHA5SzPmq0Wj6HiEnnk=
|
github.com/templexxx/cpu v0.0.10-0.20211111114238-98168dcec14a/go.mod h1:w7Tb+7qgcAlIyX4NhLuDKt78AHA5SzPmq0Wj6HiEnnk=
|
||||||
github.com/templexxx/xorsimd v0.4.1 h1:iUZcywbOYDRAZUasAs2eSCUW8eobuZDy0I9FJiORkVg=
|
github.com/templexxx/xorsimd v0.4.1 h1:iUZcywbOYDRAZUasAs2eSCUW8eobuZDy0I9FJiORkVg=
|
||||||
github.com/templexxx/xorsimd v0.4.1/go.mod h1:W+ffZz8jJMH2SXwuKu9WhygqBMbFnp14G2fqEr8qaNo=
|
github.com/templexxx/xorsimd v0.4.1/go.mod h1:W+ffZz8jJMH2SXwuKu9WhygqBMbFnp14G2fqEr8qaNo=
|
||||||
github.com/tjfoc/gmsm v1.3.2 h1:7JVkAn5bvUJ7HtU08iW6UiD+UTmJTIToHCfeFzkcCxM=
|
github.com/tjfoc/gmsm v1.3.2 h1:7JVkAn5bvUJ7HtU08iW6UiD+UTmJTIToHCfeFzkcCxM=
|
||||||
github.com/tjfoc/gmsm v1.3.2/go.mod h1:HaUcFuY0auTiaHB9MHFGCPx5IaLhTUd2atbCFBQXn9w=
|
github.com/tjfoc/gmsm v1.3.2/go.mod h1:HaUcFuY0auTiaHB9MHFGCPx5IaLhTUd2atbCFBQXn9w=
|
||||||
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
|
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
|
||||||
github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs=
|
github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M=
|
||||||
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
|
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
|
||||||
github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU=
|
github.com/ugorji/go/codec v1.2.7 h1:YPXUKf7fYbp/y8xloBqZOw2qaVggbfwMlI8WM3wZUJ0=
|
||||||
github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM=
|
github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY=
|
||||||
|
github.com/vishvananda/netlink v1.1.0 h1:1iyaYNBLmP6L0220aDnYQpo1QEV4t4hJ+xEEhhJH8j0=
|
||||||
|
github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE=
|
||||||
|
github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df h1:OviZH7qLw/7ZovXvuNyL3XQl8UFofeikI1NW1Gypu7k=
|
||||||
|
github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU=
|
||||||
github.com/xtaci/kcp-go/v5 v5.6.1 h1:Pwn0aoeNSPF9dTS7IgiPXn0HEtaIlVb6y5UKWPsx8bI=
|
github.com/xtaci/kcp-go/v5 v5.6.1 h1:Pwn0aoeNSPF9dTS7IgiPXn0HEtaIlVb6y5UKWPsx8bI=
|
||||||
github.com/xtaci/kcp-go/v5 v5.6.1/go.mod h1:W3kVPyNYwZ06p79dNwFWQOVFrdcBpDBsdyvK8moQrYo=
|
github.com/xtaci/kcp-go/v5 v5.6.1/go.mod h1:W3kVPyNYwZ06p79dNwFWQOVFrdcBpDBsdyvK8moQrYo=
|
||||||
github.com/xtaci/lossyconn v0.0.0-20190602105132-8df528c0c9ae h1:J0GxkO96kL4WF+AIT3M4mfUVinOCPgf2uUWYFUzN0sM=
|
github.com/xtaci/lossyconn v0.0.0-20190602105132-8df528c0c9ae h1:J0GxkO96kL4WF+AIT3M4mfUVinOCPgf2uUWYFUzN0sM=
|
||||||
@@ -508,47 +396,38 @@ github.com/xtaci/smux v1.5.16 h1:FBPYOkW8ZTjLKUM4LI4xnnuuDC8CQ/dB04HD519WoEk=
|
|||||||
github.com/xtaci/smux v1.5.16/go.mod h1:OMlQbT5vcgl2gb49mFkYo6SMf+zP3rcjcwQz7ZU7IGY=
|
github.com/xtaci/smux v1.5.16/go.mod h1:OMlQbT5vcgl2gb49mFkYo6SMf+zP3rcjcwQz7ZU7IGY=
|
||||||
github.com/xtaci/tcpraw v1.2.25 h1:VDlqo0op17JeXBM6e2G9ocCNLOJcw9mZbobMbJjo0vk=
|
github.com/xtaci/tcpraw v1.2.25 h1:VDlqo0op17JeXBM6e2G9ocCNLOJcw9mZbobMbJjo0vk=
|
||||||
github.com/xtaci/tcpraw v1.2.25/go.mod h1:dKyZ2V75s0cZ7cbgJYdxPvms7af0joIeOyx1GgJQbLk=
|
github.com/xtaci/tcpraw v1.2.25/go.mod h1:dKyZ2V75s0cZ7cbgJYdxPvms7af0joIeOyx1GgJQbLk=
|
||||||
|
github.com/yl2chen/cidranger v1.0.2 h1:lbOWZVCG1tCRX4u24kuM1Tb4nHqWkDxwLdoS+SevawU=
|
||||||
|
github.com/yl2chen/cidranger v1.0.2/go.mod h1:9U1yz7WPYDwf0vpNWFaeRh0bjwz5RVgRy/9UEQfHl0g=
|
||||||
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
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.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||||
go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs=
|
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||||
go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g=
|
|
||||||
go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ=
|
|
||||||
go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA=
|
|
||||||
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
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.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
||||||
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
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.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||||
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||||
go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
|
go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
|
||||||
go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
|
|
||||||
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
|
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
|
||||||
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
|
||||||
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
|
|
||||||
go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo=
|
|
||||||
go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE=
|
|
||||||
golang.org/x/arch v0.0.0-20190909030613-46d78d1859ac/go.mod h1:flIaEI6LNU6xOCD5PaJvn9wGP0agmIOqjrtsKGRguv4=
|
golang.org/x/arch v0.0.0-20190909030613-46d78d1859ac/go.mod h1:flIaEI6LNU6xOCD5PaJvn9wGP0agmIOqjrtsKGRguv4=
|
||||||
golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw=
|
|
||||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
|
||||||
golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/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-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/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-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-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
|
||||||
golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY=
|
|
||||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20191219195013-becbf705a915/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20191219195013-becbf705a915/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
|
||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||||
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||||
golang.org/x/crypto v0.0.0-20220214200702-86341886e292 h1:f+lwQ+GtmgoY+A2YaQxlSOnDjXcQ7ZRLWOHbC6HtRqE=
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
|
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||||
|
golang.org/x/crypto v0.0.0-20220427172511-eb4f295cb31f/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||||
|
golang.org/x/crypto v0.3.0 h1:a06MkbcxBrEFc0w0QIZWXrH/9cCX6KJyWbBOIwAn+7A=
|
||||||
|
golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
|
||||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/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-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||||
@@ -559,9 +438,10 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
|
|||||||
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
golang.org/x/exp v0.0.0-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-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
|
||||||
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
|
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
|
||||||
|
golang.org/x/exp v0.0.0-20220827204233-334a2380cb91 h1:tnebWN09GYg9OLPss1KXj8txwZc6X6uMr6VFdcGNbHw=
|
||||||
|
golang.org/x/exp v0.0.0-20220827204233-334a2380cb91/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE=
|
||||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
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/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||||
golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
|
||||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||||
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||||
@@ -573,7 +453,6 @@ golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRu
|
|||||||
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
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-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||||
golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||||
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
|
||||||
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
|
golang.org/x/mobile v0.0.0-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/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.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
||||||
@@ -585,19 +464,14 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
|||||||
golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/mod v0.5.1 h1:OJxoQ/rynoF0dcCdI7cLPktw/hR2cueqYfjm43oqK38=
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
|
||||||
golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
|
||||||
golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
|
||||||
golang.org/x/net v0.0.0-20181029044818-c44066c5c816/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
|
||||||
golang.org/x/net v0.0.0-20181106065722-10aee1819953/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
|
||||||
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/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-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-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190313220215-9f648a60d977/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/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-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
@@ -606,7 +480,6 @@ golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLL
|
|||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20190628185345-da137c7871d7/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-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20190923162816-aa69164e4478/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-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-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-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
@@ -617,28 +490,27 @@ golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/
|
|||||||
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/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-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-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
|
||||||
golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
golang.org/x/net v0.0.0-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-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-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-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-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-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||||
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
golang.org/x/net v0.0.0-20201201195509-5d6afe98e0b7/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||||
golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
|
|
||||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||||
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
|
|
||||||
golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
|
||||||
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd h1:O7DYs+zxREGLKzKoMQrtrEacpb0ZVXA5rIwylE2Xchk=
|
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
golang.org/x/net v0.0.0-20211201190559-0a0e4e1bb54c/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
|
golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||||
|
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||||
|
golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
|
||||||
|
golang.org/x/net v0.2.0 h1:sZfSu1wtKLGlWI4ZZayP0ck9Y73K1ynO6gqzTdBVdPU=
|
||||||
|
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
|
||||||
golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/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-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-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-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
@@ -647,13 +519,7 @@ golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ
|
|||||||
golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||||
golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||||
golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||||
golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
|
||||||
golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
|
||||||
golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||||
golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
|
||||||
golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
|
||||||
golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
|
||||||
golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw=
|
|
||||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
@@ -664,42 +530,31 @@ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJ
|
|||||||
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
|
|
||||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 h1:uVc8UZUe6tr40fFVnUP5Oj+veunVezqYl9z7DYw9xzw=
|
||||||
|
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/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-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
|
||||||
golang.org/x/sys v0.0.0-20181029174526-d69651ed3497/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
|
||||||
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/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-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190316082340-a2f829d7f35f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/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-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-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-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/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-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-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/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-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/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-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-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
@@ -709,7 +564,6 @@ golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||||||
golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/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-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-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
@@ -720,31 +574,30 @@ golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220224120231-95c6836cb0e7 h1:BXxu8t6QN0G1uff4bzZzSkpsax8+ALqTGUtz08QrV00=
|
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220224120231-95c6836cb0e7/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.2.0 h1:ljd4t30dBnAvMZaQCevtY0xLLD0A+bRZXbgLMLU1F/A=
|
||||||
|
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
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/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
|
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
|
golang.org/x/term v0.2.0 h1:z85xZCsEl7bi/KwbNADeBYoOP0++7W1ipu+aGnpwzRM=
|
||||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/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.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.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
@@ -753,15 +606,15 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
|||||||
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
|
|
||||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg=
|
||||||
|
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-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-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-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/time v0.2.0 h1:52I/1L54xyEQAYdtcSuxtiT84KGYTBGXwayxmIpNJhE=
|
||||||
|
golang.org/x/time v0.2.0/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-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20181030000716-a0a13e073c7b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
|
||||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
@@ -774,7 +627,6 @@ golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgw
|
|||||||
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/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-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-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/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-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-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-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
@@ -800,7 +652,6 @@ golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roY
|
|||||||
golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/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-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-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||||
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/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-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-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||||
golang.org/x/tools v0.0.0-20200808161706-5bf02b21f123/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
golang.org/x/tools v0.0.0-20200808161706-5bf02b21f123/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||||
@@ -809,26 +660,21 @@ golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82u
|
|||||||
golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
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-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
|
||||||
golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/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/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
|
||||||
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||||
golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
|
||||||
golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
|
||||||
golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
|
||||||
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
|
||||||
golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||||
golang.org/x/tools v0.1.9 h1:j9KsMiaP1c3B0OTQGth0/k+miLGTgLsAFUCrF2vLcF8=
|
golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU=
|
||||||
golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU=
|
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
|
|
||||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
|
golang.zx2c4.com/wintun v0.0.0-20211104114900-415007cec224 h1:Ug9qvr1myri/zFN6xL17LSCBGFDnphBBhzmILHsM5TY=
|
||||||
google.golang.org/api v0.0.0-20181030000543-1d582fd0359e/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
|
golang.zx2c4.com/wintun v0.0.0-20211104114900-415007cec224/go.mod h1:deeaetjYA+DHMHg+sMSMI58GrEteJUUzzw7en6TJQcI=
|
||||||
google.golang.org/api v0.1.0/go.mod h1:UGEZY7KEX120AnNLIHFMKIo4obdJhkp2tPbaPlQx13Y=
|
golang.zx2c4.com/wireguard v0.0.0-20220703234212-c31a7b1ab478 h1:vDy//hdR+GnROE3OdYbQKt9rdtNdHkDtONvpRwmls/0=
|
||||||
|
golang.zx2c4.com/wireguard v0.0.0-20220703234212-c31a7b1ab478/go.mod h1:bVQfyl2sCM/QIIGHpWbFGfHPuDvqnCNkT6MQLTCjO/U=
|
||||||
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
|
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.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.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
|
||||||
@@ -848,17 +694,7 @@ google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz513
|
|||||||
google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg=
|
google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg=
|
||||||
google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE=
|
google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE=
|
||||||
google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8=
|
google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8=
|
||||||
google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU=
|
|
||||||
google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94=
|
|
||||||
google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo=
|
|
||||||
google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4=
|
|
||||||
google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw=
|
|
||||||
google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU=
|
|
||||||
google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k=
|
|
||||||
google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE=
|
|
||||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||||
google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
|
||||||
google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
|
||||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
google.golang.org/appengine v1.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.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.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
|
||||||
@@ -866,10 +702,6 @@ google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCID
|
|||||||
google.golang.org/appengine v1.6.6/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/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-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||||
google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
|
||||||
google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
|
||||||
google.golang.org/genproto v0.0.0-20181202183823-bd91e49a0898/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg=
|
|
||||||
google.golang.org/genproto v0.0.0-20190306203927-b5d61aea6440/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
|
||||||
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
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-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-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||||
@@ -904,28 +736,10 @@ google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6D
|
|||||||
google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
|
||||||
google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
|
||||||
google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A=
|
|
||||||
google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A=
|
|
||||||
google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
|
|
||||||
google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
|
|
||||||
google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
|
|
||||||
google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24=
|
|
||||||
google.golang.org/genproto v0.0.0-20210713002101-d411969a0d9a/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k=
|
|
||||||
google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k=
|
|
||||||
google.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48=
|
|
||||||
google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48=
|
|
||||||
google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w=
|
|
||||||
google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
|
|
||||||
google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
|
|
||||||
google.golang.org/genproto v0.0.0-20220126215142-9970aeb2e350 h1:YxHp5zqIcAShDEvRr5/0rVESVS+njYF68PSdazrNLJo=
|
google.golang.org/genproto v0.0.0-20220126215142-9970aeb2e350 h1:YxHp5zqIcAShDEvRr5/0rVESVS+njYF68PSdazrNLJo=
|
||||||
google.golang.org/genproto v0.0.0-20220126215142-9970aeb2e350/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
google.golang.org/genproto v0.0.0-20220126215142-9970aeb2e350/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||||
google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
|
||||||
google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio=
|
|
||||||
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
|
|
||||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
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.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||||
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||||
@@ -944,16 +758,9 @@ google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv
|
|||||||
google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8=
|
google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8=
|
||||||
google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
||||||
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
||||||
google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
|
||||||
google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
|
|
||||||
google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
|
|
||||||
google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
|
|
||||||
google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=
|
|
||||||
google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=
|
|
||||||
google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
|
google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
|
||||||
google.golang.org/grpc v1.44.0 h1:weqSxi/TMs1SqFRMHCtBgXRs8k3X39QIDEZ0pRcttUg=
|
google.golang.org/grpc v1.51.0 h1:E1eGv1FTqoLIdnBCZufiSHgKjlqG6fKFf6pPWtMTh8U=
|
||||||
google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
|
google.golang.org/grpc v1.51.0/go.mod h1:wgNDFcnuBGmxLKI/qn4T+m5BtEBYXJPvibbUPsAIPww=
|
||||||
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
|
|
||||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
google.golang.org/protobuf v0.0.0-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-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 v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||||
@@ -966,22 +773,23 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj
|
|||||||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||||
google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ=
|
|
||||||
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||||
|
google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
|
||||||
|
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
|
|
||||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
|
||||||
gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE=
|
gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE=
|
||||||
gopkg.in/go-playground/validator.v9 v9.29.1/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ=
|
gopkg.in/go-playground/validator.v9 v9.29.1/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ=
|
||||||
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
|
gopkg.in/ini.v1 v1.66.4 h1:SsAcf+mM7mRZo2nJNGt8mZCjG8ZRaNGMURJw7BsIST4=
|
||||||
gopkg.in/ini.v1 v1.63.2 h1:tGK/CyBg7SMzb60vP1M03vNZ3VDu3wGQJwn7Sxi9r3c=
|
gopkg.in/ini.v1 v1.66.4/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||||
gopkg.in/ini.v1 v1.63.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8=
|
||||||
|
gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k=
|
||||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
|
||||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
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.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
@@ -992,10 +800,8 @@ gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
|||||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
|
|
||||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
|
||||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-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-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-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
@@ -1007,5 +813,3 @@ rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8
|
|||||||
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
|
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
|
||||||
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
||||||
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
|
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
|
||||||
sourcegraph.com/sourcegraph/go-diff v0.5.0/go.mod h1:kuch7UrkMzY0X+p9CRK03kfuPQ2zzQcaEFbx8wA8rck=
|
|
||||||
sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0=
|
|
||||||
|
|||||||
@@ -1,283 +1,145 @@
|
|||||||
log:
|
|
||||||
output: stderr # none, stderr, stdout, /path/to/file
|
|
||||||
level: debug # debug, info, warn, error, fatal
|
|
||||||
format: json # text, json
|
|
||||||
|
|
||||||
services:
|
services:
|
||||||
- name: http+tcp
|
- name: service-0
|
||||||
addr: ":28000"
|
addr: ":8080"
|
||||||
# bypass: bypass01
|
interface: eth0
|
||||||
|
admission: admission-0
|
||||||
|
bypass: bypass-0
|
||||||
|
resolver: resolver-0
|
||||||
|
hosts: hosts-0
|
||||||
handler:
|
handler:
|
||||||
type: http
|
type: http
|
||||||
chain: chain01
|
auth:
|
||||||
metadata:
|
username: user
|
||||||
proxyAgent: "gost/3.0"
|
password: pass
|
||||||
auths:
|
auther: auther-0
|
||||||
- user1:pass1
|
chain: chain-0
|
||||||
- user2:pass2
|
retries: 1
|
||||||
# probeResist: code:404 # code, web, host, file
|
metadata:
|
||||||
# knock: example.com
|
foo: bar
|
||||||
|
bar: baz
|
||||||
listener:
|
listener:
|
||||||
type: tcp
|
type: tcp
|
||||||
|
auth:
|
||||||
|
username: user
|
||||||
|
password: pass
|
||||||
|
auther: auther-0
|
||||||
|
chain: chain-0
|
||||||
|
tls:
|
||||||
|
certFile: cert.pem
|
||||||
|
keyFile: key.pem
|
||||||
|
caFile: ca.pem
|
||||||
metadata:
|
metadata:
|
||||||
keepAlive: 15s
|
abc: xyz
|
||||||
- name: ss
|
def: 456
|
||||||
addr: ":28338"
|
|
||||||
# bypass: bypass01
|
|
||||||
handler:
|
|
||||||
type: ss
|
|
||||||
# chain: chain01
|
|
||||||
metadata:
|
|
||||||
method: chacha20-ietf
|
|
||||||
password: gost
|
|
||||||
readTimeout: 5s
|
|
||||||
udp: true
|
|
||||||
bufferSize: 4096
|
|
||||||
listener:
|
|
||||||
type: tcp
|
|
||||||
metadata:
|
|
||||||
keepAlive: 15s
|
|
||||||
- name: socks5
|
|
||||||
addr: ":21080"
|
|
||||||
# bypass: bypass01
|
|
||||||
handler:
|
|
||||||
type: socks5
|
|
||||||
# chain: chain-ss
|
|
||||||
metadata:
|
|
||||||
auths:
|
|
||||||
- gost:gost
|
|
||||||
readTimeout: 5s
|
|
||||||
notls: true
|
|
||||||
bind: true
|
|
||||||
udp: true
|
|
||||||
# udpBufferSize: 4096 # range [512, 66560]
|
|
||||||
listener:
|
|
||||||
type: tcp
|
|
||||||
metadata:
|
|
||||||
keepAlive: 15s
|
|
||||||
- name: socks5+tcp
|
|
||||||
addr: ":21081"
|
|
||||||
handler:
|
|
||||||
type: socks5
|
|
||||||
metadata:
|
|
||||||
auths:
|
|
||||||
- gost:gost
|
|
||||||
readTimeout: 5s
|
|
||||||
notls: true
|
|
||||||
# udpBufferSize: 1024
|
|
||||||
listener:
|
|
||||||
type: tcp
|
|
||||||
metadata:
|
|
||||||
keepAlive: 15s
|
|
||||||
- name: forward
|
|
||||||
addr: ":10053"
|
|
||||||
forwarder:
|
forwarder:
|
||||||
targets:
|
nodes:
|
||||||
- 192.168.8.8:53
|
- name: target-0
|
||||||
- 192.168.8.1:53
|
addr: 192.168.1.1:1234
|
||||||
- 1.1.1.1:53
|
- name: target-1
|
||||||
|
addr: 192.168.1.2:2345
|
||||||
selector:
|
selector:
|
||||||
strategy: fifo
|
strategy: rand
|
||||||
maxFails: 1
|
maxFails: 1
|
||||||
failTimeout: 30s
|
failTimeout: 30s
|
||||||
handler:
|
|
||||||
type: forward
|
|
||||||
chain: chain-ss
|
|
||||||
metadata:
|
|
||||||
readTimeout: 5s
|
|
||||||
listener:
|
|
||||||
type: udp
|
|
||||||
metadata:
|
|
||||||
keepAlive: 15s
|
|
||||||
|
|
||||||
- name: kcp-forward-tunnel
|
|
||||||
addr: ":8388"
|
|
||||||
forwarder:
|
|
||||||
targets:
|
|
||||||
- 127.0.0.1:28338
|
|
||||||
handler:
|
|
||||||
type: forward
|
|
||||||
metadata:
|
|
||||||
readTimeout: 5s
|
|
||||||
listener:
|
|
||||||
type: kcp
|
|
||||||
metadata:
|
|
||||||
keepAlive: 15s
|
|
||||||
|
|
||||||
- name: rtcp
|
|
||||||
addr: ":28100"
|
|
||||||
forwarder:
|
|
||||||
targets:
|
|
||||||
- 192.168.8.8:80
|
|
||||||
handler:
|
|
||||||
type: forward
|
|
||||||
metadata:
|
|
||||||
readTimeout: 5s
|
|
||||||
listener:
|
|
||||||
type: rtcp
|
|
||||||
# chain: chain-socks5
|
|
||||||
metadata:
|
|
||||||
keepAlive: 15s
|
|
||||||
mux: true
|
|
||||||
- name: rudp
|
|
||||||
addr: ":1053"
|
|
||||||
forwarder:
|
|
||||||
targets:
|
|
||||||
- 192.168.8.8:53
|
|
||||||
- 192.168.8.1:53
|
|
||||||
selector:
|
|
||||||
strategy: round
|
|
||||||
maxFails: 1
|
|
||||||
failTimeout: 30s
|
|
||||||
handler:
|
|
||||||
type: forward
|
|
||||||
metadata:
|
|
||||||
readTimeout: 5s
|
|
||||||
listener:
|
|
||||||
type: rudp
|
|
||||||
chain: chain-socks5
|
|
||||||
metadata:
|
|
||||||
keepAlive: 15s
|
|
||||||
|
|
||||||
chains:
|
chains:
|
||||||
- name: chain01
|
- name: chain-0
|
||||||
# chain level selector
|
|
||||||
selector:
|
selector:
|
||||||
strategy: round
|
strategy: round
|
||||||
maxFails: 1
|
maxFails: 1
|
||||||
failTimeout: 30s
|
failTimeout: 30s
|
||||||
hops:
|
hops:
|
||||||
- name: hop01
|
- name: hop-0
|
||||||
# hop level selector
|
- name: hop-1
|
||||||
|
interface: 192.168.1.2
|
||||||
selector:
|
selector:
|
||||||
strategy: round
|
strategy: rand
|
||||||
maxFails: 1
|
maxFails: 3
|
||||||
failTimeout: 30s
|
failTimeout: 60s
|
||||||
|
bypass: bypass-0
|
||||||
nodes:
|
nodes:
|
||||||
- name: node01
|
- name: node-0
|
||||||
addr: ":8081"
|
addr: ":1080"
|
||||||
# bypass: bypass01
|
interface: eth1
|
||||||
connector:
|
bypass: bypass-0
|
||||||
type: http
|
|
||||||
metadata:
|
|
||||||
userAgent: "gost/3.0"
|
|
||||||
auth: user1:pass1
|
|
||||||
dialer:
|
|
||||||
type: tcp
|
|
||||||
metadata: {}
|
|
||||||
- name: node02
|
|
||||||
addr: ":8082"
|
|
||||||
# bypass: bypass01
|
|
||||||
connector:
|
|
||||||
type: http
|
|
||||||
metadata:
|
|
||||||
userAgent: "gost/3.0"
|
|
||||||
auth: user2:pass2
|
|
||||||
dialer:
|
|
||||||
type: tcp
|
|
||||||
metadata: {}
|
|
||||||
- name: hop02
|
|
||||||
# hop level selector
|
|
||||||
selector:
|
|
||||||
strategy: round
|
|
||||||
maxFails: 1
|
|
||||||
failTimeout: 30s
|
|
||||||
nodes:
|
|
||||||
- name: node03
|
|
||||||
addr: ":8083"
|
|
||||||
# bypass: bypass01
|
|
||||||
connector:
|
|
||||||
type: http
|
|
||||||
metadata:
|
|
||||||
userAgent: "gost/3.0"
|
|
||||||
auth: user3:pass3
|
|
||||||
dialer:
|
|
||||||
type: tcp
|
|
||||||
metadata: {}
|
|
||||||
- name: chain-socks4
|
|
||||||
hops:
|
|
||||||
- name: hop01
|
|
||||||
nodes:
|
|
||||||
- name: node01
|
|
||||||
addr: ":8081"
|
|
||||||
url: "http://gost:gost@:8081"
|
|
||||||
# bypass: bypass01
|
|
||||||
connector:
|
|
||||||
type: socks4
|
|
||||||
metadata: {}
|
|
||||||
dialer:
|
|
||||||
type: tcp
|
|
||||||
metadata: {}
|
|
||||||
- name: chain-socks5
|
|
||||||
hops:
|
|
||||||
- name: hop01
|
|
||||||
nodes:
|
|
||||||
- name: node01
|
|
||||||
addr: ":21080"
|
|
||||||
# bypass: bypass01
|
|
||||||
connector:
|
connector:
|
||||||
type: socks5
|
type: socks5
|
||||||
|
auth:
|
||||||
|
username: user
|
||||||
|
password: pass
|
||||||
metadata:
|
metadata:
|
||||||
notls: true
|
foo: bar
|
||||||
auth: gost:gost
|
|
||||||
dialer:
|
dialer:
|
||||||
type: tcp
|
type: tcp
|
||||||
metadata: {}
|
auth:
|
||||||
- name: chain-ss
|
username: user
|
||||||
hops:
|
password: pass
|
||||||
- name: hop01
|
tls:
|
||||||
nodes:
|
caFile: "ca.pem"
|
||||||
- name: node01
|
secure: true
|
||||||
addr: ":28338"
|
serverName: "example.com"
|
||||||
url: "http://gost:gost@:8081"
|
metadata:
|
||||||
# bypass: bypass01
|
bar: baz
|
||||||
connector:
|
|
||||||
type: ss
|
hops:
|
||||||
metadata:
|
- name: hop-0
|
||||||
method: chacha20-ietf
|
interface: 192.168.1.2
|
||||||
password: gost
|
selector:
|
||||||
readTimeout: 5s
|
strategy: rand
|
||||||
nodelay: true
|
maxFails: 3
|
||||||
udp: true
|
failTimeout: 60s
|
||||||
bufferSize: 4096
|
bypass: bypass-0
|
||||||
dialer:
|
nodes:
|
||||||
type: tcp
|
- name: node-0
|
||||||
metadata: {}
|
addr: ":1080"
|
||||||
|
interface: eth1
|
||||||
|
bypass: bypass-0
|
||||||
|
connector:
|
||||||
|
type: socks5
|
||||||
|
auth:
|
||||||
|
username: user
|
||||||
|
password: pass
|
||||||
|
metadata:
|
||||||
|
foo: bar
|
||||||
|
dialer:
|
||||||
|
type: tcp
|
||||||
|
auth:
|
||||||
|
username: user
|
||||||
|
password: pass
|
||||||
|
tls:
|
||||||
|
caFile: "ca.pem"
|
||||||
|
secure: true
|
||||||
|
serverName: "example.com"
|
||||||
|
metadata:
|
||||||
|
bar: baz
|
||||||
|
|
||||||
|
tls:
|
||||||
|
certFile: "cert.pem"
|
||||||
|
keyFile: "key.pem"
|
||||||
|
caFile: "ca.pem"
|
||||||
|
|
||||||
|
authers:
|
||||||
|
- name: auther-0
|
||||||
|
auths:
|
||||||
|
- username: user1
|
||||||
|
password: pass1
|
||||||
|
- username: user2
|
||||||
|
password: pass2
|
||||||
|
|
||||||
|
admissions:
|
||||||
|
- name: admission-0
|
||||||
|
whitelist: false
|
||||||
|
matchers:
|
||||||
|
- 127.0.0.1
|
||||||
|
- 192.168.0.0/16
|
||||||
|
|
||||||
bypasses:
|
bypasses:
|
||||||
- name: bypass-0
|
- name: bypass-0
|
||||||
reverse: false
|
whitelist: false
|
||||||
matchers:
|
matchers:
|
||||||
- .baidu.com
|
- "*.example.com"
|
||||||
- "*.example.com" # domain wildcard
|
- .example.org
|
||||||
- .example.org # will match example.org and *.example.org
|
- 0.0.0.0/8
|
||||||
|
|
||||||
# From IANA IPv4 Special-Purpose Address Registry
|
|
||||||
# http://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml
|
|
||||||
- 0.0.0.0/8 # RFC1122: "This host on this network"
|
|
||||||
- 10.0.0.0/8 # RFC1918: Private-Use
|
|
||||||
- 100.64.0.0/10 # RFC6598: Shared Address Space
|
|
||||||
- 127.0.0.0/8 # RFC1122: Loopback
|
|
||||||
- 169.254.0.0/16 # RFC3927: Link Local
|
|
||||||
- 172.16.0.0/12 # RFC1918: Private-Use
|
|
||||||
- 192.0.0.0/24 # RFC6890: IETF Protocol Assignments
|
|
||||||
- 192.0.2.0/24 # RFC5737: Documentation (TEST-NET-1)
|
|
||||||
- 192.88.99.0/24 # RFC3068: 6to4 Relay Anycast
|
|
||||||
- 192.168.0.0/16 # RFC1918: Private-Use
|
|
||||||
- 198.18.0.0/15 # RFC2544: Benchmarking
|
|
||||||
- 198.51.100.0/24 # RFC5737: Documentation (TEST-NET-2)
|
|
||||||
- 203.0.113.0/24 # RFC5737: Documentation (TEST-NET-3)
|
|
||||||
- 240.0.0.0/4 # RFC1112: Reserved
|
|
||||||
- 255.255.255.255/32 # RFC0919: Limited Broadcast
|
|
||||||
|
|
||||||
# From IANA Multicast Address Space Registry
|
|
||||||
# http://www.iana.org/assignments/multicast-addresses/multicast-addresses.xhtml
|
|
||||||
- 224.0.0.0/4 # RFC5771: Multicast/Reserved
|
|
||||||
|
|
||||||
tls:
|
|
||||||
cert: "cert.pem"
|
|
||||||
key: "key.pem"
|
|
||||||
# ca: "root.ca"
|
|
||||||
|
|
||||||
resolvers:
|
resolvers:
|
||||||
- name: resolver-0
|
- name: resolver-0
|
||||||
@@ -308,6 +170,23 @@ hosts:
|
|||||||
- bar
|
- bar
|
||||||
- baz
|
- baz
|
||||||
|
|
||||||
|
log:
|
||||||
|
output: stderr
|
||||||
|
level: debug
|
||||||
|
format: json
|
||||||
|
|
||||||
profiling:
|
profiling:
|
||||||
addr: ":6060"
|
addr: ":6060"
|
||||||
enabled: true
|
|
||||||
|
api:
|
||||||
|
addr: ":18080"
|
||||||
|
pathPrefix: /api
|
||||||
|
accesslog: true
|
||||||
|
auth:
|
||||||
|
username: user
|
||||||
|
password: pass
|
||||||
|
auther: auther-0
|
||||||
|
|
||||||
|
metrics:
|
||||||
|
addr: :9000
|
||||||
|
path: /metrics
|
||||||
|
|||||||
@@ -1,85 +0,0 @@
|
|||||||
package admission
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net"
|
|
||||||
"strconv"
|
|
||||||
|
|
||||||
"github.com/go-gost/gost/pkg/common/matcher"
|
|
||||||
"github.com/go-gost/gost/pkg/logger"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Admission interface {
|
|
||||||
Admit(addr string) bool
|
|
||||||
}
|
|
||||||
|
|
||||||
type options struct {
|
|
||||||
logger logger.Logger
|
|
||||||
}
|
|
||||||
|
|
||||||
type Option func(opts *options)
|
|
||||||
|
|
||||||
func LoggerOption(logger logger.Logger) Option {
|
|
||||||
return func(opts *options) {
|
|
||||||
opts.logger = logger
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type admission struct {
|
|
||||||
matchers []matcher.Matcher
|
|
||||||
reversed bool
|
|
||||||
options options
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewAdmission creates and initializes a new Admission using matchers as its match rules.
|
|
||||||
// The rules will be reversed if the reversed is true.
|
|
||||||
func NewAdmission(reversed bool, matchers []matcher.Matcher, opts ...Option) Admission {
|
|
||||||
options := options{}
|
|
||||||
for _, opt := range opts {
|
|
||||||
opt(&options)
|
|
||||||
}
|
|
||||||
return &admission{
|
|
||||||
matchers: matchers,
|
|
||||||
reversed: reversed,
|
|
||||||
options: options,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewAdmissionPatterns creates and initializes a new Admission using matcher patterns as its match rules.
|
|
||||||
// The rules will be reversed if the reverse is true.
|
|
||||||
func NewAdmissionPatterns(reversed bool, patterns []string, opts ...Option) Admission {
|
|
||||||
var matchers []matcher.Matcher
|
|
||||||
for _, pattern := range patterns {
|
|
||||||
if m := matcher.NewMatcher(pattern); m != nil {
|
|
||||||
matchers = append(matchers, m)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return NewAdmission(reversed, matchers, opts...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *admission) Admit(addr string) bool {
|
|
||||||
if addr == "" || p == nil || len(p.matchers) == 0 {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// try to strip the port
|
|
||||||
if host, port, _ := net.SplitHostPort(addr); host != "" && port != "" {
|
|
||||||
if p, _ := strconv.Atoi(port); p > 0 { // port is valid
|
|
||||||
addr = host
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var matched bool
|
|
||||||
for _, matcher := range p.matchers {
|
|
||||||
if matcher == nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if matcher.Match(addr) {
|
|
||||||
matched = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
b := !p.reversed && matched ||
|
|
||||||
p.reversed && !matched
|
|
||||||
return b
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
package api
|
|
||||||
|
|
||||||
import (
|
|
||||||
"embed"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
//go:embed swagger.yaml
|
|
||||||
swaggerDoc embed.FS
|
|
||||||
)
|
|
||||||
|
|
||||||
type Response struct {
|
|
||||||
Code int `json:"code,omitempty"`
|
|
||||||
Msg string `json:"msg,omitempty"`
|
|
||||||
}
|
|
||||||
@@ -1,118 +0,0 @@
|
|||||||
package api
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
"os"
|
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"github.com/go-gost/gost/pkg/config"
|
|
||||||
)
|
|
||||||
|
|
||||||
// swagger:parameters getConfigRequest
|
|
||||||
type getConfigRequest struct {
|
|
||||||
// output format, one of yaml|json, default is json.
|
|
||||||
// in: query
|
|
||||||
Format string `form:"format" json:"format"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// successful operation.
|
|
||||||
// swagger:response getConfigResponse
|
|
||||||
type getConfigResponse struct {
|
|
||||||
Config *config.Config
|
|
||||||
}
|
|
||||||
|
|
||||||
func getConfig(ctx *gin.Context) {
|
|
||||||
// swagger:route GET /config ConfigManagement getConfigRequest
|
|
||||||
//
|
|
||||||
// Get current config.
|
|
||||||
//
|
|
||||||
// Security:
|
|
||||||
// basicAuth: []
|
|
||||||
//
|
|
||||||
// Responses:
|
|
||||||
// 200: getConfigResponse
|
|
||||||
|
|
||||||
var req getConfigRequest
|
|
||||||
ctx.ShouldBindQuery(&req)
|
|
||||||
|
|
||||||
var resp getConfigResponse
|
|
||||||
resp.Config = config.Global()
|
|
||||||
|
|
||||||
buf := &bytes.Buffer{}
|
|
||||||
switch req.Format {
|
|
||||||
case "yaml":
|
|
||||||
default:
|
|
||||||
req.Format = "json"
|
|
||||||
}
|
|
||||||
|
|
||||||
resp.Config.Write(buf, req.Format)
|
|
||||||
|
|
||||||
contentType := "application/json"
|
|
||||||
if req.Format == "yaml" {
|
|
||||||
contentType = "text/x-yaml"
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx.Data(http.StatusOK, contentType, buf.Bytes())
|
|
||||||
}
|
|
||||||
|
|
||||||
// swagger:parameters saveConfigRequest
|
|
||||||
type saveConfigRequest struct {
|
|
||||||
// output format, one of yaml|json, default is yaml.
|
|
||||||
// in: query
|
|
||||||
Format string `form:"format" json:"format"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// successful operation.
|
|
||||||
// swagger:response saveConfigResponse
|
|
||||||
type saveConfigResponse struct {
|
|
||||||
Data Response
|
|
||||||
}
|
|
||||||
|
|
||||||
func saveConfig(ctx *gin.Context) {
|
|
||||||
// swagger:route POST /config ConfigManagement saveConfigRequest
|
|
||||||
//
|
|
||||||
// Save current config to file (gost.yaml or gost.json).
|
|
||||||
//
|
|
||||||
// Security:
|
|
||||||
// basicAuth: []
|
|
||||||
//
|
|
||||||
// Responses:
|
|
||||||
// 200: saveConfigResponse
|
|
||||||
|
|
||||||
var req saveConfigRequest
|
|
||||||
ctx.ShouldBindQuery(&req)
|
|
||||||
|
|
||||||
file := "gost.yaml"
|
|
||||||
switch req.Format {
|
|
||||||
case "json":
|
|
||||||
file = "gost.json"
|
|
||||||
default:
|
|
||||||
req.Format = "yaml"
|
|
||||||
}
|
|
||||||
|
|
||||||
f, err := os.Create(file)
|
|
||||||
if err != nil {
|
|
||||||
writeError(ctx, &Error{
|
|
||||||
statusCode: http.StatusInternalServerError,
|
|
||||||
Code: 40005,
|
|
||||||
Msg: fmt.Sprintf("create file: %s", err.Error()),
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer f.Close()
|
|
||||||
|
|
||||||
if err := config.Global().Write(f, req.Format); err != nil {
|
|
||||||
writeError(ctx, &Error{
|
|
||||||
statusCode: http.StatusInternalServerError,
|
|
||||||
Code: 40006,
|
|
||||||
Msg: fmt.Sprintf("write: %s", err.Error()),
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx.JSON(http.StatusOK, Response{
|
|
||||||
Msg: "OK",
|
|
||||||
})
|
|
||||||
}
|
|
||||||
@@ -1,166 +0,0 @@
|
|||||||
package api
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/http"
|
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"github.com/go-gost/gost/pkg/config"
|
|
||||||
"github.com/go-gost/gost/pkg/config/parsing"
|
|
||||||
"github.com/go-gost/gost/pkg/registry"
|
|
||||||
)
|
|
||||||
|
|
||||||
// swagger:parameters createAdmissionRequest
|
|
||||||
type createAdmissionRequest struct {
|
|
||||||
// in: body
|
|
||||||
Data config.AdmissionConfig `json:"data"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// successful operation.
|
|
||||||
// swagger:response createAdmissionResponse
|
|
||||||
type createAdmissionResponse struct {
|
|
||||||
Data Response
|
|
||||||
}
|
|
||||||
|
|
||||||
func createAdmission(ctx *gin.Context) {
|
|
||||||
// swagger:route POST /config/admissions ConfigManagement createAdmissionRequest
|
|
||||||
//
|
|
||||||
// Create a new admission, the name of admission must be unique in admission list.
|
|
||||||
//
|
|
||||||
// Security:
|
|
||||||
// basicAuth: []
|
|
||||||
//
|
|
||||||
// Responses:
|
|
||||||
// 200: createAdmissionResponse
|
|
||||||
|
|
||||||
var req createAdmissionRequest
|
|
||||||
ctx.ShouldBindJSON(&req.Data)
|
|
||||||
|
|
||||||
if req.Data.Name == "" {
|
|
||||||
writeError(ctx, ErrInvalid)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
v := parsing.ParseAdmission(&req.Data)
|
|
||||||
|
|
||||||
if err := registry.AdmissionRegistry().Register(req.Data.Name, v); err != nil {
|
|
||||||
writeError(ctx, ErrDup)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
cfg := config.Global()
|
|
||||||
cfg.Admissions = append(cfg.Admissions, &req.Data)
|
|
||||||
config.SetGlobal(cfg)
|
|
||||||
|
|
||||||
ctx.JSON(http.StatusOK, Response{
|
|
||||||
Msg: "OK",
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// swagger:parameters updateAdmissionRequest
|
|
||||||
type updateAdmissionRequest struct {
|
|
||||||
// in: path
|
|
||||||
// required: true
|
|
||||||
Admission string `uri:"admission" json:"admission"`
|
|
||||||
// in: body
|
|
||||||
Data config.AdmissionConfig `json:"data"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// successful operation.
|
|
||||||
// swagger:response updateAdmissionResponse
|
|
||||||
type updateAdmissionResponse struct {
|
|
||||||
Data Response
|
|
||||||
}
|
|
||||||
|
|
||||||
func updateAdmission(ctx *gin.Context) {
|
|
||||||
// swagger:route PUT /config/admissions/{admission} ConfigManagement updateAdmissionRequest
|
|
||||||
//
|
|
||||||
// Update admission by name, the admission must already exist.
|
|
||||||
//
|
|
||||||
// Security:
|
|
||||||
// basicAuth: []
|
|
||||||
//
|
|
||||||
// Responses:
|
|
||||||
// 200: updateAdmissionResponse
|
|
||||||
|
|
||||||
var req updateAdmissionRequest
|
|
||||||
ctx.ShouldBindUri(&req)
|
|
||||||
ctx.ShouldBindJSON(&req.Data)
|
|
||||||
|
|
||||||
if !registry.AdmissionRegistry().IsRegistered(req.Admission) {
|
|
||||||
writeError(ctx, ErrNotFound)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
req.Data.Name = req.Admission
|
|
||||||
|
|
||||||
v := parsing.ParseAdmission(&req.Data)
|
|
||||||
|
|
||||||
registry.AdmissionRegistry().Unregister(req.Admission)
|
|
||||||
|
|
||||||
if err := registry.AdmissionRegistry().Register(req.Admission, v); err != nil {
|
|
||||||
writeError(ctx, ErrDup)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
cfg := config.Global()
|
|
||||||
for i := range cfg.Admissions {
|
|
||||||
if cfg.Admissions[i].Name == req.Admission {
|
|
||||||
cfg.Admissions[i] = &req.Data
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
config.SetGlobal(cfg)
|
|
||||||
|
|
||||||
ctx.JSON(http.StatusOK, Response{
|
|
||||||
Msg: "OK",
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// swagger:parameters deleteAdmissionRequest
|
|
||||||
type deleteAdmissionRequest struct {
|
|
||||||
// in: path
|
|
||||||
// required: true
|
|
||||||
Admission string `uri:"admission" json:"admission"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// successful operation.
|
|
||||||
// swagger:response deleteAdmissionResponse
|
|
||||||
type deleteAdmissionResponse struct {
|
|
||||||
Data Response
|
|
||||||
}
|
|
||||||
|
|
||||||
func deleteAdmission(ctx *gin.Context) {
|
|
||||||
// swagger:route DELETE /config/admissions/{admission} ConfigManagement deleteAdmissionRequest
|
|
||||||
//
|
|
||||||
// Delete admission by name.
|
|
||||||
//
|
|
||||||
// Security:
|
|
||||||
// basicAuth: []
|
|
||||||
//
|
|
||||||
// Responses:
|
|
||||||
// 200: deleteAdmissionResponse
|
|
||||||
|
|
||||||
var req deleteAdmissionRequest
|
|
||||||
ctx.ShouldBindUri(&req)
|
|
||||||
|
|
||||||
if !registry.AdmissionRegistry().IsRegistered(req.Admission) {
|
|
||||||
writeError(ctx, ErrNotFound)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
registry.AdmissionRegistry().Unregister(req.Admission)
|
|
||||||
|
|
||||||
cfg := config.Global()
|
|
||||||
admissiones := cfg.Admissions
|
|
||||||
cfg.Admissions = nil
|
|
||||||
for _, s := range admissiones {
|
|
||||||
if s.Name == req.Admission {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
cfg.Admissions = append(cfg.Admissions, s)
|
|
||||||
}
|
|
||||||
config.SetGlobal(cfg)
|
|
||||||
|
|
||||||
ctx.JSON(http.StatusOK, Response{
|
|
||||||
Msg: "OK",
|
|
||||||
})
|
|
||||||
}
|
|
||||||
@@ -1,164 +0,0 @@
|
|||||||
package api
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/http"
|
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"github.com/go-gost/gost/pkg/config"
|
|
||||||
"github.com/go-gost/gost/pkg/config/parsing"
|
|
||||||
"github.com/go-gost/gost/pkg/registry"
|
|
||||||
)
|
|
||||||
|
|
||||||
// swagger:parameters createAutherRequest
|
|
||||||
type createAutherRequest struct {
|
|
||||||
// in: body
|
|
||||||
Data config.AutherConfig `json:"data"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// successful operation.
|
|
||||||
// swagger:response createAutherResponse
|
|
||||||
type createAutherResponse struct {
|
|
||||||
Data Response
|
|
||||||
}
|
|
||||||
|
|
||||||
func createAuther(ctx *gin.Context) {
|
|
||||||
// swagger:route POST /config/authers ConfigManagement createAutherRequest
|
|
||||||
//
|
|
||||||
// Create a new auther, the name of the auther must be unique in auther list.
|
|
||||||
//
|
|
||||||
// Security:
|
|
||||||
// basicAuth: []
|
|
||||||
//
|
|
||||||
// Responses:
|
|
||||||
// 200: createAutherResponse
|
|
||||||
|
|
||||||
var req createAutherRequest
|
|
||||||
ctx.ShouldBindJSON(&req.Data)
|
|
||||||
|
|
||||||
if req.Data.Name == "" {
|
|
||||||
writeError(ctx, ErrInvalid)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
v := parsing.ParseAuther(&req.Data)
|
|
||||||
if err := registry.AutherRegistry().Register(req.Data.Name, v); err != nil {
|
|
||||||
writeError(ctx, ErrDup)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
cfg := config.Global()
|
|
||||||
cfg.Authers = append(cfg.Authers, &req.Data)
|
|
||||||
config.SetGlobal(cfg)
|
|
||||||
|
|
||||||
ctx.JSON(http.StatusOK, Response{
|
|
||||||
Msg: "OK",
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// swagger:parameters updateAutherRequest
|
|
||||||
type updateAutherRequest struct {
|
|
||||||
// in: path
|
|
||||||
// required: true
|
|
||||||
Auther string `uri:"auther" json:"auther"`
|
|
||||||
// in: body
|
|
||||||
Data config.AutherConfig `json:"data"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// successful operation.
|
|
||||||
// swagger:response updateAutherResponse
|
|
||||||
type updateAutherResponse struct {
|
|
||||||
Data Response
|
|
||||||
}
|
|
||||||
|
|
||||||
func updateAuther(ctx *gin.Context) {
|
|
||||||
// swagger:route PUT /config/authers/{auther} ConfigManagement updateAutherRequest
|
|
||||||
//
|
|
||||||
// Update auther by name, the auther must already exist.
|
|
||||||
//
|
|
||||||
// Security:
|
|
||||||
// basicAuth: []
|
|
||||||
//
|
|
||||||
// Responses:
|
|
||||||
// 200: updateAutherResponse
|
|
||||||
|
|
||||||
var req updateAutherRequest
|
|
||||||
ctx.ShouldBindUri(&req)
|
|
||||||
ctx.ShouldBindJSON(&req.Data)
|
|
||||||
|
|
||||||
if !registry.AutherRegistry().IsRegistered(req.Auther) {
|
|
||||||
writeError(ctx, ErrNotFound)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
req.Data.Name = req.Auther
|
|
||||||
|
|
||||||
v := parsing.ParseAuther(&req.Data)
|
|
||||||
registry.AutherRegistry().Unregister(req.Auther)
|
|
||||||
|
|
||||||
if err := registry.AutherRegistry().Register(req.Auther, v); err != nil {
|
|
||||||
writeError(ctx, ErrDup)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
cfg := config.Global()
|
|
||||||
for i := range cfg.Authers {
|
|
||||||
if cfg.Authers[i].Name == req.Auther {
|
|
||||||
cfg.Authers[i] = &req.Data
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
config.SetGlobal(cfg)
|
|
||||||
|
|
||||||
ctx.JSON(http.StatusOK, Response{
|
|
||||||
Msg: "OK",
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// swagger:parameters deleteAutherRequest
|
|
||||||
type deleteAutherRequest struct {
|
|
||||||
// in: path
|
|
||||||
// required: true
|
|
||||||
Auther string `uri:"auther" json:"auther"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// successful operation.
|
|
||||||
// swagger:response deleteAutherResponse
|
|
||||||
type deleteAutherResponse struct {
|
|
||||||
Data Response
|
|
||||||
}
|
|
||||||
|
|
||||||
func deleteAuther(ctx *gin.Context) {
|
|
||||||
// swagger:route DELETE /config/authers/{auther} ConfigManagement deleteAutherRequest
|
|
||||||
//
|
|
||||||
// Delete auther by name.
|
|
||||||
//
|
|
||||||
// Security:
|
|
||||||
// basicAuth: []
|
|
||||||
//
|
|
||||||
// Responses:
|
|
||||||
// 200: deleteAutherResponse
|
|
||||||
|
|
||||||
var req deleteAutherRequest
|
|
||||||
ctx.ShouldBindUri(&req)
|
|
||||||
|
|
||||||
if !registry.AutherRegistry().IsRegistered(req.Auther) {
|
|
||||||
writeError(ctx, ErrNotFound)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
registry.AutherRegistry().Unregister(req.Auther)
|
|
||||||
|
|
||||||
cfg := config.Global()
|
|
||||||
authers := cfg.Authers
|
|
||||||
cfg.Authers = nil
|
|
||||||
for _, s := range authers {
|
|
||||||
if s.Name == req.Auther {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
cfg.Authers = append(cfg.Authers, s)
|
|
||||||
}
|
|
||||||
config.SetGlobal(cfg)
|
|
||||||
|
|
||||||
ctx.JSON(http.StatusOK, Response{
|
|
||||||
Msg: "OK",
|
|
||||||
})
|
|
||||||
}
|
|
||||||
@@ -1,166 +0,0 @@
|
|||||||
package api
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/http"
|
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"github.com/go-gost/gost/pkg/config"
|
|
||||||
"github.com/go-gost/gost/pkg/config/parsing"
|
|
||||||
"github.com/go-gost/gost/pkg/registry"
|
|
||||||
)
|
|
||||||
|
|
||||||
// swagger:parameters createBypassRequest
|
|
||||||
type createBypassRequest struct {
|
|
||||||
// in: body
|
|
||||||
Data config.BypassConfig `json:"data"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// successful operation.
|
|
||||||
// swagger:response createBypassResponse
|
|
||||||
type createBypassResponse struct {
|
|
||||||
Data Response
|
|
||||||
}
|
|
||||||
|
|
||||||
func createBypass(ctx *gin.Context) {
|
|
||||||
// swagger:route POST /config/bypasses ConfigManagement createBypassRequest
|
|
||||||
//
|
|
||||||
// Create a new bypass, the name of bypass must be unique in bypass list.
|
|
||||||
//
|
|
||||||
// Security:
|
|
||||||
// basicAuth: []
|
|
||||||
//
|
|
||||||
// Responses:
|
|
||||||
// 200: createBypassResponse
|
|
||||||
|
|
||||||
var req createBypassRequest
|
|
||||||
ctx.ShouldBindJSON(&req.Data)
|
|
||||||
|
|
||||||
if req.Data.Name == "" {
|
|
||||||
writeError(ctx, ErrInvalid)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
v := parsing.ParseBypass(&req.Data)
|
|
||||||
|
|
||||||
if err := registry.BypassRegistry().Register(req.Data.Name, v); err != nil {
|
|
||||||
writeError(ctx, ErrDup)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
cfg := config.Global()
|
|
||||||
cfg.Bypasses = append(cfg.Bypasses, &req.Data)
|
|
||||||
config.SetGlobal(cfg)
|
|
||||||
|
|
||||||
ctx.JSON(http.StatusOK, Response{
|
|
||||||
Msg: "OK",
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// swagger:parameters updateBypassRequest
|
|
||||||
type updateBypassRequest struct {
|
|
||||||
// in: path
|
|
||||||
// required: true
|
|
||||||
Bypass string `uri:"bypass" json:"bypass"`
|
|
||||||
// in: body
|
|
||||||
Data config.BypassConfig `json:"data"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// successful operation.
|
|
||||||
// swagger:response updateBypassResponse
|
|
||||||
type updateBypassResponse struct {
|
|
||||||
Data Response
|
|
||||||
}
|
|
||||||
|
|
||||||
func updateBypass(ctx *gin.Context) {
|
|
||||||
// swagger:route PUT /config/bypasses/{bypass} ConfigManagement updateBypassRequest
|
|
||||||
//
|
|
||||||
// Update bypass by name, the bypass must already exist.
|
|
||||||
//
|
|
||||||
// Security:
|
|
||||||
// basicAuth: []
|
|
||||||
//
|
|
||||||
// Responses:
|
|
||||||
// 200: updateBypassResponse
|
|
||||||
|
|
||||||
var req updateBypassRequest
|
|
||||||
ctx.ShouldBindUri(&req)
|
|
||||||
ctx.ShouldBindJSON(&req.Data)
|
|
||||||
|
|
||||||
if !registry.BypassRegistry().IsRegistered(req.Bypass) {
|
|
||||||
writeError(ctx, ErrNotFound)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
req.Data.Name = req.Bypass
|
|
||||||
|
|
||||||
v := parsing.ParseBypass(&req.Data)
|
|
||||||
|
|
||||||
registry.BypassRegistry().Unregister(req.Bypass)
|
|
||||||
|
|
||||||
if err := registry.BypassRegistry().Register(req.Bypass, v); err != nil {
|
|
||||||
writeError(ctx, ErrDup)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
cfg := config.Global()
|
|
||||||
for i := range cfg.Bypasses {
|
|
||||||
if cfg.Bypasses[i].Name == req.Bypass {
|
|
||||||
cfg.Bypasses[i] = &req.Data
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
config.SetGlobal(cfg)
|
|
||||||
|
|
||||||
ctx.JSON(http.StatusOK, Response{
|
|
||||||
Msg: "OK",
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// swagger:parameters deleteBypassRequest
|
|
||||||
type deleteBypassRequest struct {
|
|
||||||
// in: path
|
|
||||||
// required: true
|
|
||||||
Bypass string `uri:"bypass" json:"bypass"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// successful operation.
|
|
||||||
// swagger:response deleteBypassResponse
|
|
||||||
type deleteBypassResponse struct {
|
|
||||||
Data Response
|
|
||||||
}
|
|
||||||
|
|
||||||
func deleteBypass(ctx *gin.Context) {
|
|
||||||
// swagger:route DELETE /config/bypasses/{bypass} ConfigManagement deleteBypassRequest
|
|
||||||
//
|
|
||||||
// Delete bypass by name.
|
|
||||||
//
|
|
||||||
// Security:
|
|
||||||
// basicAuth: []
|
|
||||||
//
|
|
||||||
// Responses:
|
|
||||||
// 200: deleteBypassResponse
|
|
||||||
|
|
||||||
var req deleteBypassRequest
|
|
||||||
ctx.ShouldBindUri(&req)
|
|
||||||
|
|
||||||
if !registry.BypassRegistry().IsRegistered(req.Bypass) {
|
|
||||||
writeError(ctx, ErrNotFound)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
registry.BypassRegistry().Unregister(req.Bypass)
|
|
||||||
|
|
||||||
cfg := config.Global()
|
|
||||||
bypasses := cfg.Bypasses
|
|
||||||
cfg.Bypasses = nil
|
|
||||||
for _, s := range bypasses {
|
|
||||||
if s.Name == req.Bypass {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
cfg.Bypasses = append(cfg.Bypasses, s)
|
|
||||||
}
|
|
||||||
config.SetGlobal(cfg)
|
|
||||||
|
|
||||||
ctx.JSON(http.StatusOK, Response{
|
|
||||||
Msg: "OK",
|
|
||||||
})
|
|
||||||
}
|
|
||||||
@@ -1,175 +0,0 @@
|
|||||||
package api
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/http"
|
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"github.com/go-gost/gost/pkg/config"
|
|
||||||
"github.com/go-gost/gost/pkg/config/parsing"
|
|
||||||
"github.com/go-gost/gost/pkg/registry"
|
|
||||||
)
|
|
||||||
|
|
||||||
// swagger:parameters createChainRequest
|
|
||||||
type createChainRequest struct {
|
|
||||||
// in: body
|
|
||||||
Data config.ChainConfig `json:"data"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// successful operation.
|
|
||||||
// swagger:response createChainResponse
|
|
||||||
type createChainResponse struct {
|
|
||||||
Data Response
|
|
||||||
}
|
|
||||||
|
|
||||||
func createChain(ctx *gin.Context) {
|
|
||||||
// swagger:route POST /config/chains ConfigManagement createChainRequest
|
|
||||||
//
|
|
||||||
// Create a new chain, the name of chain must be unique in chain list.
|
|
||||||
//
|
|
||||||
// Security:
|
|
||||||
// basicAuth: []
|
|
||||||
//
|
|
||||||
// Responses:
|
|
||||||
// 200: createChainResponse
|
|
||||||
|
|
||||||
var req createChainRequest
|
|
||||||
ctx.ShouldBindJSON(&req.Data)
|
|
||||||
|
|
||||||
if req.Data.Name == "" {
|
|
||||||
writeError(ctx, ErrInvalid)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
v, err := parsing.ParseChain(&req.Data)
|
|
||||||
if err != nil {
|
|
||||||
writeError(ctx, ErrCreate)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := registry.ChainRegistry().Register(req.Data.Name, v); err != nil {
|
|
||||||
writeError(ctx, ErrDup)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
cfg := config.Global()
|
|
||||||
cfg.Chains = append(cfg.Chains, &req.Data)
|
|
||||||
config.SetGlobal(cfg)
|
|
||||||
|
|
||||||
ctx.JSON(http.StatusOK, Response{
|
|
||||||
Msg: "OK",
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// swagger:parameters updateChainRequest
|
|
||||||
type updateChainRequest struct {
|
|
||||||
// in: path
|
|
||||||
// required: true
|
|
||||||
// chain name
|
|
||||||
Chain string `uri:"chain" json:"chain"`
|
|
||||||
// in: body
|
|
||||||
Data config.ChainConfig `json:"data"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// successful operation.
|
|
||||||
// swagger:response updateChainResponse
|
|
||||||
type updateChainResponse struct {
|
|
||||||
Data Response
|
|
||||||
}
|
|
||||||
|
|
||||||
func updateChain(ctx *gin.Context) {
|
|
||||||
// swagger:route PUT /config/chains/{chain} ConfigManagement updateChainRequest
|
|
||||||
//
|
|
||||||
// Update chain by name, the chain must already exist.
|
|
||||||
//
|
|
||||||
// Security:
|
|
||||||
// basicAuth: []
|
|
||||||
//
|
|
||||||
// Responses:
|
|
||||||
// 200: updateChainResponse
|
|
||||||
|
|
||||||
var req updateChainRequest
|
|
||||||
ctx.ShouldBindUri(&req)
|
|
||||||
ctx.ShouldBindJSON(&req.Data)
|
|
||||||
|
|
||||||
if !registry.ChainRegistry().IsRegistered(req.Chain) {
|
|
||||||
writeError(ctx, ErrNotFound)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
req.Data.Name = req.Chain
|
|
||||||
|
|
||||||
v, err := parsing.ParseChain(&req.Data)
|
|
||||||
if err != nil {
|
|
||||||
writeError(ctx, ErrCreate)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
registry.ChainRegistry().Unregister(req.Chain)
|
|
||||||
|
|
||||||
if err := registry.ChainRegistry().Register(req.Chain, v); err != nil {
|
|
||||||
writeError(ctx, ErrDup)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
cfg := config.Global()
|
|
||||||
for i := range cfg.Chains {
|
|
||||||
if cfg.Chains[i].Name == req.Chain {
|
|
||||||
cfg.Chains[i] = &req.Data
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
config.SetGlobal(cfg)
|
|
||||||
|
|
||||||
ctx.JSON(http.StatusOK, Response{
|
|
||||||
Msg: "OK",
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// swagger:parameters deleteChainRequest
|
|
||||||
type deleteChainRequest struct {
|
|
||||||
// in: path
|
|
||||||
// required: true
|
|
||||||
Chain string `uri:"chain" json:"chain"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// successful operation.
|
|
||||||
// swagger:response deleteChainResponse
|
|
||||||
type deleteChainResponse struct {
|
|
||||||
Data Response
|
|
||||||
}
|
|
||||||
|
|
||||||
func deleteChain(ctx *gin.Context) {
|
|
||||||
// swagger:route DELETE /config/chains/{chain} ConfigManagement deleteChainRequest
|
|
||||||
//
|
|
||||||
// Delete chain by name.
|
|
||||||
//
|
|
||||||
// Security:
|
|
||||||
// basicAuth: []
|
|
||||||
//
|
|
||||||
// Responses:
|
|
||||||
// 200: deleteChainResponse
|
|
||||||
|
|
||||||
var req deleteChainRequest
|
|
||||||
ctx.ShouldBindUri(&req)
|
|
||||||
|
|
||||||
if !registry.ChainRegistry().IsRegistered(req.Chain) {
|
|
||||||
writeError(ctx, ErrNotFound)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
registry.ChainRegistry().Unregister(req.Chain)
|
|
||||||
|
|
||||||
cfg := config.Global()
|
|
||||||
chains := cfg.Chains
|
|
||||||
cfg.Chains = nil
|
|
||||||
for _, s := range chains {
|
|
||||||
if s.Name == req.Chain {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
cfg.Chains = append(cfg.Chains, s)
|
|
||||||
}
|
|
||||||
config.SetGlobal(cfg)
|
|
||||||
|
|
||||||
ctx.JSON(http.StatusOK, Response{
|
|
||||||
Msg: "OK",
|
|
||||||
})
|
|
||||||
}
|
|
||||||
@@ -1,166 +0,0 @@
|
|||||||
package api
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/http"
|
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"github.com/go-gost/gost/pkg/config"
|
|
||||||
"github.com/go-gost/gost/pkg/config/parsing"
|
|
||||||
"github.com/go-gost/gost/pkg/registry"
|
|
||||||
)
|
|
||||||
|
|
||||||
// swagger:parameters createHostsRequest
|
|
||||||
type createHostsRequest struct {
|
|
||||||
// in: body
|
|
||||||
Data config.HostsConfig `json:"data"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// successful operation.
|
|
||||||
// swagger:response createHostsResponse
|
|
||||||
type createHostsesponse struct {
|
|
||||||
Data Response
|
|
||||||
}
|
|
||||||
|
|
||||||
func createHosts(ctx *gin.Context) {
|
|
||||||
// swagger:route POST /config/hosts ConfigManagement createHostsRequest
|
|
||||||
//
|
|
||||||
// Create a new hosts, the name of the hosts must be unique in hosts list.
|
|
||||||
//
|
|
||||||
// Security:
|
|
||||||
// basicAuth: []
|
|
||||||
//
|
|
||||||
// Responses:
|
|
||||||
// 200: createHostsResponse
|
|
||||||
|
|
||||||
var req createHostsRequest
|
|
||||||
ctx.ShouldBindJSON(&req.Data)
|
|
||||||
|
|
||||||
if req.Data.Name == "" {
|
|
||||||
writeError(ctx, ErrInvalid)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
v := parsing.ParseHosts(&req.Data)
|
|
||||||
|
|
||||||
if err := registry.HostsRegistry().Register(req.Data.Name, v); err != nil {
|
|
||||||
writeError(ctx, ErrDup)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
cfg := config.Global()
|
|
||||||
cfg.Hosts = append(cfg.Hosts, &req.Data)
|
|
||||||
config.SetGlobal(cfg)
|
|
||||||
|
|
||||||
ctx.JSON(http.StatusOK, Response{
|
|
||||||
Msg: "OK",
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// swagger:parameters updateHostsRequest
|
|
||||||
type updateHostsRequest struct {
|
|
||||||
// in: path
|
|
||||||
// required: true
|
|
||||||
Hosts string `uri:"hosts" json:"hosts"`
|
|
||||||
// in: body
|
|
||||||
Data config.HostsConfig `json:"data"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// successful operation.
|
|
||||||
// swagger:response updateHostsResponse
|
|
||||||
type updateHostsResponse struct {
|
|
||||||
Data Response
|
|
||||||
}
|
|
||||||
|
|
||||||
func updateHosts(ctx *gin.Context) {
|
|
||||||
// swagger:route PUT /config/hosts/{hosts} ConfigManagement updateHostsRequest
|
|
||||||
//
|
|
||||||
// Update hosts by name, the hosts must already exist.
|
|
||||||
//
|
|
||||||
// Security:
|
|
||||||
// basicAuth: []
|
|
||||||
//
|
|
||||||
// Responses:
|
|
||||||
// 200: updateHostsResponse
|
|
||||||
|
|
||||||
var req updateHostsRequest
|
|
||||||
ctx.ShouldBindUri(&req)
|
|
||||||
ctx.ShouldBindJSON(&req.Data)
|
|
||||||
|
|
||||||
if !registry.HostsRegistry().IsRegistered(req.Hosts) {
|
|
||||||
writeError(ctx, ErrNotFound)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
req.Data.Name = req.Hosts
|
|
||||||
|
|
||||||
v := parsing.ParseHosts(&req.Data)
|
|
||||||
|
|
||||||
registry.HostsRegistry().Unregister(req.Hosts)
|
|
||||||
|
|
||||||
if err := registry.HostsRegistry().Register(req.Hosts, v); err != nil {
|
|
||||||
writeError(ctx, ErrDup)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
cfg := config.Global()
|
|
||||||
for i := range cfg.Hosts {
|
|
||||||
if cfg.Hosts[i].Name == req.Hosts {
|
|
||||||
cfg.Hosts[i] = &req.Data
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
config.SetGlobal(cfg)
|
|
||||||
|
|
||||||
ctx.JSON(http.StatusOK, Response{
|
|
||||||
Msg: "OK",
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// swagger:parameters deleteHostsRequest
|
|
||||||
type deleteHostsRequest struct {
|
|
||||||
// in: path
|
|
||||||
// required: true
|
|
||||||
Hosts string `uri:"hosts" json:"hosts"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// successful operation.
|
|
||||||
// swagger:response deleteHostsResponse
|
|
||||||
type deleteHostsResponse struct {
|
|
||||||
Data Response
|
|
||||||
}
|
|
||||||
|
|
||||||
func deleteHosts(ctx *gin.Context) {
|
|
||||||
// swagger:route DELETE /config/hosts/{hosts} ConfigManagement deleteHostsRequest
|
|
||||||
//
|
|
||||||
// Delete hosts by name.
|
|
||||||
//
|
|
||||||
// Security:
|
|
||||||
// basicAuth: []
|
|
||||||
//
|
|
||||||
// Responses:
|
|
||||||
// 200: deleteHostsResponse
|
|
||||||
|
|
||||||
var req deleteHostsRequest
|
|
||||||
ctx.ShouldBindUri(&req)
|
|
||||||
|
|
||||||
if !registry.HostsRegistry().IsRegistered(req.Hosts) {
|
|
||||||
writeError(ctx, ErrNotFound)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
registry.HostsRegistry().Unregister(req.Hosts)
|
|
||||||
|
|
||||||
cfg := config.Global()
|
|
||||||
hosts := cfg.Hosts
|
|
||||||
cfg.Hosts = nil
|
|
||||||
for _, s := range hosts {
|
|
||||||
if s.Name == req.Hosts {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
cfg.Hosts = append(cfg.Hosts, s)
|
|
||||||
}
|
|
||||||
config.SetGlobal(cfg)
|
|
||||||
|
|
||||||
ctx.JSON(http.StatusOK, Response{
|
|
||||||
Msg: "OK",
|
|
||||||
})
|
|
||||||
}
|
|
||||||
@@ -1,174 +0,0 @@
|
|||||||
package api
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/http"
|
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"github.com/go-gost/gost/pkg/config"
|
|
||||||
"github.com/go-gost/gost/pkg/config/parsing"
|
|
||||||
"github.com/go-gost/gost/pkg/registry"
|
|
||||||
)
|
|
||||||
|
|
||||||
// swagger:parameters createResolverRequest
|
|
||||||
type createResolverRequest struct {
|
|
||||||
// in: body
|
|
||||||
Data config.ResolverConfig `json:"data"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// successful operation.
|
|
||||||
// swagger:response createResolverResponse
|
|
||||||
type createResolverResponse struct {
|
|
||||||
Data Response
|
|
||||||
}
|
|
||||||
|
|
||||||
func createResolver(ctx *gin.Context) {
|
|
||||||
// swagger:route POST /config/resolvers ConfigManagement createResolverRequest
|
|
||||||
//
|
|
||||||
// Create a new resolver, the name of the resolver must be unique in resolver list.
|
|
||||||
//
|
|
||||||
// Security:
|
|
||||||
// basicAuth: []
|
|
||||||
//
|
|
||||||
// Responses:
|
|
||||||
// 200: createResolverResponse
|
|
||||||
|
|
||||||
var req createResolverRequest
|
|
||||||
ctx.ShouldBindJSON(&req.Data)
|
|
||||||
|
|
||||||
if req.Data.Name == "" {
|
|
||||||
writeError(ctx, ErrInvalid)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
v, err := parsing.ParseResolver(&req.Data)
|
|
||||||
if err != nil {
|
|
||||||
writeError(ctx, ErrCreate)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := registry.ResolverRegistry().Register(req.Data.Name, v); err != nil {
|
|
||||||
writeError(ctx, ErrDup)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
cfg := config.Global()
|
|
||||||
cfg.Resolvers = append(cfg.Resolvers, &req.Data)
|
|
||||||
config.SetGlobal(cfg)
|
|
||||||
|
|
||||||
ctx.JSON(http.StatusOK, Response{
|
|
||||||
Msg: "OK",
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// swagger:parameters updateResolverRequest
|
|
||||||
type updateResolverRequest struct {
|
|
||||||
// in: path
|
|
||||||
// required: true
|
|
||||||
Resolver string `uri:"resolver" json:"resolver"`
|
|
||||||
// in: body
|
|
||||||
Data config.ResolverConfig `json:"data"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// successful operation.
|
|
||||||
// swagger:response updateResolverResponse
|
|
||||||
type updateResolverResponse struct {
|
|
||||||
Data Response
|
|
||||||
}
|
|
||||||
|
|
||||||
func updateResolver(ctx *gin.Context) {
|
|
||||||
// swagger:route PUT /config/resolvers/{resolver} ConfigManagement updateResolverRequest
|
|
||||||
//
|
|
||||||
// Update resolver by name, the resolver must already exist.
|
|
||||||
//
|
|
||||||
// Security:
|
|
||||||
// basicAuth: []
|
|
||||||
//
|
|
||||||
// Responses:
|
|
||||||
// 200: updateResolverResponse
|
|
||||||
|
|
||||||
var req updateResolverRequest
|
|
||||||
ctx.ShouldBindUri(&req)
|
|
||||||
ctx.ShouldBindJSON(&req.Data)
|
|
||||||
|
|
||||||
if !registry.ResolverRegistry().IsRegistered(req.Resolver) {
|
|
||||||
writeError(ctx, ErrNotFound)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
req.Data.Name = req.Resolver
|
|
||||||
|
|
||||||
v, err := parsing.ParseResolver(&req.Data)
|
|
||||||
if err != nil {
|
|
||||||
writeError(ctx, ErrCreate)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
registry.ResolverRegistry().Unregister(req.Resolver)
|
|
||||||
|
|
||||||
if err := registry.ResolverRegistry().Register(req.Resolver, v); err != nil {
|
|
||||||
writeError(ctx, ErrDup)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
cfg := config.Global()
|
|
||||||
for i := range cfg.Resolvers {
|
|
||||||
if cfg.Resolvers[i].Name == req.Resolver {
|
|
||||||
cfg.Resolvers[i] = &req.Data
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
config.SetGlobal(cfg)
|
|
||||||
|
|
||||||
ctx.JSON(http.StatusOK, Response{
|
|
||||||
Msg: "OK",
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// swagger:parameters deleteResolverRequest
|
|
||||||
type deleteResolverRequest struct {
|
|
||||||
// in: path
|
|
||||||
// required: true
|
|
||||||
Resolver string `uri:"resolver" json:"resolver"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// successful operation.
|
|
||||||
// swagger:response deleteResolverResponse
|
|
||||||
type deleteResolverResponse struct {
|
|
||||||
Data Response
|
|
||||||
}
|
|
||||||
|
|
||||||
func deleteResolver(ctx *gin.Context) {
|
|
||||||
// swagger:route DELETE /config/resolvers/{resolver} ConfigManagement deleteResolverRequest
|
|
||||||
//
|
|
||||||
// Delete resolver by name.
|
|
||||||
//
|
|
||||||
// Security:
|
|
||||||
// basicAuth: []
|
|
||||||
//
|
|
||||||
// Responses:
|
|
||||||
// 200: deleteResolverResponse
|
|
||||||
|
|
||||||
var req deleteResolverRequest
|
|
||||||
ctx.ShouldBindUri(&req)
|
|
||||||
|
|
||||||
if !registry.ResolverRegistry().IsRegistered(req.Resolver) {
|
|
||||||
writeError(ctx, ErrNotFound)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
registry.ResolverRegistry().Unregister(req.Resolver)
|
|
||||||
|
|
||||||
cfg := config.Global()
|
|
||||||
resolvers := cfg.Resolvers
|
|
||||||
cfg.Resolvers = nil
|
|
||||||
for _, s := range resolvers {
|
|
||||||
if s.Name == req.Resolver {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
cfg.Resolvers = append(cfg.Resolvers, s)
|
|
||||||
}
|
|
||||||
config.SetGlobal(cfg)
|
|
||||||
|
|
||||||
ctx.JSON(http.StatusOK, Response{
|
|
||||||
Msg: "OK",
|
|
||||||
})
|
|
||||||
}
|
|
||||||
@@ -1,190 +0,0 @@
|
|||||||
package api
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/http"
|
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"github.com/go-gost/gost/pkg/config"
|
|
||||||
"github.com/go-gost/gost/pkg/config/parsing"
|
|
||||||
"github.com/go-gost/gost/pkg/registry"
|
|
||||||
)
|
|
||||||
|
|
||||||
// swagger:parameters createServiceRequest
|
|
||||||
type createServiceRequest struct {
|
|
||||||
// in: body
|
|
||||||
Data config.ServiceConfig `json:"data"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// successful operation.
|
|
||||||
// swagger:response createServiceResponse
|
|
||||||
type createServiceResponse struct {
|
|
||||||
Data Response
|
|
||||||
}
|
|
||||||
|
|
||||||
func createService(ctx *gin.Context) {
|
|
||||||
// swagger:route POST /config/services ConfigManagement createServiceRequest
|
|
||||||
//
|
|
||||||
// Create a new service, the name of the service must be unique in service list.
|
|
||||||
//
|
|
||||||
// Security:
|
|
||||||
// basicAuth: []
|
|
||||||
//
|
|
||||||
// Responses:
|
|
||||||
// 200: createServiceResponse
|
|
||||||
|
|
||||||
var req createServiceRequest
|
|
||||||
ctx.ShouldBindJSON(&req.Data)
|
|
||||||
|
|
||||||
if req.Data.Name == "" {
|
|
||||||
writeError(ctx, ErrInvalid)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if registry.ServiceRegistry().IsRegistered(req.Data.Name) {
|
|
||||||
writeError(ctx, ErrDup)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
svc, err := parsing.ParseService(&req.Data)
|
|
||||||
if err != nil {
|
|
||||||
writeError(ctx, ErrCreate)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := registry.ServiceRegistry().Register(req.Data.Name, svc); err != nil {
|
|
||||||
svc.Close()
|
|
||||||
writeError(ctx, ErrDup)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
go svc.Serve()
|
|
||||||
|
|
||||||
cfg := config.Global()
|
|
||||||
cfg.Services = append(cfg.Services, &req.Data)
|
|
||||||
config.SetGlobal(cfg)
|
|
||||||
|
|
||||||
ctx.JSON(http.StatusOK, Response{
|
|
||||||
Msg: "OK",
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// swagger:parameters updateServiceRequest
|
|
||||||
type updateServiceRequest struct {
|
|
||||||
// in: path
|
|
||||||
// required: true
|
|
||||||
Service string `uri:"service" json:"service"`
|
|
||||||
// in: body
|
|
||||||
Data config.ServiceConfig `json:"data"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// successful operation.
|
|
||||||
// swagger:response updateServiceResponse
|
|
||||||
type updateServiceResponse struct {
|
|
||||||
Data Response
|
|
||||||
}
|
|
||||||
|
|
||||||
func updateService(ctx *gin.Context) {
|
|
||||||
// swagger:route PUT /config/services/{service} ConfigManagement updateServiceRequest
|
|
||||||
//
|
|
||||||
// Update service by name, the service must already exist.
|
|
||||||
//
|
|
||||||
// Security:
|
|
||||||
// basicAuth: []
|
|
||||||
//
|
|
||||||
// Responses:
|
|
||||||
// 200: updateServiceResponse
|
|
||||||
|
|
||||||
var req updateServiceRequest
|
|
||||||
ctx.ShouldBindUri(&req)
|
|
||||||
ctx.ShouldBindJSON(&req.Data)
|
|
||||||
|
|
||||||
old := registry.ServiceRegistry().Get(req.Service)
|
|
||||||
if old == nil {
|
|
||||||
writeError(ctx, ErrNotFound)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
old.Close()
|
|
||||||
|
|
||||||
req.Data.Name = req.Service
|
|
||||||
|
|
||||||
svc, err := parsing.ParseService(&req.Data)
|
|
||||||
if err != nil {
|
|
||||||
writeError(ctx, ErrCreate)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
registry.ServiceRegistry().Unregister(req.Service)
|
|
||||||
|
|
||||||
if err := registry.ServiceRegistry().Register(req.Service, svc); err != nil {
|
|
||||||
svc.Close()
|
|
||||||
writeError(ctx, ErrDup)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
go svc.Serve()
|
|
||||||
|
|
||||||
cfg := config.Global()
|
|
||||||
for i := range cfg.Services {
|
|
||||||
if cfg.Services[i].Name == req.Service {
|
|
||||||
cfg.Services[i] = &req.Data
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
config.SetGlobal(cfg)
|
|
||||||
|
|
||||||
ctx.JSON(http.StatusOK, Response{
|
|
||||||
Msg: "OK",
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// swagger:parameters deleteServiceRequest
|
|
||||||
type deleteServiceRequest struct {
|
|
||||||
// in: path
|
|
||||||
// required: true
|
|
||||||
Service string `uri:"service" json:"service"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// successful operation.
|
|
||||||
// swagger:response deleteServiceResponse
|
|
||||||
type deleteServiceResponse struct {
|
|
||||||
Data Response
|
|
||||||
}
|
|
||||||
|
|
||||||
func deleteService(ctx *gin.Context) {
|
|
||||||
// swagger:route DELETE /config/services/{service} ConfigManagement deleteServiceRequest
|
|
||||||
//
|
|
||||||
// Delete service by name.
|
|
||||||
//
|
|
||||||
// Security:
|
|
||||||
// basicAuth: []
|
|
||||||
//
|
|
||||||
// Responses:
|
|
||||||
// 200: deleteServiceResponse
|
|
||||||
|
|
||||||
var req deleteServiceRequest
|
|
||||||
ctx.ShouldBindUri(&req)
|
|
||||||
|
|
||||||
svc := registry.ServiceRegistry().Get(req.Service)
|
|
||||||
if svc == nil {
|
|
||||||
writeError(ctx, ErrNotFound)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
registry.ServiceRegistry().Unregister(req.Service)
|
|
||||||
svc.Close()
|
|
||||||
|
|
||||||
cfg := config.Global()
|
|
||||||
services := cfg.Services
|
|
||||||
cfg.Services = nil
|
|
||||||
for _, s := range services {
|
|
||||||
if s.Name == req.Service {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
cfg.Services = append(cfg.Services, s)
|
|
||||||
}
|
|
||||||
config.SetGlobal(cfg)
|
|
||||||
|
|
||||||
ctx.JSON(http.StatusOK, Response{
|
|
||||||
Msg: "OK",
|
|
||||||
})
|
|
||||||
}
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
// Documentation of Web API.
|
|
||||||
//
|
|
||||||
// Schemes: https, http
|
|
||||||
// BasePath: /
|
|
||||||
// Version: 1.0.0
|
|
||||||
//
|
|
||||||
// Consumes:
|
|
||||||
// - application/json
|
|
||||||
//
|
|
||||||
// Produces:
|
|
||||||
// - application/json
|
|
||||||
//
|
|
||||||
// SecurityDefinitions:
|
|
||||||
// basicAuth:
|
|
||||||
// type: basic
|
|
||||||
//
|
|
||||||
// swagger:meta
|
|
||||||
package api
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
package api
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"net/http"
|
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
ErrInvalid = &Error{statusCode: http.StatusBadRequest, Code: 40001, Msg: "object invalid"}
|
|
||||||
ErrDup = &Error{statusCode: http.StatusBadRequest, Code: 40002, Msg: "object duplicated"}
|
|
||||||
ErrCreate = &Error{statusCode: http.StatusConflict, Code: 40003, Msg: "object creation failed"}
|
|
||||||
ErrNotFound = &Error{statusCode: http.StatusBadRequest, Code: 40004, Msg: "object not found"}
|
|
||||||
ErrSave = &Error{statusCode: http.StatusInternalServerError, Code: 40005, Msg: "save config failed"}
|
|
||||||
)
|
|
||||||
|
|
||||||
// Error is an api error.
|
|
||||||
type Error struct {
|
|
||||||
statusCode int
|
|
||||||
Code int `json:"code"`
|
|
||||||
Msg string `json:"msg"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *Error) Error() string {
|
|
||||||
b, _ := json.Marshal(e)
|
|
||||||
return string(b)
|
|
||||||
}
|
|
||||||
|
|
||||||
func writeError(c *gin.Context, err error) {
|
|
||||||
// c.Set(HTTPResponseTag, err)
|
|
||||||
c.JSON(getStatusCode(err), err)
|
|
||||||
}
|
|
||||||
|
|
||||||
func getStatusCode(err error) int {
|
|
||||||
if err == nil {
|
|
||||||
return http.StatusOK
|
|
||||||
}
|
|
||||||
if e, ok := err.(*Error); ok {
|
|
||||||
if e.statusCode >= http.StatusOK && e.statusCode < 600 {
|
|
||||||
return e.statusCode
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return http.StatusInternalServerError
|
|
||||||
}
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
package api
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/http"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"github.com/go-gost/gost/pkg/auth"
|
|
||||||
"github.com/go-gost/gost/pkg/logger"
|
|
||||||
)
|
|
||||||
|
|
||||||
func mwLogger() gin.HandlerFunc {
|
|
||||||
return func(ctx *gin.Context) {
|
|
||||||
// start time
|
|
||||||
startTime := time.Now()
|
|
||||||
// Processing request
|
|
||||||
ctx.Next()
|
|
||||||
duration := time.Since(startTime)
|
|
||||||
|
|
||||||
logger.Default().WithFields(map[string]any{
|
|
||||||
"kind": "api",
|
|
||||||
"method": ctx.Request.Method,
|
|
||||||
"uri": ctx.Request.RequestURI,
|
|
||||||
"code": ctx.Writer.Status(),
|
|
||||||
"client": ctx.ClientIP(),
|
|
||||||
"duration": duration,
|
|
||||||
}).Infof("| %3d | %13v | %15s | %-7s %s",
|
|
||||||
ctx.Writer.Status(), duration, ctx.ClientIP(), ctx.Request.Method, ctx.Request.RequestURI)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func mwBasicAuth(auther auth.Authenticator) gin.HandlerFunc {
|
|
||||||
return func(c *gin.Context) {
|
|
||||||
if auther == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
u, p, _ := c.Request.BasicAuth()
|
|
||||||
if !auther.Authenticate(u, p) {
|
|
||||||
c.AbortWithStatus(http.StatusUnauthorized)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,132 +0,0 @@
|
|||||||
package api
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net"
|
|
||||||
"net/http"
|
|
||||||
|
|
||||||
"github.com/gin-contrib/cors"
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"github.com/go-gost/gost/pkg/auth"
|
|
||||||
"github.com/go-gost/gost/pkg/service"
|
|
||||||
)
|
|
||||||
|
|
||||||
type options struct {
|
|
||||||
accessLog bool
|
|
||||||
pathPrefix string
|
|
||||||
auther auth.Authenticator
|
|
||||||
}
|
|
||||||
|
|
||||||
type Option func(*options)
|
|
||||||
|
|
||||||
func PathPrefixOption(pathPrefix string) Option {
|
|
||||||
return func(o *options) {
|
|
||||||
o.pathPrefix = pathPrefix
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func AccessLogOption(enable bool) Option {
|
|
||||||
return func(o *options) {
|
|
||||||
o.accessLog = enable
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func AutherOption(auther auth.Authenticator) Option {
|
|
||||||
return func(o *options) {
|
|
||||||
o.auther = auther
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type server struct {
|
|
||||||
s *http.Server
|
|
||||||
ln net.Listener
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewService(addr string, opts ...Option) (service.Service, error) {
|
|
||||||
ln, err := net.Listen("tcp", addr)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var options options
|
|
||||||
for _, opt := range opts {
|
|
||||||
opt(&options)
|
|
||||||
}
|
|
||||||
|
|
||||||
gin.SetMode(gin.ReleaseMode)
|
|
||||||
|
|
||||||
r := gin.New()
|
|
||||||
r.Use(
|
|
||||||
cors.New((cors.Config{
|
|
||||||
AllowAllOrigins: true,
|
|
||||||
AllowMethods: []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"},
|
|
||||||
AllowHeaders: []string{"*"},
|
|
||||||
})),
|
|
||||||
gin.Recovery(),
|
|
||||||
)
|
|
||||||
if options.accessLog {
|
|
||||||
r.Use(mwLogger())
|
|
||||||
}
|
|
||||||
|
|
||||||
router := r.Group("")
|
|
||||||
if options.pathPrefix != "" {
|
|
||||||
router = router.Group(options.pathPrefix)
|
|
||||||
}
|
|
||||||
|
|
||||||
router.StaticFS("/docs", http.FS(swaggerDoc))
|
|
||||||
|
|
||||||
config := router.Group("/config")
|
|
||||||
config.Use(mwBasicAuth(options.auther))
|
|
||||||
registerConfig(config)
|
|
||||||
|
|
||||||
return &server{
|
|
||||||
s: &http.Server{
|
|
||||||
Handler: r,
|
|
||||||
},
|
|
||||||
ln: ln,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *server) Serve() error {
|
|
||||||
return s.s.Serve(s.ln)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *server) Addr() net.Addr {
|
|
||||||
return s.ln.Addr()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *server) Close() error {
|
|
||||||
return s.s.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
func registerConfig(config *gin.RouterGroup) {
|
|
||||||
config.GET("", getConfig)
|
|
||||||
config.POST("", saveConfig)
|
|
||||||
|
|
||||||
config.POST("/services", createService)
|
|
||||||
config.PUT("/services/:service", updateService)
|
|
||||||
config.DELETE("/services/:service", deleteService)
|
|
||||||
|
|
||||||
config.POST("/chains", createChain)
|
|
||||||
config.PUT("/chains/:chain", updateChain)
|
|
||||||
config.DELETE("/chains/:chain", deleteChain)
|
|
||||||
|
|
||||||
config.POST("/authers", createAuther)
|
|
||||||
config.PUT("/authers/:auther", updateAuther)
|
|
||||||
config.DELETE("/authers/:auther", deleteAuther)
|
|
||||||
|
|
||||||
config.POST("/admissions", createAdmission)
|
|
||||||
config.PUT("/admissions/:admission", updateAdmission)
|
|
||||||
config.DELETE("/admissions/:admission", deleteAdmission)
|
|
||||||
|
|
||||||
config.POST("/bypasses", createBypass)
|
|
||||||
config.PUT("/bypasses/:bypass", updateBypass)
|
|
||||||
config.DELETE("/bypasses/:bypass", deleteBypass)
|
|
||||||
|
|
||||||
config.POST("/resolvers", createResolver)
|
|
||||||
config.PUT("/resolvers/:resolver", updateResolver)
|
|
||||||
config.DELETE("/resolvers/:resolver", deleteResolver)
|
|
||||||
|
|
||||||
config.POST("/hosts", createHosts)
|
|
||||||
config.PUT("/hosts/:hosts", updateHosts)
|
|
||||||
config.DELETE("/hosts/:hosts", deleteHosts)
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,28 +0,0 @@
|
|||||||
package auth
|
|
||||||
|
|
||||||
// Authenticator is an interface for user authentication.
|
|
||||||
type Authenticator interface {
|
|
||||||
Authenticate(user, password string) bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// LocalAuthenticator is an Authenticator that authenticates client by local key-value pairs.
|
|
||||||
type MapAuthenticator struct {
|
|
||||||
kvs map[string]string
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewMapAuthenticator creates an Authenticator that authenticates client by local infos.
|
|
||||||
func NewMapAuthenticator(kvs map[string]string) Authenticator {
|
|
||||||
return &MapAuthenticator{
|
|
||||||
kvs: kvs,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Authenticate checks the validity of the provided user-password pair.
|
|
||||||
func (au *MapAuthenticator) Authenticate(user, password string) bool {
|
|
||||||
if au == nil || len(au.kvs) == 0 {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
v, ok := au.kvs[user]
|
|
||||||
return ok && (v == "" || password == v)
|
|
||||||
}
|
|
||||||
@@ -1,90 +0,0 @@
|
|||||||
package bypass
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net"
|
|
||||||
"strconv"
|
|
||||||
|
|
||||||
"github.com/go-gost/gost/pkg/common/matcher"
|
|
||||||
"github.com/go-gost/gost/pkg/logger"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Bypass is a filter of address (IP or domain).
|
|
||||||
type Bypass interface {
|
|
||||||
// Contains reports whether the bypass includes addr.
|
|
||||||
Contains(addr string) bool
|
|
||||||
}
|
|
||||||
|
|
||||||
type options struct {
|
|
||||||
logger logger.Logger
|
|
||||||
}
|
|
||||||
|
|
||||||
type Option func(opts *options)
|
|
||||||
|
|
||||||
func LoggerOption(logger logger.Logger) Option {
|
|
||||||
return func(opts *options) {
|
|
||||||
opts.logger = logger
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type bypass struct {
|
|
||||||
matchers []matcher.Matcher
|
|
||||||
reversed bool
|
|
||||||
options options
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewBypass creates and initializes a new Bypass using matchers as its match rules.
|
|
||||||
// The rules will be reversed if the reversed is true.
|
|
||||||
func NewBypass(reversed bool, matchers []matcher.Matcher, opts ...Option) Bypass {
|
|
||||||
options := options{}
|
|
||||||
for _, opt := range opts {
|
|
||||||
opt(&options)
|
|
||||||
}
|
|
||||||
return &bypass{
|
|
||||||
matchers: matchers,
|
|
||||||
reversed: reversed,
|
|
||||||
options: options,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewBypassPatterns creates and initializes a new Bypass using matcher patterns as its match rules.
|
|
||||||
// The rules will be reversed if the reverse is true.
|
|
||||||
func NewBypassPatterns(reversed bool, patterns []string, opts ...Option) Bypass {
|
|
||||||
var matchers []matcher.Matcher
|
|
||||||
for _, pattern := range patterns {
|
|
||||||
if m := matcher.NewMatcher(pattern); m != nil {
|
|
||||||
matchers = append(matchers, m)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return NewBypass(reversed, matchers, opts...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (bp *bypass) Contains(addr string) bool {
|
|
||||||
if addr == "" || bp == nil || len(bp.matchers) == 0 {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// try to strip the port
|
|
||||||
if host, port, _ := net.SplitHostPort(addr); host != "" && port != "" {
|
|
||||||
if p, _ := strconv.Atoi(port); p > 0 { // port is valid
|
|
||||||
addr = host
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var matched bool
|
|
||||||
for _, matcher := range bp.matchers {
|
|
||||||
if matcher == nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if matcher.Match(addr) {
|
|
||||||
matched = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
b := !bp.reversed && matched ||
|
|
||||||
bp.reversed && !matched
|
|
||||||
if b {
|
|
||||||
bp.options.logger.Debugf("bypass: %s", addr)
|
|
||||||
}
|
|
||||||
return b
|
|
||||||
}
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
package chain
|
|
||||||
|
|
||||||
type Chainer interface {
|
|
||||||
Route(network, address string) *Route
|
|
||||||
}
|
|
||||||
|
|
||||||
type Chain struct {
|
|
||||||
groups []*NodeGroup
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Chain) AddNodeGroup(group *NodeGroup) {
|
|
||||||
c.groups = append(c.groups, group)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Chain) Route(network, address string) (r *Route) {
|
|
||||||
if c == nil || len(c.groups) == 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
r = &Route{}
|
|
||||||
for _, group := range c.groups {
|
|
||||||
node := group.Next()
|
|
||||||
if node == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if node.Bypass != nil && node.Bypass.Contains(address) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
if node.Transport.Multiplex() {
|
|
||||||
tr := node.Transport.Copy().
|
|
||||||
WithRoute(r)
|
|
||||||
node = node.Copy()
|
|
||||||
node.Transport = tr
|
|
||||||
r = &Route{}
|
|
||||||
}
|
|
||||||
|
|
||||||
r.addNode(node)
|
|
||||||
}
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
@@ -1,97 +0,0 @@
|
|||||||
package chain
|
|
||||||
|
|
||||||
import (
|
|
||||||
"sync/atomic"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/go-gost/gost/pkg/bypass"
|
|
||||||
"github.com/go-gost/gost/pkg/hosts"
|
|
||||||
"github.com/go-gost/gost/pkg/resolver"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Node struct {
|
|
||||||
Name string
|
|
||||||
Addr string
|
|
||||||
Transport *Transport
|
|
||||||
Bypass bypass.Bypass
|
|
||||||
Resolver resolver.Resolver
|
|
||||||
Hosts hosts.HostMapper
|
|
||||||
Marker *FailMarker
|
|
||||||
}
|
|
||||||
|
|
||||||
func (node *Node) Copy() *Node {
|
|
||||||
n := &Node{}
|
|
||||||
*n = *node
|
|
||||||
return n
|
|
||||||
}
|
|
||||||
|
|
||||||
type NodeGroup struct {
|
|
||||||
nodes []*Node
|
|
||||||
selector Selector
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewNodeGroup(nodes ...*Node) *NodeGroup {
|
|
||||||
return &NodeGroup{
|
|
||||||
nodes: nodes,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (g *NodeGroup) AddNode(node *Node) {
|
|
||||||
g.nodes = append(g.nodes, node)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (g *NodeGroup) WithSelector(selector Selector) *NodeGroup {
|
|
||||||
g.selector = selector
|
|
||||||
return g
|
|
||||||
}
|
|
||||||
|
|
||||||
func (g *NodeGroup) Next() *Node {
|
|
||||||
if g == nil || len(g.nodes) == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
s := g.selector
|
|
||||||
if s == nil {
|
|
||||||
s = DefaultSelector
|
|
||||||
}
|
|
||||||
|
|
||||||
return s.Select(g.nodes...)
|
|
||||||
}
|
|
||||||
|
|
||||||
type FailMarker struct {
|
|
||||||
failTime int64
|
|
||||||
failCount int64
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *FailMarker) FailTime() int64 {
|
|
||||||
if m == nil {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
return atomic.LoadInt64(&m.failTime)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *FailMarker) FailCount() int64 {
|
|
||||||
if m == nil {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
return atomic.LoadInt64(&m.failCount)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *FailMarker) Mark() {
|
|
||||||
if m == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
atomic.AddInt64(&m.failCount, 1)
|
|
||||||
atomic.StoreInt64(&m.failTime, time.Now().Unix())
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *FailMarker) Reset() {
|
|
||||||
if m == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
atomic.StoreInt64(&m.failCount, 0)
|
|
||||||
}
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
package chain
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"net"
|
|
||||||
|
|
||||||
"github.com/go-gost/gost/pkg/hosts"
|
|
||||||
"github.com/go-gost/gost/pkg/logger"
|
|
||||||
"github.com/go-gost/gost/pkg/resolver"
|
|
||||||
)
|
|
||||||
|
|
||||||
func resolve(ctx context.Context, network, addr string, r resolver.Resolver, hosts hosts.HostMapper, log logger.Logger) (string, error) {
|
|
||||||
if addr == "" {
|
|
||||||
return addr, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
host, port, err := net.SplitHostPort(addr)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
if host == "" {
|
|
||||||
return addr, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if hosts != nil {
|
|
||||||
if ips, _ := hosts.Lookup(network, host); len(ips) > 0 {
|
|
||||||
log.Debugf("hit host mapper: %s -> %s", host, ips)
|
|
||||||
return net.JoinHostPort(ips[0].String(), port), nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if r != nil {
|
|
||||||
ips, err := r.Resolve(ctx, network, host)
|
|
||||||
if err != nil {
|
|
||||||
if err == resolver.ErrInvalid {
|
|
||||||
return addr, nil
|
|
||||||
}
|
|
||||||
log.Error(err)
|
|
||||||
}
|
|
||||||
if len(ips) == 0 {
|
|
||||||
return "", fmt.Errorf("resolver: domain %s does not exists", host)
|
|
||||||
}
|
|
||||||
return net.JoinHostPort(ips[0].String(), port), nil
|
|
||||||
}
|
|
||||||
return addr, nil
|
|
||||||
}
|
|
||||||
@@ -1,192 +0,0 @@
|
|||||||
package chain
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"net"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/go-gost/gost/pkg/common/net/dialer"
|
|
||||||
"github.com/go-gost/gost/pkg/common/util/udp"
|
|
||||||
"github.com/go-gost/gost/pkg/connector"
|
|
||||||
"github.com/go-gost/gost/pkg/logger"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
ErrEmptyRoute = errors.New("empty route")
|
|
||||||
)
|
|
||||||
|
|
||||||
type Route struct {
|
|
||||||
nodes []*Node
|
|
||||||
ifceName string
|
|
||||||
logger logger.Logger
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *Route) addNode(node *Node) {
|
|
||||||
r.nodes = append(r.nodes, node)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *Route) Dial(ctx context.Context, network, address string) (net.Conn, error) {
|
|
||||||
if r.Len() == 0 {
|
|
||||||
netd := dialer.NetDialer{
|
|
||||||
Timeout: 30 * time.Second,
|
|
||||||
}
|
|
||||||
if r != nil {
|
|
||||||
netd.Interface = r.ifceName
|
|
||||||
}
|
|
||||||
return netd.Dial(ctx, network, address)
|
|
||||||
}
|
|
||||||
|
|
||||||
conn, err := r.connect(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
cc, err := r.GetNode(r.Len()-1).Transport.Connect(ctx, conn, network, address)
|
|
||||||
if err != nil {
|
|
||||||
conn.Close()
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return cc, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *Route) Bind(ctx context.Context, network, address string, opts ...connector.BindOption) (net.Listener, error) {
|
|
||||||
if r.Len() == 0 {
|
|
||||||
return r.bindLocal(ctx, network, address, opts...)
|
|
||||||
}
|
|
||||||
|
|
||||||
conn, err := r.connect(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
ln, err := r.GetNode(r.Len()-1).Transport.Bind(ctx, conn, network, address, opts...)
|
|
||||||
if err != nil {
|
|
||||||
conn.Close()
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return ln, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *Route) connect(ctx context.Context) (conn net.Conn, err error) {
|
|
||||||
if r.Len() == 0 {
|
|
||||||
return nil, ErrEmptyRoute
|
|
||||||
}
|
|
||||||
|
|
||||||
network := "ip"
|
|
||||||
node := r.nodes[0]
|
|
||||||
|
|
||||||
addr, err := resolve(ctx, network, node.Addr, node.Resolver, node.Hosts, r.logger)
|
|
||||||
if err != nil {
|
|
||||||
node.Marker.Mark()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
cc, err := node.Transport.Dial(ctx, addr)
|
|
||||||
if err != nil {
|
|
||||||
node.Marker.Mark()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
cn, err := node.Transport.Handshake(ctx, cc)
|
|
||||||
if err != nil {
|
|
||||||
cc.Close()
|
|
||||||
node.Marker.Mark()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
node.Marker.Reset()
|
|
||||||
|
|
||||||
preNode := node
|
|
||||||
for _, node := range r.nodes[1:] {
|
|
||||||
addr, err = resolve(ctx, network, node.Addr, node.Resolver, node.Hosts, r.logger)
|
|
||||||
if err != nil {
|
|
||||||
cn.Close()
|
|
||||||
node.Marker.Mark()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
cc, err = preNode.Transport.Connect(ctx, cn, "tcp", addr)
|
|
||||||
if err != nil {
|
|
||||||
cn.Close()
|
|
||||||
node.Marker.Mark()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
cc, err = node.Transport.Handshake(ctx, cc)
|
|
||||||
if err != nil {
|
|
||||||
cn.Close()
|
|
||||||
node.Marker.Mark()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
node.Marker.Reset()
|
|
||||||
|
|
||||||
cn = cc
|
|
||||||
preNode = node
|
|
||||||
}
|
|
||||||
|
|
||||||
conn = cn
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *Route) Len() int {
|
|
||||||
if r == nil {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
return len(r.nodes)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *Route) GetNode(index int) *Node {
|
|
||||||
if r.Len() == 0 || index < 0 || index >= len(r.nodes) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return r.nodes[index]
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *Route) Path() (path []*Node) {
|
|
||||||
if r == nil || len(r.nodes) == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, node := range r.nodes {
|
|
||||||
if node.Transport != nil && node.Transport.route != nil {
|
|
||||||
path = append(path, node.Transport.route.Path()...)
|
|
||||||
}
|
|
||||||
path = append(path, node)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *Route) bindLocal(ctx context.Context, network, address string, opts ...connector.BindOption) (net.Listener, error) {
|
|
||||||
options := connector.BindOptions{}
|
|
||||||
for _, opt := range opts {
|
|
||||||
opt(&options)
|
|
||||||
}
|
|
||||||
|
|
||||||
switch network {
|
|
||||||
case "tcp", "tcp4", "tcp6":
|
|
||||||
addr, err := net.ResolveTCPAddr(network, address)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return net.ListenTCP(network, addr)
|
|
||||||
case "udp", "udp4", "udp6":
|
|
||||||
addr, err := net.ResolveUDPAddr(network, address)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
conn, err := net.ListenUDP(network, addr)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
logger := logger.Default().WithFields(map[string]any{
|
|
||||||
"network": network,
|
|
||||||
"address": address,
|
|
||||||
})
|
|
||||||
ln := udp.NewListener(conn, addr,
|
|
||||||
options.Backlog, options.UDPDataQueueSize, options.UDPDataBufferSize,
|
|
||||||
options.UDPConnTTL, logger)
|
|
||||||
return ln, err
|
|
||||||
default:
|
|
||||||
err := fmt.Errorf("network %s unsupported", network)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,169 +0,0 @@
|
|||||||
package chain
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"net"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/go-gost/gost/pkg/connector"
|
|
||||||
"github.com/go-gost/gost/pkg/hosts"
|
|
||||||
"github.com/go-gost/gost/pkg/logger"
|
|
||||||
"github.com/go-gost/gost/pkg/resolver"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Router struct {
|
|
||||||
timeout time.Duration
|
|
||||||
retries int
|
|
||||||
ifceName string
|
|
||||||
chain Chainer
|
|
||||||
resolver resolver.Resolver
|
|
||||||
hosts hosts.HostMapper
|
|
||||||
logger logger.Logger
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *Router) WithTimeout(timeout time.Duration) *Router {
|
|
||||||
r.timeout = timeout
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *Router) WithRetries(retries int) *Router {
|
|
||||||
r.retries = retries
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *Router) WithInterface(ifceName string) *Router {
|
|
||||||
r.ifceName = ifceName
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *Router) WithChain(chain Chainer) *Router {
|
|
||||||
r.chain = chain
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *Router) WithResolver(resolver resolver.Resolver) *Router {
|
|
||||||
r.resolver = resolver
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *Router) WithHosts(hosts hosts.HostMapper) *Router {
|
|
||||||
r.hosts = hosts
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *Router) Hosts() hosts.HostMapper {
|
|
||||||
if r != nil {
|
|
||||||
return r.hosts
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *Router) WithLogger(logger logger.Logger) *Router {
|
|
||||||
r.logger = logger
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *Router) Dial(ctx context.Context, network, address string) (conn net.Conn, err error) {
|
|
||||||
conn, err = r.dial(ctx, network, address)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if network == "udp" || network == "udp4" || network == "udp6" {
|
|
||||||
if _, ok := conn.(net.PacketConn); !ok {
|
|
||||||
return &packetConn{conn}, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *Router) dial(ctx context.Context, network, address string) (conn net.Conn, err error) {
|
|
||||||
count := r.retries + 1
|
|
||||||
if count <= 0 {
|
|
||||||
count = 1
|
|
||||||
}
|
|
||||||
r.logger.Debugf("dial %s/%s", address, network)
|
|
||||||
|
|
||||||
for i := 0; i < count; i++ {
|
|
||||||
var route *Route
|
|
||||||
if r.chain != nil {
|
|
||||||
route = r.chain.Route(network, address)
|
|
||||||
}
|
|
||||||
|
|
||||||
if r.logger.IsLevelEnabled(logger.DebugLevel) {
|
|
||||||
buf := bytes.Buffer{}
|
|
||||||
for _, node := range route.Path() {
|
|
||||||
fmt.Fprintf(&buf, "%s@%s > ", node.Name, node.Addr)
|
|
||||||
}
|
|
||||||
fmt.Fprintf(&buf, "%s", address)
|
|
||||||
r.logger.Debugf("route(retry=%d) %s", i, buf.String())
|
|
||||||
}
|
|
||||||
|
|
||||||
address, err = resolve(ctx, "ip", address, r.resolver, r.hosts, r.logger)
|
|
||||||
if err != nil {
|
|
||||||
r.logger.Error(err)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
if route == nil {
|
|
||||||
route = &Route{}
|
|
||||||
}
|
|
||||||
route.ifceName = r.ifceName
|
|
||||||
route.logger = r.logger
|
|
||||||
|
|
||||||
conn, err = route.Dial(ctx, network, address)
|
|
||||||
if err == nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
r.logger.Errorf("route(retry=%d) %s", i, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *Router) Bind(ctx context.Context, network, address string, opts ...connector.BindOption) (ln net.Listener, err error) {
|
|
||||||
count := r.retries + 1
|
|
||||||
if count <= 0 {
|
|
||||||
count = 1
|
|
||||||
}
|
|
||||||
r.logger.Debugf("bind on %s/%s", address, network)
|
|
||||||
|
|
||||||
for i := 0; i < count; i++ {
|
|
||||||
var route *Route
|
|
||||||
if r.chain != nil {
|
|
||||||
route = r.chain.Route(network, address)
|
|
||||||
}
|
|
||||||
|
|
||||||
if r.logger.IsLevelEnabled(logger.DebugLevel) {
|
|
||||||
buf := bytes.Buffer{}
|
|
||||||
for _, node := range route.Path() {
|
|
||||||
fmt.Fprintf(&buf, "%s@%s > ", node.Name, node.Addr)
|
|
||||||
}
|
|
||||||
fmt.Fprintf(&buf, "%s", address)
|
|
||||||
r.logger.Debugf("route(retry=%d) %s", i, buf.String())
|
|
||||||
}
|
|
||||||
|
|
||||||
ln, err = route.Bind(ctx, network, address, opts...)
|
|
||||||
if err == nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
r.logger.Errorf("route(retry=%d) %s", i, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
type packetConn struct {
|
|
||||||
net.Conn
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *packetConn) ReadFrom(b []byte) (n int, addr net.Addr, err error) {
|
|
||||||
n, err = c.Read(b)
|
|
||||||
addr = c.Conn.RemoteAddr()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *packetConn) WriteTo(b []byte, addr net.Addr) (n int, err error) {
|
|
||||||
return c.Write(b)
|
|
||||||
}
|
|
||||||
@@ -1,170 +0,0 @@
|
|||||||
package chain
|
|
||||||
|
|
||||||
import (
|
|
||||||
"math/rand"
|
|
||||||
"net"
|
|
||||||
"strconv"
|
|
||||||
"sync"
|
|
||||||
"sync/atomic"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
// default options for FailFilter
|
|
||||||
const (
|
|
||||||
DefaultFailTimeout = 30 * time.Second
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
DefaultSelector = NewSelector(RoundRobinStrategy())
|
|
||||||
)
|
|
||||||
|
|
||||||
type Selector interface {
|
|
||||||
Select(nodes ...*Node) *Node
|
|
||||||
}
|
|
||||||
|
|
||||||
type selector struct {
|
|
||||||
strategy Strategy
|
|
||||||
filters []Filter
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewSelector(strategy Strategy, filters ...Filter) Selector {
|
|
||||||
return &selector{
|
|
||||||
filters: filters,
|
|
||||||
strategy: strategy,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *selector) Select(nodes ...*Node) *Node {
|
|
||||||
for _, filter := range s.filters {
|
|
||||||
nodes = filter.Filter(nodes...)
|
|
||||||
}
|
|
||||||
if len(nodes) == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return s.strategy.Apply(nodes...)
|
|
||||||
}
|
|
||||||
|
|
||||||
type Strategy interface {
|
|
||||||
Apply(nodes ...*Node) *Node
|
|
||||||
}
|
|
||||||
|
|
||||||
type roundRobinStrategy struct {
|
|
||||||
counter uint64
|
|
||||||
}
|
|
||||||
|
|
||||||
// RoundRobinStrategy is a strategy for node selector.
|
|
||||||
// The node will be selected by round-robin algorithm.
|
|
||||||
func RoundRobinStrategy() Strategy {
|
|
||||||
return &roundRobinStrategy{}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *roundRobinStrategy) Apply(nodes ...*Node) *Node {
|
|
||||||
if len(nodes) == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
n := atomic.AddUint64(&s.counter, 1) - 1
|
|
||||||
return nodes[int(n%uint64(len(nodes)))]
|
|
||||||
}
|
|
||||||
|
|
||||||
type randomStrategy struct {
|
|
||||||
rand *rand.Rand
|
|
||||||
mux sync.Mutex
|
|
||||||
}
|
|
||||||
|
|
||||||
// RandomStrategy is a strategy for node selector.
|
|
||||||
// The node will be selected randomly.
|
|
||||||
func RandomStrategy() Strategy {
|
|
||||||
return &randomStrategy{
|
|
||||||
rand: rand.New(rand.NewSource(time.Now().UnixNano())),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *randomStrategy) Apply(nodes ...*Node) *Node {
|
|
||||||
if len(nodes) == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
s.mux.Lock()
|
|
||||||
defer s.mux.Unlock()
|
|
||||||
|
|
||||||
r := s.rand.Int()
|
|
||||||
|
|
||||||
return nodes[r%len(nodes)]
|
|
||||||
}
|
|
||||||
|
|
||||||
type fifoStrategy struct{}
|
|
||||||
|
|
||||||
// FIFOStrategy is a strategy for node selector.
|
|
||||||
// The node will be selected from first to last,
|
|
||||||
// and will stick to the selected node until it is failed.
|
|
||||||
func FIFOStrategy() Strategy {
|
|
||||||
return &fifoStrategy{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Apply applies the fifo strategy for the nodes.
|
|
||||||
func (s *fifoStrategy) Apply(nodes ...*Node) *Node {
|
|
||||||
if len(nodes) == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return nodes[0]
|
|
||||||
}
|
|
||||||
|
|
||||||
type Filter interface {
|
|
||||||
Filter(nodes ...*Node) []*Node
|
|
||||||
}
|
|
||||||
|
|
||||||
type failFilter struct {
|
|
||||||
maxFails int
|
|
||||||
failTimeout time.Duration
|
|
||||||
}
|
|
||||||
|
|
||||||
// FailFilter filters the dead node.
|
|
||||||
// A node is marked as dead if its failed count is greater than MaxFails.
|
|
||||||
func FailFilter(maxFails int, timeout time.Duration) Filter {
|
|
||||||
return &failFilter{
|
|
||||||
maxFails: maxFails,
|
|
||||||
failTimeout: timeout,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Filter filters dead nodes.
|
|
||||||
func (f *failFilter) Filter(nodes ...*Node) []*Node {
|
|
||||||
maxFails := f.maxFails
|
|
||||||
failTimeout := f.failTimeout
|
|
||||||
if failTimeout == 0 {
|
|
||||||
failTimeout = DefaultFailTimeout
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(nodes) <= 1 || maxFails <= 0 {
|
|
||||||
return nodes
|
|
||||||
}
|
|
||||||
var nl []*Node
|
|
||||||
for _, node := range nodes {
|
|
||||||
if node.Marker.FailCount() < int64(maxFails) ||
|
|
||||||
time.Since(time.Unix(node.Marker.FailTime(), 0)) >= failTimeout {
|
|
||||||
nl = append(nl, node)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nl
|
|
||||||
}
|
|
||||||
|
|
||||||
type invalidFilter struct{}
|
|
||||||
|
|
||||||
// InvalidFilter filters the invalid node.
|
|
||||||
// A node is invalid if its port is invalid (negative or zero value).
|
|
||||||
func InvalidFilter() Filter {
|
|
||||||
return &invalidFilter{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Filter filters invalid nodes.
|
|
||||||
func (f *invalidFilter) Filter(nodes ...*Node) []*Node {
|
|
||||||
var nl []*Node
|
|
||||||
for _, node := range nodes {
|
|
||||||
_, sport, _ := net.SplitHostPort(node.Addr)
|
|
||||||
if port, _ := strconv.Atoi(sport); port > 0 {
|
|
||||||
nl = append(nl, node)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nl
|
|
||||||
}
|
|
||||||
@@ -1,100 +0,0 @@
|
|||||||
package chain
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"net"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
net_dialer "github.com/go-gost/gost/pkg/common/net/dialer"
|
|
||||||
"github.com/go-gost/gost/pkg/connector"
|
|
||||||
"github.com/go-gost/gost/pkg/dialer"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Transport struct {
|
|
||||||
addr string
|
|
||||||
ifceName string
|
|
||||||
route *Route
|
|
||||||
dialer dialer.Dialer
|
|
||||||
connector connector.Connector
|
|
||||||
}
|
|
||||||
|
|
||||||
func (tr *Transport) Copy() *Transport {
|
|
||||||
tr2 := &Transport{}
|
|
||||||
*tr2 = *tr
|
|
||||||
return tr
|
|
||||||
}
|
|
||||||
|
|
||||||
func (tr *Transport) WithInterface(ifceName string) *Transport {
|
|
||||||
tr.ifceName = ifceName
|
|
||||||
return tr
|
|
||||||
}
|
|
||||||
|
|
||||||
func (tr *Transport) WithDialer(dialer dialer.Dialer) *Transport {
|
|
||||||
tr.dialer = dialer
|
|
||||||
return tr
|
|
||||||
}
|
|
||||||
|
|
||||||
func (tr *Transport) WithConnector(connector connector.Connector) *Transport {
|
|
||||||
tr.connector = connector
|
|
||||||
return tr
|
|
||||||
}
|
|
||||||
|
|
||||||
func (tr *Transport) Dial(ctx context.Context, addr string) (net.Conn, error) {
|
|
||||||
netd := &net_dialer.NetDialer{
|
|
||||||
Interface: tr.ifceName,
|
|
||||||
Timeout: 30 * time.Second,
|
|
||||||
}
|
|
||||||
if tr.route.Len() > 0 {
|
|
||||||
netd.DialFunc = func(ctx context.Context, network, addr string) (net.Conn, error) {
|
|
||||||
return tr.route.Dial(ctx, network, addr)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
opts := []dialer.DialOption{
|
|
||||||
dialer.HostDialOption(tr.addr),
|
|
||||||
dialer.NetDialerDialOption(netd),
|
|
||||||
}
|
|
||||||
return tr.dialer.Dial(ctx, addr, opts...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (tr *Transport) Handshake(ctx context.Context, conn net.Conn) (net.Conn, error) {
|
|
||||||
var err error
|
|
||||||
if hs, ok := tr.dialer.(dialer.Handshaker); ok {
|
|
||||||
conn, err = hs.Handshake(ctx, conn,
|
|
||||||
dialer.AddrHandshakeOption(tr.addr))
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if hs, ok := tr.connector.(connector.Handshaker); ok {
|
|
||||||
return hs.Handshake(ctx, conn)
|
|
||||||
}
|
|
||||||
return conn, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (tr *Transport) Connect(ctx context.Context, conn net.Conn, network, address string) (net.Conn, error) {
|
|
||||||
return tr.connector.Connect(ctx, conn, network, address)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (tr *Transport) Bind(ctx context.Context, conn net.Conn, network, address string, opts ...connector.BindOption) (net.Listener, error) {
|
|
||||||
if binder, ok := tr.connector.(connector.Binder); ok {
|
|
||||||
return binder.Bind(ctx, conn, network, address, opts...)
|
|
||||||
}
|
|
||||||
return nil, connector.ErrBindUnsupported
|
|
||||||
}
|
|
||||||
|
|
||||||
func (tr *Transport) Multiplex() bool {
|
|
||||||
if mux, ok := tr.dialer.(dialer.Multiplexer); ok {
|
|
||||||
return mux.Multiplex()
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (tr *Transport) WithRoute(r *Route) *Transport {
|
|
||||||
tr.route = r
|
|
||||||
return tr
|
|
||||||
}
|
|
||||||
|
|
||||||
func (tr *Transport) WithAddr(addr string) *Transport {
|
|
||||||
tr.addr = addr
|
|
||||||
return tr
|
|
||||||
}
|
|
||||||
@@ -1,113 +0,0 @@
|
|||||||
package bufpool
|
|
||||||
|
|
||||||
import "sync"
|
|
||||||
|
|
||||||
var (
|
|
||||||
pools = []struct {
|
|
||||||
size int
|
|
||||||
pool sync.Pool
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
size: 128,
|
|
||||||
pool: sync.Pool{
|
|
||||||
New: func() any {
|
|
||||||
b := make([]byte, 128)
|
|
||||||
return &b
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
size: 512,
|
|
||||||
pool: sync.Pool{
|
|
||||||
New: func() any {
|
|
||||||
b := make([]byte, 512)
|
|
||||||
return &b
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
size: 1024,
|
|
||||||
pool: sync.Pool{
|
|
||||||
New: func() any {
|
|
||||||
b := make([]byte, 1024)
|
|
||||||
return &b
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
size: 4096,
|
|
||||||
pool: sync.Pool{
|
|
||||||
New: func() any {
|
|
||||||
b := make([]byte, 4096)
|
|
||||||
return &b
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
size: 8192,
|
|
||||||
pool: sync.Pool{
|
|
||||||
New: func() any {
|
|
||||||
b := make([]byte, 8192)
|
|
||||||
return &b
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
size: 16 * 1024,
|
|
||||||
pool: sync.Pool{
|
|
||||||
New: func() any {
|
|
||||||
b := make([]byte, 16*1024)
|
|
||||||
return &b
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
size: 32 * 1024,
|
|
||||||
pool: sync.Pool{
|
|
||||||
New: func() any {
|
|
||||||
b := make([]byte, 32*1024)
|
|
||||||
return &b
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
size: 64 * 1024,
|
|
||||||
pool: sync.Pool{
|
|
||||||
New: func() any {
|
|
||||||
b := make([]byte, 64*1024)
|
|
||||||
return &b
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
size: 65 * 1024,
|
|
||||||
pool: sync.Pool{
|
|
||||||
New: func() any {
|
|
||||||
b := make([]byte, 65*1024)
|
|
||||||
return &b
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
// Get returns a buffer of specified size.
|
|
||||||
func Get(size int) *[]byte {
|
|
||||||
for i := range pools {
|
|
||||||
if size <= pools[i].size {
|
|
||||||
b := pools[i].pool.Get().(*[]byte)
|
|
||||||
*b = (*b)[:size]
|
|
||||||
return b
|
|
||||||
}
|
|
||||||
}
|
|
||||||
b := make([]byte, size)
|
|
||||||
return &b
|
|
||||||
}
|
|
||||||
|
|
||||||
func Put(b *[]byte) {
|
|
||||||
for i := range pools {
|
|
||||||
if cap(*b) == pools[i].size {
|
|
||||||
pools[i].pool.Put(b)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,99 +0,0 @@
|
|||||||
package matcher
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/gobwas/glob"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Matcher is a generic pattern matcher,
|
|
||||||
// it gives the match result of the given pattern for specific v.
|
|
||||||
type Matcher interface {
|
|
||||||
Match(v string) bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewMatcher creates a Matcher for the given pattern.
|
|
||||||
// The acutal Matcher depends on the pattern:
|
|
||||||
// IP Matcher if pattern is a valid IP address.
|
|
||||||
// CIDR Matcher if pattern is a valid CIDR address.
|
|
||||||
// Domain Matcher if both of the above are not.
|
|
||||||
func NewMatcher(pattern string) Matcher {
|
|
||||||
if pattern == "" {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if ip := net.ParseIP(pattern); ip != nil {
|
|
||||||
return IPMatcher(ip)
|
|
||||||
}
|
|
||||||
if _, inet, err := net.ParseCIDR(pattern); err == nil {
|
|
||||||
return CIDRMatcher(inet)
|
|
||||||
}
|
|
||||||
return DomainMatcher(pattern)
|
|
||||||
}
|
|
||||||
|
|
||||||
type ipMatcher struct {
|
|
||||||
ip net.IP
|
|
||||||
}
|
|
||||||
|
|
||||||
// IPMatcher creates a Matcher for a specific IP address.
|
|
||||||
func IPMatcher(ip net.IP) Matcher {
|
|
||||||
return &ipMatcher{
|
|
||||||
ip: ip,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *ipMatcher) Match(ip string) bool {
|
|
||||||
if m == nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return m.ip.Equal(net.ParseIP(ip))
|
|
||||||
}
|
|
||||||
|
|
||||||
type cidrMatcher struct {
|
|
||||||
ipNet *net.IPNet
|
|
||||||
}
|
|
||||||
|
|
||||||
// CIDRMatcher creates a Matcher for a specific CIDR notation IP address.
|
|
||||||
func CIDRMatcher(inet *net.IPNet) Matcher {
|
|
||||||
return &cidrMatcher{
|
|
||||||
ipNet: inet,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *cidrMatcher) Match(ip string) bool {
|
|
||||||
if m == nil || m.ipNet == nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return m.ipNet.Contains(net.ParseIP(ip))
|
|
||||||
}
|
|
||||||
|
|
||||||
type domainMatcher struct {
|
|
||||||
pattern string
|
|
||||||
glob glob.Glob
|
|
||||||
}
|
|
||||||
|
|
||||||
// DomainMatcher creates a Matcher for a specific domain pattern,
|
|
||||||
// the pattern can be a plain domain such as 'example.com',
|
|
||||||
// a wildcard such as '*.exmaple.com' or a special wildcard '.example.com'.
|
|
||||||
func DomainMatcher(pattern string) Matcher {
|
|
||||||
p := pattern
|
|
||||||
if strings.HasPrefix(pattern, ".") {
|
|
||||||
p = pattern[1:] // trim the prefix '.'
|
|
||||||
pattern = "*" + p
|
|
||||||
}
|
|
||||||
return &domainMatcher{
|
|
||||||
pattern: p,
|
|
||||||
glob: glob.MustCompile(pattern),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *domainMatcher) Match(domain string) bool {
|
|
||||||
if m == nil || m.glob == nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
if domain == m.pattern {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return m.glob.Match(domain)
|
|
||||||
}
|
|
||||||
@@ -1,222 +0,0 @@
|
|||||||
package metrics
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"io"
|
|
||||||
"net"
|
|
||||||
"syscall"
|
|
||||||
|
|
||||||
"github.com/go-gost/gost/pkg/metrics"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
errUnsupport = errors.New("unsupported operation")
|
|
||||||
)
|
|
||||||
|
|
||||||
// ServerConn is a server side Conn with metrics supported.
|
|
||||||
type serverConn struct {
|
|
||||||
net.Conn
|
|
||||||
service string
|
|
||||||
}
|
|
||||||
|
|
||||||
func WrapConn(service string, c net.Conn) net.Conn {
|
|
||||||
return &serverConn{
|
|
||||||
service: service,
|
|
||||||
Conn: c,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *serverConn) Read(b []byte) (n int, err error) {
|
|
||||||
n, err = c.Conn.Read(b)
|
|
||||||
metrics.InputBytes(c.service).Add(float64(n))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *serverConn) Write(b []byte) (n int, err error) {
|
|
||||||
n, err = c.Conn.Write(b)
|
|
||||||
metrics.OutputBytes(c.service).Add(float64(n))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
type packetConn struct {
|
|
||||||
net.PacketConn
|
|
||||||
service string
|
|
||||||
}
|
|
||||||
|
|
||||||
func WrapPacketConn(service string, pc net.PacketConn) net.PacketConn {
|
|
||||||
return &packetConn{
|
|
||||||
PacketConn: pc,
|
|
||||||
service: service,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *packetConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) {
|
|
||||||
n, addr, err = c.PacketConn.ReadFrom(p)
|
|
||||||
metrics.InputBytes(c.service).Add(float64(n))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *packetConn) WriteTo(p []byte, addr net.Addr) (n int, err error) {
|
|
||||||
n, err = c.PacketConn.WriteTo(p, addr)
|
|
||||||
metrics.OutputBytes(c.service).Add(float64(n))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
type udpConn struct {
|
|
||||||
net.PacketConn
|
|
||||||
service string
|
|
||||||
}
|
|
||||||
|
|
||||||
func WrapUDPConn(service string, pc net.PacketConn) UDPConn {
|
|
||||||
return &udpConn{
|
|
||||||
PacketConn: pc,
|
|
||||||
service: service,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *udpConn) RemoteAddr() net.Addr {
|
|
||||||
if nc, ok := c.PacketConn.(remoteAddr); ok {
|
|
||||||
return nc.RemoteAddr()
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *udpConn) SetReadBuffer(n int) error {
|
|
||||||
if nc, ok := c.PacketConn.(setBuffer); ok {
|
|
||||||
return nc.SetReadBuffer(n)
|
|
||||||
}
|
|
||||||
return errUnsupport
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *udpConn) SetWriteBuffer(n int) error {
|
|
||||||
if nc, ok := c.PacketConn.(setBuffer); ok {
|
|
||||||
return nc.SetWriteBuffer(n)
|
|
||||||
}
|
|
||||||
return errUnsupport
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *udpConn) Read(b []byte) (n int, err error) {
|
|
||||||
if nc, ok := c.PacketConn.(io.Reader); ok {
|
|
||||||
n, err = nc.Read(b)
|
|
||||||
metrics.InputBytes(c.service).Add(float64(n))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
err = errUnsupport
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *udpConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) {
|
|
||||||
n, addr, err = c.PacketConn.ReadFrom(p)
|
|
||||||
metrics.InputBytes(c.service).Add(float64(n))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *udpConn) ReadFromUDP(b []byte) (n int, addr *net.UDPAddr, err error) {
|
|
||||||
if nc, ok := c.PacketConn.(readUDP); ok {
|
|
||||||
n, addr, err = nc.ReadFromUDP(b)
|
|
||||||
metrics.InputBytes(c.service).Add(float64(n))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
err = errUnsupport
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *udpConn) ReadMsgUDP(b, oob []byte) (n, oobn, flags int, addr *net.UDPAddr, err error) {
|
|
||||||
if nc, ok := c.PacketConn.(readUDP); ok {
|
|
||||||
n, oobn, flags, addr, err = nc.ReadMsgUDP(b, oob)
|
|
||||||
metrics.InputBytes(c.service).Add(float64(n + oobn))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
err = errUnsupport
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *udpConn) Write(b []byte) (n int, err error) {
|
|
||||||
if nc, ok := c.PacketConn.(io.Writer); ok {
|
|
||||||
n, err = nc.Write(b)
|
|
||||||
metrics.OutputBytes(c.service).Add(float64(n))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
err = errUnsupport
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *udpConn) WriteTo(p []byte, addr net.Addr) (n int, err error) {
|
|
||||||
n, err = c.PacketConn.WriteTo(p, addr)
|
|
||||||
metrics.OutputBytes(c.service).Add(float64(n))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *udpConn) WriteToUDP(b []byte, addr *net.UDPAddr) (n int, err error) {
|
|
||||||
if nc, ok := c.PacketConn.(writeUDP); ok {
|
|
||||||
n, err = nc.WriteToUDP(b, addr)
|
|
||||||
metrics.OutputBytes(c.service).Add(float64(n))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
err = errUnsupport
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *udpConn) WriteMsgUDP(b, oob []byte, addr *net.UDPAddr) (n, oobn int, err error) {
|
|
||||||
if nc, ok := c.PacketConn.(writeUDP); ok {
|
|
||||||
n, oobn, err = nc.WriteMsgUDP(b, oob, addr)
|
|
||||||
metrics.OutputBytes(c.service).Add(float64(n + oobn))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
err = errUnsupport
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *udpConn) SyscallConn() (rc syscall.RawConn, err error) {
|
|
||||||
if nc, ok := c.PacketConn.(syscallConn); ok {
|
|
||||||
return nc.SyscallConn()
|
|
||||||
}
|
|
||||||
err = errUnsupport
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *udpConn) SetDSCP(n int) error {
|
|
||||||
if nc, ok := c.PacketConn.(setDSCP); ok {
|
|
||||||
return nc.SetDSCP(n)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type UDPConn interface {
|
|
||||||
net.PacketConn
|
|
||||||
io.Reader
|
|
||||||
io.Writer
|
|
||||||
readUDP
|
|
||||||
writeUDP
|
|
||||||
setBuffer
|
|
||||||
syscallConn
|
|
||||||
remoteAddr
|
|
||||||
}
|
|
||||||
|
|
||||||
type setBuffer interface {
|
|
||||||
SetReadBuffer(bytes int) error
|
|
||||||
SetWriteBuffer(bytes int) error
|
|
||||||
}
|
|
||||||
|
|
||||||
type readUDP interface {
|
|
||||||
ReadFromUDP(b []byte) (n int, addr *net.UDPAddr, err error)
|
|
||||||
ReadMsgUDP(b, oob []byte) (n, oobn, flags int, addr *net.UDPAddr, err error)
|
|
||||||
}
|
|
||||||
|
|
||||||
type writeUDP interface {
|
|
||||||
WriteToUDP(b []byte, addr *net.UDPAddr) (int, error)
|
|
||||||
WriteMsgUDP(b, oob []byte, addr *net.UDPAddr) (n, oobn int, err error)
|
|
||||||
}
|
|
||||||
|
|
||||||
type syscallConn interface {
|
|
||||||
SyscallConn() (syscall.RawConn, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
type remoteAddr interface {
|
|
||||||
RemoteAddr() net.Addr
|
|
||||||
}
|
|
||||||
|
|
||||||
// tcpraw.TCPConn
|
|
||||||
type setDSCP interface {
|
|
||||||
SetDSCP(int) error
|
|
||||||
}
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
package metrics
|
|
||||||
|
|
||||||
import "net"
|
|
||||||
|
|
||||||
type listener struct {
|
|
||||||
service string
|
|
||||||
net.Listener
|
|
||||||
}
|
|
||||||
|
|
||||||
func WrapListener(service string, ln net.Listener) net.Listener {
|
|
||||||
return &listener{
|
|
||||||
service: service,
|
|
||||||
Listener: ln,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ln *listener) Accept() (net.Conn, error) {
|
|
||||||
c, err := ln.Listener.Accept()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return WrapConn(ln.service, c), nil
|
|
||||||
}
|
|
||||||
@@ -1,144 +0,0 @@
|
|||||||
package dialer
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"net"
|
|
||||||
"syscall"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/go-gost/gost/pkg/logger"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
DefaultNetDialer = &NetDialer{
|
|
||||||
Timeout: 30 * time.Second,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
type NetDialer struct {
|
|
||||||
Interface string
|
|
||||||
Timeout time.Duration
|
|
||||||
DialFunc func(ctx context.Context, network, addr string) (net.Conn, error)
|
|
||||||
Logger logger.Logger
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *NetDialer) Dial(ctx context.Context, network, addr string) (net.Conn, error) {
|
|
||||||
if d == nil {
|
|
||||||
d = DefaultNetDialer
|
|
||||||
}
|
|
||||||
log := d.Logger
|
|
||||||
if log == nil {
|
|
||||||
log = logger.Default()
|
|
||||||
}
|
|
||||||
|
|
||||||
ifceName, ifAddr, err := parseInterfaceAddr(d.Interface, network)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if d.DialFunc != nil {
|
|
||||||
return d.DialFunc(ctx, network, addr)
|
|
||||||
}
|
|
||||||
logger.Default().Infof("interface: %s %v/%s", ifceName, ifAddr, network)
|
|
||||||
|
|
||||||
switch network {
|
|
||||||
case "udp", "udp4", "udp6":
|
|
||||||
if addr == "" {
|
|
||||||
var laddr *net.UDPAddr
|
|
||||||
if ifAddr != nil {
|
|
||||||
laddr, _ = ifAddr.(*net.UDPAddr)
|
|
||||||
}
|
|
||||||
|
|
||||||
return net.ListenUDP(network, laddr)
|
|
||||||
}
|
|
||||||
case "tcp", "tcp4", "tcp6":
|
|
||||||
default:
|
|
||||||
return nil, fmt.Errorf("dial: unsupported network %s", network)
|
|
||||||
}
|
|
||||||
netd := net.Dialer{
|
|
||||||
Timeout: d.Timeout,
|
|
||||||
LocalAddr: ifAddr,
|
|
||||||
Control: func(network, address string, c syscall.RawConn) error {
|
|
||||||
var cerr error
|
|
||||||
err := c.Control(func(fd uintptr) {
|
|
||||||
cerr = bindDevice(fd, ifceName)
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if cerr != nil {
|
|
||||||
return cerr
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
}
|
|
||||||
return netd.DialContext(ctx, network, addr)
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseInterfaceAddr(ifceName, network string) (ifce string, addr net.Addr, err error) {
|
|
||||||
if ifceName == "" {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
ip := net.ParseIP(ifceName)
|
|
||||||
if ip == nil {
|
|
||||||
var ife *net.Interface
|
|
||||||
ife, err = net.InterfaceByName(ifceName)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
var addrs []net.Addr
|
|
||||||
addrs, err = ife.Addrs()
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if len(addrs) == 0 {
|
|
||||||
err = fmt.Errorf("addr not found for interface %s", ifceName)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ip = addrs[0].(*net.IPNet).IP
|
|
||||||
ifce = ifceName
|
|
||||||
} else {
|
|
||||||
ifce, err = findInterfaceByIP(ip)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
port := 0
|
|
||||||
switch network {
|
|
||||||
case "tcp", "tcp4", "tcp6":
|
|
||||||
addr = &net.TCPAddr{IP: ip, Port: port}
|
|
||||||
return
|
|
||||||
case "udp", "udp4", "udp6":
|
|
||||||
addr = &net.UDPAddr{IP: ip, Port: port}
|
|
||||||
return
|
|
||||||
default:
|
|
||||||
addr = &net.IPAddr{IP: ip}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func findInterfaceByIP(ip net.IP) (string, error) {
|
|
||||||
ifces, err := net.Interfaces()
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
for _, ifce := range ifces {
|
|
||||||
addrs, _ := ifce.Addrs()
|
|
||||||
if len(addrs) == 0 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
for _, addr := range addrs {
|
|
||||||
ipAddr, _ := addr.(*net.IPNet)
|
|
||||||
if ipAddr == nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
// logger.Default().Infof("%s-%s", ipAddr, ip)
|
|
||||||
if ipAddr.IP.Equal(ip) {
|
|
||||||
return ifce.Name, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return "", nil
|
|
||||||
}
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
package dialer
|
|
||||||
|
|
||||||
import (
|
|
||||||
"golang.org/x/sys/unix"
|
|
||||||
)
|
|
||||||
|
|
||||||
func bindDevice(fd uintptr, ifceName string) error {
|
|
||||||
// unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_REUSEADDR, 1)
|
|
||||||
// unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_REUSEPORT, 1)
|
|
||||||
if ifceName == "" {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return unix.BindToDevice(int(fd), ifceName)
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
//go:build !linux
|
|
||||||
|
|
||||||
package dialer
|
|
||||||
|
|
||||||
func bindDevice(fd uintptr, ifceName string) error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
@@ -1,126 +0,0 @@
|
|||||||
package relay
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net"
|
|
||||||
|
|
||||||
"github.com/go-gost/gost/pkg/bypass"
|
|
||||||
"github.com/go-gost/gost/pkg/common/bufpool"
|
|
||||||
"github.com/go-gost/gost/pkg/logger"
|
|
||||||
)
|
|
||||||
|
|
||||||
type UDPRelay struct {
|
|
||||||
pc1 net.PacketConn
|
|
||||||
pc2 net.PacketConn
|
|
||||||
|
|
||||||
bypass bypass.Bypass
|
|
||||||
bufferSize int
|
|
||||||
logger logger.Logger
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewUDPRelay(pc1, pc2 net.PacketConn) *UDPRelay {
|
|
||||||
return &UDPRelay{
|
|
||||||
pc1: pc1,
|
|
||||||
pc2: pc2,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *UDPRelay) WithBypass(bp bypass.Bypass) *UDPRelay {
|
|
||||||
r.bypass = bp
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *UDPRelay) WithLogger(logger logger.Logger) *UDPRelay {
|
|
||||||
r.logger = logger
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *UDPRelay) SetBufferSize(n int) {
|
|
||||||
r.bufferSize = n
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *UDPRelay) Run() (err error) {
|
|
||||||
bufSize := r.bufferSize
|
|
||||||
if bufSize <= 0 {
|
|
||||||
bufSize = 1024
|
|
||||||
}
|
|
||||||
|
|
||||||
errc := make(chan error, 2)
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
for {
|
|
||||||
err := func() error {
|
|
||||||
b := bufpool.Get(bufSize)
|
|
||||||
defer bufpool.Put(b)
|
|
||||||
|
|
||||||
n, raddr, err := r.pc1.ReadFrom(*b)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if r.bypass != nil && r.bypass.Contains(raddr.String()) {
|
|
||||||
if r.logger != nil {
|
|
||||||
r.logger.Warn("bypass: ", raddr)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, err := r.pc2.WriteTo((*b)[:n], raddr); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if r.logger != nil {
|
|
||||||
r.logger.Debugf("%s >>> %s data: %d",
|
|
||||||
r.pc2.LocalAddr(), raddr, n)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}()
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
errc <- err
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
for {
|
|
||||||
err := func() error {
|
|
||||||
b := bufpool.Get(bufSize)
|
|
||||||
defer bufpool.Put(b)
|
|
||||||
|
|
||||||
n, raddr, err := r.pc2.ReadFrom(*b)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if r.bypass != nil && r.bypass.Contains(raddr.String()) {
|
|
||||||
if r.logger != nil {
|
|
||||||
r.logger.Warn("bypass: ", raddr)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, err := r.pc1.WriteTo((*b)[:n], raddr); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if r.logger != nil {
|
|
||||||
r.logger.Debugf("%s <<< %s data: %d",
|
|
||||||
r.pc2.LocalAddr(), raddr, n)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}()
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
errc <- err
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
return <-errc
|
|
||||||
}
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
package net
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bufio"
|
|
||||||
"io"
|
|
||||||
"net"
|
|
||||||
|
|
||||||
"github.com/go-gost/gost/pkg/common/bufpool"
|
|
||||||
)
|
|
||||||
|
|
||||||
func Transport(rw1, rw2 io.ReadWriter) error {
|
|
||||||
errc := make(chan error, 1)
|
|
||||||
go func() {
|
|
||||||
errc <- copyBuffer(rw1, rw2)
|
|
||||||
}()
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
errc <- copyBuffer(rw2, rw1)
|
|
||||||
}()
|
|
||||||
|
|
||||||
err := <-errc
|
|
||||||
if err != nil && err == io.EOF {
|
|
||||||
err = nil
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func copyBuffer(dst io.Writer, src io.Reader) error {
|
|
||||||
buf := bufpool.Get(16 * 1024)
|
|
||||||
defer bufpool.Put(buf)
|
|
||||||
|
|
||||||
_, err := io.CopyBuffer(dst, src, *buf)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
type bufferReaderConn struct {
|
|
||||||
net.Conn
|
|
||||||
br *bufio.Reader
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewBufferReaderConn(conn net.Conn, br *bufio.Reader) net.Conn {
|
|
||||||
return &bufferReaderConn{
|
|
||||||
Conn: conn,
|
|
||||||
br: br,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *bufferReaderConn) Read(b []byte) (int, error) {
|
|
||||||
return c.br.Read(b)
|
|
||||||
}
|
|
||||||
@@ -1,148 +0,0 @@
|
|||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
|
||||||
// versions:
|
|
||||||
// protoc-gen-go v1.26.0
|
|
||||||
// protoc v3.12.4
|
|
||||||
// source: gost.proto
|
|
||||||
|
|
||||||
package proto
|
|
||||||
|
|
||||||
import (
|
|
||||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
|
||||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
|
||||||
reflect "reflect"
|
|
||||||
sync "sync"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
// Verify that this generated code is sufficiently up-to-date.
|
|
||||||
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
|
||||||
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
|
||||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
|
||||||
)
|
|
||||||
|
|
||||||
type Chunk struct {
|
|
||||||
state protoimpl.MessageState
|
|
||||||
sizeCache protoimpl.SizeCache
|
|
||||||
unknownFields protoimpl.UnknownFields
|
|
||||||
|
|
||||||
Data []byte `protobuf:"bytes,1,opt,name=data,proto3" json:"data,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *Chunk) Reset() {
|
|
||||||
*x = Chunk{}
|
|
||||||
if protoimpl.UnsafeEnabled {
|
|
||||||
mi := &file_gost_proto_msgTypes[0]
|
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
|
||||||
ms.StoreMessageInfo(mi)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *Chunk) String() string {
|
|
||||||
return protoimpl.X.MessageStringOf(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (*Chunk) ProtoMessage() {}
|
|
||||||
|
|
||||||
func (x *Chunk) ProtoReflect() protoreflect.Message {
|
|
||||||
mi := &file_gost_proto_msgTypes[0]
|
|
||||||
if protoimpl.UnsafeEnabled && x != nil {
|
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
|
||||||
if ms.LoadMessageInfo() == nil {
|
|
||||||
ms.StoreMessageInfo(mi)
|
|
||||||
}
|
|
||||||
return ms
|
|
||||||
}
|
|
||||||
return mi.MessageOf(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deprecated: Use Chunk.ProtoReflect.Descriptor instead.
|
|
||||||
func (*Chunk) Descriptor() ([]byte, []int) {
|
|
||||||
return file_gost_proto_rawDescGZIP(), []int{0}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *Chunk) GetData() []byte {
|
|
||||||
if x != nil {
|
|
||||||
return x.Data
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var File_gost_proto protoreflect.FileDescriptor
|
|
||||||
|
|
||||||
var file_gost_proto_rawDesc = []byte{
|
|
||||||
0x0a, 0x0a, 0x67, 0x6f, 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x1b, 0x0a, 0x05,
|
|
||||||
0x43, 0x68, 0x75, 0x6e, 0x6b, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20,
|
|
||||||
0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x32, 0x29, 0x0a, 0x09, 0x47, 0x6f, 0x73,
|
|
||||||
0x74, 0x54, 0x75, 0x6e, 0x65, 0x6c, 0x12, 0x1c, 0x0a, 0x06, 0x54, 0x75, 0x6e, 0x6e, 0x65, 0x6c,
|
|
||||||
0x12, 0x06, 0x2e, 0x43, 0x68, 0x75, 0x6e, 0x6b, 0x1a, 0x06, 0x2e, 0x43, 0x68, 0x75, 0x6e, 0x6b,
|
|
||||||
0x28, 0x01, 0x30, 0x01, 0x42, 0x34, 0x5a, 0x32, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63,
|
|
||||||
0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x2d, 0x67, 0x6f, 0x73, 0x74, 0x2f, 0x67, 0x6f, 0x73, 0x74, 0x2f,
|
|
||||||
0x70, 0x6b, 0x67, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x75, 0x74, 0x69, 0x6c, 0x2f,
|
|
||||||
0x67, 0x72, 0x70, 0x63, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74,
|
|
||||||
0x6f, 0x33,
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
file_gost_proto_rawDescOnce sync.Once
|
|
||||||
file_gost_proto_rawDescData = file_gost_proto_rawDesc
|
|
||||||
)
|
|
||||||
|
|
||||||
func file_gost_proto_rawDescGZIP() []byte {
|
|
||||||
file_gost_proto_rawDescOnce.Do(func() {
|
|
||||||
file_gost_proto_rawDescData = protoimpl.X.CompressGZIP(file_gost_proto_rawDescData)
|
|
||||||
})
|
|
||||||
return file_gost_proto_rawDescData
|
|
||||||
}
|
|
||||||
|
|
||||||
var file_gost_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
|
|
||||||
var file_gost_proto_goTypes = []any{
|
|
||||||
(*Chunk)(nil), // 0: Chunk
|
|
||||||
}
|
|
||||||
var file_gost_proto_depIdxs = []int32{
|
|
||||||
0, // 0: GostTunel.Tunnel:input_type -> Chunk
|
|
||||||
0, // 1: GostTunel.Tunnel:output_type -> Chunk
|
|
||||||
1, // [1:2] is the sub-list for method output_type
|
|
||||||
0, // [0:1] is the sub-list for method input_type
|
|
||||||
0, // [0:0] is the sub-list for extension type_name
|
|
||||||
0, // [0:0] is the sub-list for extension extendee
|
|
||||||
0, // [0:0] is the sub-list for field type_name
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() { file_gost_proto_init() }
|
|
||||||
func file_gost_proto_init() {
|
|
||||||
if File_gost_proto != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if !protoimpl.UnsafeEnabled {
|
|
||||||
file_gost_proto_msgTypes[0].Exporter = func(v any, i int) any {
|
|
||||||
switch v := v.(*Chunk); i {
|
|
||||||
case 0:
|
|
||||||
return &v.state
|
|
||||||
case 1:
|
|
||||||
return &v.sizeCache
|
|
||||||
case 2:
|
|
||||||
return &v.unknownFields
|
|
||||||
default:
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
type x struct{}
|
|
||||||
out := protoimpl.TypeBuilder{
|
|
||||||
File: protoimpl.DescBuilder{
|
|
||||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
|
||||||
RawDescriptor: file_gost_proto_rawDesc,
|
|
||||||
NumEnums: 0,
|
|
||||||
NumMessages: 1,
|
|
||||||
NumExtensions: 0,
|
|
||||||
NumServices: 1,
|
|
||||||
},
|
|
||||||
GoTypes: file_gost_proto_goTypes,
|
|
||||||
DependencyIndexes: file_gost_proto_depIdxs,
|
|
||||||
MessageInfos: file_gost_proto_msgTypes,
|
|
||||||
}.Build()
|
|
||||||
File_gost_proto = out.File
|
|
||||||
file_gost_proto_rawDesc = nil
|
|
||||||
file_gost_proto_goTypes = nil
|
|
||||||
file_gost_proto_depIdxs = nil
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
syntax = "proto3";
|
|
||||||
option go_package = "github.com/go-gost/gost/pkg/common/util/grpc/proto";
|
|
||||||
|
|
||||||
message Chunk {
|
|
||||||
bytes data = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
service GostTunel {
|
|
||||||
rpc Tunnel (stream Chunk) returns (stream Chunk);
|
|
||||||
}
|
|
||||||
@@ -1,133 +0,0 @@
|
|||||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
|
||||||
|
|
||||||
package proto
|
|
||||||
|
|
||||||
import (
|
|
||||||
context "context"
|
|
||||||
grpc "google.golang.org/grpc"
|
|
||||||
codes "google.golang.org/grpc/codes"
|
|
||||||
status "google.golang.org/grpc/status"
|
|
||||||
)
|
|
||||||
|
|
||||||
// This is a compile-time assertion to ensure that this generated file
|
|
||||||
// is compatible with the grpc package it is being compiled against.
|
|
||||||
// Requires gRPC-Go v1.32.0 or later.
|
|
||||||
const _ = grpc.SupportPackageIsVersion7
|
|
||||||
|
|
||||||
// GostTunelClient is the client API for GostTunel service.
|
|
||||||
//
|
|
||||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
|
|
||||||
type GostTunelClient interface {
|
|
||||||
Tunnel(ctx context.Context, opts ...grpc.CallOption) (GostTunel_TunnelClient, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
type gostTunelClient struct {
|
|
||||||
cc grpc.ClientConnInterface
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewGostTunelClient(cc grpc.ClientConnInterface) GostTunelClient {
|
|
||||||
return &gostTunelClient{cc}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *gostTunelClient) Tunnel(ctx context.Context, opts ...grpc.CallOption) (GostTunel_TunnelClient, error) {
|
|
||||||
stream, err := c.cc.NewStream(ctx, &GostTunel_ServiceDesc.Streams[0], "/GostTunel/Tunnel", opts...)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
x := &gostTunelTunnelClient{stream}
|
|
||||||
return x, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type GostTunel_TunnelClient interface {
|
|
||||||
Send(*Chunk) error
|
|
||||||
Recv() (*Chunk, error)
|
|
||||||
grpc.ClientStream
|
|
||||||
}
|
|
||||||
|
|
||||||
type gostTunelTunnelClient struct {
|
|
||||||
grpc.ClientStream
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *gostTunelTunnelClient) Send(m *Chunk) error {
|
|
||||||
return x.ClientStream.SendMsg(m)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *gostTunelTunnelClient) Recv() (*Chunk, error) {
|
|
||||||
m := new(Chunk)
|
|
||||||
if err := x.ClientStream.RecvMsg(m); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return m, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GostTunelServer is the server API for GostTunel service.
|
|
||||||
// All implementations must embed UnimplementedGostTunelServer
|
|
||||||
// for forward compatibility
|
|
||||||
type GostTunelServer interface {
|
|
||||||
Tunnel(GostTunel_TunnelServer) error
|
|
||||||
mustEmbedUnimplementedGostTunelServer()
|
|
||||||
}
|
|
||||||
|
|
||||||
// UnimplementedGostTunelServer must be embedded to have forward compatible implementations.
|
|
||||||
type UnimplementedGostTunelServer struct {
|
|
||||||
}
|
|
||||||
|
|
||||||
func (UnimplementedGostTunelServer) Tunnel(GostTunel_TunnelServer) error {
|
|
||||||
return status.Errorf(codes.Unimplemented, "method Tunnel not implemented")
|
|
||||||
}
|
|
||||||
func (UnimplementedGostTunelServer) mustEmbedUnimplementedGostTunelServer() {}
|
|
||||||
|
|
||||||
// UnsafeGostTunelServer may be embedded to opt out of forward compatibility for this service.
|
|
||||||
// Use of this interface is not recommended, as added methods to GostTunelServer will
|
|
||||||
// result in compilation errors.
|
|
||||||
type UnsafeGostTunelServer interface {
|
|
||||||
mustEmbedUnimplementedGostTunelServer()
|
|
||||||
}
|
|
||||||
|
|
||||||
func RegisterGostTunelServer(s grpc.ServiceRegistrar, srv GostTunelServer) {
|
|
||||||
s.RegisterService(&GostTunel_ServiceDesc, srv)
|
|
||||||
}
|
|
||||||
|
|
||||||
func _GostTunel_Tunnel_Handler(srv any, stream grpc.ServerStream) error {
|
|
||||||
return srv.(GostTunelServer).Tunnel(&gostTunelTunnelServer{stream})
|
|
||||||
}
|
|
||||||
|
|
||||||
type GostTunel_TunnelServer interface {
|
|
||||||
Send(*Chunk) error
|
|
||||||
Recv() (*Chunk, error)
|
|
||||||
grpc.ServerStream
|
|
||||||
}
|
|
||||||
|
|
||||||
type gostTunelTunnelServer struct {
|
|
||||||
grpc.ServerStream
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *gostTunelTunnelServer) Send(m *Chunk) error {
|
|
||||||
return x.ServerStream.SendMsg(m)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *gostTunelTunnelServer) Recv() (*Chunk, error) {
|
|
||||||
m := new(Chunk)
|
|
||||||
if err := x.ServerStream.RecvMsg(m); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return m, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GostTunel_ServiceDesc is the grpc.ServiceDesc for GostTunel service.
|
|
||||||
// It's only intended for direct use with grpc.RegisterService,
|
|
||||||
// and not to be introspected or modified (even as a copy)
|
|
||||||
var GostTunel_ServiceDesc = grpc.ServiceDesc{
|
|
||||||
ServiceName: "GostTunel",
|
|
||||||
HandlerType: (*GostTunelServer)(nil),
|
|
||||||
Methods: []grpc.MethodDesc{},
|
|
||||||
Streams: []grpc.StreamDesc{
|
|
||||||
{
|
|
||||||
StreamName: "Tunnel",
|
|
||||||
Handler: _GostTunel_Tunnel_Handler,
|
|
||||||
ServerStreams: true,
|
|
||||||
ClientStreams: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Metadata: "gost.proto",
|
|
||||||
}
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
protoc --go_out=. --go_opt=paths=source_relative \
|
|
||||||
--go-grpc_out=. --go-grpc_opt=paths=source_relative \
|
|
||||||
gost.proto
|
|
||||||
@@ -1,115 +0,0 @@
|
|||||||
package kcp
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/sha1"
|
|
||||||
|
|
||||||
"github.com/xtaci/kcp-go/v5"
|
|
||||||
"golang.org/x/crypto/pbkdf2"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
// DefaultSalt is the default salt for KCP cipher.
|
|
||||||
DefaultSalt = "kcp-go"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
// DefaultKCPConfig is the default KCP config.
|
|
||||||
DefaultConfig = &Config{
|
|
||||||
Key: "it's a secrect",
|
|
||||||
Crypt: "aes",
|
|
||||||
Mode: "fast",
|
|
||||||
MTU: 1350,
|
|
||||||
SndWnd: 1024,
|
|
||||||
RcvWnd: 1024,
|
|
||||||
DataShard: 10,
|
|
||||||
ParityShard: 3,
|
|
||||||
DSCP: 0,
|
|
||||||
NoComp: false,
|
|
||||||
AckNodelay: false,
|
|
||||||
NoDelay: 0,
|
|
||||||
Interval: 50,
|
|
||||||
Resend: 0,
|
|
||||||
NoCongestion: 0,
|
|
||||||
SockBuf: 4194304,
|
|
||||||
KeepAlive: 10,
|
|
||||||
SnmpLog: "",
|
|
||||||
SnmpPeriod: 60,
|
|
||||||
Signal: false,
|
|
||||||
TCP: false,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
// KCPConfig describes the config for KCP.
|
|
||||||
type Config struct {
|
|
||||||
Key string `json:"key"`
|
|
||||||
Crypt string `json:"crypt"`
|
|
||||||
Mode string `json:"mode"`
|
|
||||||
MTU int `json:"mtu"`
|
|
||||||
SndWnd int `json:"sndwnd"`
|
|
||||||
RcvWnd int `json:"rcvwnd"`
|
|
||||||
DataShard int `json:"datashard"`
|
|
||||||
ParityShard int `json:"parityshard"`
|
|
||||||
DSCP int `json:"dscp"`
|
|
||||||
NoComp bool `json:"nocomp"`
|
|
||||||
AckNodelay bool `json:"acknodelay"`
|
|
||||||
NoDelay int `json:"nodelay"`
|
|
||||||
Interval int `json:"interval"`
|
|
||||||
Resend int `json:"resend"`
|
|
||||||
NoCongestion int `json:"nc"`
|
|
||||||
SockBuf int `json:"sockbuf"`
|
|
||||||
KeepAlive int `json:"keepalive"`
|
|
||||||
SnmpLog string `json:"snmplog"`
|
|
||||||
SnmpPeriod int `json:"snmpperiod"`
|
|
||||||
Signal bool `json:"signal"` // Signal enables the signal SIGUSR1 feature.
|
|
||||||
TCP bool `json:"tcp"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Init initializes the KCP config.
|
|
||||||
func (c *Config) Init() {
|
|
||||||
switch c.Mode {
|
|
||||||
case "normal":
|
|
||||||
c.NoDelay, c.Interval, c.Resend, c.NoCongestion = 0, 40, 2, 1
|
|
||||||
case "fast":
|
|
||||||
c.NoDelay, c.Interval, c.Resend, c.NoCongestion = 0, 30, 2, 1
|
|
||||||
case "fast2":
|
|
||||||
c.NoDelay, c.Interval, c.Resend, c.NoCongestion = 1, 20, 2, 1
|
|
||||||
case "fast3":
|
|
||||||
c.NoDelay, c.Interval, c.Resend, c.NoCongestion = 1, 10, 2, 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BlockCrypt(key, crypt, salt string) (block kcp.BlockCrypt) {
|
|
||||||
pass := pbkdf2.Key([]byte(key), []byte(salt), 4096, 32, sha1.New)
|
|
||||||
|
|
||||||
switch crypt {
|
|
||||||
case "sm4":
|
|
||||||
block, _ = kcp.NewSM4BlockCrypt(pass[:16])
|
|
||||||
case "tea":
|
|
||||||
block, _ = kcp.NewTEABlockCrypt(pass[:16])
|
|
||||||
case "xor":
|
|
||||||
block, _ = kcp.NewSimpleXORBlockCrypt(pass)
|
|
||||||
case "none":
|
|
||||||
block, _ = kcp.NewNoneBlockCrypt(pass)
|
|
||||||
case "aes-128":
|
|
||||||
block, _ = kcp.NewAESBlockCrypt(pass[:16])
|
|
||||||
case "aes-192":
|
|
||||||
block, _ = kcp.NewAESBlockCrypt(pass[:24])
|
|
||||||
case "blowfish":
|
|
||||||
block, _ = kcp.NewBlowfishBlockCrypt(pass)
|
|
||||||
case "twofish":
|
|
||||||
block, _ = kcp.NewTwofishBlockCrypt(pass)
|
|
||||||
case "cast5":
|
|
||||||
block, _ = kcp.NewCast5BlockCrypt(pass[:16])
|
|
||||||
case "3des":
|
|
||||||
block, _ = kcp.NewTripleDESBlockCrypt(pass[:24])
|
|
||||||
case "xtea":
|
|
||||||
block, _ = kcp.NewXTEABlockCrypt(pass[:16])
|
|
||||||
case "salsa20":
|
|
||||||
block, _ = kcp.NewSalsa20BlockCrypt(pass)
|
|
||||||
case "aes":
|
|
||||||
fallthrough
|
|
||||||
default: // aes
|
|
||||||
block, _ = kcp.NewAESBlockCrypt(pass)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
package kcp
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net"
|
|
||||||
|
|
||||||
"github.com/golang/snappy"
|
|
||||||
)
|
|
||||||
|
|
||||||
type kcpCompStreamConn struct {
|
|
||||||
net.Conn
|
|
||||||
w *snappy.Writer
|
|
||||||
r *snappy.Reader
|
|
||||||
}
|
|
||||||
|
|
||||||
func CompStreamConn(conn net.Conn) net.Conn {
|
|
||||||
return &kcpCompStreamConn{
|
|
||||||
Conn: conn,
|
|
||||||
w: snappy.NewBufferedWriter(conn),
|
|
||||||
r: snappy.NewReader(conn),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *kcpCompStreamConn) Read(b []byte) (n int, err error) {
|
|
||||||
return c.r.Read(b)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *kcpCompStreamConn) Write(b []byte) (n int, err error) {
|
|
||||||
n, err = c.w.Write(b)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
err = c.w.Flush()
|
|
||||||
return n, err
|
|
||||||
}
|
|
||||||
@@ -1,85 +0,0 @@
|
|||||||
package mux
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net"
|
|
||||||
|
|
||||||
smux "github.com/xtaci/smux"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Session struct {
|
|
||||||
conn net.Conn
|
|
||||||
session *smux.Session
|
|
||||||
}
|
|
||||||
|
|
||||||
func ClientSession(conn net.Conn) (*Session, error) {
|
|
||||||
s, err := smux.Client(conn, smux.DefaultConfig())
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &Session{
|
|
||||||
conn: conn,
|
|
||||||
session: s,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func ServerSession(conn net.Conn) (*Session, error) {
|
|
||||||
s, err := smux.Server(conn, smux.DefaultConfig())
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &Session{
|
|
||||||
conn: conn,
|
|
||||||
session: s,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (session *Session) GetConn() (net.Conn, error) {
|
|
||||||
stream, err := session.session.OpenStream()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &streamConn{Conn: session.conn, stream: stream}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (session *Session) Accept() (net.Conn, error) {
|
|
||||||
stream, err := session.session.AcceptStream()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &streamConn{Conn: session.conn, stream: stream}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (session *Session) Close() error {
|
|
||||||
if session.session == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return session.session.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (session *Session) IsClosed() bool {
|
|
||||||
if session.session == nil {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return session.session.IsClosed()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (session *Session) NumStreams() int {
|
|
||||||
return session.session.NumStreams()
|
|
||||||
}
|
|
||||||
|
|
||||||
type streamConn struct {
|
|
||||||
net.Conn
|
|
||||||
stream *smux.Stream
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *streamConn) Read(b []byte) (n int, err error) {
|
|
||||||
return c.stream.Read(b)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *streamConn) Write(b []byte) (n int, err error) {
|
|
||||||
return c.stream.Write(b)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *streamConn) Close() error {
|
|
||||||
return c.stream.Close()
|
|
||||||
}
|
|
||||||
@@ -1,172 +0,0 @@
|
|||||||
package socks
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"net"
|
|
||||||
|
|
||||||
"github.com/go-gost/gosocks5"
|
|
||||||
"github.com/go-gost/gost/pkg/common/bufpool"
|
|
||||||
)
|
|
||||||
|
|
||||||
type udpTunConn struct {
|
|
||||||
net.Conn
|
|
||||||
taddr net.Addr
|
|
||||||
}
|
|
||||||
|
|
||||||
func UDPTunClientConn(c net.Conn, targetAddr net.Addr) net.Conn {
|
|
||||||
return &udpTunConn{
|
|
||||||
Conn: c,
|
|
||||||
taddr: targetAddr,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func UDPTunClientPacketConn(c net.Conn) net.PacketConn {
|
|
||||||
return &udpTunConn{
|
|
||||||
Conn: c,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func UDPTunServerConn(c net.Conn) net.PacketConn {
|
|
||||||
return &udpTunConn{
|
|
||||||
Conn: c,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *udpTunConn) ReadFrom(b []byte) (n int, addr net.Addr, err error) {
|
|
||||||
socksAddr := gosocks5.Addr{}
|
|
||||||
header := gosocks5.UDPHeader{
|
|
||||||
Addr: &socksAddr,
|
|
||||||
}
|
|
||||||
dgram := gosocks5.UDPDatagram{
|
|
||||||
Header: &header,
|
|
||||||
Data: b,
|
|
||||||
}
|
|
||||||
_, err = dgram.ReadFrom(c.Conn)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
n = len(dgram.Data)
|
|
||||||
if n > len(b) {
|
|
||||||
n = copy(b, dgram.Data)
|
|
||||||
}
|
|
||||||
addr, err = net.ResolveUDPAddr("udp", socksAddr.String())
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *udpTunConn) Read(b []byte) (n int, err error) {
|
|
||||||
n, _, err = c.ReadFrom(b)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *udpTunConn) WriteTo(b []byte, addr net.Addr) (n int, err error) {
|
|
||||||
socksAddr := gosocks5.Addr{}
|
|
||||||
if err = socksAddr.ParseFrom(addr.String()); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
header := gosocks5.UDPHeader{
|
|
||||||
Addr: &socksAddr,
|
|
||||||
}
|
|
||||||
dgram := gosocks5.UDPDatagram{
|
|
||||||
Header: &header,
|
|
||||||
Data: b,
|
|
||||||
}
|
|
||||||
dgram.Header.Rsv = uint16(len(dgram.Data))
|
|
||||||
dgram.Header.Frag = 0xff // UDP tun relay flag, used by shadowsocks
|
|
||||||
_, err = dgram.WriteTo(c.Conn)
|
|
||||||
n = len(b)
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *udpTunConn) Write(b []byte) (n int, err error) {
|
|
||||||
return c.WriteTo(b, c.taddr)
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
DefaultBufferSize = 4096
|
|
||||||
)
|
|
||||||
|
|
||||||
type udpConn struct {
|
|
||||||
net.PacketConn
|
|
||||||
raddr net.Addr
|
|
||||||
taddr net.Addr
|
|
||||||
bufferSize int
|
|
||||||
}
|
|
||||||
|
|
||||||
func UDPConn(c net.PacketConn, bufferSize int) net.PacketConn {
|
|
||||||
return &udpConn{
|
|
||||||
PacketConn: c,
|
|
||||||
bufferSize: bufferSize,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ReadFrom reads an UDP datagram.
|
|
||||||
// NOTE: for server side,
|
|
||||||
// the returned addr is the target address the client want to relay to.
|
|
||||||
func (c *udpConn) ReadFrom(b []byte) (n int, addr net.Addr, err error) {
|
|
||||||
rbuf := bufpool.Get(c.bufferSize)
|
|
||||||
defer bufpool.Put(rbuf)
|
|
||||||
|
|
||||||
n, c.raddr, err = c.PacketConn.ReadFrom(*rbuf)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
socksAddr := gosocks5.Addr{}
|
|
||||||
header := gosocks5.UDPHeader{
|
|
||||||
Addr: &socksAddr,
|
|
||||||
}
|
|
||||||
hlen, err := header.ReadFrom(bytes.NewReader((*rbuf)[:n]))
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
n = copy(b, (*rbuf)[hlen:n])
|
|
||||||
|
|
||||||
addr, err = net.ResolveUDPAddr("udp", socksAddr.String())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *udpConn) Read(b []byte) (n int, err error) {
|
|
||||||
n, _, err = c.ReadFrom(b)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *udpConn) WriteTo(b []byte, addr net.Addr) (n int, err error) {
|
|
||||||
wbuf := bufpool.Get(c.bufferSize)
|
|
||||||
defer bufpool.Put(wbuf)
|
|
||||||
|
|
||||||
socksAddr := gosocks5.Addr{}
|
|
||||||
if err = socksAddr.ParseFrom(addr.String()); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
header := gosocks5.UDPHeader{
|
|
||||||
Addr: &socksAddr,
|
|
||||||
}
|
|
||||||
dgram := gosocks5.UDPDatagram{
|
|
||||||
Header: &header,
|
|
||||||
Data: b,
|
|
||||||
}
|
|
||||||
|
|
||||||
buf := bytes.NewBuffer((*wbuf)[:0])
|
|
||||||
_, err = dgram.WriteTo(buf)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = c.PacketConn.WriteTo(buf.Bytes(), c.raddr)
|
|
||||||
n = len(b)
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *udpConn) Write(b []byte) (n int, err error) {
|
|
||||||
return c.WriteTo(b, c.taddr)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *udpConn) RemoteAddr() net.Addr {
|
|
||||||
return c.raddr
|
|
||||||
}
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
package socks
|
|
||||||
|
|
||||||
const (
|
|
||||||
// MethodTLS is an extended SOCKS5 method with tls encryption support.
|
|
||||||
MethodTLS uint8 = 0x80
|
|
||||||
// MethodTLSAuth is an extended SOCKS5 method with tls encryption and authentication support.
|
|
||||||
MethodTLSAuth uint8 = 0x82
|
|
||||||
// MethodMux is an extended SOCKS5 method for stream multiplexing.
|
|
||||||
MethodMux = 0x88
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
// CmdMuxBind is an extended SOCKS5 request CMD for
|
|
||||||
// multiplexing transport with the binding server.
|
|
||||||
CmdMuxBind uint8 = 0xF2
|
|
||||||
// CmdUDPTun is an extended SOCKS5 request CMD for UDP over TCP.
|
|
||||||
CmdUDPTun uint8 = 0xF3
|
|
||||||
)
|
|
||||||
@@ -1,96 +0,0 @@
|
|||||||
package ss
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"net"
|
|
||||||
|
|
||||||
"github.com/go-gost/gosocks5"
|
|
||||||
"github.com/go-gost/gost/pkg/common/bufpool"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
DefaultBufferSize = 4096
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
_ net.PacketConn = (*UDPConn)(nil)
|
|
||||||
_ net.Conn = (*UDPConn)(nil)
|
|
||||||
)
|
|
||||||
|
|
||||||
type UDPConn struct {
|
|
||||||
net.PacketConn
|
|
||||||
raddr net.Addr
|
|
||||||
taddr net.Addr
|
|
||||||
bufferSize int
|
|
||||||
}
|
|
||||||
|
|
||||||
func UDPClientConn(c net.PacketConn, remoteAddr, targetAddr net.Addr, bufferSize int) *UDPConn {
|
|
||||||
return &UDPConn{
|
|
||||||
PacketConn: c,
|
|
||||||
raddr: remoteAddr,
|
|
||||||
taddr: targetAddr,
|
|
||||||
bufferSize: bufferSize,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func UDPServerConn(c net.PacketConn, remoteAddr net.Addr, bufferSize int) *UDPConn {
|
|
||||||
return &UDPConn{
|
|
||||||
PacketConn: c,
|
|
||||||
raddr: remoteAddr,
|
|
||||||
bufferSize: bufferSize,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *UDPConn) ReadFrom(b []byte) (n int, addr net.Addr, err error) {
|
|
||||||
rbuf := bufpool.Get(c.bufferSize)
|
|
||||||
defer bufpool.Put(rbuf)
|
|
||||||
|
|
||||||
n, _, err = c.PacketConn.ReadFrom(*rbuf)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
saddr := gosocks5.Addr{}
|
|
||||||
addrLen, err := saddr.ReadFrom(bytes.NewReader((*rbuf)[:n]))
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
n = copy(b, (*rbuf)[addrLen:n])
|
|
||||||
addr, err = net.ResolveUDPAddr("udp", saddr.String())
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *UDPConn) Read(b []byte) (n int, err error) {
|
|
||||||
n, _, err = c.ReadFrom(b)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *UDPConn) WriteTo(b []byte, addr net.Addr) (n int, err error) {
|
|
||||||
wbuf := bufpool.Get(c.bufferSize)
|
|
||||||
defer bufpool.Put(wbuf)
|
|
||||||
|
|
||||||
socksAddr := gosocks5.Addr{}
|
|
||||||
if err = socksAddr.ParseFrom(addr.String()); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
addrLen, err := socksAddr.Encode(*wbuf)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
n = copy((*wbuf)[addrLen:], b)
|
|
||||||
_, err = c.PacketConn.WriteTo((*wbuf)[:addrLen+n], c.raddr)
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *UDPConn) Write(b []byte) (n int, err error) {
|
|
||||||
return c.WriteTo(b, c.taddr)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *UDPConn) RemoteAddr() net.Addr {
|
|
||||||
return c.raddr
|
|
||||||
}
|
|
||||||
@@ -1,60 +0,0 @@
|
|||||||
package ss
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"net"
|
|
||||||
|
|
||||||
"github.com/shadowsocks/go-shadowsocks2/core"
|
|
||||||
ss "github.com/shadowsocks/shadowsocks-go/shadowsocks"
|
|
||||||
)
|
|
||||||
|
|
||||||
type shadowCipher struct {
|
|
||||||
cipher *ss.Cipher
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *shadowCipher) StreamConn(conn net.Conn) net.Conn {
|
|
||||||
return ss.NewConn(conn, c.cipher.Copy())
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *shadowCipher) PacketConn(conn net.PacketConn) net.PacketConn {
|
|
||||||
return ss.NewSecurePacketConn(conn, c.cipher.Copy())
|
|
||||||
}
|
|
||||||
|
|
||||||
func ShadowCipher(method, password string, key string) (core.Cipher, error) {
|
|
||||||
if method == "" && password == "" {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
c, _ := ss.NewCipher(method, password)
|
|
||||||
if c != nil {
|
|
||||||
return &shadowCipher{cipher: c}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return core.PickCipher(method, []byte(key), password)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Due to in/out byte length is inconsistent of the shadowsocks.Conn.Write,
|
|
||||||
// we wrap around it to make io.Copy happy.
|
|
||||||
type shadowConn struct {
|
|
||||||
net.Conn
|
|
||||||
wbuf *bytes.Buffer
|
|
||||||
}
|
|
||||||
|
|
||||||
func ShadowConn(conn net.Conn, header []byte) net.Conn {
|
|
||||||
return &shadowConn{
|
|
||||||
Conn: conn,
|
|
||||||
wbuf: bytes.NewBuffer(header),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *shadowConn) Write(b []byte) (n int, err error) {
|
|
||||||
n = len(b) // force byte length consistent
|
|
||||||
if c.wbuf.Len() > 0 {
|
|
||||||
c.wbuf.Write(b) // append the data to the cached header
|
|
||||||
_, err = c.Conn.Write(c.wbuf.Bytes())
|
|
||||||
c.wbuf.Reset()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
_, err = c.Conn.Write(b)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
package util
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
defaultKeepAlivePeriod = 180 * time.Second
|
|
||||||
)
|
|
||||||
|
|
||||||
// TCPKeepAliveListener is a TCP listener with keep alive enabled.
|
|
||||||
type TCPKeepAliveListener struct {
|
|
||||||
KeepAlivePeriod time.Duration
|
|
||||||
*net.TCPListener
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *TCPKeepAliveListener) Accept() (c net.Conn, err error) {
|
|
||||||
tc, err := l.AcceptTCP()
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
tc.SetKeepAlive(true)
|
|
||||||
period := l.KeepAlivePeriod
|
|
||||||
if period <= 0 {
|
|
||||||
period = defaultKeepAlivePeriod
|
|
||||||
}
|
|
||||||
tc.SetKeepAlivePeriod(period)
|
|
||||||
|
|
||||||
return tc, nil
|
|
||||||
}
|
|
||||||
@@ -1,178 +0,0 @@
|
|||||||
package tls
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/tls"
|
|
||||||
"crypto/x509"
|
|
||||||
"errors"
|
|
||||||
"io/ioutil"
|
|
||||||
"net"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
// DefaultConfig is a default TLS config for global use.
|
|
||||||
DefaultConfig *tls.Config
|
|
||||||
)
|
|
||||||
|
|
||||||
// LoadServerConfig loads the certificate from cert & key files and optional client CA file.
|
|
||||||
func LoadServerConfig(certFile, keyFile, caFile string) (*tls.Config, error) {
|
|
||||||
if certFile == "" && keyFile == "" {
|
|
||||||
return DefaultConfig.Clone(), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
cert, err := tls.LoadX509KeyPair(certFile, keyFile)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
cfg := &tls.Config{Certificates: []tls.Certificate{cert}}
|
|
||||||
|
|
||||||
pool, err := loadCA(caFile)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if pool != nil {
|
|
||||||
cfg.ClientCAs = pool
|
|
||||||
cfg.ClientAuth = tls.RequireAndVerifyClientCert
|
|
||||||
}
|
|
||||||
|
|
||||||
return cfg, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// LoadClientConfig loads the certificate from cert & key files and optional CA file.
|
|
||||||
func LoadClientConfig(certFile, keyFile, caFile string, verify bool, serverName string) (*tls.Config, error) {
|
|
||||||
var cfg *tls.Config
|
|
||||||
|
|
||||||
if certFile == "" && keyFile == "" {
|
|
||||||
cfg = &tls.Config{}
|
|
||||||
} else {
|
|
||||||
cert, err := tls.LoadX509KeyPair(certFile, keyFile)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
cfg = &tls.Config{
|
|
||||||
Certificates: []tls.Certificate{cert},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
rootCAs, err := loadCA(caFile)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
cfg.RootCAs = rootCAs
|
|
||||||
cfg.ServerName = serverName
|
|
||||||
cfg.InsecureSkipVerify = !verify
|
|
||||||
|
|
||||||
// If the root ca is given, but skip verify, we verify the certificate manually.
|
|
||||||
if cfg.RootCAs != nil && !verify {
|
|
||||||
cfg.VerifyConnection = func(state tls.ConnectionState) error {
|
|
||||||
opts := x509.VerifyOptions{
|
|
||||||
Roots: cfg.RootCAs,
|
|
||||||
CurrentTime: time.Now(),
|
|
||||||
DNSName: "",
|
|
||||||
Intermediates: x509.NewCertPool(),
|
|
||||||
}
|
|
||||||
|
|
||||||
certs := state.PeerCertificates
|
|
||||||
for i, cert := range certs {
|
|
||||||
if i == 0 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
opts.Intermediates.AddCert(cert)
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err := certs[0].Verify(opts)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return cfg, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func loadCA(caFile string) (cp *x509.CertPool, err error) {
|
|
||||||
if caFile == "" {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
cp = x509.NewCertPool()
|
|
||||||
data, err := ioutil.ReadFile(caFile)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if !cp.AppendCertsFromPEM(data) {
|
|
||||||
return nil, errors.New("AppendCertsFromPEM failed")
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wrap a net.Conn into a client tls connection, performing any
|
|
||||||
// additional verification as needed.
|
|
||||||
//
|
|
||||||
// As of go 1.3, crypto/tls only supports either doing no certificate
|
|
||||||
// verification, or doing full verification including of the peer's
|
|
||||||
// DNS name. For consul, we want to validate that the certificate is
|
|
||||||
// signed by a known CA, but because consul doesn't use DNS names for
|
|
||||||
// node names, we don't verify the certificate DNS names. Since go 1.3
|
|
||||||
// no longer supports this mode of operation, we have to do it
|
|
||||||
// manually.
|
|
||||||
//
|
|
||||||
// This code is taken from consul:
|
|
||||||
// https://github.com/hashicorp/consul/blob/master/tlsutil/config.go
|
|
||||||
func WrapTLSClient(conn net.Conn, tlsConfig *tls.Config, timeout time.Duration) (net.Conn, error) {
|
|
||||||
var err error
|
|
||||||
var tlsConn *tls.Conn
|
|
||||||
|
|
||||||
if timeout > 0 {
|
|
||||||
conn.SetDeadline(time.Now().Add(timeout))
|
|
||||||
defer conn.SetDeadline(time.Time{})
|
|
||||||
}
|
|
||||||
|
|
||||||
tlsConn = tls.Client(conn, tlsConfig)
|
|
||||||
|
|
||||||
// Otherwise perform handshake, but don't verify the domain
|
|
||||||
//
|
|
||||||
// The following is lightly-modified from the doFullHandshake
|
|
||||||
// method in https://golang.org/src/crypto/tls/handshake_client.go
|
|
||||||
if err = tlsConn.Handshake(); err != nil {
|
|
||||||
tlsConn.Close()
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// We can do this in `tls.Config.VerifyConnection`, which effective for
|
|
||||||
// other TLS protocols such as WebSocket. See `route.go:parseChainNode`
|
|
||||||
/*
|
|
||||||
// If crypto/tls is doing verification, there's no need to do our own.
|
|
||||||
if tlsConfig.InsecureSkipVerify == false {
|
|
||||||
return tlsConn, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Similarly if we use host's CA, we can do full handshake
|
|
||||||
if tlsConfig.RootCAs == nil {
|
|
||||||
return tlsConn, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
opts := x509.VerifyOptions{
|
|
||||||
Roots: tlsConfig.RootCAs,
|
|
||||||
CurrentTime: time.Now(),
|
|
||||||
DNSName: "",
|
|
||||||
Intermediates: x509.NewCertPool(),
|
|
||||||
}
|
|
||||||
|
|
||||||
certs := tlsConn.ConnectionState().PeerCertificates
|
|
||||||
for i, cert := range certs {
|
|
||||||
if i == 0 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
opts.Intermediates.AddCert(cert)
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = certs[0].Verify(opts)
|
|
||||||
if err != nil {
|
|
||||||
tlsConn.Close()
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
return tlsConn, err
|
|
||||||
}
|
|
||||||
@@ -1,102 +0,0 @@
|
|||||||
package udp
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"net"
|
|
||||||
"sync"
|
|
||||||
"sync/atomic"
|
|
||||||
|
|
||||||
"github.com/go-gost/gost/pkg/common/bufpool"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Conn is a server side connection for UDP client peer, it implements net.Conn and net.PacketConn.
|
|
||||||
type Conn struct {
|
|
||||||
net.PacketConn
|
|
||||||
localAddr net.Addr
|
|
||||||
remoteAddr net.Addr
|
|
||||||
rc chan []byte // data receive queue
|
|
||||||
idle int32 // indicate the connection is idle
|
|
||||||
closed chan struct{}
|
|
||||||
closeMutex sync.Mutex
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewConn(c net.PacketConn, localAddr, remoteAddr net.Addr, queueSize int) *Conn {
|
|
||||||
return &Conn{
|
|
||||||
PacketConn: c,
|
|
||||||
localAddr: localAddr,
|
|
||||||
remoteAddr: remoteAddr,
|
|
||||||
rc: make(chan []byte, queueSize),
|
|
||||||
closed: make(chan struct{}),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Conn) ReadFrom(b []byte) (n int, addr net.Addr, err error) {
|
|
||||||
select {
|
|
||||||
case bb := <-c.rc:
|
|
||||||
n = copy(b, bb)
|
|
||||||
c.SetIdle(false)
|
|
||||||
bufpool.Put(&bb)
|
|
||||||
|
|
||||||
case <-c.closed:
|
|
||||||
err = net.ErrClosed
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
addr = c.remoteAddr
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Conn) Read(b []byte) (n int, err error) {
|
|
||||||
n, _, err = c.ReadFrom(b)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Conn) Write(b []byte) (n int, err error) {
|
|
||||||
return c.WriteTo(b, c.remoteAddr)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Conn) Close() error {
|
|
||||||
c.closeMutex.Lock()
|
|
||||||
defer c.closeMutex.Unlock()
|
|
||||||
|
|
||||||
select {
|
|
||||||
case <-c.closed:
|
|
||||||
default:
|
|
||||||
close(c.closed)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Conn) LocalAddr() net.Addr {
|
|
||||||
return c.localAddr
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Conn) RemoteAddr() net.Addr {
|
|
||||||
return c.remoteAddr
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Conn) IsIdle() bool {
|
|
||||||
return atomic.LoadInt32(&c.idle) > 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Conn) SetIdle(idle bool) {
|
|
||||||
v := int32(0)
|
|
||||||
if idle {
|
|
||||||
v = 1
|
|
||||||
}
|
|
||||||
atomic.StoreInt32(&c.idle, v)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Conn) WriteQueue(b []byte) error {
|
|
||||||
select {
|
|
||||||
case c.rc <- b:
|
|
||||||
return nil
|
|
||||||
|
|
||||||
case <-c.closed:
|
|
||||||
return net.ErrClosed
|
|
||||||
|
|
||||||
default:
|
|
||||||
return errors.New("recv queue is full")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,120 +0,0 @@
|
|||||||
package udp
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net"
|
|
||||||
"sync"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/go-gost/gost/pkg/common/bufpool"
|
|
||||||
"github.com/go-gost/gost/pkg/logger"
|
|
||||||
)
|
|
||||||
|
|
||||||
type listener struct {
|
|
||||||
addr net.Addr
|
|
||||||
conn net.PacketConn
|
|
||||||
cqueue chan net.Conn
|
|
||||||
readQueueSize int
|
|
||||||
readBufferSize int
|
|
||||||
connPool *ConnPool
|
|
||||||
mux sync.Mutex
|
|
||||||
closed chan struct{}
|
|
||||||
errChan chan error
|
|
||||||
logger logger.Logger
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewListener(conn net.PacketConn, addr net.Addr, backlog, dataQueueSize, dataBufferSize int, ttl time.Duration, logger logger.Logger) net.Listener {
|
|
||||||
ln := &listener{
|
|
||||||
conn: conn,
|
|
||||||
addr: addr,
|
|
||||||
cqueue: make(chan net.Conn, backlog),
|
|
||||||
connPool: NewConnPool(ttl).WithLogger(logger),
|
|
||||||
readQueueSize: dataQueueSize,
|
|
||||||
readBufferSize: dataBufferSize,
|
|
||||||
closed: make(chan struct{}),
|
|
||||||
errChan: make(chan error, 1),
|
|
||||||
logger: logger,
|
|
||||||
}
|
|
||||||
go ln.listenLoop()
|
|
||||||
|
|
||||||
return ln
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ln *listener) Accept() (conn net.Conn, err error) {
|
|
||||||
select {
|
|
||||||
case conn = <-ln.cqueue:
|
|
||||||
return
|
|
||||||
case <-ln.closed:
|
|
||||||
return nil, net.ErrClosed
|
|
||||||
case err = <-ln.errChan:
|
|
||||||
if err == nil {
|
|
||||||
err = net.ErrClosed
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ln *listener) listenLoop() {
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case <-ln.closed:
|
|
||||||
return
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
|
|
||||||
b := bufpool.Get(ln.readBufferSize)
|
|
||||||
|
|
||||||
n, raddr, err := ln.conn.ReadFrom(*b)
|
|
||||||
if err != nil {
|
|
||||||
ln.errChan <- err
|
|
||||||
close(ln.errChan)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
c := ln.getConn(raddr)
|
|
||||||
if c == nil {
|
|
||||||
bufpool.Put(b)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := c.WriteQueue((*b)[:n]); err != nil {
|
|
||||||
ln.logger.Warn("data discarded: ", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ln *listener) Addr() net.Addr {
|
|
||||||
return ln.addr
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ln *listener) Close() error {
|
|
||||||
select {
|
|
||||||
case <-ln.closed:
|
|
||||||
default:
|
|
||||||
close(ln.closed)
|
|
||||||
ln.conn.Close()
|
|
||||||
ln.connPool.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ln *listener) getConn(raddr net.Addr) *Conn {
|
|
||||||
ln.mux.Lock()
|
|
||||||
defer ln.mux.Unlock()
|
|
||||||
|
|
||||||
c, ok := ln.connPool.Get(raddr.String())
|
|
||||||
if ok {
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
|
|
||||||
c = NewConn(ln.conn, ln.addr, raddr, ln.readQueueSize)
|
|
||||||
select {
|
|
||||||
case ln.cqueue <- c:
|
|
||||||
ln.connPool.Set(raddr.String(), c)
|
|
||||||
return c
|
|
||||||
default:
|
|
||||||
c.Close()
|
|
||||||
ln.logger.Warnf("connection queue is full, client %s discarded", raddr)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,100 +0,0 @@
|
|||||||
package udp
|
|
||||||
|
|
||||||
import (
|
|
||||||
"sync"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/go-gost/gost/pkg/logger"
|
|
||||||
)
|
|
||||||
|
|
||||||
type ConnPool struct {
|
|
||||||
m sync.Map
|
|
||||||
ttl time.Duration
|
|
||||||
closed chan struct{}
|
|
||||||
logger logger.Logger
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewConnPool(ttl time.Duration) *ConnPool {
|
|
||||||
p := &ConnPool{
|
|
||||||
ttl: ttl,
|
|
||||||
closed: make(chan struct{}),
|
|
||||||
}
|
|
||||||
go p.idleCheck()
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *ConnPool) WithLogger(logger logger.Logger) *ConnPool {
|
|
||||||
p.logger = logger
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *ConnPool) Get(key any) (c *Conn, ok bool) {
|
|
||||||
v, ok := p.m.Load(key)
|
|
||||||
if ok {
|
|
||||||
c, ok = v.(*Conn)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *ConnPool) Set(key any, c *Conn) {
|
|
||||||
p.m.Store(key, c)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *ConnPool) Delete(key any) {
|
|
||||||
p.m.Delete(key)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *ConnPool) Close() {
|
|
||||||
select {
|
|
||||||
case <-p.closed:
|
|
||||||
return
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
|
|
||||||
close(p.closed)
|
|
||||||
|
|
||||||
p.m.Range(func(k, v any) bool {
|
|
||||||
if c, ok := v.(*Conn); ok && c != nil {
|
|
||||||
c.Close()
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *ConnPool) idleCheck() {
|
|
||||||
ticker := time.NewTicker(p.ttl)
|
|
||||||
defer ticker.Stop()
|
|
||||||
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case <-ticker.C:
|
|
||||||
size := 0
|
|
||||||
idles := 0
|
|
||||||
p.m.Range(func(key, value any) bool {
|
|
||||||
c, ok := value.(*Conn)
|
|
||||||
if !ok || c == nil {
|
|
||||||
p.Delete(key)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
size++
|
|
||||||
|
|
||||||
if c.IsIdle() {
|
|
||||||
idles++
|
|
||||||
p.Delete(key)
|
|
||||||
c.Close()
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
c.SetIdle(true)
|
|
||||||
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
|
|
||||||
if idles > 0 {
|
|
||||||
p.logger.Debugf("connection pool: size=%d, idle=%d", size, idles)
|
|
||||||
}
|
|
||||||
case <-p.closed:
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,274 +0,0 @@
|
|||||||
package config
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"io"
|
|
||||||
"sync"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/spf13/viper"
|
|
||||||
"gopkg.in/yaml.v2"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
v = viper.GetViper()
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
v.SetConfigName("gost")
|
|
||||||
v.AddConfigPath("/etc/gost/")
|
|
||||||
v.AddConfigPath("$HOME/.gost/")
|
|
||||||
v.AddConfigPath(".")
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
global = &Config{}
|
|
||||||
globalMux sync.RWMutex
|
|
||||||
)
|
|
||||||
|
|
||||||
func Global() *Config {
|
|
||||||
globalMux.RLock()
|
|
||||||
defer globalMux.RUnlock()
|
|
||||||
|
|
||||||
cfg := &Config{}
|
|
||||||
*cfg = *global
|
|
||||||
return cfg
|
|
||||||
}
|
|
||||||
|
|
||||||
func SetGlobal(c *Config) {
|
|
||||||
globalMux.Lock()
|
|
||||||
defer globalMux.Unlock()
|
|
||||||
|
|
||||||
global = c
|
|
||||||
}
|
|
||||||
|
|
||||||
type LogConfig struct {
|
|
||||||
Output string `yaml:",omitempty" json:"output,omitempty"`
|
|
||||||
Level string `yaml:",omitempty" json:"level,omitempty"`
|
|
||||||
Format string `yaml:",omitempty" json:"format,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type ProfilingConfig struct {
|
|
||||||
Addr string `json:"addr"`
|
|
||||||
Enable bool `json:"enable"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type APIConfig struct {
|
|
||||||
Addr string `json:"addr"`
|
|
||||||
PathPrefix string `yaml:"pathPrefix,omitempty" json:"pathPrefix,omitempty"`
|
|
||||||
AccessLog bool `yaml:"accesslog,omitempty" json:"accesslog,omitempty"`
|
|
||||||
Auth *AuthConfig `yaml:",omitempty" json:"auth,omitempty"`
|
|
||||||
Auther string `yaml:",omitempty" json:"auther,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type MetricsConfig struct {
|
|
||||||
Addr string `json:"addr"`
|
|
||||||
Path string `json:"path"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type TLSConfig struct {
|
|
||||||
CertFile string `yaml:"certFile,omitempty" json:"certFile,omitempty"`
|
|
||||||
KeyFile string `yaml:"keyFile,omitempty" json:"keyFile,omitempty"`
|
|
||||||
CAFile string `yaml:"caFile,omitempty" json:"caFile,omitempty"`
|
|
||||||
Secure bool `yaml:",omitempty" json:"secure,omitempty"`
|
|
||||||
ServerName string `yaml:"serverName,omitempty" json:"serverName,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type AutherConfig struct {
|
|
||||||
Name string `json:"name"`
|
|
||||||
// inline, file, redis, etc.
|
|
||||||
Type string `yaml:",omitempty" json:"type,omitempty"`
|
|
||||||
Auths []*AuthConfig `yaml:",omitempty" json:"auths"`
|
|
||||||
// File string `yaml:",omitempty" json:"file"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type AuthConfig struct {
|
|
||||||
Username string `json:"username"`
|
|
||||||
Password string `yaml:",omitempty" json:"password,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type SelectorConfig struct {
|
|
||||||
Strategy string `json:"strategy"`
|
|
||||||
MaxFails int `yaml:"maxFails" json:"maxFails"`
|
|
||||||
FailTimeout time.Duration `yaml:"failTimeout" json:"failTimeout"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type AdmissionConfig struct {
|
|
||||||
Name string `json:"name"`
|
|
||||||
// inline, file, etc.
|
|
||||||
Type string `yaml:",omitempty" json:"type,omitempty"`
|
|
||||||
Reverse bool `yaml:",omitempty" json:"reverse,omitempty"`
|
|
||||||
Matchers []string `json:"matchers"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type BypassConfig struct {
|
|
||||||
Name string `json:"name"`
|
|
||||||
// inline, file, etc.
|
|
||||||
Type string `yaml:",omitempty" json:"type,omitempty"`
|
|
||||||
Reverse bool `yaml:",omitempty" json:"reverse,omitempty"`
|
|
||||||
Matchers []string `json:"matchers"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type NameserverConfig struct {
|
|
||||||
Addr string `json:"addr"`
|
|
||||||
Chain string `yaml:",omitempty" json:"chain,omitempty"`
|
|
||||||
Prefer string `yaml:",omitempty" json:"prefer,omitempty"`
|
|
||||||
ClientIP string `yaml:"clientIP,omitempty" json:"clientIP,omitempty"`
|
|
||||||
Hostname string `yaml:",omitempty" json:"hostname,omitempty"`
|
|
||||||
TTL time.Duration `yaml:",omitempty" json:"ttl,omitempty"`
|
|
||||||
Timeout time.Duration `yaml:",omitempty" json:"timeout,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type ResolverConfig struct {
|
|
||||||
Name string `json:"name"`
|
|
||||||
// inline, file, etc.
|
|
||||||
Type string `yaml:",omitempty" json:"type,omitempty"`
|
|
||||||
Nameservers []*NameserverConfig `json:"nameservers"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type HostMappingConfig struct {
|
|
||||||
IP string `json:"ip"`
|
|
||||||
Hostname string `json:"hostname"`
|
|
||||||
Aliases []string `yaml:",omitempty" json:"aliases,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type HostsConfig struct {
|
|
||||||
Name string `json:"name"`
|
|
||||||
// inline, file, etc.
|
|
||||||
Type string `yaml:",omitempty" json:"type,omitempty"`
|
|
||||||
Mappings []*HostMappingConfig `json:"mappings"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type ListenerConfig struct {
|
|
||||||
Type string `json:"type"`
|
|
||||||
Chain string `yaml:",omitempty" json:"chain,omitempty"`
|
|
||||||
Auther string `yaml:",omitempty" json:"auther,omitempty"`
|
|
||||||
Auth *AuthConfig `yaml:",omitempty" json:"auth,omitempty"`
|
|
||||||
TLS *TLSConfig `yaml:",omitempty" json:"tls,omitempty"`
|
|
||||||
Metadata map[string]any `yaml:",omitempty" json:"metadata,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type HandlerConfig struct {
|
|
||||||
Type string `json:"type"`
|
|
||||||
Retries int `yaml:",omitempty" json:"retries,omitempty"`
|
|
||||||
Chain string `yaml:",omitempty" json:"chain,omitempty"`
|
|
||||||
Auther string `yaml:",omitempty" json:"auther,omitempty"`
|
|
||||||
Auth *AuthConfig `yaml:",omitempty" json:"auth,omitempty"`
|
|
||||||
TLS *TLSConfig `yaml:",omitempty" json:"tls,omitempty"`
|
|
||||||
Metadata map[string]any `yaml:",omitempty" json:"metadata,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type ForwarderConfig struct {
|
|
||||||
Targets []string `json:"targets"`
|
|
||||||
Selector *SelectorConfig `yaml:",omitempty" json:"selector,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type DialerConfig struct {
|
|
||||||
Type string `json:"type"`
|
|
||||||
Auth *AuthConfig `yaml:",omitempty" json:"auth,omitempty"`
|
|
||||||
TLS *TLSConfig `yaml:",omitempty" json:"tls,omitempty"`
|
|
||||||
Metadata map[string]any `yaml:",omitempty" json:"metadata,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type ConnectorConfig struct {
|
|
||||||
Type string `json:"type"`
|
|
||||||
Auth *AuthConfig `yaml:",omitempty" json:"auth,omitempty"`
|
|
||||||
TLS *TLSConfig `yaml:",omitempty" json:"tls,omitempty"`
|
|
||||||
Metadata map[string]any `yaml:",omitempty" json:"metadata,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type ServiceConfig struct {
|
|
||||||
Name string `json:"name"`
|
|
||||||
Addr string `yaml:",omitempty" json:"addr,omitempty"`
|
|
||||||
Interface string `yaml:",omitempty" json:"interface,omitempty"`
|
|
||||||
Admission string `yaml:",omitempty" json:"admission,omitempty"`
|
|
||||||
Bypass string `yaml:",omitempty" json:"bypass,omitempty"`
|
|
||||||
Resolver string `yaml:",omitempty" json:"resolver,omitempty"`
|
|
||||||
Hosts string `yaml:",omitempty" json:"hosts,omitempty"`
|
|
||||||
Handler *HandlerConfig `yaml:",omitempty" json:"handler,omitempty"`
|
|
||||||
Listener *ListenerConfig `yaml:",omitempty" json:"listener,omitempty"`
|
|
||||||
Forwarder *ForwarderConfig `yaml:",omitempty" json:"forwarder,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type ChainConfig struct {
|
|
||||||
Name string `json:"name"`
|
|
||||||
Selector *SelectorConfig `yaml:",omitempty" json:"selector,omitempty"`
|
|
||||||
Hops []*HopConfig `json:"hops"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type HopConfig struct {
|
|
||||||
Name string `json:"name"`
|
|
||||||
Interface string `yaml:",omitempty" json:"interface,omitempty"`
|
|
||||||
Selector *SelectorConfig `yaml:",omitempty" json:"selector,omitempty"`
|
|
||||||
Bypass string `yaml:",omitempty" json:"bypass,omitempty"`
|
|
||||||
Resolver string `yaml:",omitempty" json:"resolver,omitempty"`
|
|
||||||
Hosts string `yaml:",omitempty" json:"hosts,omitempty"`
|
|
||||||
Nodes []*NodeConfig `json:"nodes"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type NodeConfig struct {
|
|
||||||
Name string `json:"name"`
|
|
||||||
Addr string `yaml:",omitempty" json:"addr,omitempty"`
|
|
||||||
Interface string `yaml:",omitempty" json:"interface,omitempty"`
|
|
||||||
Bypass string `yaml:",omitempty" json:"bypass,omitempty"`
|
|
||||||
Resolver string `yaml:",omitempty" json:"resolver,omitempty"`
|
|
||||||
Hosts string `yaml:",omitempty" json:"hosts,omitempty"`
|
|
||||||
Connector *ConnectorConfig `yaml:",omitempty" json:"connector,omitempty"`
|
|
||||||
Dialer *DialerConfig `yaml:",omitempty" json:"dialer,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type Config struct {
|
|
||||||
Services []*ServiceConfig `json:"services"`
|
|
||||||
Chains []*ChainConfig `yaml:",omitempty" json:"chains,omitempty"`
|
|
||||||
Authers []*AutherConfig `yaml:",omitempty" json:"authers,omitempty"`
|
|
||||||
Admissions []*AdmissionConfig `yaml:",omitempty" json:"admissions,omitempty"`
|
|
||||||
Bypasses []*BypassConfig `yaml:",omitempty" json:"bypasses,omitempty"`
|
|
||||||
Resolvers []*ResolverConfig `yaml:",omitempty" json:"resolvers,omitempty"`
|
|
||||||
Hosts []*HostsConfig `yaml:",omitempty" json:"hosts,omitempty"`
|
|
||||||
TLS *TLSConfig `yaml:",omitempty" json:"tls,omitempty"`
|
|
||||||
Log *LogConfig `yaml:",omitempty" json:"log,omitempty"`
|
|
||||||
Profiling *ProfilingConfig `yaml:",omitempty" json:"profiling,omitempty"`
|
|
||||||
API *APIConfig `yaml:",omitempty" json:"api,omitempty"`
|
|
||||||
Metrics *MetricsConfig `yaml:",omitempty" json:"metrics,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Config) Load() error {
|
|
||||||
if err := v.ReadInConfig(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return v.Unmarshal(c)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Config) Read(r io.Reader) error {
|
|
||||||
if err := v.ReadConfig(r); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return v.Unmarshal(c)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Config) ReadFile(file string) error {
|
|
||||||
v.SetConfigFile(file)
|
|
||||||
if err := v.ReadInConfig(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return v.Unmarshal(c)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Config) Write(w io.Writer, format string) error {
|
|
||||||
switch format {
|
|
||||||
case "json":
|
|
||||||
enc := json.NewEncoder(w)
|
|
||||||
enc.SetIndent("", " ")
|
|
||||||
enc.Encode(c)
|
|
||||||
return nil
|
|
||||||
case "yaml":
|
|
||||||
fallthrough
|
|
||||||
default:
|
|
||||||
enc := yaml.NewEncoder(w)
|
|
||||||
defer enc.Close()
|
|
||||||
|
|
||||||
return enc.Encode(c)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,136 +0,0 @@
|
|||||||
package parsing
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/go-gost/gost/pkg/chain"
|
|
||||||
tls_util "github.com/go-gost/gost/pkg/common/util/tls"
|
|
||||||
"github.com/go-gost/gost/pkg/config"
|
|
||||||
"github.com/go-gost/gost/pkg/connector"
|
|
||||||
"github.com/go-gost/gost/pkg/dialer"
|
|
||||||
"github.com/go-gost/gost/pkg/logger"
|
|
||||||
"github.com/go-gost/gost/pkg/metadata"
|
|
||||||
"github.com/go-gost/gost/pkg/registry"
|
|
||||||
)
|
|
||||||
|
|
||||||
func ParseChain(cfg *config.ChainConfig) (chain.Chainer, error) {
|
|
||||||
if cfg == nil {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
chainLogger := logger.Default().WithFields(map[string]any{
|
|
||||||
"kind": "chain",
|
|
||||||
"chain": cfg.Name,
|
|
||||||
})
|
|
||||||
|
|
||||||
c := &chain.Chain{}
|
|
||||||
selector := parseSelector(cfg.Selector)
|
|
||||||
for _, hop := range cfg.Hops {
|
|
||||||
group := &chain.NodeGroup{}
|
|
||||||
for _, v := range hop.Nodes {
|
|
||||||
nodeLogger := chainLogger.WithFields(map[string]any{
|
|
||||||
"kind": "node",
|
|
||||||
"connector": v.Connector.Type,
|
|
||||||
"dialer": v.Dialer.Type,
|
|
||||||
"hop": hop.Name,
|
|
||||||
"node": v.Name,
|
|
||||||
})
|
|
||||||
connectorLogger := nodeLogger.WithFields(map[string]any{
|
|
||||||
"kind": "connector",
|
|
||||||
})
|
|
||||||
|
|
||||||
tlsCfg := v.Connector.TLS
|
|
||||||
if tlsCfg == nil {
|
|
||||||
tlsCfg = &config.TLSConfig{}
|
|
||||||
}
|
|
||||||
tlsConfig, err := tls_util.LoadClientConfig(
|
|
||||||
tlsCfg.CertFile, tlsCfg.KeyFile, tlsCfg.CAFile,
|
|
||||||
tlsCfg.Secure, tlsCfg.ServerName)
|
|
||||||
if err != nil {
|
|
||||||
chainLogger.Error(err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
cr := registry.ConnectorRegistry().Get(v.Connector.Type)(
|
|
||||||
connector.AuthOption(parseAuth(v.Connector.Auth)),
|
|
||||||
connector.TLSConfigOption(tlsConfig),
|
|
||||||
connector.LoggerOption(connectorLogger),
|
|
||||||
)
|
|
||||||
|
|
||||||
if v.Connector.Metadata == nil {
|
|
||||||
v.Connector.Metadata = make(map[string]any)
|
|
||||||
}
|
|
||||||
if err := cr.Init(metadata.MapMetadata(v.Connector.Metadata)); err != nil {
|
|
||||||
connectorLogger.Error("init: ", err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
dialerLogger := nodeLogger.WithFields(map[string]any{
|
|
||||||
"kind": "dialer",
|
|
||||||
})
|
|
||||||
|
|
||||||
tlsCfg = v.Dialer.TLS
|
|
||||||
if tlsCfg == nil {
|
|
||||||
tlsCfg = &config.TLSConfig{}
|
|
||||||
}
|
|
||||||
tlsConfig, err = tls_util.LoadClientConfig(
|
|
||||||
tlsCfg.CertFile, tlsCfg.KeyFile, tlsCfg.CAFile,
|
|
||||||
tlsCfg.Secure, tlsCfg.ServerName)
|
|
||||||
if err != nil {
|
|
||||||
chainLogger.Error(err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
d := registry.DialerRegistry().Get(v.Dialer.Type)(
|
|
||||||
dialer.AuthOption(parseAuth(v.Dialer.Auth)),
|
|
||||||
dialer.TLSConfigOption(tlsConfig),
|
|
||||||
dialer.LoggerOption(dialerLogger),
|
|
||||||
)
|
|
||||||
|
|
||||||
if v.Dialer.Metadata == nil {
|
|
||||||
v.Dialer.Metadata = make(map[string]any)
|
|
||||||
}
|
|
||||||
if err := d.Init(metadata.MapMetadata(v.Dialer.Metadata)); err != nil {
|
|
||||||
dialerLogger.Error("init: ", err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if v.Bypass == "" {
|
|
||||||
v.Bypass = hop.Bypass
|
|
||||||
}
|
|
||||||
if v.Resolver == "" {
|
|
||||||
v.Resolver = hop.Resolver
|
|
||||||
}
|
|
||||||
if v.Hosts == "" {
|
|
||||||
v.Hosts = hop.Hosts
|
|
||||||
}
|
|
||||||
if v.Interface == "" {
|
|
||||||
v.Interface = hop.Interface
|
|
||||||
}
|
|
||||||
|
|
||||||
tr := (&chain.Transport{}).
|
|
||||||
WithConnector(cr).
|
|
||||||
WithDialer(d).
|
|
||||||
WithAddr(v.Addr).
|
|
||||||
WithInterface(v.Interface)
|
|
||||||
|
|
||||||
node := &chain.Node{
|
|
||||||
Name: v.Name,
|
|
||||||
Addr: v.Addr,
|
|
||||||
Bypass: registry.BypassRegistry().Get(v.Bypass),
|
|
||||||
Resolver: registry.ResolverRegistry().Get(v.Resolver),
|
|
||||||
Hosts: registry.HostsRegistry().Get(v.Hosts),
|
|
||||||
Marker: &chain.FailMarker{},
|
|
||||||
Transport: tr,
|
|
||||||
}
|
|
||||||
group.AddNode(node)
|
|
||||||
}
|
|
||||||
|
|
||||||
sel := selector
|
|
||||||
if s := parseSelector(hop.Selector); s != nil {
|
|
||||||
sel = s
|
|
||||||
}
|
|
||||||
group.WithSelector(sel)
|
|
||||||
c.AddNodeGroup(group)
|
|
||||||
}
|
|
||||||
|
|
||||||
return c, nil
|
|
||||||
}
|
|
||||||
@@ -1,161 +0,0 @@
|
|||||||
package parsing
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net"
|
|
||||||
"net/url"
|
|
||||||
|
|
||||||
"github.com/go-gost/gost/pkg/admission"
|
|
||||||
"github.com/go-gost/gost/pkg/auth"
|
|
||||||
"github.com/go-gost/gost/pkg/bypass"
|
|
||||||
"github.com/go-gost/gost/pkg/chain"
|
|
||||||
"github.com/go-gost/gost/pkg/config"
|
|
||||||
hostspkg "github.com/go-gost/gost/pkg/hosts"
|
|
||||||
"github.com/go-gost/gost/pkg/logger"
|
|
||||||
"github.com/go-gost/gost/pkg/registry"
|
|
||||||
"github.com/go-gost/gost/pkg/resolver"
|
|
||||||
resolver_impl "github.com/go-gost/gost/pkg/resolver/impl"
|
|
||||||
)
|
|
||||||
|
|
||||||
func ParseAuther(cfg *config.AutherConfig) auth.Authenticator {
|
|
||||||
if cfg == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
m := make(map[string]string)
|
|
||||||
|
|
||||||
for _, user := range cfg.Auths {
|
|
||||||
if user.Username == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
m[user.Username] = user.Password
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(m) == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return auth.NewMapAuthenticator(m)
|
|
||||||
}
|
|
||||||
|
|
||||||
func ParseAutherFromAuth(au *config.AuthConfig) auth.Authenticator {
|
|
||||||
if au == nil || au.Username == "" {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return auth.NewMapAuthenticator(map[string]string{
|
|
||||||
au.Username: au.Password,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseAuth(cfg *config.AuthConfig) *url.Userinfo {
|
|
||||||
if cfg == nil || cfg.Username == "" {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if cfg.Password == "" {
|
|
||||||
return url.User(cfg.Username)
|
|
||||||
}
|
|
||||||
return url.UserPassword(cfg.Username, cfg.Password)
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseSelector(cfg *config.SelectorConfig) chain.Selector {
|
|
||||||
if cfg == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var strategy chain.Strategy
|
|
||||||
switch cfg.Strategy {
|
|
||||||
case "round", "rr":
|
|
||||||
strategy = chain.RoundRobinStrategy()
|
|
||||||
case "random", "rand":
|
|
||||||
strategy = chain.RandomStrategy()
|
|
||||||
case "fifo", "ha":
|
|
||||||
strategy = chain.FIFOStrategy()
|
|
||||||
default:
|
|
||||||
strategy = chain.RoundRobinStrategy()
|
|
||||||
}
|
|
||||||
|
|
||||||
return chain.NewSelector(
|
|
||||||
strategy,
|
|
||||||
chain.InvalidFilter(),
|
|
||||||
chain.FailFilter(cfg.MaxFails, cfg.FailTimeout),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
func ParseAdmission(cfg *config.AdmissionConfig) admission.Admission {
|
|
||||||
if cfg == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return admission.NewAdmissionPatterns(
|
|
||||||
cfg.Reverse,
|
|
||||||
cfg.Matchers,
|
|
||||||
admission.LoggerOption(logger.Default().WithFields(map[string]any{
|
|
||||||
"kind": "admission",
|
|
||||||
"admission": cfg.Name,
|
|
||||||
})),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
func ParseBypass(cfg *config.BypassConfig) bypass.Bypass {
|
|
||||||
if cfg == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return bypass.NewBypassPatterns(
|
|
||||||
cfg.Reverse,
|
|
||||||
cfg.Matchers,
|
|
||||||
bypass.LoggerOption(logger.Default().WithFields(map[string]any{
|
|
||||||
"kind": "bypass",
|
|
||||||
"bypass": cfg.Name,
|
|
||||||
})),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
func ParseResolver(cfg *config.ResolverConfig) (resolver.Resolver, error) {
|
|
||||||
if cfg == nil {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
var nameservers []resolver_impl.NameServer
|
|
||||||
for _, server := range cfg.Nameservers {
|
|
||||||
nameservers = append(nameservers, resolver_impl.NameServer{
|
|
||||||
Addr: server.Addr,
|
|
||||||
Chain: registry.ChainRegistry().Get(server.Chain),
|
|
||||||
TTL: server.TTL,
|
|
||||||
Timeout: server.Timeout,
|
|
||||||
ClientIP: net.ParseIP(server.ClientIP),
|
|
||||||
Prefer: server.Prefer,
|
|
||||||
Hostname: server.Hostname,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return resolver_impl.NewResolver(
|
|
||||||
nameservers,
|
|
||||||
resolver_impl.LoggerResolverOption(
|
|
||||||
logger.Default().WithFields(map[string]any{
|
|
||||||
"kind": "resolver",
|
|
||||||
"resolver": cfg.Name,
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
func ParseHosts(cfg *config.HostsConfig) hostspkg.HostMapper {
|
|
||||||
if cfg == nil || len(cfg.Mappings) == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
hosts := hostspkg.NewHosts()
|
|
||||||
hosts.Logger = logger.Default().WithFields(map[string]any{
|
|
||||||
"kind": "hosts",
|
|
||||||
"hosts": cfg.Name,
|
|
||||||
})
|
|
||||||
|
|
||||||
for _, host := range cfg.Mappings {
|
|
||||||
if host.IP == "" || host.Hostname == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
ip := net.ParseIP(host.IP)
|
|
||||||
if ip == nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
hosts.Map(ip, host.Hostname, host.Aliases...)
|
|
||||||
}
|
|
||||||
return hosts
|
|
||||||
}
|
|
||||||
@@ -1,148 +0,0 @@
|
|||||||
package parsing
|
|
||||||
|
|
||||||
import (
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/go-gost/gost/pkg/chain"
|
|
||||||
tls_util "github.com/go-gost/gost/pkg/common/util/tls"
|
|
||||||
"github.com/go-gost/gost/pkg/config"
|
|
||||||
"github.com/go-gost/gost/pkg/handler"
|
|
||||||
"github.com/go-gost/gost/pkg/listener"
|
|
||||||
"github.com/go-gost/gost/pkg/logger"
|
|
||||||
"github.com/go-gost/gost/pkg/metadata"
|
|
||||||
"github.com/go-gost/gost/pkg/registry"
|
|
||||||
"github.com/go-gost/gost/pkg/service"
|
|
||||||
)
|
|
||||||
|
|
||||||
func ParseService(cfg *config.ServiceConfig) (service.Service, error) {
|
|
||||||
if cfg.Listener == nil {
|
|
||||||
cfg.Listener = &config.ListenerConfig{
|
|
||||||
Type: "tcp",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if cfg.Handler == nil {
|
|
||||||
cfg.Handler = &config.HandlerConfig{
|
|
||||||
Type: "auto",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
serviceLogger := logger.Default().WithFields(map[string]any{
|
|
||||||
"kind": "service",
|
|
||||||
"service": cfg.Name,
|
|
||||||
"listener": cfg.Listener.Type,
|
|
||||||
"handler": cfg.Handler.Type,
|
|
||||||
})
|
|
||||||
|
|
||||||
listenerLogger := serviceLogger.WithFields(map[string]any{
|
|
||||||
"kind": "listener",
|
|
||||||
})
|
|
||||||
|
|
||||||
tlsCfg := cfg.Listener.TLS
|
|
||||||
if tlsCfg == nil {
|
|
||||||
tlsCfg = &config.TLSConfig{}
|
|
||||||
}
|
|
||||||
tlsConfig, err := tls_util.LoadServerConfig(
|
|
||||||
tlsCfg.CertFile, tlsCfg.KeyFile, tlsCfg.CAFile)
|
|
||||||
if err != nil {
|
|
||||||
listenerLogger.Error(err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
auther := ParseAutherFromAuth(cfg.Listener.Auth)
|
|
||||||
if cfg.Listener.Auther != "" {
|
|
||||||
auther = registry.AutherRegistry().Get(cfg.Listener.Auther)
|
|
||||||
}
|
|
||||||
|
|
||||||
ln := registry.ListenerRegistry().Get(cfg.Listener.Type)(
|
|
||||||
listener.AddrOption(cfg.Addr),
|
|
||||||
listener.ChainOption(registry.ChainRegistry().Get(cfg.Listener.Chain)),
|
|
||||||
listener.AutherOption(auther),
|
|
||||||
listener.AuthOption(parseAuth(cfg.Listener.Auth)),
|
|
||||||
listener.TLSConfigOption(tlsConfig),
|
|
||||||
listener.LoggerOption(listenerLogger),
|
|
||||||
listener.ServiceOption(cfg.Name),
|
|
||||||
)
|
|
||||||
|
|
||||||
if cfg.Listener.Metadata == nil {
|
|
||||||
cfg.Listener.Metadata = make(map[string]any)
|
|
||||||
}
|
|
||||||
if err := ln.Init(metadata.MapMetadata(cfg.Listener.Metadata)); err != nil {
|
|
||||||
listenerLogger.Error("init: ", err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
handlerLogger := serviceLogger.WithFields(map[string]any{
|
|
||||||
"kind": "handler",
|
|
||||||
})
|
|
||||||
|
|
||||||
tlsCfg = cfg.Handler.TLS
|
|
||||||
if tlsCfg == nil {
|
|
||||||
tlsCfg = &config.TLSConfig{}
|
|
||||||
}
|
|
||||||
tlsConfig, err = tls_util.LoadServerConfig(
|
|
||||||
tlsCfg.CertFile, tlsCfg.KeyFile, tlsCfg.CAFile)
|
|
||||||
if err != nil {
|
|
||||||
handlerLogger.Error(err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
auther = ParseAutherFromAuth(cfg.Handler.Auth)
|
|
||||||
if cfg.Handler.Auther != "" {
|
|
||||||
auther = registry.AutherRegistry().Get(cfg.Handler.Auther)
|
|
||||||
}
|
|
||||||
|
|
||||||
router := (&chain.Router{}).
|
|
||||||
WithRetries(cfg.Handler.Retries).
|
|
||||||
// WithTimeout(timeout time.Duration).
|
|
||||||
WithInterface(cfg.Interface).
|
|
||||||
WithChain(registry.ChainRegistry().Get(cfg.Handler.Chain)).
|
|
||||||
WithResolver(registry.ResolverRegistry().Get(cfg.Resolver)).
|
|
||||||
WithHosts(registry.HostsRegistry().Get(cfg.Hosts)).
|
|
||||||
WithLogger(handlerLogger)
|
|
||||||
|
|
||||||
h := registry.HandlerRegistry().Get(cfg.Handler.Type)(
|
|
||||||
handler.RouterOption(router),
|
|
||||||
handler.AutherOption(auther),
|
|
||||||
handler.AuthOption(parseAuth(cfg.Handler.Auth)),
|
|
||||||
handler.BypassOption(registry.BypassRegistry().Get(cfg.Bypass)),
|
|
||||||
handler.TLSConfigOption(tlsConfig),
|
|
||||||
handler.LoggerOption(handlerLogger),
|
|
||||||
)
|
|
||||||
|
|
||||||
if forwarder, ok := h.(handler.Forwarder); ok {
|
|
||||||
forwarder.Forward(parseForwarder(cfg.Forwarder))
|
|
||||||
}
|
|
||||||
|
|
||||||
if cfg.Handler.Metadata == nil {
|
|
||||||
cfg.Handler.Metadata = make(map[string]any)
|
|
||||||
}
|
|
||||||
if err := h.Init(metadata.MapMetadata(cfg.Handler.Metadata)); err != nil {
|
|
||||||
handlerLogger.Error("init: ", err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
s := service.NewService(cfg.Name, ln, h,
|
|
||||||
service.AdmissionOption(registry.AdmissionRegistry().Get(cfg.Admission)),
|
|
||||||
service.LoggerOption(serviceLogger),
|
|
||||||
)
|
|
||||||
|
|
||||||
serviceLogger.Infof("listening on %s/%s", s.Addr().String(), s.Addr().Network())
|
|
||||||
return s, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseForwarder(cfg *config.ForwarderConfig) *chain.NodeGroup {
|
|
||||||
if cfg == nil || len(cfg.Targets) == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
group := &chain.NodeGroup{}
|
|
||||||
for _, target := range cfg.Targets {
|
|
||||||
if v := strings.TrimSpace(target); v != "" {
|
|
||||||
group.AddNode(&chain.Node{
|
|
||||||
Name: target,
|
|
||||||
Addr: target,
|
|
||||||
Marker: &chain.FailMarker{},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return group.WithSelector(parseSelector(cfg.Selector))
|
|
||||||
}
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
package connector
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"errors"
|
|
||||||
"net"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
ErrBindUnsupported = errors.New("bind unsupported")
|
|
||||||
)
|
|
||||||
|
|
||||||
type Accepter interface {
|
|
||||||
Accept() (net.Conn, error)
|
|
||||||
Addr() net.Addr
|
|
||||||
Close() error
|
|
||||||
}
|
|
||||||
|
|
||||||
type Binder interface {
|
|
||||||
Bind(ctx context.Context, conn net.Conn, network, address string, opts ...BindOption) (net.Listener, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
type AcceptError struct {
|
|
||||||
err error
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewAcceptError(err error) error {
|
|
||||||
return &AcceptError{err: err}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *AcceptError) Error() string {
|
|
||||||
return e.err.Error()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *AcceptError) Timeout() bool {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *AcceptError) Temporary() bool {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *AcceptError) Unwrap() error {
|
|
||||||
return e.err
|
|
||||||
}
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
package connector
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"net"
|
|
||||||
|
|
||||||
"github.com/go-gost/gost/pkg/metadata"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Connector is responsible for connecting to the destination address.
|
|
||||||
type Connector interface {
|
|
||||||
Init(metadata.Metadata) error
|
|
||||||
Connect(ctx context.Context, conn net.Conn, network, address string, opts ...ConnectOption) (net.Conn, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
type Handshaker interface {
|
|
||||||
Handshake(ctx context.Context, conn net.Conn) (net.Conn, error)
|
|
||||||
}
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
package forward
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"net"
|
|
||||||
|
|
||||||
"github.com/go-gost/gost/pkg/connector"
|
|
||||||
md "github.com/go-gost/gost/pkg/metadata"
|
|
||||||
"github.com/go-gost/gost/pkg/registry"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
registry.ConnectorRegistry().Register("forward", NewConnector)
|
|
||||||
}
|
|
||||||
|
|
||||||
type forwardConnector struct {
|
|
||||||
options connector.Options
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewConnector(opts ...connector.Option) connector.Connector {
|
|
||||||
options := connector.Options{}
|
|
||||||
for _, opt := range opts {
|
|
||||||
opt(&options)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &forwardConnector{
|
|
||||||
options: options,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *forwardConnector) Init(md md.Metadata) (err error) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *forwardConnector) Connect(ctx context.Context, conn net.Conn, network, address string, opts ...connector.ConnectOption) (net.Conn, error) {
|
|
||||||
log := c.options.Logger.WithFields(map[string]any{
|
|
||||||
"remote": conn.RemoteAddr().String(),
|
|
||||||
"local": conn.LocalAddr().String(),
|
|
||||||
"network": network,
|
|
||||||
"address": address,
|
|
||||||
})
|
|
||||||
log.Infof("connect %s/%s", address, network)
|
|
||||||
|
|
||||||
return conn, nil
|
|
||||||
}
|
|
||||||
@@ -1,129 +0,0 @@
|
|||||||
package http
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bufio"
|
|
||||||
"context"
|
|
||||||
"encoding/base64"
|
|
||||||
"fmt"
|
|
||||||
"net"
|
|
||||||
"net/http"
|
|
||||||
"net/http/httputil"
|
|
||||||
"net/url"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/go-gost/gost/pkg/common/util/socks"
|
|
||||||
"github.com/go-gost/gost/pkg/connector"
|
|
||||||
"github.com/go-gost/gost/pkg/logger"
|
|
||||||
md "github.com/go-gost/gost/pkg/metadata"
|
|
||||||
"github.com/go-gost/gost/pkg/registry"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
registry.ConnectorRegistry().Register("http", NewConnector)
|
|
||||||
}
|
|
||||||
|
|
||||||
type httpConnector struct {
|
|
||||||
md metadata
|
|
||||||
options connector.Options
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewConnector(opts ...connector.Option) connector.Connector {
|
|
||||||
options := connector.Options{}
|
|
||||||
for _, opt := range opts {
|
|
||||||
opt(&options)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &httpConnector{
|
|
||||||
options: options,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *httpConnector) Init(md md.Metadata) (err error) {
|
|
||||||
return c.parseMetadata(md)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *httpConnector) Connect(ctx context.Context, conn net.Conn, network, address string, opts ...connector.ConnectOption) (net.Conn, error) {
|
|
||||||
log := c.options.Logger.WithFields(map[string]any{
|
|
||||||
"local": conn.LocalAddr().String(),
|
|
||||||
"remote": conn.RemoteAddr().String(),
|
|
||||||
"network": network,
|
|
||||||
"address": address,
|
|
||||||
})
|
|
||||||
log.Infof("connect %s/%s", address, network)
|
|
||||||
|
|
||||||
req := &http.Request{
|
|
||||||
Method: http.MethodConnect,
|
|
||||||
URL: &url.URL{Host: address},
|
|
||||||
Host: address,
|
|
||||||
ProtoMajor: 1,
|
|
||||||
ProtoMinor: 1,
|
|
||||||
Header: c.md.header,
|
|
||||||
}
|
|
||||||
|
|
||||||
if req.Header == nil {
|
|
||||||
req.Header = http.Header{}
|
|
||||||
}
|
|
||||||
req.Header.Set("Proxy-Connection", "keep-alive")
|
|
||||||
|
|
||||||
if user := c.options.Auth; user != nil {
|
|
||||||
u := user.Username()
|
|
||||||
p, _ := user.Password()
|
|
||||||
req.Header.Set("Proxy-Authorization",
|
|
||||||
"Basic "+base64.StdEncoding.EncodeToString([]byte(u+":"+p)))
|
|
||||||
}
|
|
||||||
|
|
||||||
switch network {
|
|
||||||
case "tcp", "tcp4", "tcp6":
|
|
||||||
if _, ok := conn.(net.PacketConn); ok {
|
|
||||||
err := fmt.Errorf("tcp over udp is unsupported")
|
|
||||||
log.Error(err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
case "udp", "udp4", "udp6":
|
|
||||||
req.Header.Set("X-Gost-Protocol", "udp")
|
|
||||||
default:
|
|
||||||
err := fmt.Errorf("network %s is unsupported", network)
|
|
||||||
log.Error(err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if log.IsLevelEnabled(logger.DebugLevel) {
|
|
||||||
dump, _ := httputil.DumpRequest(req, false)
|
|
||||||
log.Debug(string(dump))
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.md.connectTimeout > 0 {
|
|
||||||
conn.SetDeadline(time.Now().Add(c.md.connectTimeout))
|
|
||||||
defer conn.SetDeadline(time.Time{})
|
|
||||||
}
|
|
||||||
|
|
||||||
req = req.WithContext(ctx)
|
|
||||||
if err := req.Write(conn); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := http.ReadResponse(bufio.NewReader(conn), req)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
// NOTE: the server may return `Transfer-Encoding: chunked` header,
|
|
||||||
// then the Content-Length of response will be unknown (-1),
|
|
||||||
// in this case, close body will be blocked, so we leave it untouched.
|
|
||||||
// defer resp.Body.Close()
|
|
||||||
|
|
||||||
if log.IsLevelEnabled(logger.DebugLevel) {
|
|
||||||
dump, _ := httputil.DumpResponse(resp, false)
|
|
||||||
log.Debug(string(dump))
|
|
||||||
}
|
|
||||||
|
|
||||||
if resp.StatusCode != http.StatusOK {
|
|
||||||
return nil, fmt.Errorf("%s", resp.Status)
|
|
||||||
}
|
|
||||||
|
|
||||||
if network == "udp" {
|
|
||||||
addr, _ := net.ResolveUDPAddr(network, address)
|
|
||||||
return socks.UDPTunClientConn(conn, addr), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return conn, nil
|
|
||||||
}
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
package http
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/http"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
mdata "github.com/go-gost/gost/pkg/metadata"
|
|
||||||
)
|
|
||||||
|
|
||||||
type metadata struct {
|
|
||||||
connectTimeout time.Duration
|
|
||||||
header http.Header
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *httpConnector) parseMetadata(md mdata.Metadata) (err error) {
|
|
||||||
const (
|
|
||||||
connectTimeout = "timeout"
|
|
||||||
header = "header"
|
|
||||||
)
|
|
||||||
|
|
||||||
c.md.connectTimeout = mdata.GetDuration(md, connectTimeout)
|
|
||||||
|
|
||||||
if mm := mdata.GetStringMapString(md, header); len(mm) > 0 {
|
|
||||||
hd := http.Header{}
|
|
||||||
for k, v := range mm {
|
|
||||||
hd.Add(k, v)
|
|
||||||
}
|
|
||||||
c.md.header = hd
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
@@ -1,54 +0,0 @@
|
|||||||
package http2
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"io"
|
|
||||||
"net"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
// HTTP2 connection, wrapped up just like a net.Conn.
|
|
||||||
type http2Conn struct {
|
|
||||||
r io.Reader
|
|
||||||
w io.Writer
|
|
||||||
remoteAddr net.Addr
|
|
||||||
localAddr net.Addr
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *http2Conn) Read(b []byte) (n int, err error) {
|
|
||||||
return c.r.Read(b)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *http2Conn) Write(b []byte) (n int, err error) {
|
|
||||||
return c.w.Write(b)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *http2Conn) Close() (err error) {
|
|
||||||
if r, ok := c.r.(io.Closer); ok {
|
|
||||||
err = r.Close()
|
|
||||||
}
|
|
||||||
if w, ok := c.w.(io.Closer); ok {
|
|
||||||
err = w.Close()
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *http2Conn) LocalAddr() net.Addr {
|
|
||||||
return c.localAddr
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *http2Conn) RemoteAddr() net.Addr {
|
|
||||||
return c.remoteAddr
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *http2Conn) SetDeadline(t time.Time) error {
|
|
||||||
return &net.OpError{Op: "set", Net: "http2", Source: nil, Addr: nil, Err: errors.New("deadline not supported")}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *http2Conn) SetReadDeadline(t time.Time) error {
|
|
||||||
return &net.OpError{Op: "set", Net: "http2", Source: nil, Addr: nil, Err: errors.New("deadline not supported")}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *http2Conn) SetWriteDeadline(t time.Time) error {
|
|
||||||
return &net.OpError{Op: "set", Net: "http2", Source: nil, Addr: nil, Err: errors.New("deadline not supported")}
|
|
||||||
}
|
|
||||||
@@ -1,121 +0,0 @@
|
|||||||
package http2
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"encoding/base64"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"net"
|
|
||||||
"net/http"
|
|
||||||
"net/http/httputil"
|
|
||||||
"net/url"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/go-gost/gost/pkg/connector"
|
|
||||||
http2_util "github.com/go-gost/gost/pkg/internal/util/http2"
|
|
||||||
"github.com/go-gost/gost/pkg/logger"
|
|
||||||
md "github.com/go-gost/gost/pkg/metadata"
|
|
||||||
"github.com/go-gost/gost/pkg/registry"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
registry.ConnectorRegistry().Register("http2", NewConnector)
|
|
||||||
}
|
|
||||||
|
|
||||||
type http2Connector struct {
|
|
||||||
md metadata
|
|
||||||
options connector.Options
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewConnector(opts ...connector.Option) connector.Connector {
|
|
||||||
options := connector.Options{}
|
|
||||||
for _, opt := range opts {
|
|
||||||
opt(&options)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &http2Connector{
|
|
||||||
options: options,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *http2Connector) Init(md md.Metadata) (err error) {
|
|
||||||
return c.parseMetadata(md)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *http2Connector) Connect(ctx context.Context, conn net.Conn, network, address string, opts ...connector.ConnectOption) (net.Conn, error) {
|
|
||||||
log := c.options.Logger.WithFields(map[string]any{
|
|
||||||
"local": conn.LocalAddr().String(),
|
|
||||||
"remote": conn.RemoteAddr().String(),
|
|
||||||
"network": network,
|
|
||||||
"address": address,
|
|
||||||
})
|
|
||||||
log.Infof("connect %s/%s", address, network)
|
|
||||||
|
|
||||||
cc, ok := conn.(*http2_util.ClientConn)
|
|
||||||
if !ok {
|
|
||||||
err := errors.New("wrong connection type")
|
|
||||||
log.Error(err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
pr, pw := io.Pipe()
|
|
||||||
req := &http.Request{
|
|
||||||
Method: http.MethodConnect,
|
|
||||||
URL: &url.URL{Scheme: "https", Host: conn.RemoteAddr().String()},
|
|
||||||
Host: address,
|
|
||||||
ProtoMajor: 2,
|
|
||||||
ProtoMinor: 0,
|
|
||||||
Header: make(http.Header),
|
|
||||||
Body: pr,
|
|
||||||
// ContentLength: -1,
|
|
||||||
}
|
|
||||||
if c.md.UserAgent != "" {
|
|
||||||
req.Header.Set("User-Agent", c.md.UserAgent)
|
|
||||||
}
|
|
||||||
|
|
||||||
if user := c.options.Auth; user != nil {
|
|
||||||
u := user.Username()
|
|
||||||
p, _ := user.Password()
|
|
||||||
req.Header.Set("Proxy-Authorization",
|
|
||||||
"Basic "+base64.StdEncoding.EncodeToString([]byte(u+":"+p)))
|
|
||||||
}
|
|
||||||
|
|
||||||
if log.IsLevelEnabled(logger.DebugLevel) {
|
|
||||||
dump, _ := httputil.DumpRequest(req, false)
|
|
||||||
log.Debug(string(dump))
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.md.connectTimeout > 0 {
|
|
||||||
conn.SetDeadline(time.Now().Add(c.md.connectTimeout))
|
|
||||||
defer conn.SetDeadline(time.Time{})
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := cc.Client().Do(req.WithContext(ctx))
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
cc.Close()
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if log.IsLevelEnabled(logger.DebugLevel) {
|
|
||||||
dump, _ := httputil.DumpResponse(resp, false)
|
|
||||||
log.Debug(string(dump))
|
|
||||||
}
|
|
||||||
if resp.StatusCode != http.StatusOK {
|
|
||||||
resp.Body.Close()
|
|
||||||
err = fmt.Errorf("%s", resp.Status)
|
|
||||||
log.Error(err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
hc := &http2Conn{
|
|
||||||
r: resp.Body,
|
|
||||||
w: pw,
|
|
||||||
localAddr: conn.RemoteAddr(),
|
|
||||||
}
|
|
||||||
|
|
||||||
hc.remoteAddr, _ = net.ResolveTCPAddr(network, address)
|
|
||||||
|
|
||||||
return hc, nil
|
|
||||||
}
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
package http2
|
|
||||||
|
|
||||||
import (
|
|
||||||
"time"
|
|
||||||
|
|
||||||
mdata "github.com/go-gost/gost/pkg/metadata"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
defaultUserAgent = "Chrome/78.0.3904.106"
|
|
||||||
)
|
|
||||||
|
|
||||||
type metadata struct {
|
|
||||||
connectTimeout time.Duration
|
|
||||||
UserAgent string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *http2Connector) parseMetadata(md mdata.Metadata) (err error) {
|
|
||||||
const (
|
|
||||||
connectTimeout = "timeout"
|
|
||||||
userAgent = "userAgent"
|
|
||||||
)
|
|
||||||
|
|
||||||
c.md.connectTimeout = mdata.GetDuration(md, connectTimeout)
|
|
||||||
c.md.UserAgent = mdata.GetString(md, userAgent)
|
|
||||||
if c.md.UserAgent == "" {
|
|
||||||
c.md.UserAgent = defaultUserAgent
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
@@ -1,80 +0,0 @@
|
|||||||
package connector
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/tls"
|
|
||||||
"net/url"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/go-gost/gost/pkg/logger"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Options struct {
|
|
||||||
Auth *url.Userinfo
|
|
||||||
TLSConfig *tls.Config
|
|
||||||
Logger logger.Logger
|
|
||||||
}
|
|
||||||
|
|
||||||
type Option func(opts *Options)
|
|
||||||
|
|
||||||
func AuthOption(auth *url.Userinfo) Option {
|
|
||||||
return func(opts *Options) {
|
|
||||||
opts.Auth = auth
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TLSConfigOption(tlsConfig *tls.Config) Option {
|
|
||||||
return func(opts *Options) {
|
|
||||||
opts.TLSConfig = tlsConfig
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func LoggerOption(logger logger.Logger) Option {
|
|
||||||
return func(opts *Options) {
|
|
||||||
opts.Logger = logger
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type ConnectOptions struct {
|
|
||||||
}
|
|
||||||
|
|
||||||
type ConnectOption func(opts *ConnectOptions)
|
|
||||||
|
|
||||||
type BindOptions struct {
|
|
||||||
Mux bool
|
|
||||||
Backlog int
|
|
||||||
UDPDataQueueSize int
|
|
||||||
UDPDataBufferSize int
|
|
||||||
UDPConnTTL time.Duration
|
|
||||||
}
|
|
||||||
|
|
||||||
type BindOption func(opts *BindOptions)
|
|
||||||
|
|
||||||
func MuxBindOption(mux bool) BindOption {
|
|
||||||
return func(opts *BindOptions) {
|
|
||||||
opts.Mux = mux
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BacklogBindOption(backlog int) BindOption {
|
|
||||||
return func(opts *BindOptions) {
|
|
||||||
opts.Backlog = backlog
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func UDPDataQueueSizeBindOption(size int) BindOption {
|
|
||||||
return func(opts *BindOptions) {
|
|
||||||
opts.UDPDataQueueSize = size
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func UDPDataBufferSizeBindOption(size int) BindOption {
|
|
||||||
return func(opts *BindOptions) {
|
|
||||||
opts.UDPDataBufferSize = size
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func UDPConnTTLBindOption(ttl time.Duration) BindOption {
|
|
||||||
return func(opts *BindOptions) {
|
|
||||||
opts.UDPConnTTL = ttl
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,133 +0,0 @@
|
|||||||
package relay
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"net"
|
|
||||||
"strconv"
|
|
||||||
|
|
||||||
"github.com/go-gost/gost/pkg/common/util/mux"
|
|
||||||
"github.com/go-gost/gost/pkg/common/util/socks"
|
|
||||||
"github.com/go-gost/gost/pkg/common/util/udp"
|
|
||||||
"github.com/go-gost/gost/pkg/connector"
|
|
||||||
"github.com/go-gost/gost/pkg/logger"
|
|
||||||
"github.com/go-gost/relay"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Bind implements connector.Binder.
|
|
||||||
func (c *relayConnector) Bind(ctx context.Context, conn net.Conn, network, address string, opts ...connector.BindOption) (net.Listener, error) {
|
|
||||||
log := c.options.Logger.WithFields(map[string]any{
|
|
||||||
"network": network,
|
|
||||||
"address": address,
|
|
||||||
})
|
|
||||||
log.Infof("bind on %s/%s", address, network)
|
|
||||||
|
|
||||||
options := connector.BindOptions{}
|
|
||||||
for _, opt := range opts {
|
|
||||||
opt(&options)
|
|
||||||
}
|
|
||||||
|
|
||||||
switch network {
|
|
||||||
case "tcp", "tcp4", "tcp6":
|
|
||||||
return c.bindTCP(ctx, conn, network, address, log)
|
|
||||||
case "udp", "udp4", "udp6":
|
|
||||||
return c.bindUDP(ctx, conn, network, address, &options, log)
|
|
||||||
default:
|
|
||||||
err := fmt.Errorf("network %s is unsupported", network)
|
|
||||||
log.Error(err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *relayConnector) bindTCP(ctx context.Context, conn net.Conn, network, address string, log logger.Logger) (net.Listener, error) {
|
|
||||||
laddr, err := c.bind(conn, relay.BIND, network, address)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
log.Debugf("bind on %s/%s OK", laddr, laddr.Network())
|
|
||||||
|
|
||||||
session, err := mux.ServerSession(conn)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return &tcpListener{
|
|
||||||
addr: laddr,
|
|
||||||
session: session,
|
|
||||||
logger: log,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *relayConnector) bindUDP(ctx context.Context, conn net.Conn, network, address string, opts *connector.BindOptions, log logger.Logger) (net.Listener, error) {
|
|
||||||
laddr, err := c.bind(conn, relay.FUDP|relay.BIND, network, address)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
log.Debugf("bind on %s/%s OK", laddr, laddr.Network())
|
|
||||||
|
|
||||||
ln := udp.NewListener(
|
|
||||||
socks.UDPTunClientPacketConn(conn),
|
|
||||||
laddr,
|
|
||||||
opts.Backlog,
|
|
||||||
opts.UDPDataQueueSize, opts.UDPDataBufferSize,
|
|
||||||
opts.UDPConnTTL,
|
|
||||||
log)
|
|
||||||
|
|
||||||
return ln, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *relayConnector) bind(conn net.Conn, cmd uint8, network, address string) (net.Addr, error) {
|
|
||||||
req := relay.Request{
|
|
||||||
Version: relay.Version1,
|
|
||||||
Flags: cmd,
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.options.Auth != nil {
|
|
||||||
pwd, _ := c.options.Auth.Password()
|
|
||||||
req.Features = append(req.Features, &relay.UserAuthFeature{
|
|
||||||
Username: c.options.Auth.Username(),
|
|
||||||
Password: pwd,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
fa := &relay.AddrFeature{}
|
|
||||||
fa.ParseFrom(address)
|
|
||||||
req.Features = append(req.Features, fa)
|
|
||||||
if _, err := req.WriteTo(conn); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// first reply, bind status
|
|
||||||
resp := relay.Response{}
|
|
||||||
if _, err := resp.ReadFrom(conn); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if resp.Status != relay.StatusOK {
|
|
||||||
return nil, fmt.Errorf("bind on %s/%s failed", address, network)
|
|
||||||
}
|
|
||||||
|
|
||||||
var addr string
|
|
||||||
for _, f := range resp.Features {
|
|
||||||
if f.Type() == relay.FeatureAddr {
|
|
||||||
if fa, ok := f.(*relay.AddrFeature); ok {
|
|
||||||
addr = net.JoinHostPort(fa.Host, strconv.Itoa(int(fa.Port)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var baddr net.Addr
|
|
||||||
var err error
|
|
||||||
switch network {
|
|
||||||
case "tcp", "tcp4", "tcp6":
|
|
||||||
baddr, err = net.ResolveTCPAddr(network, addr)
|
|
||||||
case "udp", "udp4", "udp6":
|
|
||||||
baddr, err = net.ResolveUDPAddr(network, addr)
|
|
||||||
default:
|
|
||||||
err = fmt.Errorf("unknown network %s", network)
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return baddr, nil
|
|
||||||
}
|
|
||||||
@@ -1,132 +0,0 @@
|
|||||||
package relay
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/binary"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"math"
|
|
||||||
"net"
|
|
||||||
"sync"
|
|
||||||
|
|
||||||
"github.com/go-gost/relay"
|
|
||||||
)
|
|
||||||
|
|
||||||
type tcpConn struct {
|
|
||||||
net.Conn
|
|
||||||
wbuf bytes.Buffer
|
|
||||||
once sync.Once
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *tcpConn) Read(b []byte) (n int, err error) {
|
|
||||||
c.once.Do(func() {
|
|
||||||
err = readResponse(c.Conn)
|
|
||||||
})
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
return c.Conn.Read(b)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *tcpConn) Write(b []byte) (n int, err error) {
|
|
||||||
n = len(b) // force byte length consistent
|
|
||||||
if c.wbuf.Len() > 0 {
|
|
||||||
c.wbuf.Write(b) // append the data to the cached header
|
|
||||||
_, err = c.Conn.Write(c.wbuf.Bytes())
|
|
||||||
c.wbuf.Reset()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
_, err = c.Conn.Write(b)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
type udpConn struct {
|
|
||||||
net.Conn
|
|
||||||
wbuf bytes.Buffer
|
|
||||||
once sync.Once
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *udpConn) Read(b []byte) (n int, err error) {
|
|
||||||
c.once.Do(func() {
|
|
||||||
err = readResponse(c.Conn)
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var bb [2]byte
|
|
||||||
_, err = io.ReadFull(c.Conn, bb[:])
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
dlen := int(binary.BigEndian.Uint16(bb[:]))
|
|
||||||
if len(b) >= dlen {
|
|
||||||
return io.ReadFull(c.Conn, b[:dlen])
|
|
||||||
}
|
|
||||||
buf := make([]byte, dlen)
|
|
||||||
_, err = io.ReadFull(c.Conn, buf)
|
|
||||||
n = copy(b, buf)
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *udpConn) Write(b []byte) (n int, err error) {
|
|
||||||
if len(b) > math.MaxUint16 {
|
|
||||||
err = errors.New("write: data maximum exceeded")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
n = len(b)
|
|
||||||
if c.wbuf.Len() > 0 {
|
|
||||||
var bb [2]byte
|
|
||||||
binary.BigEndian.PutUint16(bb[:], uint16(len(b)))
|
|
||||||
c.wbuf.Write(bb[:])
|
|
||||||
c.wbuf.Write(b) // append the data to the cached header
|
|
||||||
_, err = c.wbuf.WriteTo(c.Conn)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var bb [2]byte
|
|
||||||
binary.BigEndian.PutUint16(bb[:], uint16(len(b)))
|
|
||||||
_, err = c.Conn.Write(bb[:])
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
return c.Conn.Write(b)
|
|
||||||
}
|
|
||||||
|
|
||||||
func readResponse(r io.Reader) (err error) {
|
|
||||||
resp := relay.Response{}
|
|
||||||
_, err = resp.ReadFrom(r)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if resp.Version != relay.Version1 {
|
|
||||||
err = relay.ErrBadVersion
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if resp.Status != relay.StatusOK {
|
|
||||||
err = fmt.Errorf("status %d", resp.Status)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type bindConn struct {
|
|
||||||
net.Conn
|
|
||||||
localAddr net.Addr
|
|
||||||
remoteAddr net.Addr
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *bindConn) LocalAddr() net.Addr {
|
|
||||||
return c.localAddr
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *bindConn) RemoteAddr() net.Addr {
|
|
||||||
return c.remoteAddr
|
|
||||||
}
|
|
||||||
@@ -1,127 +0,0 @@
|
|||||||
package relay
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"net"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/go-gost/gost/pkg/common/util/socks"
|
|
||||||
"github.com/go-gost/gost/pkg/connector"
|
|
||||||
md "github.com/go-gost/gost/pkg/metadata"
|
|
||||||
"github.com/go-gost/gost/pkg/registry"
|
|
||||||
"github.com/go-gost/relay"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
registry.ConnectorRegistry().Register("relay", NewConnector)
|
|
||||||
}
|
|
||||||
|
|
||||||
type relayConnector struct {
|
|
||||||
md metadata
|
|
||||||
options connector.Options
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewConnector(opts ...connector.Option) connector.Connector {
|
|
||||||
options := connector.Options{}
|
|
||||||
for _, opt := range opts {
|
|
||||||
opt(&options)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &relayConnector{
|
|
||||||
options: options,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *relayConnector) Init(md md.Metadata) (err error) {
|
|
||||||
return c.parseMetadata(md)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *relayConnector) Connect(ctx context.Context, conn net.Conn, network, address string, opts ...connector.ConnectOption) (net.Conn, error) {
|
|
||||||
log := c.options.Logger.WithFields(map[string]any{
|
|
||||||
"remote": conn.RemoteAddr().String(),
|
|
||||||
"local": conn.LocalAddr().String(),
|
|
||||||
"network": network,
|
|
||||||
"address": address,
|
|
||||||
})
|
|
||||||
log.Infof("connect %s/%s", address, network)
|
|
||||||
|
|
||||||
if c.md.connectTimeout > 0 {
|
|
||||||
conn.SetDeadline(time.Now().Add(c.md.connectTimeout))
|
|
||||||
defer conn.SetDeadline(time.Time{})
|
|
||||||
}
|
|
||||||
|
|
||||||
req := relay.Request{
|
|
||||||
Version: relay.Version1,
|
|
||||||
Flags: relay.CONNECT,
|
|
||||||
}
|
|
||||||
if network == "udp" || network == "udp4" || network == "udp6" {
|
|
||||||
req.Flags |= relay.FUDP
|
|
||||||
|
|
||||||
// UDP association
|
|
||||||
if address == "" {
|
|
||||||
baddr, err := c.bind(conn, relay.FUDP|relay.BIND, network, address)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
log.Debugf("associate on %s OK", baddr)
|
|
||||||
|
|
||||||
return socks.UDPTunClientConn(conn, nil), nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.options.Auth != nil {
|
|
||||||
pwd, _ := c.options.Auth.Password()
|
|
||||||
req.Features = append(req.Features, &relay.UserAuthFeature{
|
|
||||||
Username: c.options.Auth.Username(),
|
|
||||||
Password: pwd,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
if address != "" {
|
|
||||||
af := &relay.AddrFeature{}
|
|
||||||
if err := af.ParseFrom(address); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// forward mode if port is 0.
|
|
||||||
if af.Port > 0 {
|
|
||||||
req.Features = append(req.Features, af)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.md.noDelay {
|
|
||||||
if _, err := req.WriteTo(conn); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch network {
|
|
||||||
case "tcp", "tcp4", "tcp6":
|
|
||||||
cc := &tcpConn{
|
|
||||||
Conn: conn,
|
|
||||||
}
|
|
||||||
if !c.md.noDelay {
|
|
||||||
if _, err := req.WriteTo(&cc.wbuf); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
conn = cc
|
|
||||||
case "udp", "udp4", "udp6":
|
|
||||||
cc := &udpConn{
|
|
||||||
Conn: conn,
|
|
||||||
}
|
|
||||||
if !c.md.noDelay {
|
|
||||||
if _, err := req.WriteTo(&cc.wbuf); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
conn = cc
|
|
||||||
default:
|
|
||||||
err := fmt.Errorf("network %s is unsupported", network)
|
|
||||||
log.Error(err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return conn, nil
|
|
||||||
}
|
|
||||||
@@ -1,73 +0,0 @@
|
|||||||
package relay
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"net"
|
|
||||||
"strconv"
|
|
||||||
|
|
||||||
"github.com/go-gost/gost/pkg/common/util/mux"
|
|
||||||
"github.com/go-gost/gost/pkg/logger"
|
|
||||||
"github.com/go-gost/relay"
|
|
||||||
)
|
|
||||||
|
|
||||||
type tcpListener struct {
|
|
||||||
addr net.Addr
|
|
||||||
session *mux.Session
|
|
||||||
logger logger.Logger
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *tcpListener) Accept() (net.Conn, error) {
|
|
||||||
cc, err := p.session.Accept()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
conn, err := p.getPeerConn(cc)
|
|
||||||
if err != nil {
|
|
||||||
cc.Close()
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return conn, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *tcpListener) getPeerConn(conn net.Conn) (net.Conn, error) {
|
|
||||||
// second reply, peer connected
|
|
||||||
resp := relay.Response{}
|
|
||||||
if _, err := resp.ReadFrom(conn); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if resp.Status != relay.StatusOK {
|
|
||||||
err := fmt.Errorf("peer connect failed")
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var address string
|
|
||||||
for _, f := range resp.Features {
|
|
||||||
if f.Type() == relay.FeatureAddr {
|
|
||||||
if fa, ok := f.(*relay.AddrFeature); ok {
|
|
||||||
address = net.JoinHostPort(fa.Host, strconv.Itoa(int(fa.Port)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
raddr, err := net.ResolveTCPAddr("tcp", address)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return &bindConn{
|
|
||||||
Conn: conn,
|
|
||||||
localAddr: p.addr,
|
|
||||||
remoteAddr: raddr,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *tcpListener) Addr() net.Addr {
|
|
||||||
return p.addr
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *tcpListener) Close() error {
|
|
||||||
return p.session.Close()
|
|
||||||
}
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
package relay
|
|
||||||
|
|
||||||
import (
|
|
||||||
"time"
|
|
||||||
|
|
||||||
mdata "github.com/go-gost/gost/pkg/metadata"
|
|
||||||
)
|
|
||||||
|
|
||||||
type metadata struct {
|
|
||||||
connectTimeout time.Duration
|
|
||||||
noDelay bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *relayConnector) parseMetadata(md mdata.Metadata) (err error) {
|
|
||||||
const (
|
|
||||||
connectTimeout = "connectTimeout"
|
|
||||||
noDelay = "nodelay"
|
|
||||||
)
|
|
||||||
|
|
||||||
c.md.connectTimeout = mdata.GetDuration(md, connectTimeout)
|
|
||||||
c.md.noDelay = mdata.GetBool(md, noDelay)
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
@@ -1,128 +0,0 @@
|
|||||||
package sni
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bufio"
|
|
||||||
"bytes"
|
|
||||||
"encoding/base64"
|
|
||||||
"encoding/binary"
|
|
||||||
"hash/crc32"
|
|
||||||
"io"
|
|
||||||
"net"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
dissector "github.com/go-gost/tls-dissector"
|
|
||||||
)
|
|
||||||
|
|
||||||
type sniClientConn struct {
|
|
||||||
host string
|
|
||||||
obfuscated bool
|
|
||||||
net.Conn
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *sniClientConn) Write(p []byte) (int, error) {
|
|
||||||
b, err := c.obfuscate(p)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
if _, err = c.Conn.Write(b); err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
return len(p), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *sniClientConn) obfuscate(p []byte) ([]byte, error) {
|
|
||||||
if c.host == "" {
|
|
||||||
return p, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.obfuscated {
|
|
||||||
return p, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if p[0] == dissector.Handshake {
|
|
||||||
b, err := readClientHelloRecord(bytes.NewReader(p), c.host)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
c.obfuscated = true
|
|
||||||
return b, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
buf := &bytes.Buffer{}
|
|
||||||
br := bufio.NewReader(bytes.NewReader(p))
|
|
||||||
for {
|
|
||||||
s, err := br.ReadString('\n')
|
|
||||||
if err != nil {
|
|
||||||
if err != io.EOF {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if s != "" {
|
|
||||||
buf.Write([]byte(s))
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
// end of HTTP header
|
|
||||||
if s == "\r\n" {
|
|
||||||
buf.Write([]byte(s))
|
|
||||||
// drain the remain bytes.
|
|
||||||
io.Copy(buf, br)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
if strings.HasPrefix(s, "Host") {
|
|
||||||
s = strings.TrimSpace(strings.TrimSuffix(strings.TrimPrefix(s, "Host:"), "\r\n"))
|
|
||||||
host := encodeServerName(s)
|
|
||||||
buf.WriteString("Host: " + c.host + "\r\n")
|
|
||||||
buf.WriteString("Gost-Target: " + host + "\r\n")
|
|
||||||
// drain the remain bytes.
|
|
||||||
io.Copy(buf, br)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
buf.Write([]byte(s))
|
|
||||||
}
|
|
||||||
c.obfuscated = true
|
|
||||||
return buf.Bytes(), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func readClientHelloRecord(r io.Reader, host string) ([]byte, error) {
|
|
||||||
record, err := dissector.ReadRecord(r)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
clientHello := dissector.ClientHelloMsg{}
|
|
||||||
if err := clientHello.Decode(record.Opaque); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, ext := range clientHello.Extensions {
|
|
||||||
if ext.Type() == dissector.ExtServerName {
|
|
||||||
snExtension := ext.(*dissector.ServerNameExtension)
|
|
||||||
if host != "" {
|
|
||||||
e, _ := dissector.NewExtension(0xFFFE, []byte(encodeServerName(snExtension.Name)))
|
|
||||||
clientHello.Extensions = append(clientHello.Extensions, e)
|
|
||||||
snExtension.Name = host
|
|
||||||
}
|
|
||||||
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
record.Opaque, err = clientHello.Encode()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
buf := &bytes.Buffer{}
|
|
||||||
if _, err := record.WriteTo(buf); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return buf.Bytes(), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func encodeServerName(name string) string {
|
|
||||||
buf := &bytes.Buffer{}
|
|
||||||
binary.Write(buf, binary.BigEndian, crc32.ChecksumIEEE([]byte(name)))
|
|
||||||
buf.WriteString(base64.RawURLEncoding.EncodeToString([]byte(name)))
|
|
||||||
return base64.RawURLEncoding.EncodeToString(buf.Bytes())
|
|
||||||
}
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
package sni
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"net"
|
|
||||||
|
|
||||||
"github.com/go-gost/gost/pkg/connector"
|
|
||||||
md "github.com/go-gost/gost/pkg/metadata"
|
|
||||||
"github.com/go-gost/gost/pkg/registry"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
registry.ConnectorRegistry().Register("sni", NewConnector)
|
|
||||||
}
|
|
||||||
|
|
||||||
type sniConnector struct {
|
|
||||||
md metadata
|
|
||||||
options connector.Options
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewConnector(opts ...connector.Option) connector.Connector {
|
|
||||||
options := connector.Options{}
|
|
||||||
for _, opt := range opts {
|
|
||||||
opt(&options)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &sniConnector{
|
|
||||||
options: options,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *sniConnector) Init(md md.Metadata) (err error) {
|
|
||||||
return c.parseMetadata(md)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *sniConnector) Connect(ctx context.Context, conn net.Conn, network, address string, opts ...connector.ConnectOption) (net.Conn, error) {
|
|
||||||
log := c.options.Logger.WithFields(map[string]any{
|
|
||||||
"remote": conn.RemoteAddr().String(),
|
|
||||||
"local": conn.LocalAddr().String(),
|
|
||||||
"network": network,
|
|
||||||
"address": address,
|
|
||||||
})
|
|
||||||
log.Infof("connect %s/%s", address, network)
|
|
||||||
|
|
||||||
return &sniClientConn{Conn: conn, host: c.md.host}, nil
|
|
||||||
}
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
package sni
|
|
||||||
|
|
||||||
import (
|
|
||||||
"time"
|
|
||||||
|
|
||||||
mdata "github.com/go-gost/gost/pkg/metadata"
|
|
||||||
)
|
|
||||||
|
|
||||||
type metadata struct {
|
|
||||||
host string
|
|
||||||
connectTimeout time.Duration
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *sniConnector) parseMetadata(md mdata.Metadata) (err error) {
|
|
||||||
const (
|
|
||||||
host = "host"
|
|
||||||
connectTimeout = "timeout"
|
|
||||||
)
|
|
||||||
|
|
||||||
c.md.host = mdata.GetString(md, host)
|
|
||||||
c.md.connectTimeout = mdata.GetDuration(md, connectTimeout)
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
@@ -1,123 +0,0 @@
|
|||||||
package v4
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"net"
|
|
||||||
"strconv"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/go-gost/gosocks4"
|
|
||||||
"github.com/go-gost/gost/pkg/connector"
|
|
||||||
md "github.com/go-gost/gost/pkg/metadata"
|
|
||||||
"github.com/go-gost/gost/pkg/registry"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
registry.ConnectorRegistry().Register("socks4", NewConnector)
|
|
||||||
registry.ConnectorRegistry().Register("socks4a", NewConnector)
|
|
||||||
}
|
|
||||||
|
|
||||||
type socks4Connector struct {
|
|
||||||
md metadata
|
|
||||||
options connector.Options
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewConnector(opts ...connector.Option) connector.Connector {
|
|
||||||
options := connector.Options{}
|
|
||||||
for _, opt := range opts {
|
|
||||||
opt(&options)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &socks4Connector{
|
|
||||||
options: options,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *socks4Connector) Init(md md.Metadata) (err error) {
|
|
||||||
return c.parseMetadata(md)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *socks4Connector) Connect(ctx context.Context, conn net.Conn, network, address string, opts ...connector.ConnectOption) (net.Conn, error) {
|
|
||||||
log := c.options.Logger.WithFields(map[string]any{
|
|
||||||
"remote": conn.RemoteAddr().String(),
|
|
||||||
"local": conn.LocalAddr().String(),
|
|
||||||
"network": network,
|
|
||||||
"address": address,
|
|
||||||
})
|
|
||||||
log.Infof("connect %s/%s", address, network)
|
|
||||||
|
|
||||||
switch network {
|
|
||||||
case "tcp", "tcp4", "tcp6":
|
|
||||||
if _, ok := conn.(net.PacketConn); ok {
|
|
||||||
err := fmt.Errorf("tcp over udp is unsupported")
|
|
||||||
log.Error(err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
err := fmt.Errorf("network %s is unsupported", network)
|
|
||||||
log.Error(err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var addr *gosocks4.Addr
|
|
||||||
|
|
||||||
if c.md.disable4a {
|
|
||||||
taddr, err := net.ResolveTCPAddr("tcp4", address)
|
|
||||||
if err != nil {
|
|
||||||
log.Error("resolve: ", err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if len(taddr.IP) == 0 {
|
|
||||||
taddr.IP = net.IPv4zero
|
|
||||||
}
|
|
||||||
addr = &gosocks4.Addr{
|
|
||||||
Type: gosocks4.AddrIPv4,
|
|
||||||
Host: taddr.IP.String(),
|
|
||||||
Port: uint16(taddr.Port),
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
host, port, err := net.SplitHostPort(address)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
p, _ := strconv.Atoi(port)
|
|
||||||
addr = &gosocks4.Addr{
|
|
||||||
Type: gosocks4.AddrDomain,
|
|
||||||
Host: host,
|
|
||||||
Port: uint16(p),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.md.connectTimeout > 0 {
|
|
||||||
conn.SetDeadline(time.Now().Add(c.md.connectTimeout))
|
|
||||||
defer conn.SetDeadline(time.Time{})
|
|
||||||
}
|
|
||||||
|
|
||||||
var userid []byte
|
|
||||||
if c.options.Auth != nil {
|
|
||||||
userid = []byte(c.options.Auth.Username())
|
|
||||||
}
|
|
||||||
req := gosocks4.NewRequest(gosocks4.CmdConnect, addr, userid)
|
|
||||||
if err := req.Write(conn); err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
log.Debug(req)
|
|
||||||
|
|
||||||
reply, err := gosocks4.ReadReply(conn)
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
log.Debug(reply)
|
|
||||||
|
|
||||||
if reply.Code != gosocks4.Granted {
|
|
||||||
err = errors.New("host unreachable")
|
|
||||||
log.Error(err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return conn, nil
|
|
||||||
}
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
package v4
|
|
||||||
|
|
||||||
import (
|
|
||||||
"time"
|
|
||||||
|
|
||||||
mdata "github.com/go-gost/gost/pkg/metadata"
|
|
||||||
)
|
|
||||||
|
|
||||||
type metadata struct {
|
|
||||||
connectTimeout time.Duration
|
|
||||||
disable4a bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *socks4Connector) parseMetadata(md mdata.Metadata) (err error) {
|
|
||||||
const (
|
|
||||||
connectTimeout = "timeout"
|
|
||||||
disable4a = "disable4a"
|
|
||||||
)
|
|
||||||
|
|
||||||
c.md.connectTimeout = mdata.GetDuration(md, connectTimeout)
|
|
||||||
c.md.disable4a = mdata.GetBool(md, disable4a)
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
@@ -1,130 +0,0 @@
|
|||||||
package v5
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"net"
|
|
||||||
|
|
||||||
"github.com/go-gost/gosocks5"
|
|
||||||
"github.com/go-gost/gost/pkg/common/util/mux"
|
|
||||||
"github.com/go-gost/gost/pkg/common/util/socks"
|
|
||||||
"github.com/go-gost/gost/pkg/common/util/udp"
|
|
||||||
"github.com/go-gost/gost/pkg/connector"
|
|
||||||
"github.com/go-gost/gost/pkg/logger"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Bind implements connector.Binder.
|
|
||||||
func (c *socks5Connector) Bind(ctx context.Context, conn net.Conn, network, address string, opts ...connector.BindOption) (net.Listener, error) {
|
|
||||||
log := c.options.Logger.WithFields(map[string]any{
|
|
||||||
"remote": conn.RemoteAddr().String(),
|
|
||||||
"local": conn.LocalAddr().String(),
|
|
||||||
"network": network,
|
|
||||||
"address": address,
|
|
||||||
})
|
|
||||||
log.Infof("bind on %s/%s", address, network)
|
|
||||||
|
|
||||||
options := connector.BindOptions{}
|
|
||||||
for _, opt := range opts {
|
|
||||||
opt(&options)
|
|
||||||
}
|
|
||||||
|
|
||||||
switch network {
|
|
||||||
case "tcp", "tcp4", "tcp6":
|
|
||||||
if options.Mux {
|
|
||||||
return c.muxBindTCP(ctx, conn, network, address, log)
|
|
||||||
}
|
|
||||||
return c.bindTCP(ctx, conn, network, address, log)
|
|
||||||
case "udp", "udp4", "udp6":
|
|
||||||
return c.bindUDP(ctx, conn, network, address, &options, log)
|
|
||||||
default:
|
|
||||||
err := fmt.Errorf("network %s is unsupported", network)
|
|
||||||
log.Error(err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *socks5Connector) bindTCP(ctx context.Context, conn net.Conn, network, address string, log logger.Logger) (net.Listener, error) {
|
|
||||||
laddr, err := c.bind(conn, gosocks5.CmdBind, network, address, log)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return &tcpListener{
|
|
||||||
addr: laddr,
|
|
||||||
conn: conn,
|
|
||||||
logger: log,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *socks5Connector) muxBindTCP(ctx context.Context, conn net.Conn, network, address string, log logger.Logger) (net.Listener, error) {
|
|
||||||
laddr, err := c.bind(conn, socks.CmdMuxBind, network, address, log)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
session, err := mux.ServerSession(conn)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return &tcpMuxListener{
|
|
||||||
addr: laddr,
|
|
||||||
session: session,
|
|
||||||
logger: log,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *socks5Connector) bindUDP(ctx context.Context, conn net.Conn, network, address string, opts *connector.BindOptions, log logger.Logger) (net.Listener, error) {
|
|
||||||
laddr, err := c.bind(conn, socks.CmdUDPTun, network, address, log)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
ln := udp.NewListener(
|
|
||||||
socks.UDPTunClientPacketConn(conn),
|
|
||||||
laddr,
|
|
||||||
opts.Backlog,
|
|
||||||
opts.UDPDataQueueSize, opts.UDPDataBufferSize,
|
|
||||||
opts.UDPConnTTL,
|
|
||||||
log)
|
|
||||||
|
|
||||||
return ln, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *socks5Connector) bind(conn net.Conn, cmd uint8, network, address string, log logger.Logger) (net.Addr, error) {
|
|
||||||
addr := gosocks5.Addr{}
|
|
||||||
addr.ParseFrom(address)
|
|
||||||
req := gosocks5.NewRequest(cmd, &addr)
|
|
||||||
if err := req.Write(conn); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
log.Debug(req)
|
|
||||||
|
|
||||||
// first reply, bind status
|
|
||||||
reply, err := gosocks5.ReadReply(conn)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Debug(reply)
|
|
||||||
|
|
||||||
if reply.Rep != gosocks5.Succeeded {
|
|
||||||
return nil, fmt.Errorf("bind on %s/%s failed", address, network)
|
|
||||||
}
|
|
||||||
|
|
||||||
var baddr net.Addr
|
|
||||||
switch network {
|
|
||||||
case "tcp", "tcp4", "tcp6":
|
|
||||||
baddr, err = net.ResolveTCPAddr(network, reply.Addr.String())
|
|
||||||
case "udp", "udp4", "udp6":
|
|
||||||
baddr, err = net.ResolveUDPAddr(network, reply.Addr.String())
|
|
||||||
default:
|
|
||||||
err = fmt.Errorf("unknown network %s", network)
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
log.Debugf("bind on %s/%s OK", baddr, baddr.Network())
|
|
||||||
|
|
||||||
return baddr, nil
|
|
||||||
}
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
package v5
|
|
||||||
|
|
||||||
import "net"
|
|
||||||
|
|
||||||
type bindConn struct {
|
|
||||||
net.Conn
|
|
||||||
localAddr net.Addr
|
|
||||||
remoteAddr net.Addr
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *bindConn) LocalAddr() net.Addr {
|
|
||||||
return c.localAddr
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *bindConn) RemoteAddr() net.Addr {
|
|
||||||
return c.remoteAddr
|
|
||||||
}
|
|
||||||
@@ -1,173 +0,0 @@
|
|||||||
package v5
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"crypto/tls"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"net"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/go-gost/gosocks5"
|
|
||||||
"github.com/go-gost/gost/pkg/common/util/socks"
|
|
||||||
"github.com/go-gost/gost/pkg/connector"
|
|
||||||
"github.com/go-gost/gost/pkg/logger"
|
|
||||||
md "github.com/go-gost/gost/pkg/metadata"
|
|
||||||
"github.com/go-gost/gost/pkg/registry"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
registry.ConnectorRegistry().Register("socks5", NewConnector)
|
|
||||||
registry.ConnectorRegistry().Register("socks", NewConnector)
|
|
||||||
}
|
|
||||||
|
|
||||||
type socks5Connector struct {
|
|
||||||
selector gosocks5.Selector
|
|
||||||
md metadata
|
|
||||||
options connector.Options
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewConnector(opts ...connector.Option) connector.Connector {
|
|
||||||
options := connector.Options{}
|
|
||||||
for _, opt := range opts {
|
|
||||||
opt(&options)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &socks5Connector{
|
|
||||||
options: options,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *socks5Connector) Init(md md.Metadata) (err error) {
|
|
||||||
if err = c.parseMetadata(md); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
selector := &clientSelector{
|
|
||||||
methods: []uint8{
|
|
||||||
gosocks5.MethodNoAuth,
|
|
||||||
gosocks5.MethodUserPass,
|
|
||||||
},
|
|
||||||
User: c.options.Auth,
|
|
||||||
TLSConfig: c.options.TLSConfig,
|
|
||||||
logger: c.options.Logger,
|
|
||||||
}
|
|
||||||
if !c.md.noTLS {
|
|
||||||
selector.methods = append(selector.methods, socks.MethodTLS)
|
|
||||||
if selector.TLSConfig == nil {
|
|
||||||
selector.TLSConfig = &tls.Config{
|
|
||||||
InsecureSkipVerify: true,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
c.selector = selector
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handshake implements connector.Handshaker.
|
|
||||||
func (c *socks5Connector) Handshake(ctx context.Context, conn net.Conn) (net.Conn, error) {
|
|
||||||
log := c.options.Logger.WithFields(map[string]any{
|
|
||||||
"remote": conn.RemoteAddr().String(),
|
|
||||||
"local": conn.LocalAddr().String(),
|
|
||||||
})
|
|
||||||
|
|
||||||
if c.md.connectTimeout > 0 {
|
|
||||||
conn.SetDeadline(time.Now().Add(c.md.connectTimeout))
|
|
||||||
defer conn.SetDeadline(time.Time{})
|
|
||||||
}
|
|
||||||
|
|
||||||
cc := gosocks5.ClientConn(conn, c.selector)
|
|
||||||
if err := cc.Handleshake(); err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return cc, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *socks5Connector) Connect(ctx context.Context, conn net.Conn, network, address string, opts ...connector.ConnectOption) (net.Conn, error) {
|
|
||||||
log := c.options.Logger.WithFields(map[string]any{
|
|
||||||
"remote": conn.RemoteAddr().String(),
|
|
||||||
"local": conn.LocalAddr().String(),
|
|
||||||
"network": network,
|
|
||||||
"address": address,
|
|
||||||
})
|
|
||||||
log.Infof("connect %s/%s", address, network)
|
|
||||||
|
|
||||||
if c.md.connectTimeout > 0 {
|
|
||||||
conn.SetDeadline(time.Now().Add(c.md.connectTimeout))
|
|
||||||
defer conn.SetDeadline(time.Time{})
|
|
||||||
}
|
|
||||||
|
|
||||||
switch network {
|
|
||||||
case "udp", "udp4", "udp6":
|
|
||||||
return c.connectUDP(ctx, conn, network, address, log)
|
|
||||||
case "tcp", "tcp4", "tcp6":
|
|
||||||
if _, ok := conn.(net.PacketConn); ok {
|
|
||||||
err := fmt.Errorf("tcp over udp is unsupported")
|
|
||||||
log.Error(err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
err := fmt.Errorf("network %s is unsupported", network)
|
|
||||||
log.Error(err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
addr := gosocks5.Addr{}
|
|
||||||
if err := addr.ParseFrom(address); err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
req := gosocks5.NewRequest(gosocks5.CmdConnect, &addr)
|
|
||||||
if err := req.Write(conn); err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
log.Debug(req)
|
|
||||||
|
|
||||||
reply, err := gosocks5.ReadReply(conn)
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
log.Debug(reply)
|
|
||||||
|
|
||||||
if reply.Rep != gosocks5.Succeeded {
|
|
||||||
err = errors.New("host unreachable")
|
|
||||||
log.Error(err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return conn, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *socks5Connector) connectUDP(ctx context.Context, conn net.Conn, network, address string, log logger.Logger) (net.Conn, error) {
|
|
||||||
addr, err := net.ResolveUDPAddr(network, address)
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
req := gosocks5.NewRequest(socks.CmdUDPTun, nil)
|
|
||||||
if err := req.Write(conn); err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
log.Debug(req)
|
|
||||||
|
|
||||||
reply, err := gosocks5.ReadReply(conn)
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
log.Debug(reply)
|
|
||||||
|
|
||||||
if reply.Rep != gosocks5.Succeeded {
|
|
||||||
return nil, errors.New("get socks5 UDP tunnel failure")
|
|
||||||
}
|
|
||||||
|
|
||||||
return socks.UDPTunClientConn(conn, addr), nil
|
|
||||||
}
|
|
||||||
@@ -1,102 +0,0 @@
|
|||||||
package v5
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"net"
|
|
||||||
|
|
||||||
"github.com/go-gost/gosocks5"
|
|
||||||
"github.com/go-gost/gost/pkg/common/util/mux"
|
|
||||||
"github.com/go-gost/gost/pkg/logger"
|
|
||||||
)
|
|
||||||
|
|
||||||
type tcpListener struct {
|
|
||||||
addr net.Addr
|
|
||||||
conn net.Conn
|
|
||||||
logger logger.Logger
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *tcpListener) Accept() (net.Conn, error) {
|
|
||||||
// second reply, peer connected
|
|
||||||
rep, err := gosocks5.ReadReply(p.conn)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
p.logger.Debug(rep)
|
|
||||||
|
|
||||||
if rep.Rep != gosocks5.Succeeded {
|
|
||||||
return nil, fmt.Errorf("peer connect failed")
|
|
||||||
}
|
|
||||||
|
|
||||||
raddr, err := net.ResolveTCPAddr("tcp", rep.Addr.String())
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return &bindConn{
|
|
||||||
Conn: p.conn,
|
|
||||||
localAddr: p.addr,
|
|
||||||
remoteAddr: raddr,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *tcpListener) Addr() net.Addr {
|
|
||||||
return p.addr
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *tcpListener) Close() error {
|
|
||||||
return p.conn.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
type tcpMuxListener struct {
|
|
||||||
addr net.Addr
|
|
||||||
session *mux.Session
|
|
||||||
logger logger.Logger
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *tcpMuxListener) Accept() (net.Conn, error) {
|
|
||||||
cc, err := p.session.Accept()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
conn, err := p.getPeerConn(cc)
|
|
||||||
if err != nil {
|
|
||||||
cc.Close()
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return conn, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *tcpMuxListener) getPeerConn(conn net.Conn) (net.Conn, error) {
|
|
||||||
// second reply, peer connected
|
|
||||||
rep, err := gosocks5.ReadReply(conn)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
p.logger.Debug(rep)
|
|
||||||
|
|
||||||
if rep.Rep != gosocks5.Succeeded {
|
|
||||||
err = fmt.Errorf("peer connect failed")
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
raddr, err := net.ResolveTCPAddr("tcp", rep.Addr.String())
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return &bindConn{
|
|
||||||
Conn: conn,
|
|
||||||
localAddr: p.addr,
|
|
||||||
remoteAddr: raddr,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *tcpMuxListener) Addr() net.Addr {
|
|
||||||
return p.addr
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *tcpMuxListener) Close() error {
|
|
||||||
return p.session.Close()
|
|
||||||
}
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
package v5
|
|
||||||
|
|
||||||
import (
|
|
||||||
"time"
|
|
||||||
|
|
||||||
mdata "github.com/go-gost/gost/pkg/metadata"
|
|
||||||
)
|
|
||||||
|
|
||||||
type metadata struct {
|
|
||||||
connectTimeout time.Duration
|
|
||||||
noTLS bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *socks5Connector) parseMetadata(md mdata.Metadata) (err error) {
|
|
||||||
const (
|
|
||||||
connectTimeout = "timeout"
|
|
||||||
noTLS = "notls"
|
|
||||||
)
|
|
||||||
|
|
||||||
c.md.connectTimeout = mdata.GetDuration(md, connectTimeout)
|
|
||||||
c.md.noTLS = mdata.GetBool(md, noTLS)
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
@@ -1,73 +0,0 @@
|
|||||||
package v5
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/tls"
|
|
||||||
"net"
|
|
||||||
"net/url"
|
|
||||||
|
|
||||||
"github.com/go-gost/gosocks5"
|
|
||||||
"github.com/go-gost/gost/pkg/common/util/socks"
|
|
||||||
"github.com/go-gost/gost/pkg/logger"
|
|
||||||
)
|
|
||||||
|
|
||||||
type clientSelector struct {
|
|
||||||
methods []uint8
|
|
||||||
User *url.Userinfo
|
|
||||||
TLSConfig *tls.Config
|
|
||||||
logger logger.Logger
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *clientSelector) Methods() []uint8 {
|
|
||||||
s.logger.Debug("methods: ", s.methods)
|
|
||||||
return s.methods
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *clientSelector) AddMethod(methods ...uint8) {
|
|
||||||
s.methods = append(s.methods, methods...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *clientSelector) Select(methods ...uint8) (method uint8) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *clientSelector) OnSelected(method uint8, conn net.Conn) (net.Conn, error) {
|
|
||||||
s.logger.Debug("method selected: ", method)
|
|
||||||
|
|
||||||
switch method {
|
|
||||||
case socks.MethodTLS:
|
|
||||||
conn = tls.Client(conn, s.TLSConfig)
|
|
||||||
|
|
||||||
case gosocks5.MethodUserPass, socks.MethodTLSAuth:
|
|
||||||
if method == socks.MethodTLSAuth {
|
|
||||||
conn = tls.Client(conn, s.TLSConfig)
|
|
||||||
}
|
|
||||||
|
|
||||||
var username, password string
|
|
||||||
if s.User != nil {
|
|
||||||
username = s.User.Username()
|
|
||||||
password, _ = s.User.Password()
|
|
||||||
}
|
|
||||||
|
|
||||||
req := gosocks5.NewUserPassRequest(gosocks5.UserPassVer, username, password)
|
|
||||||
if err := req.Write(conn); err != nil {
|
|
||||||
s.logger.Error(err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
s.logger.Debug(req)
|
|
||||||
|
|
||||||
resp, err := gosocks5.ReadUserPassResponse(conn)
|
|
||||||
if err != nil {
|
|
||||||
s.logger.Error(err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
s.logger.Debug(resp)
|
|
||||||
|
|
||||||
if resp.Status != gosocks5.Succeeded {
|
|
||||||
return nil, gosocks5.ErrAuthFailure
|
|
||||||
}
|
|
||||||
case gosocks5.MethodNoAcceptable:
|
|
||||||
return nil, gosocks5.ErrBadMethod
|
|
||||||
}
|
|
||||||
|
|
||||||
return conn, nil
|
|
||||||
}
|
|
||||||
@@ -1,111 +0,0 @@
|
|||||||
package ss
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"net"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/go-gost/gosocks5"
|
|
||||||
"github.com/go-gost/gost/pkg/common/bufpool"
|
|
||||||
"github.com/go-gost/gost/pkg/common/util/ss"
|
|
||||||
"github.com/go-gost/gost/pkg/connector"
|
|
||||||
md "github.com/go-gost/gost/pkg/metadata"
|
|
||||||
"github.com/go-gost/gost/pkg/registry"
|
|
||||||
"github.com/shadowsocks/go-shadowsocks2/core"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
registry.ConnectorRegistry().Register("ss", NewConnector)
|
|
||||||
}
|
|
||||||
|
|
||||||
type ssConnector struct {
|
|
||||||
cipher core.Cipher
|
|
||||||
md metadata
|
|
||||||
options connector.Options
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewConnector(opts ...connector.Option) connector.Connector {
|
|
||||||
options := connector.Options{}
|
|
||||||
for _, opt := range opts {
|
|
||||||
opt(&options)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &ssConnector{
|
|
||||||
options: options,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *ssConnector) Init(md md.Metadata) (err error) {
|
|
||||||
if err = c.parseMetadata(md); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.options.Auth != nil {
|
|
||||||
method := c.options.Auth.Username()
|
|
||||||
password, _ := c.options.Auth.Password()
|
|
||||||
c.cipher, err = ss.ShadowCipher(method, password, c.md.key)
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *ssConnector) Connect(ctx context.Context, conn net.Conn, network, address string, opts ...connector.ConnectOption) (net.Conn, error) {
|
|
||||||
log := c.options.Logger.WithFields(map[string]any{
|
|
||||||
"remote": conn.RemoteAddr().String(),
|
|
||||||
"local": conn.LocalAddr().String(),
|
|
||||||
"network": network,
|
|
||||||
"address": address,
|
|
||||||
})
|
|
||||||
log.Infof("connect %s/%s", address, network)
|
|
||||||
|
|
||||||
switch network {
|
|
||||||
case "tcp", "tcp4", "tcp6":
|
|
||||||
if _, ok := conn.(net.PacketConn); ok {
|
|
||||||
err := fmt.Errorf("tcp over udp is unsupported")
|
|
||||||
log.Error(err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
err := fmt.Errorf("network %s is unsupported", network)
|
|
||||||
log.Error(err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
addr := gosocks5.Addr{}
|
|
||||||
if err := addr.ParseFrom(address); err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
rawaddr := bufpool.Get(512)
|
|
||||||
defer bufpool.Put(rawaddr)
|
|
||||||
|
|
||||||
n, err := addr.Encode(*rawaddr)
|
|
||||||
if err != nil {
|
|
||||||
log.Error("encoding addr: ", err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.md.connectTimeout > 0 {
|
|
||||||
conn.SetDeadline(time.Now().Add(c.md.connectTimeout))
|
|
||||||
defer conn.SetDeadline(time.Time{})
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.cipher != nil {
|
|
||||||
conn = c.cipher.StreamConn(conn)
|
|
||||||
}
|
|
||||||
|
|
||||||
var sc net.Conn
|
|
||||||
if c.md.noDelay {
|
|
||||||
sc = ss.ShadowConn(conn, nil)
|
|
||||||
// write the addr at once.
|
|
||||||
if _, err := sc.Write((*rawaddr)[:n]); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// cache the header
|
|
||||||
sc = ss.ShadowConn(conn, (*rawaddr)[:n])
|
|
||||||
}
|
|
||||||
|
|
||||||
return sc, nil
|
|
||||||
}
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
package ss
|
|
||||||
|
|
||||||
import (
|
|
||||||
"time"
|
|
||||||
|
|
||||||
mdata "github.com/go-gost/gost/pkg/metadata"
|
|
||||||
)
|
|
||||||
|
|
||||||
type metadata struct {
|
|
||||||
key string
|
|
||||||
connectTimeout time.Duration
|
|
||||||
noDelay bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *ssConnector) parseMetadata(md mdata.Metadata) (err error) {
|
|
||||||
const (
|
|
||||||
key = "key"
|
|
||||||
connectTimeout = "timeout"
|
|
||||||
noDelay = "nodelay"
|
|
||||||
)
|
|
||||||
|
|
||||||
c.md.key = mdata.GetString(md, key)
|
|
||||||
c.md.connectTimeout = mdata.GetDuration(md, connectTimeout)
|
|
||||||
c.md.noDelay = mdata.GetBool(md, noDelay)
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
@@ -1,95 +0,0 @@
|
|||||||
package ss
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"net"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/go-gost/gost/pkg/common/util/socks"
|
|
||||||
"github.com/go-gost/gost/pkg/common/util/ss"
|
|
||||||
"github.com/go-gost/gost/pkg/connector"
|
|
||||||
md "github.com/go-gost/gost/pkg/metadata"
|
|
||||||
"github.com/go-gost/gost/pkg/registry"
|
|
||||||
"github.com/shadowsocks/go-shadowsocks2/core"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
registry.ConnectorRegistry().Register("ssu", NewConnector)
|
|
||||||
}
|
|
||||||
|
|
||||||
type ssuConnector struct {
|
|
||||||
cipher core.Cipher
|
|
||||||
md metadata
|
|
||||||
options connector.Options
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewConnector(opts ...connector.Option) connector.Connector {
|
|
||||||
options := connector.Options{}
|
|
||||||
for _, opt := range opts {
|
|
||||||
opt(&options)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &ssuConnector{
|
|
||||||
options: options,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *ssuConnector) Init(md md.Metadata) (err error) {
|
|
||||||
if err = c.parseMetadata(md); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.options.Auth != nil {
|
|
||||||
method := c.options.Auth.Username()
|
|
||||||
password, _ := c.options.Auth.Password()
|
|
||||||
c.cipher, err = ss.ShadowCipher(method, password, c.md.key)
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *ssuConnector) Connect(ctx context.Context, conn net.Conn, network, address string, opts ...connector.ConnectOption) (net.Conn, error) {
|
|
||||||
log := c.options.Logger.WithFields(map[string]any{
|
|
||||||
"remote": conn.RemoteAddr().String(),
|
|
||||||
"local": conn.LocalAddr().String(),
|
|
||||||
"network": network,
|
|
||||||
"address": address,
|
|
||||||
})
|
|
||||||
log.Infof("connect %s/%s", address, network)
|
|
||||||
|
|
||||||
switch network {
|
|
||||||
case "udp", "udp4", "udp6":
|
|
||||||
default:
|
|
||||||
err := fmt.Errorf("network %s is unsupported", network)
|
|
||||||
log.Error(err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.md.connectTimeout > 0 {
|
|
||||||
conn.SetDeadline(time.Now().Add(c.md.connectTimeout))
|
|
||||||
defer conn.SetDeadline(time.Time{})
|
|
||||||
}
|
|
||||||
|
|
||||||
taddr, _ := net.ResolveUDPAddr(network, address)
|
|
||||||
if taddr == nil {
|
|
||||||
taddr = &net.UDPAddr{}
|
|
||||||
}
|
|
||||||
|
|
||||||
pc, ok := conn.(net.PacketConn)
|
|
||||||
if ok {
|
|
||||||
if c.cipher != nil {
|
|
||||||
pc = c.cipher.PacketConn(pc)
|
|
||||||
}
|
|
||||||
|
|
||||||
// standard UDP relay
|
|
||||||
return ss.UDPClientConn(pc, conn.RemoteAddr(), taddr, c.md.bufferSize), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.cipher != nil {
|
|
||||||
conn = ss.ShadowConn(c.cipher.StreamConn(conn), nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
// UDP over TCP
|
|
||||||
return socks.UDPTunClientConn(conn, taddr), nil
|
|
||||||
}
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
package ss
|
|
||||||
|
|
||||||
import (
|
|
||||||
"math"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
mdata "github.com/go-gost/gost/pkg/metadata"
|
|
||||||
)
|
|
||||||
|
|
||||||
type metadata struct {
|
|
||||||
key string
|
|
||||||
connectTimeout time.Duration
|
|
||||||
bufferSize int
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *ssuConnector) parseMetadata(md mdata.Metadata) (err error) {
|
|
||||||
const (
|
|
||||||
key = "key"
|
|
||||||
connectTimeout = "timeout"
|
|
||||||
bufferSize = "bufferSize" // udp buffer size
|
|
||||||
)
|
|
||||||
|
|
||||||
c.md.key = mdata.GetString(md, key)
|
|
||||||
c.md.connectTimeout = mdata.GetDuration(md, connectTimeout)
|
|
||||||
|
|
||||||
if bs := mdata.GetInt(md, bufferSize); bs > 0 {
|
|
||||||
c.md.bufferSize = int(math.Min(math.Max(float64(bs), 512), 64*1024))
|
|
||||||
} else {
|
|
||||||
c.md.bufferSize = 1024
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
@@ -1,80 +0,0 @@
|
|||||||
package sshd
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"errors"
|
|
||||||
"net"
|
|
||||||
|
|
||||||
"github.com/go-gost/gost/pkg/connector"
|
|
||||||
ssh_util "github.com/go-gost/gost/pkg/internal/util/ssh"
|
|
||||||
md "github.com/go-gost/gost/pkg/metadata"
|
|
||||||
"github.com/go-gost/gost/pkg/registry"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
registry.ConnectorRegistry().Register("sshd", NewConnector)
|
|
||||||
}
|
|
||||||
|
|
||||||
type sshdConnector struct {
|
|
||||||
options connector.Options
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewConnector(opts ...connector.Option) connector.Connector {
|
|
||||||
options := connector.Options{}
|
|
||||||
for _, opt := range opts {
|
|
||||||
opt(&options)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &sshdConnector{
|
|
||||||
options: options,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *sshdConnector) Init(md md.Metadata) (err error) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *sshdConnector) Connect(ctx context.Context, conn net.Conn, network, address string, opts ...connector.ConnectOption) (net.Conn, error) {
|
|
||||||
log := c.options.Logger.WithFields(map[string]any{
|
|
||||||
"remote": conn.RemoteAddr().String(),
|
|
||||||
"local": conn.LocalAddr().String(),
|
|
||||||
"network": network,
|
|
||||||
"address": address,
|
|
||||||
})
|
|
||||||
log.Infof("connect %s/%s", address, network)
|
|
||||||
|
|
||||||
cc, ok := conn.(*ssh_util.ClientConn)
|
|
||||||
if !ok {
|
|
||||||
return nil, errors.New("ssh: invalid connection")
|
|
||||||
}
|
|
||||||
|
|
||||||
conn, err := cc.Client().Dial(network, address)
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return conn, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bind implements connector.Binder.
|
|
||||||
func (c *sshdConnector) Bind(ctx context.Context, conn net.Conn, network, address string, opts ...connector.BindOption) (net.Listener, error) {
|
|
||||||
log := c.options.Logger.WithFields(map[string]any{
|
|
||||||
"remote": conn.RemoteAddr().String(),
|
|
||||||
"local": conn.LocalAddr().String(),
|
|
||||||
"network": network,
|
|
||||||
"address": address,
|
|
||||||
})
|
|
||||||
log.Infof("bind on %s/%s", address, network)
|
|
||||||
|
|
||||||
cc, ok := conn.(*ssh_util.ClientConn)
|
|
||||||
if !ok {
|
|
||||||
return nil, errors.New("ssh: invalid connection")
|
|
||||||
}
|
|
||||||
|
|
||||||
if host, port, _ := net.SplitHostPort(address); host == "" {
|
|
||||||
address = net.JoinHostPort("0.0.0.0", port)
|
|
||||||
}
|
|
||||||
|
|
||||||
return cc.Client().Listen(network, address)
|
|
||||||
}
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
package dialer
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"net"
|
|
||||||
|
|
||||||
"github.com/go-gost/gost/pkg/metadata"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Transporter is responsible for dialing to the proxy server.
|
|
||||||
type Dialer interface {
|
|
||||||
Init(metadata.Metadata) error
|
|
||||||
Dial(ctx context.Context, addr string, opts ...DialOption) (net.Conn, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
type Handshaker interface {
|
|
||||||
Handshake(ctx context.Context, conn net.Conn, opts ...HandshakeOption) (net.Conn, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
type Multiplexer interface {
|
|
||||||
Multiplex() bool
|
|
||||||
}
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
package ftcp
|
|
||||||
|
|
||||||
import "net"
|
|
||||||
|
|
||||||
type fakeTCPConn struct {
|
|
||||||
raddr net.Addr
|
|
||||||
net.PacketConn
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *fakeTCPConn) Read(b []byte) (n int, err error) {
|
|
||||||
n, _, err = c.ReadFrom(b)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *fakeTCPConn) Write(b []byte) (n int, err error) {
|
|
||||||
return c.WriteTo(b, c.raddr)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *fakeTCPConn) RemoteAddr() net.Addr {
|
|
||||||
return c.raddr
|
|
||||||
}
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
package ftcp
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"net"
|
|
||||||
|
|
||||||
"github.com/go-gost/gost/pkg/dialer"
|
|
||||||
"github.com/go-gost/gost/pkg/logger"
|
|
||||||
md "github.com/go-gost/gost/pkg/metadata"
|
|
||||||
"github.com/go-gost/gost/pkg/registry"
|
|
||||||
"github.com/xtaci/tcpraw"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
registry.DialerRegistry().Register("ftcp", NewDialer)
|
|
||||||
}
|
|
||||||
|
|
||||||
type ftcpDialer struct {
|
|
||||||
md metadata
|
|
||||||
logger logger.Logger
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewDialer(opts ...dialer.Option) dialer.Dialer {
|
|
||||||
options := &dialer.Options{}
|
|
||||||
for _, opt := range opts {
|
|
||||||
opt(options)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &ftcpDialer{
|
|
||||||
logger: options.Logger,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *ftcpDialer) Init(md md.Metadata) (err error) {
|
|
||||||
return d.parseMetadata(md)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *ftcpDialer) Dial(ctx context.Context, addr string, opts ...dialer.DialOption) (conn net.Conn, err error) {
|
|
||||||
raddr, er := net.ResolveTCPAddr("tcp", addr)
|
|
||||||
if er != nil {
|
|
||||||
return nil, er
|
|
||||||
}
|
|
||||||
c, err := tcpraw.Dial("tcp", addr)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
return &fakeTCPConn{
|
|
||||||
raddr: raddr,
|
|
||||||
PacketConn: c,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user