Merge remote branch
This commit is contained in:
commit
4f7a0ec129
97 changed files with 1147 additions and 577 deletions
12
.github/workflows/linter.yml
vendored
Normal file
12
.github/workflows/linter.yml
vendored
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
name: Linter
|
||||||
|
on: [push, pull_request]
|
||||||
|
jobs:
|
||||||
|
lint:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: golangci-lint
|
||||||
|
uses: golangci/golangci-lint-action@v2
|
||||||
|
with:
|
||||||
|
version: latest
|
||||||
|
args: --build-tags=build_local --disable-all -E govet -E gofumpt -E megacheck ./...
|
|
@ -1,9 +1,7 @@
|
||||||
name: Go
|
name: Release
|
||||||
on: [push]
|
on: [push]
|
||||||
jobs:
|
jobs:
|
||||||
|
|
||||||
build:
|
build:
|
||||||
name: Build
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Get latest go version
|
- name: Get latest go version
|
||||||
|
@ -27,7 +25,7 @@ jobs:
|
||||||
restore-keys: |
|
restore-keys: |
|
||||||
${{ runner.os }}-go-
|
${{ runner.os }}-go-
|
||||||
|
|
||||||
- name: Get dependencies, run test and static check
|
- name: Get dependencies, run test
|
||||||
run: |
|
run: |
|
||||||
# fetch python cross compile source files
|
# fetch python cross compile source files
|
||||||
mkdir -p bin/python/
|
mkdir -p bin/python/
|
||||||
|
@ -50,9 +48,6 @@ jobs:
|
||||||
cd ../../
|
cd ../../
|
||||||
|
|
||||||
go test ./...
|
go test ./...
|
||||||
go vet ./...
|
|
||||||
go install honnef.co/go/tools/cmd/staticcheck@latest
|
|
||||||
staticcheck -- $(go list ./...)
|
|
||||||
|
|
||||||
# init xgo
|
# init xgo
|
||||||
docker pull techknowlogick/xgo:latest
|
docker pull techknowlogick/xgo:latest
|
5
.gitignore
vendored
5
.gitignore
vendored
|
@ -12,7 +12,7 @@ bin/*
|
||||||
# Output of the go coverage tool, specifically when used with LiteIDE
|
# Output of the go coverage tool, specifically when used with LiteIDE
|
||||||
*.out
|
*.out
|
||||||
|
|
||||||
# dep
|
# go mod vendor
|
||||||
vendor
|
vendor
|
||||||
|
|
||||||
# GoLand
|
# GoLand
|
||||||
|
@ -20,3 +20,6 @@ vendor
|
||||||
|
|
||||||
# macOS file
|
# macOS file
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
|
||||||
|
# test suite
|
||||||
|
test/config/cache*
|
||||||
|
|
3
Makefile
3
Makefile
|
@ -76,6 +76,9 @@ all-arch: $(PLATFORM_LIST) $(WINDOWS_ARCH_LIST)
|
||||||
|
|
||||||
releases: $(gz_releases) $(zip_releases)
|
releases: $(gz_releases) $(zip_releases)
|
||||||
|
|
||||||
|
lint:
|
||||||
|
golangci-lint run --build-tags=build_local --disable-all -E govet -E gofumpt -E megacheck ./...
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -rf $(BINDIR)/
|
rm -rf $(BINDIR)/
|
||||||
mkdir -p $(BINDIR)
|
mkdir -p $(BINDIR)
|
||||||
|
|
|
@ -36,12 +36,24 @@ func (p *Proxy) Dial(metadata *C.Metadata) (C.Conn, error) {
|
||||||
// DialContext implements C.ProxyAdapter
|
// DialContext implements C.ProxyAdapter
|
||||||
func (p *Proxy) DialContext(ctx context.Context, metadata *C.Metadata) (C.Conn, error) {
|
func (p *Proxy) DialContext(ctx context.Context, metadata *C.Metadata) (C.Conn, error) {
|
||||||
conn, err := p.ProxyAdapter.DialContext(ctx, metadata)
|
conn, err := p.ProxyAdapter.DialContext(ctx, metadata)
|
||||||
if err != nil {
|
p.alive.Store(err == nil)
|
||||||
p.alive.Store(false)
|
|
||||||
}
|
|
||||||
return conn, err
|
return conn, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DialUDP implements C.ProxyAdapter
|
||||||
|
func (p *Proxy) DialUDP(metadata *C.Metadata) (C.PacketConn, error) {
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), C.DefaultUDPTimeout)
|
||||||
|
defer cancel()
|
||||||
|
return p.ListenPacketContext(ctx, metadata)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListenPacketContext implements C.ProxyAdapter
|
||||||
|
func (p *Proxy) ListenPacketContext(ctx context.Context, metadata *C.Metadata) (C.PacketConn, error) {
|
||||||
|
pc, err := p.ProxyAdapter.ListenPacketContext(ctx, metadata)
|
||||||
|
p.alive.Store(err == nil)
|
||||||
|
return pc, err
|
||||||
|
}
|
||||||
|
|
||||||
// DelayHistory implements C.Proxy
|
// DelayHistory implements C.Proxy
|
||||||
func (p *Proxy) DelayHistory() []C.DelayHistory {
|
func (p *Proxy) DelayHistory() []C.DelayHistory {
|
||||||
queue := p.history.Copy()
|
queue := p.history.Copy()
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package outbound
|
package outbound
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"net"
|
"net"
|
||||||
|
@ -30,8 +31,8 @@ func (b *Base) StreamConn(c net.Conn, metadata *C.Metadata) (net.Conn, error) {
|
||||||
return c, errors.New("no support")
|
return c, errors.New("no support")
|
||||||
}
|
}
|
||||||
|
|
||||||
// DialUDP implements C.ProxyAdapter
|
// ListenPacketContext implements C.ProxyAdapter
|
||||||
func (b *Base) DialUDP(metadata *C.Metadata) (C.PacketConn, error) {
|
func (b *Base) ListenPacketContext(ctx context.Context, metadata *C.Metadata) (C.PacketConn, error) {
|
||||||
return nil, errors.New("no support")
|
return nil, errors.New("no support")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,9 +22,9 @@ func (d *Direct) DialContext(ctx context.Context, metadata *C.Metadata) (C.Conn,
|
||||||
return NewConn(c, d), nil
|
return NewConn(c, d), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// DialUDP implements C.ProxyAdapter
|
// ListenPacketContext implements C.ProxyAdapter
|
||||||
func (d *Direct) DialUDP(metadata *C.Metadata) (C.PacketConn, error) {
|
func (d *Direct) ListenPacketContext(ctx context.Context, metadata *C.Metadata) (C.PacketConn, error) {
|
||||||
pc, err := dialer.ListenPacket(context.Background(), "udp", "")
|
pc, err := dialer.ListenPacket(ctx, "udp", "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,8 +19,8 @@ func (r *Reject) DialContext(ctx context.Context, metadata *C.Metadata) (C.Conn,
|
||||||
return NewConn(&NopConn{}, r), nil
|
return NewConn(&NopConn{}, r), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// DialUDP implements C.ProxyAdapter
|
// ListenPacketContext implements C.ProxyAdapter
|
||||||
func (r *Reject) DialUDP(metadata *C.Metadata) (C.PacketConn, error) {
|
func (r *Reject) ListenPacketContext(ctx context.Context, metadata *C.Metadata) (C.PacketConn, error) {
|
||||||
return nil, errors.New("match reject rule")
|
return nil, errors.New("match reject rule")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -87,9 +87,9 @@ func (ss *ShadowSocks) DialContext(ctx context.Context, metadata *C.Metadata) (_
|
||||||
return NewConn(c, ss), err
|
return NewConn(c, ss), err
|
||||||
}
|
}
|
||||||
|
|
||||||
// DialUDP implements C.ProxyAdapter
|
// ListenPacketContext implements C.ProxyAdapter
|
||||||
func (ss *ShadowSocks) DialUDP(metadata *C.Metadata) (C.PacketConn, error) {
|
func (ss *ShadowSocks) ListenPacketContext(ctx context.Context, metadata *C.Metadata) (C.PacketConn, error) {
|
||||||
pc, err := dialer.ListenPacket(context.Background(), "udp", "")
|
pc, err := dialer.ListenPacket(ctx, "udp", "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,9 +72,9 @@ func (ssr *ShadowSocksR) DialContext(ctx context.Context, metadata *C.Metadata)
|
||||||
return NewConn(c, ssr), err
|
return NewConn(c, ssr), err
|
||||||
}
|
}
|
||||||
|
|
||||||
// DialUDP implements C.ProxyAdapter
|
// ListenPacketContext implements C.ProxyAdapter
|
||||||
func (ssr *ShadowSocksR) DialUDP(metadata *C.Metadata) (C.PacketConn, error) {
|
func (ssr *ShadowSocksR) ListenPacketContext(ctx context.Context, metadata *C.Metadata) (C.PacketConn, error) {
|
||||||
pc, err := dialer.ListenPacket(context.Background(), "udp", "")
|
pc, err := dialer.ListenPacket(ctx, "udp", "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,6 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
|
||||||
"net"
|
"net"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
@ -77,10 +76,8 @@ func (ss *Socks5) DialContext(ctx context.Context, metadata *C.Metadata) (_ C.Co
|
||||||
return NewConn(c, ss), nil
|
return NewConn(c, ss), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// DialUDP implements C.ProxyAdapter
|
// ListenPacketContext implements C.ProxyAdapter
|
||||||
func (ss *Socks5) DialUDP(metadata *C.Metadata) (_ C.PacketConn, err error) {
|
func (ss *Socks5) ListenPacketContext(ctx context.Context, metadata *C.Metadata) (_ C.PacketConn, err error) {
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), C.DefaultTCPTimeout)
|
|
||||||
defer cancel()
|
|
||||||
c, err := dialer.DialContext(ctx, "tcp", ss.addr)
|
c, err := dialer.DialContext(ctx, "tcp", ss.addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = fmt.Errorf("%s connect error: %w", ss.addr, err)
|
err = fmt.Errorf("%s connect error: %w", ss.addr, err)
|
||||||
|
@ -110,13 +107,13 @@ func (ss *Socks5) DialUDP(metadata *C.Metadata) (_ C.PacketConn, err error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
pc, err := dialer.ListenPacket(context.Background(), "udp", "")
|
pc, err := dialer.ListenPacket(ctx, "udp", "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
io.Copy(ioutil.Discard, c)
|
io.Copy(io.Discard, c)
|
||||||
c.Close()
|
c.Close()
|
||||||
// A UDP association terminates when the TCP connection that the UDP
|
// A UDP association terminates when the TCP connection that the UDP
|
||||||
// ASSOCIATE request arrived on terminates. RFC1928
|
// ASSOCIATE request arrived on terminates. RFC1928
|
||||||
|
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"github.com/Dreamacro/clash/component/dialer"
|
"github.com/Dreamacro/clash/component/dialer"
|
||||||
|
@ -18,6 +19,7 @@ import (
|
||||||
type Trojan struct {
|
type Trojan struct {
|
||||||
*Base
|
*Base
|
||||||
instance *trojan.Trojan
|
instance *trojan.Trojan
|
||||||
|
option *TrojanOption
|
||||||
|
|
||||||
// for gun mux
|
// for gun mux
|
||||||
gunTLSConfig *tls.Config
|
gunTLSConfig *tls.Config
|
||||||
|
@ -36,6 +38,34 @@ type TrojanOption struct {
|
||||||
UDP bool `proxy:"udp,omitempty"`
|
UDP bool `proxy:"udp,omitempty"`
|
||||||
Network string `proxy:"network,omitempty"`
|
Network string `proxy:"network,omitempty"`
|
||||||
GrpcOpts GrpcOptions `proxy:"grpc-opts,omitempty"`
|
GrpcOpts GrpcOptions `proxy:"grpc-opts,omitempty"`
|
||||||
|
WSOpts WSOptions `proxy:"ws-opts,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Trojan) plainStream(c net.Conn) (net.Conn, error) {
|
||||||
|
if t.option.Network == "ws" {
|
||||||
|
host, port, _ := net.SplitHostPort(t.addr)
|
||||||
|
wsOpts := &trojan.WebsocketOption{
|
||||||
|
Host: host,
|
||||||
|
Port: port,
|
||||||
|
Path: t.option.WSOpts.Path,
|
||||||
|
}
|
||||||
|
|
||||||
|
if t.option.SNI != "" {
|
||||||
|
wsOpts.Host = t.option.SNI
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(t.option.WSOpts.Headers) != 0 {
|
||||||
|
header := http.Header{}
|
||||||
|
for key, value := range t.option.WSOpts.Headers {
|
||||||
|
header.Add(key, value)
|
||||||
|
}
|
||||||
|
wsOpts.Headers = header
|
||||||
|
}
|
||||||
|
|
||||||
|
return t.instance.StreamWebsocketConn(c, wsOpts)
|
||||||
|
}
|
||||||
|
|
||||||
|
return t.instance.StreamConn(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
// StreamConn implements C.ProxyAdapter
|
// StreamConn implements C.ProxyAdapter
|
||||||
|
@ -44,7 +74,7 @@ func (t *Trojan) StreamConn(c net.Conn, metadata *C.Metadata) (net.Conn, error)
|
||||||
if t.transport != nil {
|
if t.transport != nil {
|
||||||
c, err = gun.StreamGunWithConn(c, t.gunTLSConfig, t.gunConfig)
|
c, err = gun.StreamGunWithConn(c, t.gunTLSConfig, t.gunConfig)
|
||||||
} else {
|
} else {
|
||||||
c, err = t.instance.StreamConn(c)
|
c, err = t.plainStream(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -88,8 +118,8 @@ func (t *Trojan) DialContext(ctx context.Context, metadata *C.Metadata) (_ C.Con
|
||||||
return NewConn(c, t), err
|
return NewConn(c, t), err
|
||||||
}
|
}
|
||||||
|
|
||||||
// DialUDP implements C.ProxyAdapter
|
// ListenPacketContext implements C.ProxyAdapter
|
||||||
func (t *Trojan) DialUDP(metadata *C.Metadata) (_ C.PacketConn, err error) {
|
func (t *Trojan) ListenPacketContext(ctx context.Context, metadata *C.Metadata) (_ C.PacketConn, err error) {
|
||||||
var c net.Conn
|
var c net.Conn
|
||||||
|
|
||||||
// grpc transport
|
// grpc transport
|
||||||
|
@ -100,15 +130,13 @@ func (t *Trojan) DialUDP(metadata *C.Metadata) (_ C.PacketConn, err error) {
|
||||||
}
|
}
|
||||||
defer safeConnClose(c, err)
|
defer safeConnClose(c, err)
|
||||||
} else {
|
} else {
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), C.DefaultTCPTimeout)
|
|
||||||
defer cancel()
|
|
||||||
c, err = dialer.DialContext(ctx, "tcp", t.addr)
|
c, err = dialer.DialContext(ctx, "tcp", t.addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("%s connect error: %w", t.addr, err)
|
return nil, fmt.Errorf("%s connect error: %w", t.addr, err)
|
||||||
}
|
}
|
||||||
defer safeConnClose(c, err)
|
defer safeConnClose(c, err)
|
||||||
tcpKeepAlive(c)
|
tcpKeepAlive(c)
|
||||||
c, err = t.instance.StreamConn(c)
|
c, err = t.plainStream(c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("%s connect error: %w", t.addr, err)
|
return nil, fmt.Errorf("%s connect error: %w", t.addr, err)
|
||||||
}
|
}
|
||||||
|
@ -145,6 +173,7 @@ func NewTrojan(option TrojanOption) (*Trojan, error) {
|
||||||
udp: option.UDP,
|
udp: option.UDP,
|
||||||
},
|
},
|
||||||
instance: trojan.New(tOption),
|
instance: trojan.New(tOption),
|
||||||
|
option: &option,
|
||||||
}
|
}
|
||||||
|
|
||||||
if option.Network == "grpc" {
|
if option.Network == "grpc" {
|
||||||
|
@ -158,9 +187,9 @@ func NewTrojan(option TrojanOption) (*Trojan, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
tlsConfig := &tls.Config{
|
tlsConfig := &tls.Config{
|
||||||
NextProtos: option.ALPN,
|
NextProtos: option.ALPN,
|
||||||
MinVersion: tls.VersionTLS12,
|
MinVersion: tls.VersionTLS12,
|
||||||
//InsecureSkipVerify: tOption.SkipCertVerify,
|
InsecureSkipVerify: tOption.SkipCertVerify,
|
||||||
ServerName: tOption.ServerName,
|
ServerName: tOption.ServerName,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -79,8 +79,16 @@ func (v *Vless) StreamConn(c net.Conn, metadata *C.Metadata) (net.Conn, error) {
|
||||||
|
|
||||||
if v.option.TLS {
|
if v.option.TLS {
|
||||||
wsOpts.TLS = true
|
wsOpts.TLS = true
|
||||||
wsOpts.SkipCertVerify = v.option.SkipCertVerify
|
wsOpts.TLSConfig = &tls.Config{
|
||||||
wsOpts.ServerName = v.option.ServerName
|
ServerName: host,
|
||||||
|
InsecureSkipVerify: v.option.SkipCertVerify,
|
||||||
|
NextProtos: []string{"http/1.1"},
|
||||||
|
}
|
||||||
|
if v.option.ServerName != "" {
|
||||||
|
wsOpts.TLSConfig.ServerName = v.option.ServerName
|
||||||
|
} else if host := wsOpts.Headers.Get("Host"); host != "" {
|
||||||
|
wsOpts.TLSConfig.ServerName = host
|
||||||
|
}
|
||||||
}
|
}
|
||||||
c, err = vmess.StreamWebsocketConn(c, wsOpts)
|
c, err = vmess.StreamWebsocketConn(c, wsOpts)
|
||||||
case "http":
|
case "http":
|
||||||
|
|
|
@ -31,23 +31,25 @@ type Vmess struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type VmessOption struct {
|
type VmessOption struct {
|
||||||
Name string `proxy:"name"`
|
Name string `proxy:"name"`
|
||||||
Server string `proxy:"server"`
|
Server string `proxy:"server"`
|
||||||
Port int `proxy:"port"`
|
Port int `proxy:"port"`
|
||||||
UUID string `proxy:"uuid"`
|
UUID string `proxy:"uuid"`
|
||||||
AlterID int `proxy:"alterId"`
|
AlterID int `proxy:"alterId"`
|
||||||
Cipher string `proxy:"cipher"`
|
Cipher string `proxy:"cipher"`
|
||||||
TLS bool `proxy:"tls,omitempty"`
|
UDP bool `proxy:"udp,omitempty"`
|
||||||
UDP bool `proxy:"udp,omitempty"`
|
Network string `proxy:"network,omitempty"`
|
||||||
Network string `proxy:"network,omitempty"`
|
TLS bool `proxy:"tls,omitempty"`
|
||||||
HTTPOpts HTTPOptions `proxy:"http-opts,omitempty"`
|
SkipCertVerify bool `proxy:"skip-cert-verify,omitempty"`
|
||||||
HTTP2Opts HTTP2Options `proxy:"h2-opts,omitempty"`
|
ServerName string `proxy:"servername,omitempty"`
|
||||||
GrpcOpts GrpcOptions `proxy:"grpc-opts,omitempty"`
|
HTTPOpts HTTPOptions `proxy:"http-opts,omitempty"`
|
||||||
WSOpts WSOptions `proxy:"ws-opts,omitempty"`
|
HTTP2Opts HTTP2Options `proxy:"h2-opts,omitempty"`
|
||||||
WSPath string `proxy:"ws-path,omitempty"`
|
GrpcOpts GrpcOptions `proxy:"grpc-opts,omitempty"`
|
||||||
WSHeaders map[string]string `proxy:"ws-headers,omitempty"`
|
WSOpts WSOptions `proxy:"ws-opts,omitempty"`
|
||||||
SkipCertVerify bool `proxy:"skip-cert-verify,omitempty"`
|
|
||||||
ServerName string `proxy:"servername,omitempty"`
|
// TODO: remove these until 2022
|
||||||
|
WSHeaders map[string]string `proxy:"ws-headers,omitempty"`
|
||||||
|
WSPath string `proxy:"ws-path,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type HTTPOptions struct {
|
type HTTPOptions struct {
|
||||||
|
@ -103,8 +105,16 @@ func (v *Vmess) StreamConn(c net.Conn, metadata *C.Metadata) (net.Conn, error) {
|
||||||
|
|
||||||
if v.option.TLS {
|
if v.option.TLS {
|
||||||
wsOpts.TLS = true
|
wsOpts.TLS = true
|
||||||
wsOpts.SkipCertVerify = v.option.SkipCertVerify
|
wsOpts.TLSConfig = &tls.Config{
|
||||||
wsOpts.ServerName = v.option.ServerName
|
ServerName: host,
|
||||||
|
InsecureSkipVerify: v.option.SkipCertVerify,
|
||||||
|
NextProtos: []string{"http/1.1"},
|
||||||
|
}
|
||||||
|
if v.option.ServerName != "" {
|
||||||
|
wsOpts.TLSConfig.ServerName = v.option.ServerName
|
||||||
|
} else if host := wsOpts.Headers.Get("Host"); host != "" {
|
||||||
|
wsOpts.TLSConfig.ServerName = host
|
||||||
|
}
|
||||||
}
|
}
|
||||||
c, err = vmess.StreamWebsocketConn(c, wsOpts)
|
c, err = vmess.StreamWebsocketConn(c, wsOpts)
|
||||||
case "http":
|
case "http":
|
||||||
|
@ -213,8 +223,8 @@ func (v *Vmess) DialContext(ctx context.Context, metadata *C.Metadata) (_ C.Conn
|
||||||
return NewConn(c, v), err
|
return NewConn(c, v), err
|
||||||
}
|
}
|
||||||
|
|
||||||
// DialUDP implements C.ProxyAdapter
|
// ListenPacketContext implements C.ProxyAdapter
|
||||||
func (v *Vmess) DialUDP(metadata *C.Metadata) (_ C.PacketConn, err error) {
|
func (v *Vmess) ListenPacketContext(ctx context.Context, metadata *C.Metadata) (_ C.PacketConn, err error) {
|
||||||
// vmess use stream-oriented udp with a special address, so we needs a net.UDPAddr
|
// vmess use stream-oriented udp with a special address, so we needs a net.UDPAddr
|
||||||
if !metadata.Resolved() {
|
if !metadata.Resolved() {
|
||||||
ip, err := resolver.ResolveIP(metadata.Host)
|
ip, err := resolver.ResolveIP(metadata.Host)
|
||||||
|
@ -235,8 +245,6 @@ func (v *Vmess) DialUDP(metadata *C.Metadata) (_ C.PacketConn, err error) {
|
||||||
|
|
||||||
c, err = v.client.StreamConn(c, parseVmessAddr(metadata))
|
c, err = v.client.StreamConn(c, parseVmessAddr(metadata))
|
||||||
} else {
|
} else {
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), C.DefaultTCPTimeout)
|
|
||||||
defer cancel()
|
|
||||||
c, err = dialer.DialContext(ctx, "tcp", v.addr)
|
c, err = dialer.DialContext(ctx, "tcp", v.addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("%s connect error: %s", v.addr, err.Error())
|
return nil, fmt.Errorf("%s connect error: %s", v.addr, err.Error())
|
||||||
|
|
|
@ -32,10 +32,10 @@ func (f *Fallback) DialContext(ctx context.Context, metadata *C.Metadata) (C.Con
|
||||||
return c, err
|
return c, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// DialUDP implements C.ProxyAdapter
|
// ListenPacketContext implements C.ProxyAdapter
|
||||||
func (f *Fallback) DialUDP(metadata *C.Metadata) (C.PacketConn, error) {
|
func (f *Fallback) ListenPacketContext(ctx context.Context, metadata *C.Metadata) (C.PacketConn, error) {
|
||||||
proxy := f.findAliveProxy(true)
|
proxy := f.findAliveProxy(true)
|
||||||
pc, err := proxy.DialUDP(metadata)
|
pc, err := proxy.ListenPacketContext(ctx, metadata)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
pc.AppendToChains(f)
|
pc.AppendToChains(f)
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,8 +82,8 @@ func (lb *LoadBalance) DialContext(ctx context.Context, metadata *C.Metadata) (c
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// DialUDP implements C.ProxyAdapter
|
// ListenPacketContext implements C.ProxyAdapter
|
||||||
func (lb *LoadBalance) DialUDP(metadata *C.Metadata) (pc C.PacketConn, err error) {
|
func (lb *LoadBalance) ListenPacketContext(ctx context.Context, metadata *C.Metadata) (pc C.PacketConn, err error) {
|
||||||
defer func() {
|
defer func() {
|
||||||
if err == nil {
|
if err == nil {
|
||||||
pc.AppendToChains(lb)
|
pc.AppendToChains(lb)
|
||||||
|
@ -91,8 +91,7 @@ func (lb *LoadBalance) DialUDP(metadata *C.Metadata) (pc C.PacketConn, err error
|
||||||
}()
|
}()
|
||||||
|
|
||||||
proxy := lb.Unwrap(metadata)
|
proxy := lb.Unwrap(metadata)
|
||||||
|
return proxy.ListenPacketContext(ctx, metadata)
|
||||||
return proxy.DialUDP(metadata)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SupportUDP implements C.ProxyAdapter
|
// SupportUDP implements C.ProxyAdapter
|
||||||
|
|
|
@ -28,9 +28,9 @@ func (s *Selector) DialContext(ctx context.Context, metadata *C.Metadata) (C.Con
|
||||||
return c, err
|
return c, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// DialUDP implements C.ProxyAdapter
|
// ListenPacketContext implements C.ProxyAdapter
|
||||||
func (s *Selector) DialUDP(metadata *C.Metadata) (C.PacketConn, error) {
|
func (s *Selector) ListenPacketContext(ctx context.Context, metadata *C.Metadata) (C.PacketConn, error) {
|
||||||
pc, err := s.selectedProxy(true).DialUDP(metadata)
|
pc, err := s.selectedProxy(true).ListenPacketContext(ctx, metadata)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
pc.AppendToChains(s)
|
pc.AppendToChains(s)
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,9 +42,9 @@ func (u *URLTest) DialContext(ctx context.Context, metadata *C.Metadata) (c C.Co
|
||||||
return c, err
|
return c, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// DialUDP implements C.ProxyAdapter
|
// ListenPacketContext implements C.ProxyAdapter
|
||||||
func (u *URLTest) DialUDP(metadata *C.Metadata) (C.PacketConn, error) {
|
func (u *URLTest) ListenPacketContext(ctx context.Context, metadata *C.Metadata) (C.PacketConn, error) {
|
||||||
pc, err := u.fast(true).DialUDP(metadata)
|
pc, err := u.fast(true).ListenPacketContext(ctx, metadata)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
pc.AppendToChains(u)
|
pc.AppendToChains(u)
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,6 @@ package provider
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"crypto/md5"
|
"crypto/md5"
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"time"
|
"time"
|
||||||
|
@ -13,8 +12,8 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
fileMode os.FileMode = 0666
|
fileMode os.FileMode = 0o666
|
||||||
dirMode os.FileMode = 0755
|
dirMode os.FileMode = 0o755
|
||||||
)
|
)
|
||||||
|
|
||||||
type parser = func([]byte) (interface{}, error)
|
type parser = func([]byte) (interface{}, error)
|
||||||
|
@ -45,7 +44,7 @@ func (f *fetcher) Initial() (interface{}, error) {
|
||||||
isLocal bool
|
isLocal bool
|
||||||
)
|
)
|
||||||
if stat, fErr := os.Stat(f.vehicle.Path()); fErr == nil {
|
if stat, fErr := os.Stat(f.vehicle.Path()); fErr == nil {
|
||||||
buf, err = ioutil.ReadFile(f.vehicle.Path())
|
buf, err = os.ReadFile(f.vehicle.Path())
|
||||||
modTime := stat.ModTime()
|
modTime := stat.ModTime()
|
||||||
f.updatedAt = &modTime
|
f.updatedAt = &modTime
|
||||||
isLocal = true
|
isLocal = true
|
||||||
|
@ -165,7 +164,7 @@ func safeWrite(path string, buf []byte) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ioutil.WriteFile(path, buf, fileMode)
|
return os.WriteFile(path, buf, fileMode)
|
||||||
}
|
}
|
||||||
|
|
||||||
func newFetcher(name string, interval time.Duration, vehicle types.Vehicle, parser parser, onUpdate func(interface{})) *fetcher {
|
func newFetcher(name string, interval time.Duration, vehicle types.Vehicle, parser parser, onUpdate func(interface{})) *fetcher {
|
||||||
|
|
|
@ -10,9 +10,7 @@ import (
|
||||||
types "github.com/Dreamacro/clash/constant/provider"
|
types "github.com/Dreamacro/clash/constant/provider"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var errVehicleType = errors.New("unsupport vehicle type")
|
||||||
errVehicleType = errors.New("unsupport vehicle type")
|
|
||||||
)
|
|
||||||
|
|
||||||
type healthCheckSchema struct {
|
type healthCheckSchema struct {
|
||||||
Enable bool `provider:"enable"`
|
Enable bool `provider:"enable"`
|
||||||
|
|
|
@ -2,10 +2,11 @@ package provider
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"io/ioutil"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
"os"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/Dreamacro/clash/component/dialer"
|
"github.com/Dreamacro/clash/component/dialer"
|
||||||
|
@ -25,7 +26,7 @@ func (f *FileVehicle) Path() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *FileVehicle) Read() ([]byte, error) {
|
func (f *FileVehicle) Read() ([]byte, error) {
|
||||||
return ioutil.ReadFile(f.path)
|
return os.ReadFile(f.path)
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewFileVehicle(path string) *FileVehicle {
|
func NewFileVehicle(path string) *FileVehicle {
|
||||||
|
@ -84,7 +85,7 @@ func (h *HTTPVehicle) Read() ([]byte, error) {
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
buf, err := ioutil.ReadAll(resp.Body)
|
buf, err := io.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
1
common/cache/lrucache_test.go
vendored
1
common/cache/lrucache_test.go
vendored
|
@ -149,7 +149,6 @@ func TestSetWithExpire(t *testing.T) {
|
||||||
assert.Equal(t, nil, res)
|
assert.Equal(t, nil, res)
|
||||||
assert.Equal(t, time.Time{}, expires)
|
assert.Equal(t, time.Time{}, expires)
|
||||||
assert.Equal(t, false, exist)
|
assert.Equal(t, false, exist)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestStale(t *testing.T) {
|
func TestStale(t *testing.T) {
|
||||||
|
|
|
@ -67,7 +67,6 @@ func (d *digest32) bmix(p []byte) (tail []byte) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *digest32) Sum32() (h1 uint32) {
|
func (d *digest32) Sum32() (h1 uint32) {
|
||||||
|
|
||||||
h1 = d.h1
|
h1 = d.h1
|
||||||
|
|
||||||
var k1 uint32
|
var k1 uint32
|
||||||
|
|
|
@ -38,7 +38,7 @@ func TestObservable_MultiSubscribe(t *testing.T) {
|
||||||
src := NewObservable(iter)
|
src := NewObservable(iter)
|
||||||
ch1, _ := src.Subscribe()
|
ch1, _ := src.Subscribe()
|
||||||
ch2, _ := src.Subscribe()
|
ch2, _ := src.Subscribe()
|
||||||
var count = atomic.NewInt32(0)
|
count := atomic.NewInt32(0)
|
||||||
|
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
wg.Add(2)
|
wg.Add(2)
|
||||||
|
|
|
@ -53,6 +53,7 @@ func (alloc *Allocator) Put(buf []byte) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
//lint:ignore SA6002 ignore temporarily
|
//lint:ignore SA6002 ignore temporarily
|
||||||
|
//nolint
|
||||||
alloc.buffers[bits].Put(buf)
|
alloc.buffers[bits].Put(buf)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@ import (
|
||||||
func TestBasic(t *testing.T) {
|
func TestBasic(t *testing.T) {
|
||||||
single := NewSingle(time.Millisecond * 30)
|
single := NewSingle(time.Millisecond * 30)
|
||||||
foo := 0
|
foo := 0
|
||||||
var shardCount = atomic.NewInt32(0)
|
shardCount := atomic.NewInt32(0)
|
||||||
call := func() (interface{}, error) {
|
call := func() (interface{}, error) {
|
||||||
foo++
|
foo++
|
||||||
time.Sleep(time.Millisecond * 5)
|
time.Sleep(time.Millisecond * 5)
|
||||||
|
|
|
@ -5,8 +5,10 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
var decoder = NewDecoder(Option{TagName: "test"})
|
var (
|
||||||
var weakTypeDecoder = NewDecoder(Option{TagName: "test", WeaklyTypedInput: true})
|
decoder = NewDecoder(Option{TagName: "test"})
|
||||||
|
weakTypeDecoder = NewDecoder(Option{TagName: "test", WeaklyTypedInput: true})
|
||||||
|
)
|
||||||
|
|
||||||
type Baz struct {
|
type Baz struct {
|
||||||
Foo int `test:"foo"`
|
Foo int `test:"foo"`
|
||||||
|
|
|
@ -3,9 +3,10 @@ package dhcp
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"math/rand"
|
|
||||||
"net"
|
"net"
|
||||||
|
|
||||||
|
"github.com/Dreamacro/clash/component/iface"
|
||||||
|
|
||||||
"github.com/insomniacslk/dhcp/dhcpv4"
|
"github.com/insomniacslk/dhcp/dhcpv4"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -23,7 +24,12 @@ func ResolveDNSFromDHCP(context context.Context, ifaceName string) ([]net.IP, er
|
||||||
|
|
||||||
result := make(chan []net.IP, 1)
|
result := make(chan []net.IP, 1)
|
||||||
|
|
||||||
discovery, err := dhcpv4.NewDiscovery(randomHardware(), dhcpv4.WithBroadcast(true), dhcpv4.WithRequestedOptions(dhcpv4.OptionDomainNameServer))
|
ifaceObj, err := iface.ResolveInterface(ifaceName)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
discovery, err := dhcpv4.NewDiscovery(ifaceObj.HardwareAddr, dhcpv4.WithBroadcast(true), dhcpv4.WithRequestedOptions(dhcpv4.OptionDomainNameServer))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -80,15 +86,3 @@ func receiveOffer(conn net.PacketConn, id dhcpv4.TransactionID, result chan<- []
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func randomHardware() net.HardwareAddr {
|
|
||||||
addr := make(net.HardwareAddr, 6)
|
|
||||||
|
|
||||||
addr[0] = 0xff
|
|
||||||
|
|
||||||
for i := 1; i < len(addr); i++ {
|
|
||||||
addr[i] = byte(rand.Intn(254) + 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
return addr
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
package dialer
|
package dialer
|
||||||
|
|
||||||
var (
|
var DefaultOptions []Option
|
||||||
DefaultOptions []Option
|
|
||||||
)
|
|
||||||
|
|
||||||
type config struct {
|
type config struct {
|
||||||
skipDefault bool
|
skipDefault bool
|
||||||
|
|
49
component/fakeip/cachefile.go
Normal file
49
component/fakeip/cachefile.go
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
package fakeip
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
|
||||||
|
"github.com/Dreamacro/clash/component/profile/cachefile"
|
||||||
|
)
|
||||||
|
|
||||||
|
type cachefileStore struct {
|
||||||
|
cache *cachefile.CacheFile
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetByHost implements store.GetByHost
|
||||||
|
func (c *cachefileStore) GetByHost(host string) (net.IP, bool) {
|
||||||
|
elm := c.cache.GetFakeip([]byte(host))
|
||||||
|
if elm == nil {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
return net.IP(elm), true
|
||||||
|
}
|
||||||
|
|
||||||
|
// PutByHost implements store.PutByHost
|
||||||
|
func (c *cachefileStore) PutByHost(host string, ip net.IP) {
|
||||||
|
c.cache.PutFakeip([]byte(host), ip)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetByIP implements store.GetByIP
|
||||||
|
func (c *cachefileStore) GetByIP(ip net.IP) (string, bool) {
|
||||||
|
elm := c.cache.GetFakeip(ip.To4())
|
||||||
|
if elm == nil {
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
return string(elm), true
|
||||||
|
}
|
||||||
|
|
||||||
|
// PutByIP implements store.PutByIP
|
||||||
|
func (c *cachefileStore) PutByIP(ip net.IP, host string) {
|
||||||
|
c.cache.PutFakeip(ip.To4(), []byte(host))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Exist implements store.Exist
|
||||||
|
func (c *cachefileStore) Exist(ip net.IP) bool {
|
||||||
|
_, exist := c.GetByIP(ip)
|
||||||
|
return exist
|
||||||
|
}
|
||||||
|
|
||||||
|
// CloneTo implements store.CloneTo
|
||||||
|
// already persistence
|
||||||
|
func (c *cachefileStore) CloneTo(store store) {}
|
60
component/fakeip/memory.go
Normal file
60
component/fakeip/memory.go
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
package fakeip
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
|
||||||
|
"github.com/Dreamacro/clash/common/cache"
|
||||||
|
)
|
||||||
|
|
||||||
|
type memoryStore struct {
|
||||||
|
cache *cache.LruCache
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetByHost implements store.GetByHost
|
||||||
|
func (m *memoryStore) GetByHost(host string) (net.IP, bool) {
|
||||||
|
if elm, exist := m.cache.Get(host); exist {
|
||||||
|
ip := elm.(net.IP)
|
||||||
|
|
||||||
|
// ensure ip --> host on head of linked list
|
||||||
|
m.cache.Get(ipToUint(ip.To4()))
|
||||||
|
return ip, true
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
|
||||||
|
// PutByHost implements store.PutByHost
|
||||||
|
func (m *memoryStore) PutByHost(host string, ip net.IP) {
|
||||||
|
m.cache.Set(host, ip)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetByIP implements store.GetByIP
|
||||||
|
func (m *memoryStore) GetByIP(ip net.IP) (string, bool) {
|
||||||
|
if elm, exist := m.cache.Get(ipToUint(ip.To4())); exist {
|
||||||
|
host := elm.(string)
|
||||||
|
|
||||||
|
// ensure host --> ip on head of linked list
|
||||||
|
m.cache.Get(host)
|
||||||
|
return host, true
|
||||||
|
}
|
||||||
|
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
|
||||||
|
// PutByIP implements store.PutByIP
|
||||||
|
func (m *memoryStore) PutByIP(ip net.IP, host string) {
|
||||||
|
m.cache.Set(ipToUint(ip.To4()), host)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Exist implements store.Exist
|
||||||
|
func (m *memoryStore) Exist(ip net.IP) bool {
|
||||||
|
return m.cache.Exist(ipToUint(ip.To4()))
|
||||||
|
}
|
||||||
|
|
||||||
|
// CloneTo implements store.CloneTo
|
||||||
|
// only for memoryStore to memoryStore
|
||||||
|
func (m *memoryStore) CloneTo(store store) {
|
||||||
|
if ms, ok := store.(*memoryStore); ok {
|
||||||
|
m.cache.CloneTo(ms.cache)
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,9 +6,19 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/Dreamacro/clash/common/cache"
|
"github.com/Dreamacro/clash/common/cache"
|
||||||
|
"github.com/Dreamacro/clash/component/profile/cachefile"
|
||||||
"github.com/Dreamacro/clash/component/trie"
|
"github.com/Dreamacro/clash/component/trie"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type store interface {
|
||||||
|
GetByHost(host string) (net.IP, bool)
|
||||||
|
PutByHost(host string, ip net.IP)
|
||||||
|
GetByIP(ip net.IP) (string, bool)
|
||||||
|
PutByIP(ip net.IP, host string)
|
||||||
|
Exist(ip net.IP) bool
|
||||||
|
CloneTo(store)
|
||||||
|
}
|
||||||
|
|
||||||
// Pool is a implementation about fake ip generator without storage
|
// Pool is a implementation about fake ip generator without storage
|
||||||
type Pool struct {
|
type Pool struct {
|
||||||
max uint32
|
max uint32
|
||||||
|
@ -18,25 +28,19 @@ type Pool struct {
|
||||||
mux sync.Mutex
|
mux sync.Mutex
|
||||||
host *trie.DomainTrie
|
host *trie.DomainTrie
|
||||||
ipnet *net.IPNet
|
ipnet *net.IPNet
|
||||||
cache *cache.LruCache
|
store store
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lookup return a fake ip with host
|
// Lookup return a fake ip with host
|
||||||
func (p *Pool) Lookup(host string) net.IP {
|
func (p *Pool) Lookup(host string) net.IP {
|
||||||
p.mux.Lock()
|
p.mux.Lock()
|
||||||
defer p.mux.Unlock()
|
defer p.mux.Unlock()
|
||||||
if elm, exist := p.cache.Get(host); exist {
|
if ip, exist := p.store.GetByHost(host); exist {
|
||||||
ip := elm.(net.IP)
|
|
||||||
|
|
||||||
// ensure ip --> host on head of linked list
|
|
||||||
n := ipToUint(ip.To4())
|
|
||||||
offset := n - p.min + 1
|
|
||||||
p.cache.Get(offset)
|
|
||||||
return ip
|
return ip
|
||||||
}
|
}
|
||||||
|
|
||||||
ip := p.get(host)
|
ip := p.get(host)
|
||||||
p.cache.Set(host, ip)
|
p.store.PutByHost(host, ip)
|
||||||
return ip
|
return ip
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,22 +53,11 @@ func (p *Pool) LookBack(ip net.IP) (string, bool) {
|
||||||
return "", false
|
return "", false
|
||||||
}
|
}
|
||||||
|
|
||||||
n := ipToUint(ip.To4())
|
return p.store.GetByIP(ip)
|
||||||
offset := n - p.min + 1
|
|
||||||
|
|
||||||
if elm, exist := p.cache.Get(offset); exist {
|
|
||||||
host := elm.(string)
|
|
||||||
|
|
||||||
// ensure host --> ip on head of linked list
|
|
||||||
p.cache.Get(host)
|
|
||||||
return host, true
|
|
||||||
}
|
|
||||||
|
|
||||||
return "", false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// LookupHost return if domain in host
|
// ShouldSkipped return if domain should be skipped
|
||||||
func (p *Pool) LookupHost(domain string) bool {
|
func (p *Pool) ShouldSkipped(domain string) bool {
|
||||||
if p.host == nil {
|
if p.host == nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
@ -80,9 +73,7 @@ func (p *Pool) Exist(ip net.IP) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
n := ipToUint(ip.To4())
|
return p.store.Exist(ip)
|
||||||
offset := n - p.min + 1
|
|
||||||
return p.cache.Exist(offset)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gateway return gateway ip
|
// Gateway return gateway ip
|
||||||
|
@ -95,9 +86,9 @@ func (p *Pool) IPNet() *net.IPNet {
|
||||||
return p.ipnet
|
return p.ipnet
|
||||||
}
|
}
|
||||||
|
|
||||||
// PatchFrom clone cache from old pool
|
// CloneFrom clone cache from old pool
|
||||||
func (p *Pool) PatchFrom(o *Pool) {
|
func (p *Pool) CloneFrom(o *Pool) {
|
||||||
o.cache.CloneTo(p.cache)
|
o.store.CloneTo(p.store)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Pool) get(host string) net.IP {
|
func (p *Pool) get(host string) net.IP {
|
||||||
|
@ -109,12 +100,13 @@ func (p *Pool) get(host string) net.IP {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
if !p.cache.Exist(p.offset) {
|
ip := uintToIP(p.min + p.offset - 1)
|
||||||
|
if !p.store.Exist(ip) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ip := uintToIP(p.min + p.offset - 1)
|
ip := uintToIP(p.min + p.offset - 1)
|
||||||
p.cache.Set(p.offset, host)
|
p.store.PutByIP(ip, host)
|
||||||
return ip
|
return ip
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,11 +122,24 @@ func uintToIP(v uint32) net.IP {
|
||||||
return net.IP{byte(v >> 24), byte(v >> 16), byte(v >> 8), byte(v)}
|
return net.IP{byte(v >> 24), byte(v >> 16), byte(v >> 8), byte(v)}
|
||||||
}
|
}
|
||||||
|
|
||||||
// New return Pool instance
|
type Options struct {
|
||||||
func New(ipnet *net.IPNet, size int, host *trie.DomainTrie) (*Pool, error) {
|
IPNet *net.IPNet
|
||||||
min := ipToUint(ipnet.IP) + 2
|
Host *trie.DomainTrie
|
||||||
|
|
||||||
ones, bits := ipnet.Mask.Size()
|
// Size sets the maximum number of entries in memory
|
||||||
|
// and does not work if Persistence is true
|
||||||
|
Size int
|
||||||
|
|
||||||
|
// Persistence will save the data to disk.
|
||||||
|
// Size will not work and record will be fully stored.
|
||||||
|
Persistence bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// New return Pool instance
|
||||||
|
func New(options Options) (*Pool, error) {
|
||||||
|
min := ipToUint(options.IPNet.IP) + 2
|
||||||
|
|
||||||
|
ones, bits := options.IPNet.Mask.Size()
|
||||||
total := 1<<uint(bits-ones) - 2
|
total := 1<<uint(bits-ones) - 2
|
||||||
|
|
||||||
if total <= 0 {
|
if total <= 0 {
|
||||||
|
@ -142,12 +147,22 @@ func New(ipnet *net.IPNet, size int, host *trie.DomainTrie) (*Pool, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
max := min + uint32(total) - 1
|
max := min + uint32(total) - 1
|
||||||
return &Pool{
|
pool := &Pool{
|
||||||
min: min,
|
min: min,
|
||||||
max: max,
|
max: max,
|
||||||
gateway: min - 1,
|
gateway: min - 1,
|
||||||
host: host,
|
host: options.Host,
|
||||||
ipnet: ipnet,
|
ipnet: options.IPNet,
|
||||||
cache: cache.NewLRUCache(cache.WithSize(size * 2)),
|
}
|
||||||
}, nil
|
if options.Persistence {
|
||||||
|
pool.store = &cachefileStore{
|
||||||
|
cache: cachefile.Cache(),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
pool.store = &memoryStore{
|
||||||
|
cache: cache.NewLRUCache(cache.WithSize(options.Size * 2)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return pool, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,38 +2,118 @@ package fakeip
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net"
|
"net"
|
||||||
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/Dreamacro/clash/component/profile/cachefile"
|
||||||
|
"github.com/Dreamacro/clash/component/trie"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"go.etcd.io/bbolt"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func createPools(options Options) ([]*Pool, string, error) {
|
||||||
|
pool, err := New(options)
|
||||||
|
if err != nil {
|
||||||
|
return nil, "", err
|
||||||
|
}
|
||||||
|
filePool, tempfile, err := createCachefileStore(options)
|
||||||
|
if err != nil {
|
||||||
|
return nil, "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return []*Pool{pool, filePool}, tempfile, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func createCachefileStore(options Options) (*Pool, string, error) {
|
||||||
|
pool, err := New(options)
|
||||||
|
if err != nil {
|
||||||
|
return nil, "", err
|
||||||
|
}
|
||||||
|
f, err := os.CreateTemp("", "clash")
|
||||||
|
if err != nil {
|
||||||
|
return nil, "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
db, err := bbolt.Open(f.Name(), 0o666, &bbolt.Options{Timeout: time.Second})
|
||||||
|
if err != nil {
|
||||||
|
return nil, "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
pool.store = &cachefileStore{
|
||||||
|
cache: &cachefile.CacheFile{DB: db},
|
||||||
|
}
|
||||||
|
return pool, f.Name(), nil
|
||||||
|
}
|
||||||
|
|
||||||
func TestPool_Basic(t *testing.T) {
|
func TestPool_Basic(t *testing.T) {
|
||||||
_, ipnet, _ := net.ParseCIDR("192.168.0.1/29")
|
_, ipnet, _ := net.ParseCIDR("192.168.0.1/29")
|
||||||
pool, _ := New(ipnet, 10, nil)
|
pools, tempfile, err := createPools(Options{
|
||||||
|
IPNet: ipnet,
|
||||||
|
Size: 10,
|
||||||
|
})
|
||||||
|
assert.Nil(t, err)
|
||||||
|
defer os.Remove(tempfile)
|
||||||
|
|
||||||
first := pool.Lookup("foo.com")
|
for _, pool := range pools {
|
||||||
last := pool.Lookup("bar.com")
|
first := pool.Lookup("foo.com")
|
||||||
bar, exist := pool.LookBack(last)
|
last := pool.Lookup("bar.com")
|
||||||
|
bar, exist := pool.LookBack(last)
|
||||||
|
|
||||||
assert.True(t, first.Equal(net.IP{192, 168, 0, 2}))
|
assert.True(t, first.Equal(net.IP{192, 168, 0, 2}))
|
||||||
assert.True(t, last.Equal(net.IP{192, 168, 0, 3}))
|
assert.Equal(t, pool.Lookup("foo.com"), net.IP{192, 168, 0, 2})
|
||||||
assert.True(t, exist)
|
assert.True(t, last.Equal(net.IP{192, 168, 0, 3}))
|
||||||
assert.Equal(t, bar, "bar.com")
|
assert.True(t, exist)
|
||||||
|
assert.Equal(t, bar, "bar.com")
|
||||||
|
assert.Equal(t, pool.Gateway(), net.IP{192, 168, 0, 1})
|
||||||
|
assert.Equal(t, pool.IPNet().String(), ipnet.String())
|
||||||
|
assert.True(t, pool.Exist(net.IP{192, 168, 0, 3}))
|
||||||
|
assert.False(t, pool.Exist(net.IP{192, 168, 0, 4}))
|
||||||
|
assert.False(t, pool.Exist(net.ParseIP("::1")))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPool_Cycle(t *testing.T) {
|
func TestPool_CycleUsed(t *testing.T) {
|
||||||
_, ipnet, _ := net.ParseCIDR("192.168.0.1/30")
|
_, ipnet, _ := net.ParseCIDR("192.168.0.1/30")
|
||||||
pool, _ := New(ipnet, 10, nil)
|
pools, tempfile, err := createPools(Options{
|
||||||
|
IPNet: ipnet,
|
||||||
|
Size: 10,
|
||||||
|
})
|
||||||
|
assert.Nil(t, err)
|
||||||
|
defer os.Remove(tempfile)
|
||||||
|
|
||||||
first := pool.Lookup("foo.com")
|
for _, pool := range pools {
|
||||||
same := pool.Lookup("baz.com")
|
first := pool.Lookup("foo.com")
|
||||||
|
same := pool.Lookup("baz.com")
|
||||||
|
assert.True(t, first.Equal(same))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
assert.True(t, first.Equal(same))
|
func TestPool_Skip(t *testing.T) {
|
||||||
|
_, ipnet, _ := net.ParseCIDR("192.168.0.1/30")
|
||||||
|
tree := trie.New()
|
||||||
|
tree.Insert("example.com", tree)
|
||||||
|
pools, tempfile, err := createPools(Options{
|
||||||
|
IPNet: ipnet,
|
||||||
|
Size: 10,
|
||||||
|
Host: tree,
|
||||||
|
})
|
||||||
|
assert.Nil(t, err)
|
||||||
|
defer os.Remove(tempfile)
|
||||||
|
|
||||||
|
for _, pool := range pools {
|
||||||
|
assert.True(t, pool.ShouldSkipped("example.com"))
|
||||||
|
assert.False(t, pool.ShouldSkipped("foo.com"))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPool_MaxCacheSize(t *testing.T) {
|
func TestPool_MaxCacheSize(t *testing.T) {
|
||||||
_, ipnet, _ := net.ParseCIDR("192.168.0.1/24")
|
_, ipnet, _ := net.ParseCIDR("192.168.0.1/24")
|
||||||
pool, _ := New(ipnet, 2, nil)
|
pool, _ := New(Options{
|
||||||
|
IPNet: ipnet,
|
||||||
|
Size: 2,
|
||||||
|
})
|
||||||
|
|
||||||
first := pool.Lookup("foo.com")
|
first := pool.Lookup("foo.com")
|
||||||
pool.Lookup("bar.com")
|
pool.Lookup("bar.com")
|
||||||
|
@ -45,7 +125,10 @@ func TestPool_MaxCacheSize(t *testing.T) {
|
||||||
|
|
||||||
func TestPool_DoubleMapping(t *testing.T) {
|
func TestPool_DoubleMapping(t *testing.T) {
|
||||||
_, ipnet, _ := net.ParseCIDR("192.168.0.1/24")
|
_, ipnet, _ := net.ParseCIDR("192.168.0.1/24")
|
||||||
pool, _ := New(ipnet, 2, nil)
|
pool, _ := New(Options{
|
||||||
|
IPNet: ipnet,
|
||||||
|
Size: 2,
|
||||||
|
})
|
||||||
|
|
||||||
// fill cache
|
// fill cache
|
||||||
fooIP := pool.Lookup("foo.com")
|
fooIP := pool.Lookup("foo.com")
|
||||||
|
@ -70,9 +153,35 @@ func TestPool_DoubleMapping(t *testing.T) {
|
||||||
assert.False(t, bazIP.Equal(newBazIP))
|
assert.False(t, bazIP.Equal(newBazIP))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestPool_Clone(t *testing.T) {
|
||||||
|
_, ipnet, _ := net.ParseCIDR("192.168.0.1/24")
|
||||||
|
pool, _ := New(Options{
|
||||||
|
IPNet: ipnet,
|
||||||
|
Size: 2,
|
||||||
|
})
|
||||||
|
|
||||||
|
first := pool.Lookup("foo.com")
|
||||||
|
last := pool.Lookup("bar.com")
|
||||||
|
assert.True(t, first.Equal(net.IP{192, 168, 0, 2}))
|
||||||
|
assert.True(t, last.Equal(net.IP{192, 168, 0, 3}))
|
||||||
|
|
||||||
|
newPool, _ := New(Options{
|
||||||
|
IPNet: ipnet,
|
||||||
|
Size: 2,
|
||||||
|
})
|
||||||
|
newPool.CloneFrom(pool)
|
||||||
|
_, firstExist := newPool.LookBack(first)
|
||||||
|
_, lastExist := newPool.LookBack(last)
|
||||||
|
assert.True(t, firstExist)
|
||||||
|
assert.True(t, lastExist)
|
||||||
|
}
|
||||||
|
|
||||||
func TestPool_Error(t *testing.T) {
|
func TestPool_Error(t *testing.T) {
|
||||||
_, ipnet, _ := net.ParseCIDR("192.168.0.1/31")
|
_, ipnet, _ := net.ParseCIDR("192.168.0.1/31")
|
||||||
_, err := New(ipnet, 10, nil)
|
_, err := New(Options{
|
||||||
|
IPNet: ipnet,
|
||||||
|
Size: 10,
|
||||||
|
})
|
||||||
|
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,8 +15,10 @@ type Interface struct {
|
||||||
HardwareAddr net.HardwareAddr
|
HardwareAddr net.HardwareAddr
|
||||||
}
|
}
|
||||||
|
|
||||||
var ErrIfaceNotFound = errors.New("interface not found")
|
var (
|
||||||
var ErrAddrNotFound = errors.New("addr not found")
|
ErrIfaceNotFound = errors.New("interface not found")
|
||||||
|
ErrAddrNotFound = errors.New("addr not found")
|
||||||
|
)
|
||||||
|
|
||||||
var interfaces = singledo.NewSingle(time.Second * 20)
|
var interfaces = singledo.NewSingle(time.Second * 20)
|
||||||
|
|
||||||
|
|
|
@ -5,8 +5,8 @@ import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
|
||||||
"net"
|
"net"
|
||||||
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
@ -25,8 +25,10 @@ var nativeEndian = func() binary.ByteOrder {
|
||||||
return binary.LittleEndian
|
return binary.LittleEndian
|
||||||
}()
|
}()
|
||||||
|
|
||||||
type SocketResolver func(network string, ip net.IP, srcPort int) (inode, uid int, err error)
|
type (
|
||||||
type ProcessNameResolver func(inode, uid int) (name string, err error)
|
SocketResolver func(network string, ip net.IP, srcPort int) (inode, uid int, err error)
|
||||||
|
ProcessNameResolver func(inode, uid int) (name string, err error)
|
||||||
|
)
|
||||||
|
|
||||||
// export for android
|
// export for android
|
||||||
var (
|
var (
|
||||||
|
@ -167,7 +169,7 @@ func unpackSocketDiagResponse(msg *syscall.NetlinkMessage) (inode, uid uint32) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func resolveProcessNameByProcSearch(inode, uid int) (string, error) {
|
func resolveProcessNameByProcSearch(inode, uid int) (string, error) {
|
||||||
files, err := ioutil.ReadDir(pathProc)
|
files, err := os.ReadDir(pathProc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
@ -180,14 +182,18 @@ func resolveProcessNameByProcSearch(inode, uid int) (string, error) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if f.Sys().(*syscall.Stat_t).Uid != uint32(uid) {
|
info, err := f.Info()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
if info.Sys().(*syscall.Stat_t).Uid != uint32(uid) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
processPath := path.Join(pathProc, f.Name())
|
processPath := path.Join(pathProc, f.Name())
|
||||||
fdPath := path.Join(processPath, "fd")
|
fdPath := path.Join(processPath, "fd")
|
||||||
|
|
||||||
fds, err := ioutil.ReadDir(fdPath)
|
fds, err := os.ReadDir(fdPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -199,7 +205,7 @@ func resolveProcessNameByProcSearch(inode, uid int) (string, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if bytes.Equal(buffer[:n], socket) {
|
if bytes.Equal(buffer[:n], socket) {
|
||||||
cmdline, err := ioutil.ReadFile(path.Join(processPath, "cmdline"))
|
cmdline, err := os.ReadFile(path.Join(processPath, "cmdline"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,52 +3,47 @@ package cachefile
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/gob"
|
"encoding/gob"
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
"os"
|
||||||
"sync"
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/Dreamacro/clash/component/profile"
|
"github.com/Dreamacro/clash/component/profile"
|
||||||
C "github.com/Dreamacro/clash/constant"
|
C "github.com/Dreamacro/clash/constant"
|
||||||
"github.com/Dreamacro/clash/log"
|
"github.com/Dreamacro/clash/log"
|
||||||
|
|
||||||
|
"go.etcd.io/bbolt"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
initOnce sync.Once
|
initOnce sync.Once
|
||||||
fileMode os.FileMode = 0666
|
fileMode os.FileMode = 0o666
|
||||||
defaultCache *CacheFile
|
defaultCache *CacheFile
|
||||||
)
|
|
||||||
|
|
||||||
type cache struct {
|
bucketSelected = []byte("selected")
|
||||||
Selected map[string]string
|
bucketFakeip = []byte("fakeip")
|
||||||
}
|
)
|
||||||
|
|
||||||
// CacheFile store and update the cache file
|
// CacheFile store and update the cache file
|
||||||
type CacheFile struct {
|
type CacheFile struct {
|
||||||
path string
|
DB *bbolt.DB
|
||||||
model *cache
|
|
||||||
buf *bytes.Buffer
|
|
||||||
mux sync.Mutex
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *CacheFile) SetSelected(group, selected string) {
|
func (c *CacheFile) SetSelected(group, selected string) {
|
||||||
if !profile.StoreSelected.Load() {
|
if !profile.StoreSelected.Load() {
|
||||||
return
|
return
|
||||||
}
|
} else if c.DB == nil {
|
||||||
|
|
||||||
c.mux.Lock()
|
|
||||||
defer c.mux.Unlock()
|
|
||||||
|
|
||||||
model := c.element()
|
|
||||||
|
|
||||||
model.Selected[group] = selected
|
|
||||||
c.buf.Reset()
|
|
||||||
if err := gob.NewEncoder(c.buf).Encode(model); err != nil {
|
|
||||||
log.Warnln("[CacheFile] encode gob failed: %s", err.Error())
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := ioutil.WriteFile(c.path, c.buf.Bytes(), fileMode); err != nil {
|
err := c.DB.Batch(func(t *bbolt.Tx) error {
|
||||||
log.Warnln("[CacheFile] write cache to %s failed: %s", c.path, err.Error())
|
bucket, err := t.CreateBucketIfNotExists(bucketSelected)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return bucket.Put([]byte(group), []byte(selected))
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
log.Warnln("[CacheFile] write cache to %s failed: %s", c.DB.Path(), err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -56,46 +51,131 @@ func (c *CacheFile) SetSelected(group, selected string) {
|
||||||
func (c *CacheFile) SelectedMap() map[string]string {
|
func (c *CacheFile) SelectedMap() map[string]string {
|
||||||
if !profile.StoreSelected.Load() {
|
if !profile.StoreSelected.Load() {
|
||||||
return nil
|
return nil
|
||||||
|
} else if c.DB == nil {
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
c.mux.Lock()
|
|
||||||
defer c.mux.Unlock()
|
|
||||||
|
|
||||||
model := c.element()
|
|
||||||
|
|
||||||
mapping := map[string]string{}
|
mapping := map[string]string{}
|
||||||
for k, v := range model.Selected {
|
c.DB.View(func(t *bbolt.Tx) error {
|
||||||
mapping[k] = v
|
bucket := t.Bucket(bucketSelected)
|
||||||
}
|
if bucket == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
c := bucket.Cursor()
|
||||||
|
for k, v := c.First(); k != nil; k, v = c.Next() {
|
||||||
|
mapping[string(k)] = string(v)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
return mapping
|
return mapping
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *CacheFile) element() *cache {
|
func (c *CacheFile) PutFakeip(key, value []byte) error {
|
||||||
if c.model != nil {
|
if c.DB == nil {
|
||||||
return c.model
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err := c.DB.Batch(func(t *bbolt.Tx) error {
|
||||||
|
bucket, err := t.CreateBucketIfNotExists(bucketFakeip)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return bucket.Put(key, value)
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
log.Warnln("[CacheFile] write cache to %s failed: %s", c.DB.Path(), err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *CacheFile) GetFakeip(key []byte) []byte {
|
||||||
|
if c.DB == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
tx, err := c.DB.Begin(false)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
defer tx.Rollback()
|
||||||
|
|
||||||
|
bucket := tx.Bucket(bucketFakeip)
|
||||||
|
if bucket == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return bucket.Get(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *CacheFile) Close() error {
|
||||||
|
return c.DB.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: remove migrateCache until 2022
|
||||||
|
func migrateCache() {
|
||||||
|
defer func() {
|
||||||
|
options := bbolt.Options{Timeout: time.Second}
|
||||||
|
db, err := bbolt.Open(C.Path.Cache(), fileMode, &options)
|
||||||
|
switch err {
|
||||||
|
case bbolt.ErrInvalid, bbolt.ErrChecksum, bbolt.ErrVersionMismatch:
|
||||||
|
if err = os.Remove(C.Path.Cache()); err != nil {
|
||||||
|
log.Warnln("[CacheFile] remove invalid cache file error: %s", err.Error())
|
||||||
|
break
|
||||||
|
}
|
||||||
|
log.Infoln("[CacheFile] remove invalid cache file and create new one")
|
||||||
|
db, err = bbolt.Open(C.Path.Cache(), fileMode, &options)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
log.Warnln("[CacheFile] can't open cache file: %s", err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
defaultCache = &CacheFile{
|
||||||
|
DB: db,
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
buf, err := os.ReadFile(C.Path.OldCache())
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer os.Remove(C.Path.OldCache())
|
||||||
|
|
||||||
|
// read old cache file
|
||||||
|
type cache struct {
|
||||||
|
Selected map[string]string
|
||||||
|
}
|
||||||
model := &cache{
|
model := &cache{
|
||||||
Selected: map[string]string{},
|
Selected: map[string]string{},
|
||||||
}
|
}
|
||||||
|
bufReader := bytes.NewBuffer(buf)
|
||||||
|
gob.NewDecoder(bufReader).Decode(model)
|
||||||
|
|
||||||
if buf, err := ioutil.ReadFile(c.path); err == nil {
|
// write to new cache file
|
||||||
bufReader := bytes.NewBuffer(buf)
|
db, err := bbolt.Open(C.Path.Cache(), fileMode, nil)
|
||||||
gob.NewDecoder(bufReader).Decode(model)
|
if err != nil {
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
defer db.Close()
|
||||||
|
|
||||||
c.model = model
|
db.Batch(func(t *bbolt.Tx) error {
|
||||||
return c.model
|
bucket, err := t.CreateBucketIfNotExists(bucketSelected)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for group, selected := range model.Selected {
|
||||||
|
if err := bucket.Put([]byte(group), []byte(selected)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cache return singleton of CacheFile
|
// Cache return singleton of CacheFile
|
||||||
func Cache() *CacheFile {
|
func Cache() *CacheFile {
|
||||||
initOnce.Do(func() {
|
initOnce.Do(migrateCache)
|
||||||
defaultCache = &CacheFile{
|
|
||||||
path: C.Path.Cache(),
|
|
||||||
buf: &bytes.Buffer{},
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
return defaultCache
|
return defaultCache
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,5 @@ import (
|
||||||
"go.uber.org/atomic"
|
"go.uber.org/atomic"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
// StoreSelected is a global switch for storing selected proxy to cache
|
||||||
// StoreSelected is a global switch for storing selected proxy to cache
|
var StoreSelected = atomic.NewBool(true)
|
||||||
StoreSelected = atomic.NewBool(true)
|
|
||||||
)
|
|
||||||
|
|
|
@ -2,9 +2,7 @@ package resolver
|
||||||
|
|
||||||
import D "github.com/miekg/dns"
|
import D "github.com/miekg/dns"
|
||||||
|
|
||||||
var (
|
var DefaultLocalServer LocalServer
|
||||||
DefaultLocalServer LocalServer
|
|
||||||
)
|
|
||||||
|
|
||||||
type LocalServer interface {
|
type LocalServer interface {
|
||||||
ServeMsg(msg *D.Msg) (*D.Msg, error)
|
ServeMsg(msg *D.Msg) (*D.Msg, error)
|
||||||
|
|
|
@ -12,10 +12,8 @@ const (
|
||||||
domainStep = "."
|
domainStep = "."
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
// ErrInvalidDomain means insert domain is invalid
|
||||||
// ErrInvalidDomain means insert domain is invalid
|
var ErrInvalidDomain = errors.New("invalid domain")
|
||||||
ErrInvalidDomain = errors.New("invalid domain")
|
|
||||||
)
|
|
||||||
|
|
||||||
// DomainTrie contains the main logic for adding and searching nodes for domain segments.
|
// DomainTrie contains the main logic for adding and searching nodes for domain segments.
|
||||||
// support wildcard domain (e.g *.google.com)
|
// support wildcard domain (e.g *.google.com)
|
||||||
|
|
|
@ -66,7 +66,7 @@ type DNS struct {
|
||||||
Fallback []dns.NameServer `yaml:"fallback"`
|
Fallback []dns.NameServer `yaml:"fallback"`
|
||||||
FallbackFilter FallbackFilter `yaml:"fallback-filter"`
|
FallbackFilter FallbackFilter `yaml:"fallback-filter"`
|
||||||
Listen string `yaml:"listen"`
|
Listen string `yaml:"listen"`
|
||||||
EnhancedMode dns.EnhancedMode `yaml:"enhanced-mode"`
|
EnhancedMode C.DNSMode `yaml:"enhanced-mode"`
|
||||||
DefaultNameserver []dns.NameServer `yaml:"default-nameserver"`
|
DefaultNameserver []dns.NameServer `yaml:"default-nameserver"`
|
||||||
FakeIPRange *fakeip.Pool
|
FakeIPRange *fakeip.Pool
|
||||||
Hosts *trie.DomainTrie
|
Hosts *trie.DomainTrie
|
||||||
|
@ -84,6 +84,7 @@ type FallbackFilter struct {
|
||||||
// Profile config
|
// Profile config
|
||||||
type Profile struct {
|
type Profile struct {
|
||||||
StoreSelected bool `yaml:"store-selected"`
|
StoreSelected bool `yaml:"store-selected"`
|
||||||
|
StoreFakeIP bool `yaml:"store-fakeip"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tun config
|
// Tun config
|
||||||
|
@ -126,7 +127,7 @@ type RawDNS struct {
|
||||||
Fallback []string `yaml:"fallback"`
|
Fallback []string `yaml:"fallback"`
|
||||||
FallbackFilter RawFallbackFilter `yaml:"fallback-filter"`
|
FallbackFilter RawFallbackFilter `yaml:"fallback-filter"`
|
||||||
Listen string `yaml:"listen"`
|
Listen string `yaml:"listen"`
|
||||||
EnhancedMode dns.EnhancedMode `yaml:"enhanced-mode"`
|
EnhancedMode C.DNSMode `yaml:"enhanced-mode"`
|
||||||
FakeIPRange string `yaml:"fake-ip-range"`
|
FakeIPRange string `yaml:"fake-ip-range"`
|
||||||
FakeIPFilter []string `yaml:"fake-ip-filter"`
|
FakeIPFilter []string `yaml:"fake-ip-filter"`
|
||||||
DefaultNameserver []string `yaml:"default-nameserver"`
|
DefaultNameserver []string `yaml:"default-nameserver"`
|
||||||
|
@ -264,7 +265,7 @@ func ParseRawConfig(rawCfg *RawConfig) (*Config, error) {
|
||||||
}
|
}
|
||||||
config.Hosts = hosts
|
config.Hosts = hosts
|
||||||
|
|
||||||
dnsCfg, err := parseDNS(rawCfg.DNS, hosts)
|
dnsCfg, err := parseDNS(rawCfg, hosts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -468,7 +469,7 @@ time = ClashTime()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
err := os.WriteFile(C.Path.Script(), []byte(content), 0644)
|
err := os.WriteFile(C.Path.Script(), []byte(content), 0o644)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("initialized script module failure, %s", err.Error())
|
return fmt.Errorf("initialized script module failure, %s", err.Error())
|
||||||
}
|
}
|
||||||
|
@ -533,7 +534,6 @@ func parseRules(cfg *RawConfig, proxies map[string]C.Proxy) ([]C.Rule, map[strin
|
||||||
return nil, nil, fmt.Errorf("rules[%d] [%s] error: proxy [%s] not found", idx, line, target)
|
return nil, nil, fmt.Errorf("rules[%d] [%s] error: proxy [%s] not found", idx, line, target)
|
||||||
}
|
}
|
||||||
|
|
||||||
//rule = trimArr(rule)
|
|
||||||
params = trimArr(params)
|
params = trimArr(params)
|
||||||
|
|
||||||
parsed, parseErr := R.ParseRule(ruleName, payload, target, params)
|
parsed, parseErr := R.ParseRule(ruleName, payload, target, params)
|
||||||
|
@ -687,7 +687,8 @@ func parseFallbackIPCIDR(ips []string) ([]*net.IPNet, error) {
|
||||||
return ipNets, nil
|
return ipNets, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseDNS(cfg RawDNS, hosts *trie.DomainTrie) (*DNS, error) {
|
func parseDNS(rawCfg *RawConfig, hosts *trie.DomainTrie) (*DNS, error) {
|
||||||
|
cfg := rawCfg.DNS
|
||||||
if cfg.Enable && len(cfg.NameServer) == 0 {
|
if cfg.Enable && len(cfg.NameServer) == 0 {
|
||||||
return nil, fmt.Errorf("if DNS configuration is turned on, NameServer cannot be empty")
|
return nil, fmt.Errorf("if DNS configuration is turned on, NameServer cannot be empty")
|
||||||
}
|
}
|
||||||
|
@ -728,7 +729,7 @@ func parseDNS(cfg RawDNS, hosts *trie.DomainTrie) (*DNS, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if cfg.EnhancedMode == dns.FAKEIP {
|
if cfg.EnhancedMode == C.DNSFakeIP {
|
||||||
_, ipnet, err := net.ParseCIDR(cfg.FakeIPRange)
|
_, ipnet, err := net.ParseCIDR(cfg.FakeIPRange)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -743,7 +744,12 @@ func parseDNS(cfg RawDNS, hosts *trie.DomainTrie) (*DNS, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pool, err := fakeip.New(ipnet, 1000, host)
|
pool, err := fakeip.New(fakeip.Options{
|
||||||
|
IPNet: ipnet,
|
||||||
|
Size: 1000,
|
||||||
|
Host: host,
|
||||||
|
Persistence: rawCfg.Profile.StoreFakeIP,
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -74,7 +74,7 @@ func downloadGeoSite(path string) (err error) {
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
f, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY, 0644)
|
f, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY, 0o644)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -113,7 +113,7 @@ func initGeoSite() error {
|
||||||
func Init(dir string) error {
|
func Init(dir string) error {
|
||||||
// initial homedir
|
// initial homedir
|
||||||
if _, err := os.Stat(dir); os.IsNotExist(err) {
|
if _, err := os.Stat(dir); os.IsNotExist(err) {
|
||||||
if err := os.MkdirAll(dir, 0777); err != nil {
|
if err := os.MkdirAll(dir, 0o777); err != nil {
|
||||||
return fmt.Errorf("can't create config directory %s: %s", dir, err.Error())
|
return fmt.Errorf("can't create config directory %s: %s", dir, err.Error())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -121,7 +121,7 @@ func Init(dir string) error {
|
||||||
// initial config.yaml
|
// initial config.yaml
|
||||||
if _, err := os.Stat(C.Path.Config()); os.IsNotExist(err) {
|
if _, err := os.Stat(C.Path.Config()); os.IsNotExist(err) {
|
||||||
log.Infoln("Can't find config, create a initial config file")
|
log.Infoln("Can't find config, create a initial config file")
|
||||||
f, err := os.OpenFile(C.Path.Config(), os.O_CREATE|os.O_WRONLY, 0644)
|
f, err := os.OpenFile(C.Path.Config(), os.O_CREATE|os.O_WRONLY, 0o644)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("can't create file %s: %s", C.Path.Config(), err.Error())
|
return fmt.Errorf("can't create file %s: %s", C.Path.Config(), err.Error())
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,7 @@ const (
|
||||||
|
|
||||||
const (
|
const (
|
||||||
DefaultTCPTimeout = 5 * time.Second
|
DefaultTCPTimeout = 5 * time.Second
|
||||||
|
DefaultUDPTimeout = DefaultTCPTimeout
|
||||||
)
|
)
|
||||||
|
|
||||||
type Connection interface {
|
type Connection interface {
|
||||||
|
@ -74,11 +75,14 @@ type PacketConn interface {
|
||||||
type ProxyAdapter interface {
|
type ProxyAdapter interface {
|
||||||
Name() string
|
Name() string
|
||||||
Type() AdapterType
|
Type() AdapterType
|
||||||
|
Addr() string
|
||||||
|
SupportUDP() bool
|
||||||
|
MarshalJSON() ([]byte, error)
|
||||||
|
|
||||||
// StreamConn wraps a protocol around net.Conn with Metadata.
|
// StreamConn wraps a protocol around net.Conn with Metadata.
|
||||||
//
|
//
|
||||||
// Examples:
|
// Examples:
|
||||||
// conn, _ := net.Dial("tcp", "host:port")
|
// conn, _ := net.DialContext(context.Background(), "tcp", "host:port")
|
||||||
// conn, _ = adapter.StreamConn(conn, metadata)
|
// conn, _ = adapter.StreamConn(conn, metadata)
|
||||||
//
|
//
|
||||||
// It returns a C.Conn with protocol which start with
|
// It returns a C.Conn with protocol which start with
|
||||||
|
@ -89,10 +93,8 @@ type ProxyAdapter interface {
|
||||||
// contains multiplexing-related reuse logic (if any)
|
// contains multiplexing-related reuse logic (if any)
|
||||||
DialContext(ctx context.Context, metadata *Metadata) (Conn, error)
|
DialContext(ctx context.Context, metadata *Metadata) (Conn, error)
|
||||||
|
|
||||||
DialUDP(metadata *Metadata) (PacketConn, error)
|
ListenPacketContext(ctx context.Context, metadata *Metadata) (PacketConn, error)
|
||||||
SupportUDP() bool
|
|
||||||
MarshalJSON() ([]byte, error)
|
|
||||||
Addr() string
|
|
||||||
// Unwrap extracts the proxy from a proxy-group. It returns nil when nothing to extract.
|
// Unwrap extracts the proxy from a proxy-group. It returns nil when nothing to extract.
|
||||||
Unwrap(metadata *Metadata) Proxy
|
Unwrap(metadata *Metadata) Proxy
|
||||||
}
|
}
|
||||||
|
@ -106,9 +108,14 @@ type Proxy interface {
|
||||||
ProxyAdapter
|
ProxyAdapter
|
||||||
Alive() bool
|
Alive() bool
|
||||||
DelayHistory() []DelayHistory
|
DelayHistory() []DelayHistory
|
||||||
Dial(metadata *Metadata) (Conn, error)
|
|
||||||
LastDelay() uint16
|
LastDelay() uint16
|
||||||
URLTest(ctx context.Context, url string) (uint16, error)
|
URLTest(ctx context.Context, url string) (uint16, error)
|
||||||
|
|
||||||
|
// Deprecated: use DialContext instead.
|
||||||
|
Dial(metadata *Metadata) (Conn, error)
|
||||||
|
|
||||||
|
// Deprecated: use DialPacketConn instead.
|
||||||
|
DialUDP(metadata *Metadata) (PacketConn, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// AdapterType is enum of adapter type
|
// AdapterType is enum of adapter type
|
||||||
|
|
70
constant/dns.go
Normal file
70
constant/dns.go
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
package constant
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
// DNSModeMapping is a mapping for EnhancedMode enum
|
||||||
|
var DNSModeMapping = map[string]DNSMode{
|
||||||
|
DNSNormal.String(): DNSNormal,
|
||||||
|
DNSFakeIP.String(): DNSFakeIP,
|
||||||
|
DNSMapping.String(): DNSMapping,
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
DNSNormal DNSMode = iota
|
||||||
|
DNSFakeIP
|
||||||
|
DNSMapping
|
||||||
|
)
|
||||||
|
|
||||||
|
type DNSMode int
|
||||||
|
|
||||||
|
// UnmarshalYAML unserialize EnhancedMode with yaml
|
||||||
|
func (e *DNSMode) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
||||||
|
var tp string
|
||||||
|
if err := unmarshal(&tp); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
mode, exist := DNSModeMapping[tp]
|
||||||
|
if !exist {
|
||||||
|
return errors.New("invalid mode")
|
||||||
|
}
|
||||||
|
*e = mode
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarshalYAML serialize EnhancedMode with yaml
|
||||||
|
func (e DNSMode) MarshalYAML() (interface{}, error) {
|
||||||
|
return e.String(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalJSON unserialize EnhancedMode with json
|
||||||
|
func (e *DNSMode) UnmarshalJSON(data []byte) error {
|
||||||
|
var tp string
|
||||||
|
json.Unmarshal(data, &tp)
|
||||||
|
mode, exist := DNSModeMapping[tp]
|
||||||
|
if !exist {
|
||||||
|
return errors.New("invalid mode")
|
||||||
|
}
|
||||||
|
*e = mode
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarshalJSON serialize EnhancedMode with json
|
||||||
|
func (e DNSMode) MarshalJSON() ([]byte, error) {
|
||||||
|
return json.Marshal(e.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e DNSMode) String() string {
|
||||||
|
switch e {
|
||||||
|
case DNSNormal:
|
||||||
|
return "normal"
|
||||||
|
case DNSFakeIP:
|
||||||
|
return "fake-ip"
|
||||||
|
case DNSMapping:
|
||||||
|
return "redir-host"
|
||||||
|
default:
|
||||||
|
return "unknown"
|
||||||
|
}
|
||||||
|
}
|
|
@ -78,6 +78,7 @@ type Metadata struct {
|
||||||
AddrType int `json:"-"`
|
AddrType int `json:"-"`
|
||||||
Host string `json:"host"`
|
Host string `json:"host"`
|
||||||
Process string `json:"process"`
|
Process string `json:"process"`
|
||||||
|
DNSMode DNSMode `json:"dnsMode"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Metadata) RemoteAddress() string {
|
func (m *Metadata) RemoteAddress() string {
|
||||||
|
@ -92,6 +93,23 @@ func (m *Metadata) Resolved() bool {
|
||||||
return m.DstIP != nil
|
return m.DstIP != nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Pure is used to solve unexpected behavior
|
||||||
|
// when dialing proxy connection in DNSMapping mode.
|
||||||
|
func (m *Metadata) Pure() *Metadata {
|
||||||
|
if m.DNSMode == DNSMapping && m.DstIP != nil {
|
||||||
|
copy := *m
|
||||||
|
copy.Host = ""
|
||||||
|
if copy.DstIP.To4() != nil {
|
||||||
|
copy.AddrType = AtypIPv4
|
||||||
|
} else {
|
||||||
|
copy.AddrType = AtypIPv6
|
||||||
|
}
|
||||||
|
return ©
|
||||||
|
}
|
||||||
|
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
func (m *Metadata) UDPAddr() *net.UDPAddr {
|
func (m *Metadata) UDPAddr() *net.UDPAddr {
|
||||||
if m.NetWork != UDP || m.DstIP == nil {
|
if m.NetWork != UDP || m.DstIP == nil {
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -56,10 +56,14 @@ func (p *path) MMDB() string {
|
||||||
return P.Join(p.homeDir, "Country.mmdb")
|
return P.Join(p.homeDir, "Country.mmdb")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *path) Cache() string {
|
func (p *path) OldCache() string {
|
||||||
return P.Join(p.homeDir, ".cache")
|
return P.Join(p.homeDir, ".cache")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *path) Cache() string {
|
||||||
|
return P.Join(p.homeDir, "cache.db")
|
||||||
|
}
|
||||||
|
|
||||||
func (p *path) GeoIP() string {
|
func (p *path) GeoIP() string {
|
||||||
return P.Join(p.homeDir, "geoip.dat")
|
return P.Join(p.homeDir, "geoip.dat")
|
||||||
}
|
}
|
||||||
|
@ -76,7 +80,7 @@ func (p *path) ScriptDir() string {
|
||||||
p.scriptDir = dir
|
p.scriptDir = dir
|
||||||
} else {
|
} else {
|
||||||
p.scriptDir = P.Join(os.TempDir(), Name)
|
p.scriptDir = P.Join(os.TempDir(), Name)
|
||||||
os.MkdirAll(p.scriptDir, 0644)
|
os.MkdirAll(p.scriptDir, 0o644)
|
||||||
}
|
}
|
||||||
return p.scriptDir
|
return p.scriptDir
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,7 +67,7 @@ type ProxyProvider interface {
|
||||||
Provider
|
Provider
|
||||||
Proxies() []constant.Proxy
|
Proxies() []constant.Proxy
|
||||||
// ProxiesWithTouch is used to inform the provider that the proxy is actually being used while getting the list of proxies.
|
// ProxiesWithTouch is used to inform the provider that the proxy is actually being used while getting the list of proxies.
|
||||||
// Commonly used in Dial and DialUDP
|
// Commonly used in DialContext and DialPacketConn
|
||||||
ProxiesWithTouch() []constant.Proxy
|
ProxiesWithTouch() []constant.Proxy
|
||||||
HealthCheck()
|
HealthCheck()
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,9 +15,10 @@ import (
|
||||||
|
|
||||||
type client struct {
|
type client struct {
|
||||||
*D.Client
|
*D.Client
|
||||||
r *Resolver
|
r *Resolver
|
||||||
port string
|
port string
|
||||||
host string
|
host string
|
||||||
|
iface string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *client) Exchange(m *D.Msg) (*D.Msg, error) {
|
func (c *client) Exchange(m *D.Msg) (*D.Msg, error) {
|
||||||
|
@ -45,7 +46,11 @@ func (c *client) ExchangeContext(ctx context.Context, m *D.Msg) (*D.Msg, error)
|
||||||
network = "tcp"
|
network = "tcp"
|
||||||
}
|
}
|
||||||
|
|
||||||
conn, err := dialer.DialContext(ctx, network, net.JoinHostPort(ip.String(), c.port))
|
options := []dialer.Option{}
|
||||||
|
if c.iface != "" {
|
||||||
|
options = append(options, dialer.WithInterface(c.iface))
|
||||||
|
}
|
||||||
|
conn, err := dialer.DialContext(ctx, network, net.JoinHostPort(ip.String(), c.port), options...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,8 +68,11 @@ func (d *dhcpClient) resolve(ctx context.Context) (*Resolver, error) {
|
||||||
dns, err := dhcp.ResolveDNSFromDHCP(ctx, d.ifaceName)
|
dns, err := dhcp.ResolveDNSFromDHCP(ctx, d.ifaceName)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
nameserver := make([]NameServer, 0, len(dns))
|
nameserver := make([]NameServer, 0, len(dns))
|
||||||
for _, d := range dns {
|
for _, item := range dns {
|
||||||
nameserver = append(nameserver, NameServer{Addr: net.JoinHostPort(d.String(), "53")})
|
nameserver = append(nameserver, NameServer{
|
||||||
|
Addr: net.JoinHostPort(item.String(), "53"),
|
||||||
|
Interface: d.ifaceName,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
res = NewResolver(Config{
|
res = NewResolver(Config{
|
||||||
|
|
16
dns/doh.go
16
dns/doh.go
|
@ -3,7 +3,7 @@ package dns
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"io/ioutil"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
|
@ -28,13 +28,21 @@ func (dc *dohClient) Exchange(m *D.Msg) (msg *D.Msg, err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dc *dohClient) ExchangeContext(ctx context.Context, m *D.Msg) (msg *D.Msg, err error) {
|
func (dc *dohClient) ExchangeContext(ctx context.Context, m *D.Msg) (msg *D.Msg, err error) {
|
||||||
req, err := dc.newRequest(m)
|
// https://datatracker.ietf.org/doc/html/rfc8484#section-4.1
|
||||||
|
// In order to maximize cache friendliness, SHOULD use a DNS ID of 0 in every DNS request.
|
||||||
|
newM := *m
|
||||||
|
newM.Id = 0
|
||||||
|
req, err := dc.newRequest(&newM)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
req = req.WithContext(ctx)
|
req = req.WithContext(ctx)
|
||||||
return dc.doRequest(req)
|
msg, err = dc.doRequest(req)
|
||||||
|
if err == nil {
|
||||||
|
msg.Id = m.Id
|
||||||
|
}
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// newRequest returns a new DoH request given a dns.Msg.
|
// newRequest returns a new DoH request given a dns.Msg.
|
||||||
|
@ -62,7 +70,7 @@ func (dc *dohClient) doRequest(req *http.Request) (msg *D.Msg, err error) {
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
buf, err := ioutil.ReadAll(resp.Body)
|
buf, err := io.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,20 +5,21 @@ import (
|
||||||
|
|
||||||
"github.com/Dreamacro/clash/common/cache"
|
"github.com/Dreamacro/clash/common/cache"
|
||||||
"github.com/Dreamacro/clash/component/fakeip"
|
"github.com/Dreamacro/clash/component/fakeip"
|
||||||
|
C "github.com/Dreamacro/clash/constant"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ResolverEnhancer struct {
|
type ResolverEnhancer struct {
|
||||||
mode EnhancedMode
|
mode C.DNSMode
|
||||||
fakePool *fakeip.Pool
|
fakePool *fakeip.Pool
|
||||||
mapping *cache.LruCache
|
mapping *cache.LruCache
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *ResolverEnhancer) FakeIPEnabled() bool {
|
func (h *ResolverEnhancer) FakeIPEnabled() bool {
|
||||||
return h.mode == FAKEIP
|
return h.mode == C.DNSFakeIP
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *ResolverEnhancer) MappingEnabled() bool {
|
func (h *ResolverEnhancer) MappingEnabled() bool {
|
||||||
return h.mode == FAKEIP || h.mode == MAPPING
|
return h.mode == C.DNSFakeIP || h.mode == C.DNSMapping
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *ResolverEnhancer) IsExistFakeIP(ip net.IP) bool {
|
func (h *ResolverEnhancer) IsExistFakeIP(ip net.IP) bool {
|
||||||
|
@ -67,7 +68,7 @@ func (h *ResolverEnhancer) PatchFrom(o *ResolverEnhancer) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if h.fakePool != nil && o.fakePool != nil {
|
if h.fakePool != nil && o.fakePool != nil {
|
||||||
h.fakePool.PatchFrom(o.fakePool)
|
h.fakePool.CloneFrom(o.fakePool)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,7 +76,7 @@ func NewEnhancer(cfg Config) *ResolverEnhancer {
|
||||||
var fakePool *fakeip.Pool
|
var fakePool *fakeip.Pool
|
||||||
var mapping *cache.LruCache
|
var mapping *cache.LruCache
|
||||||
|
|
||||||
if cfg.EnhancedMode != NORMAL {
|
if cfg.EnhancedMode != C.DNSNormal {
|
||||||
fakePool = cfg.Pool
|
fakePool = cfg.Pool
|
||||||
mapping = cache.NewLRUCache(cache.WithSize(4096), cache.WithStale(true))
|
mapping = cache.NewLRUCache(cache.WithSize(4096), cache.WithStale(true))
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,14 +8,17 @@ import (
|
||||||
"github.com/Dreamacro/clash/common/cache"
|
"github.com/Dreamacro/clash/common/cache"
|
||||||
"github.com/Dreamacro/clash/component/fakeip"
|
"github.com/Dreamacro/clash/component/fakeip"
|
||||||
"github.com/Dreamacro/clash/component/trie"
|
"github.com/Dreamacro/clash/component/trie"
|
||||||
|
C "github.com/Dreamacro/clash/constant"
|
||||||
"github.com/Dreamacro/clash/context"
|
"github.com/Dreamacro/clash/context"
|
||||||
"github.com/Dreamacro/clash/log"
|
"github.com/Dreamacro/clash/log"
|
||||||
|
|
||||||
D "github.com/miekg/dns"
|
D "github.com/miekg/dns"
|
||||||
)
|
)
|
||||||
|
|
||||||
type handler func(ctx *context.DNSContext, r *D.Msg) (*D.Msg, error)
|
type (
|
||||||
type middleware func(next handler) handler
|
handler func(ctx *context.DNSContext, r *D.Msg) (*D.Msg, error)
|
||||||
|
middleware func(next handler) handler
|
||||||
|
)
|
||||||
|
|
||||||
func withHosts(hosts *trie.DomainTrie) middleware {
|
func withHosts(hosts *trie.DomainTrie) middleware {
|
||||||
return func(next handler) handler {
|
return func(next handler) handler {
|
||||||
|
@ -105,7 +108,7 @@ func withFakeIP(fakePool *fakeip.Pool) middleware {
|
||||||
q := r.Question[0]
|
q := r.Question[0]
|
||||||
|
|
||||||
host := strings.TrimRight(q.Name, ".")
|
host := strings.TrimRight(q.Name, ".")
|
||||||
if fakePool.LookupHost(host) {
|
if fakePool.ShouldSkipped(host) {
|
||||||
return next(ctx, r)
|
return next(ctx, r)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -176,11 +179,11 @@ func NewHandler(resolver *Resolver, mapper *ResolverEnhancer) handler {
|
||||||
middlewares = append(middlewares, withHosts(resolver.hosts))
|
middlewares = append(middlewares, withHosts(resolver.hosts))
|
||||||
}
|
}
|
||||||
|
|
||||||
if mapper.mode == FAKEIP {
|
if mapper.mode == C.DNSFakeIP {
|
||||||
middlewares = append(middlewares, withFakeIP(mapper.fakePool))
|
middlewares = append(middlewares, withFakeIP(mapper.fakePool))
|
||||||
}
|
}
|
||||||
|
|
||||||
if mapper.mode != NORMAL {
|
if mapper.mode != C.DNSNormal {
|
||||||
middlewares = append(middlewares, withMapping(mapper.mapping))
|
middlewares = append(middlewares, withMapping(mapper.mapping))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@ import (
|
||||||
"github.com/Dreamacro/clash/component/fakeip"
|
"github.com/Dreamacro/clash/component/fakeip"
|
||||||
"github.com/Dreamacro/clash/component/resolver"
|
"github.com/Dreamacro/clash/component/resolver"
|
||||||
"github.com/Dreamacro/clash/component/trie"
|
"github.com/Dreamacro/clash/component/trie"
|
||||||
|
C "github.com/Dreamacro/clash/constant"
|
||||||
|
|
||||||
D "github.com/miekg/dns"
|
D "github.com/miekg/dns"
|
||||||
"golang.org/x/sync/singleflight"
|
"golang.org/x/sync/singleflight"
|
||||||
|
@ -215,7 +216,6 @@ func (r *Resolver) shouldOnlyQueryFallback(m *D.Msg) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Resolver) ipExchange(ctx context.Context, m *D.Msg) (msg *D.Msg, err error) {
|
func (r *Resolver) ipExchange(ctx context.Context, m *D.Msg) (msg *D.Msg, err error) {
|
||||||
|
|
||||||
if matched := r.matchPolicy(m); len(matched) != 0 {
|
if matched := r.matchPolicy(m); len(matched) != 0 {
|
||||||
res := <-r.asyncExchange(ctx, matched, m)
|
res := <-r.asyncExchange(ctx, matched, m)
|
||||||
return res.Msg, res.Error
|
return res.Msg, res.Error
|
||||||
|
@ -302,8 +302,9 @@ func (r *Resolver) asyncExchange(ctx context.Context, client []dnsClient, msg *D
|
||||||
}
|
}
|
||||||
|
|
||||||
type NameServer struct {
|
type NameServer struct {
|
||||||
Net string
|
Net string
|
||||||
Addr string
|
Addr string
|
||||||
|
Interface string
|
||||||
}
|
}
|
||||||
|
|
||||||
type FallbackFilter struct {
|
type FallbackFilter struct {
|
||||||
|
@ -317,7 +318,7 @@ type Config struct {
|
||||||
Main, Fallback []NameServer
|
Main, Fallback []NameServer
|
||||||
Default []NameServer
|
Default []NameServer
|
||||||
IPv6 bool
|
IPv6 bool
|
||||||
EnhancedMode EnhancedMode
|
EnhancedMode C.DNSMode
|
||||||
FallbackFilter FallbackFilter
|
FallbackFilter FallbackFilter
|
||||||
Pool *fakeip.Pool
|
Pool *fakeip.Pool
|
||||||
Hosts *trie.DomainTrie
|
Hosts *trie.DomainTrie
|
||||||
|
|
75
dns/util.go
75
dns/util.go
|
@ -2,8 +2,6 @@ package dns
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
|
||||||
"net"
|
"net"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -13,72 +11,6 @@ import (
|
||||||
D "github.com/miekg/dns"
|
D "github.com/miekg/dns"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
|
||||||
// EnhancedModeMapping is a mapping for EnhancedMode enum
|
|
||||||
EnhancedModeMapping = map[string]EnhancedMode{
|
|
||||||
NORMAL.String(): NORMAL,
|
|
||||||
FAKEIP.String(): FAKEIP,
|
|
||||||
MAPPING.String(): MAPPING,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
NORMAL EnhancedMode = iota
|
|
||||||
FAKEIP
|
|
||||||
MAPPING
|
|
||||||
)
|
|
||||||
|
|
||||||
type EnhancedMode int
|
|
||||||
|
|
||||||
// UnmarshalYAML unserialize EnhancedMode with yaml
|
|
||||||
func (e *EnhancedMode) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
|
||||||
var tp string
|
|
||||||
if err := unmarshal(&tp); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
mode, exist := EnhancedModeMapping[tp]
|
|
||||||
if !exist {
|
|
||||||
return errors.New("invalid mode")
|
|
||||||
}
|
|
||||||
*e = mode
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// MarshalYAML serialize EnhancedMode with yaml
|
|
||||||
func (e EnhancedMode) MarshalYAML() (interface{}, error) {
|
|
||||||
return e.String(), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// UnmarshalJSON unserialize EnhancedMode with json
|
|
||||||
func (e *EnhancedMode) UnmarshalJSON(data []byte) error {
|
|
||||||
var tp string
|
|
||||||
json.Unmarshal(data, &tp)
|
|
||||||
mode, exist := EnhancedModeMapping[tp]
|
|
||||||
if !exist {
|
|
||||||
return errors.New("invalid mode")
|
|
||||||
}
|
|
||||||
*e = mode
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// MarshalJSON serialize EnhancedMode with json
|
|
||||||
func (e EnhancedMode) MarshalJSON() ([]byte, error) {
|
|
||||||
return json.Marshal(e.String())
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e EnhancedMode) String() string {
|
|
||||||
switch e {
|
|
||||||
case NORMAL:
|
|
||||||
return "normal"
|
|
||||||
case FAKEIP:
|
|
||||||
return "fake-ip"
|
|
||||||
case MAPPING:
|
|
||||||
return "redir-host"
|
|
||||||
default:
|
|
||||||
return "unknown"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func putMsgToCache(c *cache.LruCache, key string, msg *D.Msg) {
|
func putMsgToCache(c *cache.LruCache, key string, msg *D.Msg) {
|
||||||
var ttl uint32
|
var ttl uint32
|
||||||
switch {
|
switch {
|
||||||
|
@ -138,9 +70,10 @@ func transform(servers []NameServer, resolver *Resolver) []dnsClient {
|
||||||
UDPSize: 4096,
|
UDPSize: 4096,
|
||||||
Timeout: 5 * time.Second,
|
Timeout: 5 * time.Second,
|
||||||
},
|
},
|
||||||
port: port,
|
port: port,
|
||||||
host: host,
|
host: host,
|
||||||
r: resolver,
|
iface: s.Interface,
|
||||||
|
r: resolver,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return ret
|
return ret
|
||||||
|
|
1
go.mod
1
go.mod
|
@ -17,6 +17,7 @@ require (
|
||||||
github.com/stretchr/testify v1.7.0
|
github.com/stretchr/testify v1.7.0
|
||||||
github.com/xtls/go v0.0.0-20201118062508-3632bf3b7499
|
github.com/xtls/go v0.0.0-20201118062508-3632bf3b7499
|
||||||
github.com/yaling888/go-lwip v0.0.0-20210928231210-94b50cb51cc1
|
github.com/yaling888/go-lwip v0.0.0-20210928231210-94b50cb51cc1
|
||||||
|
go.etcd.io/bbolt v1.3.6
|
||||||
go.uber.org/atomic v1.9.0
|
go.uber.org/atomic v1.9.0
|
||||||
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5
|
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5
|
||||||
golang.org/x/net v0.0.0-20210903162142-ad29c8ab022f
|
golang.org/x/net v0.0.0-20210903162142-ad29c8ab022f
|
||||||
|
|
3
go.sum
3
go.sum
|
@ -582,6 +582,8 @@ github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go
|
||||||
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||||
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||||
go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
|
go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
|
||||||
|
go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU=
|
||||||
|
go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4=
|
||||||
go.etcd.io/etcd v0.5.0-alpha.5.0.20200910180754-dd1b699fc489/go.mod h1:yVHk9ub3CSBatqGNg7GRmsnfLWtoW60w4eDYfh7vHDg=
|
go.etcd.io/etcd v0.5.0-alpha.5.0.20200910180754-dd1b699fc489/go.mod h1:yVHk9ub3CSBatqGNg7GRmsnfLWtoW60w4eDYfh7vHDg=
|
||||||
go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk=
|
go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk=
|
||||||
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
||||||
|
@ -780,6 +782,7 @@ golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||||
golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200916030750-2334cc1a136f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200916030750-2334cc1a136f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200922070232-aee5d888a860/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200922070232-aee5d888a860/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20201009025420-dfb3f7c4e634/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201009025420-dfb3f7c4e634/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20201101102859-da207088b7d1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201101102859-da207088b7d1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
|
|
@ -2,7 +2,6 @@ package executor
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
@ -32,15 +31,13 @@ import (
|
||||||
"github.com/Dreamacro/clash/tunnel"
|
"github.com/Dreamacro/clash/tunnel"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var mux sync.Mutex
|
||||||
mux sync.Mutex
|
|
||||||
)
|
|
||||||
|
|
||||||
func readConfig(path string) ([]byte, error) {
|
func readConfig(path string) ([]byte, error) {
|
||||||
if _, err := os.Stat(path); os.IsNotExist(err) {
|
if _, err := os.Stat(path); os.IsNotExist(err) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
data, err := ioutil.ReadFile(path)
|
data, err := os.ReadFile(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,9 +4,7 @@ import (
|
||||||
"github.com/Dreamacro/clash/component/auth"
|
"github.com/Dreamacro/clash/component/auth"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var authenticator auth.Authenticator
|
||||||
authenticator auth.Authenticator
|
|
||||||
)
|
|
||||||
|
|
||||||
func Authenticator() auth.Authenticator {
|
func Authenticator() auth.Authenticator {
|
||||||
return authenticator
|
return authenticator
|
||||||
|
|
|
@ -19,7 +19,6 @@ func newClient(source net.Addr, in chan<- C.ConnContext) *http.Client {
|
||||||
MaxIdleConns: 100,
|
MaxIdleConns: 100,
|
||||||
IdleConnTimeout: 90 * time.Second,
|
IdleConnTimeout: 90 * time.Second,
|
||||||
TLSHandshakeTimeout: 10 * time.Second,
|
TLSHandshakeTimeout: 10 * time.Second,
|
||||||
ResponseHeaderTimeout: 10 * time.Second,
|
|
||||||
ExpectContinueTimeout: 1 * time.Second,
|
ExpectContinueTimeout: 1 * time.Second,
|
||||||
DialContext: func(context context.Context, network, address string) (net.Conn, error) {
|
DialContext: func(context context.Context, network, address string) (net.Conn, error) {
|
||||||
if network != "tcp" && network != "tcp4" && network != "tcp6" {
|
if network != "tcp" && network != "tcp4" && network != "tcp6" {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package http
|
package http
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -43,11 +44,8 @@ func HandleConn(c net.Conn, in chan<- C.ConnContext, cache *cache.Cache) {
|
||||||
|
|
||||||
if trusted {
|
if trusted {
|
||||||
if request.Method == http.MethodConnect {
|
if request.Method == http.MethodConnect {
|
||||||
resp = responseWith(200)
|
// Manual writing to support CONNECT for http 1.0 (workaround for uplay client)
|
||||||
resp.Status = "Connection established"
|
if _, err = fmt.Fprintf(conn, "HTTP/%d.%d %03d %s\r\n\r\n", request.ProtoMajor, request.ProtoMinor, http.StatusOK, "Connection established"); err != nil {
|
||||||
resp.ContentLength = -1
|
|
||||||
|
|
||||||
if resp.Write(conn) != nil {
|
|
||||||
break // close connection
|
break // close connection
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,11 +65,11 @@ func HandleConn(c net.Conn, in chan<- C.ConnContext, cache *cache.Cache) {
|
||||||
removeExtraHTTPHostPort(request)
|
removeExtraHTTPHostPort(request)
|
||||||
|
|
||||||
if request.URL.Scheme == "" || request.URL.Host == "" {
|
if request.URL.Scheme == "" || request.URL.Host == "" {
|
||||||
resp = responseWith(http.StatusBadRequest)
|
resp = responseWith(request, http.StatusBadRequest)
|
||||||
} else {
|
} else {
|
||||||
resp, err = client.Do(request)
|
resp, err = client.Do(request)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
resp = responseWith(http.StatusBadGateway)
|
resp = responseWith(request, http.StatusBadGateway)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,7 +98,7 @@ func authenticate(request *http.Request, cache *cache.Cache) *http.Response {
|
||||||
if authenticator != nil {
|
if authenticator != nil {
|
||||||
credential := parseBasicProxyAuthorization(request)
|
credential := parseBasicProxyAuthorization(request)
|
||||||
if credential == "" {
|
if credential == "" {
|
||||||
resp := responseWith(http.StatusProxyAuthRequired)
|
resp := responseWith(request, http.StatusProxyAuthRequired)
|
||||||
resp.Header.Set("Proxy-Authenticate", "Basic")
|
resp.Header.Set("Proxy-Authenticate", "Basic")
|
||||||
return resp
|
return resp
|
||||||
}
|
}
|
||||||
|
@ -114,20 +112,20 @@ func authenticate(request *http.Request, cache *cache.Cache) *http.Response {
|
||||||
if !authed.(bool) {
|
if !authed.(bool) {
|
||||||
log.Infoln("Auth failed from %s", request.RemoteAddr)
|
log.Infoln("Auth failed from %s", request.RemoteAddr)
|
||||||
|
|
||||||
return responseWith(http.StatusForbidden)
|
return responseWith(request, http.StatusForbidden)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func responseWith(statusCode int) *http.Response {
|
func responseWith(request *http.Request, statusCode int) *http.Response {
|
||||||
return &http.Response{
|
return &http.Response{
|
||||||
StatusCode: statusCode,
|
StatusCode: statusCode,
|
||||||
Status: http.StatusText(statusCode),
|
Status: http.StatusText(statusCode),
|
||||||
Proto: "HTTP/1.1",
|
Proto: request.Proto,
|
||||||
ProtoMajor: 1,
|
ProtoMajor: request.ProtoMajor,
|
||||||
ProtoMinor: 1,
|
ProtoMinor: request.ProtoMinor,
|
||||||
Header: http.Header{},
|
Header: http.Header{},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,6 @@ package socks
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
|
||||||
"net"
|
"net"
|
||||||
|
|
||||||
"github.com/Dreamacro/clash/adapter/inbound"
|
"github.com/Dreamacro/clash/adapter/inbound"
|
||||||
|
@ -102,7 +101,7 @@ func HandleSocks5(conn net.Conn, in chan<- C.ConnContext) {
|
||||||
}
|
}
|
||||||
if command == socks5.CmdUDPAssociate {
|
if command == socks5.CmdUDPAssociate {
|
||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
io.Copy(ioutil.Discard, conn)
|
io.Copy(io.Discard, conn)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
in <- inbound.NewSocket(target, conn, C.SOCKS5)
|
in <- inbound.NewSocket(target, conn, C.SOCKS5)
|
||||||
|
|
|
@ -109,7 +109,6 @@ func SetTProxyLinuxIPTables(ifname string, tport int, dport int) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func CleanUpTProxyLinuxIPTables() {
|
func CleanUpTProxyLinuxIPTables() {
|
||||||
|
|
||||||
if interfaceName == "" || tproxyPort == 0 || dnsPort == 0 {
|
if interfaceName == "" || tproxyPort == 0 || dnsPort == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -125,7 +124,6 @@ func CleanUpTProxyLinuxIPTables() {
|
||||||
execCmd(fmt.Sprintf("ip -f inet route del local default dev %s table %s", interfaceName, PROXY_ROUTE_TABLE))
|
execCmd(fmt.Sprintf("ip -f inet route del local default dev %s table %s", interfaceName, PROXY_ROUTE_TABLE))
|
||||||
|
|
||||||
// clean FORWARD
|
// clean FORWARD
|
||||||
//execCmd("sysctl -w net.ipv4.ip_forward=0")
|
|
||||||
execCmd(fmt.Sprintf("iptables -t filter -D FORWARD -i %s ! -o %s -j ACCEPT", interfaceName, interfaceName))
|
execCmd(fmt.Sprintf("iptables -t filter -D FORWARD -i %s ! -o %s -j ACCEPT", interfaceName, interfaceName))
|
||||||
execCmd(fmt.Sprintf("iptables -t filter -D FORWARD -i %s -o %s -j ACCEPT", interfaceName, interfaceName))
|
execCmd(fmt.Sprintf("iptables -t filter -D FORWARD -i %s -o %s -j ACCEPT", interfaceName, interfaceName))
|
||||||
execCmd(fmt.Sprintf("iptables -t filter -D FORWARD -o %s -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT", interfaceName))
|
execCmd(fmt.Sprintf("iptables -t filter -D FORWARD -o %s -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT", interfaceName))
|
||||||
|
|
|
@ -20,41 +20,36 @@ import (
|
||||||
"github.com/Dreamacro/clash/common/pool"
|
"github.com/Dreamacro/clash/common/pool"
|
||||||
)
|
)
|
||||||
|
|
||||||
const utunControlName = "com.apple.net.utun_control"
|
const (
|
||||||
const _IOC_OUT = 0x40000000
|
utunControlName = "com.apple.net.utun_control"
|
||||||
const _IOC_IN = 0x80000000
|
iocOut = 0x40000000
|
||||||
const _IOC_INOUT = _IOC_IN | _IOC_OUT
|
iocIn = 0x80000000
|
||||||
|
iocInout = iocIn | iocOut
|
||||||
|
)
|
||||||
|
|
||||||
// _CTLIOCGINFO value derived from /usr/include/sys/{kern_control,ioccom}.h
|
// _CTLIOCGINFO value derived from /usr/include/sys/{kern_control,ioccom}.h
|
||||||
// https://github.com/apple/darwin-xnu/blob/master/bsd/sys/ioccom.h
|
// https://github.com/apple/darwin-xnu/blob/master/bsd/sys/ioccom.h
|
||||||
|
|
||||||
// #define CTLIOCGINFO _IOWR('N', 3, struct ctl_info) /* get id from name */ = 0xc0644e03
|
// #define CTLIOCGINFO _IOWR('N', 3, struct ctl_info) /* get id from name */ = 0xc0644e03
|
||||||
const _CTLIOCGINFO = _IOC_INOUT | ((100 & 0x1fff) << 16) | uint32(byte('N'))<<8 | 3
|
const _CTLIOCGINFO = iocInout | ((100 & 0x1fff) << 16) | uint32(byte('N'))<<8 | 3
|
||||||
|
|
||||||
// #define SIOCAIFADDR_IN6 _IOW('i', 26, struct in6_aliasreq) = 0x8080691a
|
|
||||||
//const _SIOCAIFADDR_IN6 = _IOC_IN | ((128 & 0x1fff) << 16) | uint32(byte('i'))<<8 | 26
|
|
||||||
|
|
||||||
// #define SIOCPROTOATTACH_IN6 _IOWR('i', 110, struct in6_aliasreq_64)
|
// #define SIOCPROTOATTACH_IN6 _IOWR('i', 110, struct in6_aliasreq_64)
|
||||||
const _SIOCPROTOATTACH_IN6 = _IOC_INOUT | ((128 & 0x1fff) << 16) | uint32(byte('i'))<<8 | 110
|
const siocprotoattachIn6 = iocInout | ((128 & 0x1fff) << 16) | uint32(byte('i'))<<8 | 110
|
||||||
|
|
||||||
// #define SIOCLL_START _IOWR('i', 130, struct in6_aliasreq)
|
// #define SIOCLL_START _IOWR('i', 130, struct in6Aliasreq)
|
||||||
const _SIOCLL_START = _IOC_INOUT | ((128 & 0x1fff) << 16) | uint32(byte('i'))<<8 | 130
|
const siocllStart = iocInout | ((128 & 0x1fff) << 16) | uint32(byte('i'))<<8 | 130
|
||||||
|
|
||||||
// https://github.com/apple/darwin-xnu/blob/a449c6a3b8014d9406c2ddbdc81795da24aa7443/bsd/netinet6/nd6.h#L469
|
|
||||||
const ND6_INFINITE_LIFETIME = 0xffffffff
|
|
||||||
|
|
||||||
// Following the wireguard-go solution:
|
// Following the wireguard-go solution:
|
||||||
// These unix.SYS_* constants were removed from golang.org/x/sys/unix
|
// These unix.SYS_* constants were removed from golang.org/x/sys/unix
|
||||||
// so copy them here for now.
|
// so copy them here for now.
|
||||||
// See https://github.com/golang/go/issues/41868
|
// See https://github.com/golang/go/issues/41868
|
||||||
const (
|
const (
|
||||||
sys_IOCTL = 54
|
sysIoctl = 54
|
||||||
sys_CONNECT = 98
|
sysConnect = 98
|
||||||
sys_GETSOCKOPT = 118
|
sysGetsockopt = 118
|
||||||
)
|
)
|
||||||
|
|
||||||
type tunDarwin struct {
|
type tunDarwin struct {
|
||||||
//url string
|
|
||||||
name string
|
name string
|
||||||
tunAddress string
|
tunAddress string
|
||||||
autoRoute bool
|
autoRoute bool
|
||||||
|
@ -75,6 +70,37 @@ type sockaddrCtl struct {
|
||||||
scReserved [5]uint32
|
scReserved [5]uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ctlInfo struct {
|
||||||
|
ctlID uint32
|
||||||
|
ctlName [96]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://github.com/apple/darwin-xnu/blob/a449c6a3b8014d9406c2ddbdc81795da24aa7443/bsd/sys/sockio.h#L107
|
||||||
|
// https://github.com/apple/darwin-xnu/blob/a449c6a3b8014d9406c2ddbdc81795da24aa7443/bsd/net/if.h#L570-L575
|
||||||
|
// https://man.openbsd.org/netintro.4#SIOCAIFADDR
|
||||||
|
type aliasreq struct {
|
||||||
|
ifraName [unix.IFNAMSIZ]byte
|
||||||
|
ifraAddr unix.RawSockaddrInet4
|
||||||
|
ifraDstaddr unix.RawSockaddrInet4
|
||||||
|
ifraMask unix.RawSockaddrInet4
|
||||||
|
}
|
||||||
|
|
||||||
|
// SIOCAIFADDR_IN6
|
||||||
|
// https://github.com/apple/darwin-xnu/blob/a449c6a3b8014d9406c2ddbdc81795da24aa7443/bsd/netinet6/in6_var.h#L114-L119
|
||||||
|
// https://opensource.apple.com/source/network_cmds/network_cmds-543.260.3/
|
||||||
|
type in6Addrlifetime struct{}
|
||||||
|
|
||||||
|
// https://github.com/apple/darwin-xnu/blob/a449c6a3b8014d9406c2ddbdc81795da24aa7443/bsd/netinet6/in6_var.h#L336-L343
|
||||||
|
// https://github.com/apple/darwin-xnu/blob/a449c6a3b8014d9406c2ddbdc81795da24aa7443/bsd/netinet6/in6.h#L174-L181
|
||||||
|
type in6Aliasreq struct {
|
||||||
|
ifraName [unix.IFNAMSIZ]byte
|
||||||
|
ifraAddr unix.RawSockaddrInet6
|
||||||
|
ifraDstaddr unix.RawSockaddrInet6
|
||||||
|
ifraPrefixmask unix.RawSockaddrInet6
|
||||||
|
ifraFlags int32
|
||||||
|
ifraLifetime in6Addrlifetime
|
||||||
|
}
|
||||||
|
|
||||||
// https://github.com/apple/darwin-xnu/blob/a449c6a3b8014d9406c2ddbdc81795da24aa7443/bsd/net/if.h#L402-L563
|
// https://github.com/apple/darwin-xnu/blob/a449c6a3b8014d9406c2ddbdc81795da24aa7443/bsd/net/if.h#L402-L563
|
||||||
|
|
||||||
//type ifreqAddr struct {
|
//type ifreqAddr struct {
|
||||||
|
@ -87,7 +113,6 @@ var sockaddrCtlSize uintptr = 32
|
||||||
|
|
||||||
// OpenTunDevice return a TunDevice according a URL
|
// OpenTunDevice return a TunDevice according a URL
|
||||||
func OpenTunDevice(tunAddress string, autoRoute bool) (TunDevice, error) {
|
func OpenTunDevice(tunAddress string, autoRoute bool) (TunDevice, error) {
|
||||||
|
|
||||||
name := "utun"
|
name := "utun"
|
||||||
// TODO: configure the MTU
|
// TODO: configure the MTU
|
||||||
mtu := 9000
|
mtu := 9000
|
||||||
|
@ -101,23 +126,19 @@ func OpenTunDevice(tunAddress string, autoRoute bool) (TunDevice, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fd, err := unix.Socket(unix.AF_SYSTEM, unix.SOCK_DGRAM, 2)
|
fd, err := unix.Socket(unix.AF_SYSTEM, unix.SOCK_DGRAM, 2)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var ctlInfo = &struct {
|
ctlInfo1 := &ctlInfo{}
|
||||||
ctlID uint32
|
|
||||||
ctlName [96]byte
|
|
||||||
}{}
|
|
||||||
|
|
||||||
copy(ctlInfo.ctlName[:], []byte(utunControlName))
|
copy(ctlInfo1.ctlName[:], []byte(utunControlName))
|
||||||
|
|
||||||
_, _, errno := unix.Syscall(
|
_, _, errno := unix.Syscall(
|
||||||
sys_IOCTL,
|
sysIoctl,
|
||||||
uintptr(fd),
|
uintptr(fd),
|
||||||
uintptr(_CTLIOCGINFO),
|
uintptr(_CTLIOCGINFO),
|
||||||
uintptr(unsafe.Pointer(ctlInfo)),
|
uintptr(unsafe.Pointer(ctlInfo1)),
|
||||||
)
|
)
|
||||||
|
|
||||||
if errno != 0 {
|
if errno != 0 {
|
||||||
|
@ -128,14 +149,14 @@ func OpenTunDevice(tunAddress string, autoRoute bool) (TunDevice, error) {
|
||||||
scLen: uint8(sockaddrCtlSize),
|
scLen: uint8(sockaddrCtlSize),
|
||||||
scFamily: unix.AF_SYSTEM,
|
scFamily: unix.AF_SYSTEM,
|
||||||
ssSysaddr: 2,
|
ssSysaddr: 2,
|
||||||
scID: ctlInfo.ctlID,
|
scID: ctlInfo1.ctlID,
|
||||||
scUnit: uint32(ifIndex) + 1,
|
scUnit: uint32(ifIndex) + 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
scPointer := unsafe.Pointer(&sc)
|
scPointer := unsafe.Pointer(&sc)
|
||||||
|
|
||||||
_, _, errno = unix.RawSyscall(
|
_, _, errno = unix.RawSyscall(
|
||||||
sys_CONNECT,
|
sysConnect,
|
||||||
uintptr(fd),
|
uintptr(fd),
|
||||||
uintptr(scPointer),
|
uintptr(scPointer),
|
||||||
uintptr(sockaddrCtlSize),
|
uintptr(sockaddrCtlSize),
|
||||||
|
@ -151,7 +172,6 @@ func OpenTunDevice(tunAddress string, autoRoute bool) (TunDevice, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
tun, err := CreateTUNFromFile(os.NewFile(uintptr(fd), ""), mtu, tunAddress, autoRoute)
|
tun, err := CreateTUNFromFile(os.NewFile(uintptr(fd), ""), mtu, tunAddress, autoRoute)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -271,7 +291,6 @@ func (t *tunDarwin) Close() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *tunDarwin) getInterfaceMtu() (int, error) {
|
func (t *tunDarwin) getInterfaceMtu() (int, error) {
|
||||||
|
|
||||||
// open datagram socket
|
// open datagram socket
|
||||||
|
|
||||||
fd, err := unix.Socket(
|
fd, err := unix.Socket(
|
||||||
|
@ -279,7 +298,6 @@ func (t *tunDarwin) getInterfaceMtu() (int, error) {
|
||||||
unix.SOCK_DGRAM,
|
unix.SOCK_DGRAM,
|
||||||
0,
|
0,
|
||||||
)
|
)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
@ -291,7 +309,7 @@ func (t *tunDarwin) getInterfaceMtu() (int, error) {
|
||||||
var ifr [64]byte
|
var ifr [64]byte
|
||||||
copy(ifr[:], t.name)
|
copy(ifr[:], t.name)
|
||||||
_, _, errno := unix.Syscall(
|
_, _, errno := unix.Syscall(
|
||||||
sys_IOCTL,
|
sysIoctl,
|
||||||
uintptr(fd),
|
uintptr(fd),
|
||||||
uintptr(unix.SIOCGIFMTU),
|
uintptr(unix.SIOCGIFMTU),
|
||||||
uintptr(unsafe.Pointer(&ifr[0])),
|
uintptr(unsafe.Pointer(&ifr[0])),
|
||||||
|
@ -312,7 +330,7 @@ func (t *tunDarwin) getName() (string, error) {
|
||||||
var errno syscall.Errno
|
var errno syscall.Errno
|
||||||
t.operateOnFd(func(fd uintptr) {
|
t.operateOnFd(func(fd uintptr) {
|
||||||
_, _, errno = unix.Syscall6(
|
_, _, errno = unix.Syscall6(
|
||||||
sys_GETSOCKOPT,
|
sysGetsockopt,
|
||||||
fd,
|
fd,
|
||||||
2, /* #define SYSPROTO_CONTROL 2 */
|
2, /* #define SYSPROTO_CONTROL 2 */
|
||||||
2, /* #define UTUN_OPT_IFNAME 2 */
|
2, /* #define UTUN_OPT_IFNAME 2 */
|
||||||
|
@ -335,7 +353,6 @@ func (t *tunDarwin) setMTU(n int) error {
|
||||||
unix.SOCK_DGRAM,
|
unix.SOCK_DGRAM,
|
||||||
0,
|
0,
|
||||||
)
|
)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -348,7 +365,7 @@ func (t *tunDarwin) setMTU(n int) error {
|
||||||
copy(ifr[:], t.name)
|
copy(ifr[:], t.name)
|
||||||
*(*uint32)(unsafe.Pointer(&ifr[unix.IFNAMSIZ])) = uint32(n)
|
*(*uint32)(unsafe.Pointer(&ifr[unix.IFNAMSIZ])) = uint32(n)
|
||||||
_, _, errno := unix.Syscall(
|
_, _, errno := unix.Syscall(
|
||||||
sys_IOCTL,
|
sysIoctl,
|
||||||
uintptr(fd),
|
uintptr(fd),
|
||||||
uintptr(unix.SIOCSIFMTU),
|
uintptr(unix.SIOCSIFMTU),
|
||||||
uintptr(unsafe.Pointer(&ifr[0])),
|
uintptr(unsafe.Pointer(&ifr[0])),
|
||||||
|
@ -389,32 +406,22 @@ func (t *tunDarwin) setTunAddress(addr net.IP) error {
|
||||||
}
|
}
|
||||||
defer syscall.Close(fd4)
|
defer syscall.Close(fd4)
|
||||||
|
|
||||||
// https://github.com/apple/darwin-xnu/blob/a449c6a3b8014d9406c2ddbdc81795da24aa7443/bsd/sys/sockio.h#L107
|
|
||||||
// https://github.com/apple/darwin-xnu/blob/a449c6a3b8014d9406c2ddbdc81795da24aa7443/bsd/net/if.h#L570-L575
|
|
||||||
// https://man.openbsd.org/netintro.4#SIOCAIFADDR
|
|
||||||
type aliasreq struct {
|
|
||||||
ifra_name [unix.IFNAMSIZ]byte
|
|
||||||
ifra_addr unix.RawSockaddrInet4
|
|
||||||
ifra_dstaddr unix.RawSockaddrInet4
|
|
||||||
ifra_mask unix.RawSockaddrInet4
|
|
||||||
}
|
|
||||||
|
|
||||||
var ip4 [4]byte
|
var ip4 [4]byte
|
||||||
copy(ip4[:], addr.To4())
|
copy(ip4[:], addr.To4())
|
||||||
ip4mask := [4]byte{255, 255, 0, 0}
|
ip4mask := [4]byte{255, 255, 0, 0}
|
||||||
ifra4 := aliasreq{
|
ifra4 := aliasreq{
|
||||||
ifra_name: ifr,
|
ifraName: ifr,
|
||||||
ifra_addr: unix.RawSockaddrInet4{
|
ifraAddr: unix.RawSockaddrInet4{
|
||||||
Len: unix.SizeofSockaddrInet4,
|
Len: unix.SizeofSockaddrInet4,
|
||||||
Family: unix.AF_INET,
|
Family: unix.AF_INET,
|
||||||
Addr: ip4,
|
Addr: ip4,
|
||||||
},
|
},
|
||||||
ifra_dstaddr: unix.RawSockaddrInet4{
|
ifraDstaddr: unix.RawSockaddrInet4{
|
||||||
Len: unix.SizeofSockaddrInet4,
|
Len: unix.SizeofSockaddrInet4,
|
||||||
Family: unix.AF_INET,
|
Family: unix.AF_INET,
|
||||||
Addr: ip4,
|
Addr: ip4,
|
||||||
},
|
},
|
||||||
ifra_mask: unix.RawSockaddrInet4{
|
ifraMask: unix.RawSockaddrInet4{
|
||||||
Len: unix.SizeofSockaddrInet4,
|
Len: unix.SizeofSockaddrInet4,
|
||||||
Family: unix.AF_INET,
|
Family: unix.AF_INET,
|
||||||
Addr: ip4mask,
|
Addr: ip4mask,
|
||||||
|
@ -422,7 +429,7 @@ func (t *tunDarwin) setTunAddress(addr net.IP) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, _, errno := unix.Syscall(
|
if _, _, errno := unix.Syscall(
|
||||||
sys_IOCTL,
|
sysIoctl,
|
||||||
uintptr(fd4),
|
uintptr(fd4),
|
||||||
uintptr(unix.SIOCAIFADDR),
|
uintptr(unix.SIOCAIFADDR),
|
||||||
uintptr(unsafe.Pointer(&ifra4)),
|
uintptr(unsafe.Pointer(&ifra4)),
|
||||||
|
@ -447,42 +454,24 @@ func (t *tunDarwin) attachLinkLocal() error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer syscall.Close(fd6)
|
defer syscall.Close(fd6)
|
||||||
// SIOCAIFADDR_IN6
|
|
||||||
// https://github.com/apple/darwin-xnu/blob/a449c6a3b8014d9406c2ddbdc81795da24aa7443/bsd/netinet6/in6_var.h#L114-L119
|
|
||||||
// https://opensource.apple.com/source/network_cmds/network_cmds-543.260.3/
|
|
||||||
type in6_addrlifetime struct {
|
|
||||||
//ia6t_expire uint64
|
|
||||||
//ia6t_preferred uint64
|
|
||||||
//ia6t_vltime uint32
|
|
||||||
//ia6t_pltime uint32
|
|
||||||
}
|
|
||||||
// https://github.com/apple/darwin-xnu/blob/a449c6a3b8014d9406c2ddbdc81795da24aa7443/bsd/netinet6/in6_var.h#L336-L343
|
|
||||||
// https://github.com/apple/darwin-xnu/blob/a449c6a3b8014d9406c2ddbdc81795da24aa7443/bsd/netinet6/in6.h#L174-L181
|
|
||||||
type in6_aliasreq struct {
|
|
||||||
ifra_name [unix.IFNAMSIZ]byte
|
|
||||||
ifra_addr unix.RawSockaddrInet6
|
|
||||||
ifra_dstaddr unix.RawSockaddrInet6
|
|
||||||
ifra_prefixmask unix.RawSockaddrInet6
|
|
||||||
ifra_flags int32
|
|
||||||
ifra_lifetime in6_addrlifetime
|
|
||||||
}
|
|
||||||
// Attach link-local address
|
// Attach link-local address
|
||||||
ifra6 := in6_aliasreq{
|
ifra6 := in6Aliasreq{
|
||||||
ifra_name: ifr,
|
ifraName: ifr,
|
||||||
}
|
}
|
||||||
if _, _, errno := unix.Syscall(
|
if _, _, errno := unix.Syscall(
|
||||||
sys_IOCTL,
|
sysIoctl,
|
||||||
uintptr(fd6),
|
uintptr(fd6),
|
||||||
uintptr(_SIOCPROTOATTACH_IN6),
|
uintptr(siocprotoattachIn6),
|
||||||
uintptr(unsafe.Pointer(&ifra6)),
|
uintptr(unsafe.Pointer(&ifra6)),
|
||||||
); errno != 0 {
|
); errno != 0 {
|
||||||
return fmt.Errorf("failed to attach link-local address on %s: SIOCPROTOATTACH_IN6 %v", t.name, errno)
|
return fmt.Errorf("failed to attach link-local address on %s: SIOCPROTOATTACH_IN6 %v", t.name, errno)
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, _, errno := unix.Syscall(
|
if _, _, errno := unix.Syscall(
|
||||||
sys_IOCTL,
|
sysIoctl,
|
||||||
uintptr(fd6),
|
uintptr(fd6),
|
||||||
uintptr(_SIOCLL_START),
|
uintptr(siocllStart),
|
||||||
uintptr(unsafe.Pointer(&ifra6)),
|
uintptr(unsafe.Pointer(&ifra6)),
|
||||||
); errno != 0 {
|
); errno != 0 {
|
||||||
return fmt.Errorf("failed to set ipv6 address on %s: SIOCLL_START %v", t.name, errno)
|
return fmt.Errorf("failed to set ipv6 address on %s: SIOCLL_START %v", t.name, errno)
|
||||||
|
|
|
@ -48,7 +48,6 @@ type gvisorAdapter struct {
|
||||||
|
|
||||||
// GvisorAdapter create GvisorAdapter
|
// GvisorAdapter create GvisorAdapter
|
||||||
func NewAdapter(device dev.TunDevice, conf config.Tun, tunAddress string, tcpIn chan<- C.ConnContext, udpIn chan<- *inbound.PacketAdapter) (ipstack.TunAdapter, error) {
|
func NewAdapter(device dev.TunDevice, conf config.Tun, tunAddress string, tcpIn chan<- C.ConnContext, udpIn chan<- *inbound.PacketAdapter) (ipstack.TunAdapter, error) {
|
||||||
|
|
||||||
ipstack := stack.New(stack.Options{
|
ipstack := stack.New(stack.Options{
|
||||||
NetworkProtocols: []stack.NetworkProtocolFactory{ipv4.NewProtocol, ipv6.NewProtocol},
|
NetworkProtocols: []stack.NetworkProtocolFactory{ipv4.NewProtocol, ipv6.NewProtocol},
|
||||||
TransportProtocols: []stack.TransportProtocolFactory{tcp.NewProtocol, udp.NewProtocol},
|
TransportProtocols: []stack.TransportProtocolFactory{tcp.NewProtocol, udp.NewProtocol},
|
||||||
|
@ -180,7 +179,6 @@ func (t *gvisorAdapter) AsLinkEndpoint() (result stack.LinkEndpoint, err error)
|
||||||
}
|
}
|
||||||
|
|
||||||
mtu, err := t.device.MTU()
|
mtu, err := t.device.MTU()
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.New("unable to get device mtu")
|
return nil, errors.New("unable to get device mtu")
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,7 +73,6 @@ func (e *dnsEndpoint) Close() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *dnsEndpoint) Wait() {
|
func (e *dnsEndpoint) Wait() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *dnsEndpoint) HandleError(transErr stack.TransportError, pkt *stack.PacketBuffer) {
|
func (e *dnsEndpoint) HandleError(transErr stack.TransportError, pkt *stack.PacketBuffer) {
|
||||||
|
@ -102,13 +101,16 @@ func (w *dnsResponseWriter) WriteMsg(msg *D.Msg) error {
|
||||||
_, err = w.Write(b)
|
_, err = w.Write(b)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *dnsResponseWriter) TsigStatus() error {
|
func (w *dnsResponseWriter) TsigStatus() error {
|
||||||
// Unsupported
|
// Unsupported
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *dnsResponseWriter) TsigTimersOnly(bool) {
|
func (w *dnsResponseWriter) TsigTimersOnly(bool) {
|
||||||
// Unsupported
|
// Unsupported
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *dnsResponseWriter) Hijack() {
|
func (w *dnsResponseWriter) Hijack() {
|
||||||
// Unsupported
|
// Unsupported
|
||||||
}
|
}
|
||||||
|
@ -128,7 +130,6 @@ func (w *dnsResponseWriter) Close() error {
|
||||||
|
|
||||||
// CreateDNSServer create a dns server on given netstack
|
// CreateDNSServer create a dns server on given netstack
|
||||||
func CreateDNSServer(s *stack.Stack, resolver *dns.Resolver, mapper *dns.ResolverEnhancer, ip net.IP, port int, nicID tcpip.NICID) (*DNSServer, error) {
|
func CreateDNSServer(s *stack.Stack, resolver *dns.Resolver, mapper *dns.ResolverEnhancer, ip net.IP, port int, nicID tcpip.NICID) (*DNSServer, error) {
|
||||||
|
|
||||||
var v4 bool
|
var v4 bool
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
|
|
|
@ -53,7 +53,6 @@ func (c *fakeConn) Close() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *fakeConn) Drop() {
|
func (c *fakeConn) Drop() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *fakeConn) FakeIP() bool {
|
func (c *fakeConn) FakeIP() bool {
|
||||||
|
|
|
@ -75,8 +75,7 @@ func hijackTCPDns(conn net.Conn) {
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
type dnsHandler struct {
|
type dnsHandler struct{}
|
||||||
}
|
|
||||||
|
|
||||||
func NewDnsHandler() golwip.DnsHandler {
|
func NewDnsHandler() golwip.DnsHandler {
|
||||||
return &dnsHandler{}
|
return &dnsHandler{}
|
||||||
|
|
|
@ -48,8 +48,7 @@ func (h *tcpHandler) Handle(conn net.Conn, target *net.TCPAddr) error {
|
||||||
DstIP: dst.IP,
|
DstIP: dst.IP,
|
||||||
SrcPort: strconv.Itoa(src.Port),
|
SrcPort: strconv.Itoa(src.Port),
|
||||||
DstPort: strconv.Itoa(dst.Port),
|
DstPort: strconv.Itoa(dst.Port),
|
||||||
//AddrType: addrType,
|
Host: "",
|
||||||
Host: "",
|
|
||||||
}
|
}
|
||||||
|
|
||||||
go func(conn net.Conn, metadata *C.Metadata) {
|
go func(conn net.Conn, metadata *C.Metadata) {
|
||||||
|
|
|
@ -36,8 +36,6 @@ func NewAdapter(device dev.TunDevice, conf config.Tun, mtu int, tcpIn chan<- C.C
|
||||||
adapter.lock.Lock()
|
adapter.lock.Lock()
|
||||||
defer adapter.lock.Unlock()
|
defer adapter.lock.Unlock()
|
||||||
|
|
||||||
//adapter.stopLocked()
|
|
||||||
|
|
||||||
dnsHost, _, err := net.SplitHostPort(conf.DNSListen)
|
dnsHost, _, err := net.SplitHostPort(conf.DNSListen)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
@ -24,7 +24,6 @@ func shouldHijackDns(dnsAddr binding.Address, targetAddr binding.Address) bool {
|
||||||
func hijackUDPDns(pkt []byte, ep *binding.Endpoint, sender redirect.UDPSender) {
|
func hijackUDPDns(pkt []byte, ep *binding.Endpoint, sender redirect.UDPSender) {
|
||||||
go func() {
|
go func() {
|
||||||
answer, err := D.RelayDnsPacket(pkt)
|
answer, err := D.RelayDnsPacket(pkt)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,20 +22,19 @@ func handleTCP(conn net.Conn, endpoint *binding.Endpoint, tcpIn chan<- C.ConnCon
|
||||||
Zone: "",
|
Zone: "",
|
||||||
}
|
}
|
||||||
|
|
||||||
addrType := C.AtypIPv4
|
//addrType := C.AtypIPv4
|
||||||
if dst.IP.To4() == nil {
|
//if dst.IP.To4() == nil {
|
||||||
addrType = C.AtypIPv6
|
// addrType = C.AtypIPv6
|
||||||
}
|
//}
|
||||||
|
|
||||||
metadata := &C.Metadata{
|
metadata := &C.Metadata{
|
||||||
NetWork: C.TCP,
|
NetWork: C.TCP,
|
||||||
Type: C.TUN,
|
Type: C.TUN,
|
||||||
SrcIP: src.IP,
|
SrcIP: src.IP,
|
||||||
DstIP: dst.IP,
|
DstIP: dst.IP,
|
||||||
SrcPort: strconv.Itoa(src.Port),
|
SrcPort: strconv.Itoa(src.Port),
|
||||||
DstPort: strconv.Itoa(dst.Port),
|
DstPort: strconv.Itoa(dst.Port),
|
||||||
AddrType: addrType,
|
Host: "",
|
||||||
Host: "",
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tcpIn <- context.NewConnContext(conn, metadata)
|
tcpIn <- context.NewConnContext(conn, metadata)
|
||||||
|
|
|
@ -26,7 +26,6 @@ type systemAdapter struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewAdapter(device dev.TunDevice, conf config.Tun, mtu int, gateway, mirror string, onStop func(), tcpIn chan<- C.ConnContext, udpIn chan<- *inbound.PacketAdapter) (ipstack.TunAdapter, error) {
|
func NewAdapter(device dev.TunDevice, conf config.Tun, mtu int, gateway, mirror string, onStop func(), tcpIn chan<- C.ConnContext, udpIn chan<- *inbound.PacketAdapter) (ipstack.TunAdapter, error) {
|
||||||
|
|
||||||
adapter := &systemAdapter{
|
adapter := &systemAdapter{
|
||||||
device: device,
|
device: device,
|
||||||
stackName: conf.Stack,
|
stackName: conf.Stack,
|
||||||
|
@ -37,8 +36,6 @@ func NewAdapter(device dev.TunDevice, conf config.Tun, mtu int, gateway, mirror
|
||||||
adapter.lock.Lock()
|
adapter.lock.Lock()
|
||||||
defer adapter.lock.Unlock()
|
defer adapter.lock.Unlock()
|
||||||
|
|
||||||
//adapter.stopLocked()
|
|
||||||
|
|
||||||
dnsHost, dnsPort, err := net.SplitHostPort(conf.DNSListen)
|
dnsHost, dnsPort, err := net.SplitHostPort(conf.DNSListen)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
18
log/level.go
18
log/level.go
|
@ -5,16 +5,14 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
// LogLevelMapping is a mapping for LogLevel enum
|
||||||
// LogLevelMapping is a mapping for LogLevel enum
|
var LogLevelMapping = map[string]LogLevel{
|
||||||
LogLevelMapping = map[string]LogLevel{
|
ERROR.String(): ERROR,
|
||||||
ERROR.String(): ERROR,
|
WARNING.String(): WARNING,
|
||||||
WARNING.String(): WARNING,
|
INFO.String(): INFO,
|
||||||
INFO.String(): INFO,
|
DEBUG.String(): DEBUG,
|
||||||
DEBUG.String(): DEBUG,
|
SILENT.String(): SILENT,
|
||||||
SILENT.String(): SILENT,
|
}
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
const (
|
||||||
DEBUG LogLevel = iota
|
DEBUG LogLevel = iota
|
||||||
|
|
|
@ -235,8 +235,6 @@ func (ac *ACAutomaton) Match(s string) bool {
|
||||||
if fullMatch {
|
if fullMatch {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
//default:
|
|
||||||
// //break // ineffective break statement, code "break" can not pass staticcheck check. don't sure that mean, so just block it.
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return fullMatch && ac.exists[node].exist
|
return fullMatch && ac.exists[node].exist
|
||||||
|
|
|
@ -49,7 +49,6 @@ func (gs *GEOSITE) RuleExtra() *C.RuleExtra {
|
||||||
|
|
||||||
func NewGEOSITE(country string, adapter string, ruleExtra *C.RuleExtra) (*GEOSITE, error) {
|
func NewGEOSITE(country string, adapter string, ruleExtra *C.RuleExtra) (*GEOSITE, error) {
|
||||||
geoLoaderName := "standard"
|
geoLoaderName := "standard"
|
||||||
//geoLoaderName := "memconservative"
|
|
||||||
geoLoader, err := geodata.GetGeoDataLoader(geoLoaderName)
|
geoLoader, err := geodata.GetGeoDataLoader(geoLoaderName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("load GeoSite data error, %s", err.Error())
|
return nil, fmt.Errorf("load GeoSite data error, %s", err.Error())
|
||||||
|
@ -60,10 +59,11 @@ func NewGEOSITE(country string, adapter string, ruleExtra *C.RuleExtra) (*GEOSIT
|
||||||
return nil, fmt.Errorf("load GeoSite data error, %s", err.Error())
|
return nil, fmt.Errorf("load GeoSite data error, %s", err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
//linear: linear algorithm
|
/**
|
||||||
//matcher, err := router.NewDomainMatcher(domains)
|
linear: linear algorithm
|
||||||
|
matcher, err := router.NewDomainMatcher(domains)
|
||||||
//mph:minimal perfect hash algorithm
|
mph:minimal perfect hash algorithm
|
||||||
|
*/
|
||||||
matcher, err := router.NewMphMatcherGroup(domains)
|
matcher, err := router.NewMphMatcherGroup(domains)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("load GeoSite data error, %s", err.Error())
|
return nil, fmt.Errorf("load GeoSite data error, %s", err.Error())
|
||||||
|
|
|
@ -68,7 +68,6 @@ func (p *Port) matchPortReal(portRef string) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewPort(port string, adapter string, isSource bool, ruleExtra *C.RuleExtra) (*Port, error) {
|
func NewPort(port string, adapter string, isSource bool, ruleExtra *C.RuleExtra) (*Port, error) {
|
||||||
//the port format should be like this: "123/136/137-139" or "[123]/[136-139]"
|
|
||||||
ports := strings.Split(port, "/")
|
ports := strings.Split(port, "/")
|
||||||
if len(ports) > 28 {
|
if len(ports) > 28 {
|
||||||
return nil, fmt.Errorf("%s, too many ports to use, maximum support 28 ports", errPayload.Error())
|
return nil, fmt.Errorf("%s, too many ports to use, maximum support 28 ports", errPayload.Error())
|
||||||
|
@ -93,7 +92,6 @@ func NewPort(port string, adapter string, isSource bool, ruleExtra *C.RuleExtra)
|
||||||
|
|
||||||
if subPortsLen == 1 {
|
if subPortsLen == 1 {
|
||||||
portList = append(portList, portReal{portStart, -1})
|
portList = append(portList, portReal{portStart, -1})
|
||||||
|
|
||||||
} else if subPortsLen == 2 {
|
} else if subPortsLen == 2 {
|
||||||
portEnd, err1 := strconv.Atoi(strings.Trim(subPorts[1], "[ ]"))
|
portEnd, err1 := strconv.Atoi(strings.Trim(subPorts[1], "[ ]"))
|
||||||
if err1 != nil || portEnd < 0 || portEnd > 65535 {
|
if err1 != nil || portEnd < 0 || portEnd > 65535 {
|
||||||
|
|
|
@ -24,9 +24,7 @@ func (ps *Process) RuleType() C.RuleType {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ps *Process) Match(metadata *C.Metadata) bool {
|
func (ps *Process) Match(metadata *C.Metadata) bool {
|
||||||
|
|
||||||
if metadata.Process != "" {
|
if metadata.Process != "" {
|
||||||
//log.Debugln("Use cache process: %s", metadata.Process)
|
|
||||||
return strings.EqualFold(metadata.Process, ps.process)
|
return strings.EqualFold(metadata.Process, ps.process)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,11 +2,12 @@ package rules
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"runtime"
|
||||||
|
"strings"
|
||||||
|
|
||||||
S "github.com/Dreamacro/clash/component/script"
|
S "github.com/Dreamacro/clash/component/script"
|
||||||
C "github.com/Dreamacro/clash/constant"
|
C "github.com/Dreamacro/clash/constant"
|
||||||
"github.com/Dreamacro/clash/log"
|
"github.com/Dreamacro/clash/log"
|
||||||
"runtime"
|
|
||||||
"strings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Script struct {
|
type Script struct {
|
||||||
|
|
8
test/Makefile
Normal file
8
test/Makefile
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
lint:
|
||||||
|
golangci-lint run --disable-all -E govet -E gofumpt -E megacheck ./...
|
||||||
|
|
||||||
|
test:
|
||||||
|
go test -p 1 -v ./...
|
||||||
|
|
||||||
|
benchmark:
|
||||||
|
go test -benchmem -run=^$ -bench .
|
|
@ -45,7 +45,7 @@ Prerequisite
|
||||||
* docker (support Linux and macOS)
|
* docker (support Linux and macOS)
|
||||||
|
|
||||||
```
|
```
|
||||||
$ go test -p 1 -v
|
$ make test
|
||||||
```
|
```
|
||||||
|
|
||||||
benchmark (Linux)
|
benchmark (Linux)
|
||||||
|
@ -55,5 +55,5 @@ benchmark (Linux)
|
||||||
> (change chunkSize to measure the maximum throughput of clash on your machine)
|
> (change chunkSize to measure the maximum throughput of clash on your machine)
|
||||||
|
|
||||||
```
|
```
|
||||||
$ go test -benchmem -run=^$ -bench .
|
$ make benchmark
|
||||||
```
|
```
|
||||||
|
|
|
@ -31,6 +31,7 @@ const (
|
||||||
ImageShadowsocksRust = "ghcr.io/shadowsocks/ssserver-rust:latest"
|
ImageShadowsocksRust = "ghcr.io/shadowsocks/ssserver-rust:latest"
|
||||||
ImageVmess = "v2fly/v2fly-core:latest"
|
ImageVmess = "v2fly/v2fly-core:latest"
|
||||||
ImageTrojan = "trojangfw/trojan:latest"
|
ImageTrojan = "trojangfw/trojan:latest"
|
||||||
|
ImageTrojanGo = "p4gefau1t/trojan-go:latest"
|
||||||
ImageSnell = "icpz/snell-server:latest"
|
ImageSnell = "icpz/snell-server:latest"
|
||||||
ImageXray = "teddysun/xray:latest"
|
ImageXray = "teddysun/xray:latest"
|
||||||
)
|
)
|
||||||
|
@ -96,8 +97,10 @@ func init() {
|
||||||
|
|
||||||
images := []string{
|
images := []string{
|
||||||
ImageShadowsocks,
|
ImageShadowsocks,
|
||||||
|
ImageShadowsocksRust,
|
||||||
ImageVmess,
|
ImageVmess,
|
||||||
ImageTrojan,
|
ImageTrojan,
|
||||||
|
ImageTrojanGo,
|
||||||
ImageSnell,
|
ImageSnell,
|
||||||
ImageXray,
|
ImageXray,
|
||||||
}
|
}
|
||||||
|
@ -582,7 +585,7 @@ func testSuit(t *testing.T, proxy C.ProxyAdapter) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
pc, err := proxy.DialUDP(&C.Metadata{
|
pc, err := proxy.ListenPacketContext(context.Background(), &C.Metadata{
|
||||||
NetWork: C.UDP,
|
NetWork: C.UDP,
|
||||||
DstIP: localIP,
|
DstIP: localIP,
|
||||||
DstPort: "10001",
|
DstPort: "10001",
|
||||||
|
@ -595,7 +598,7 @@ func testSuit(t *testing.T, proxy C.ProxyAdapter) {
|
||||||
|
|
||||||
assert.NoError(t, testPingPongWithPacketConn(t, pc))
|
assert.NoError(t, testPingPongWithPacketConn(t, pc))
|
||||||
|
|
||||||
pc, err = proxy.DialUDP(&C.Metadata{
|
pc, err = proxy.ListenPacketContext(context.Background(), &C.Metadata{
|
||||||
NetWork: C.UDP,
|
NetWork: C.UDP,
|
||||||
DstIP: localIP,
|
DstIP: localIP,
|
||||||
DstPort: "10001",
|
DstPort: "10001",
|
||||||
|
@ -608,7 +611,7 @@ func testSuit(t *testing.T, proxy C.ProxyAdapter) {
|
||||||
|
|
||||||
assert.NoError(t, testLargeDataWithPacketConn(t, pc))
|
assert.NoError(t, testLargeDataWithPacketConn(t, pc))
|
||||||
|
|
||||||
pc, err = proxy.DialUDP(&C.Metadata{
|
pc, err = proxy.ListenPacketContext(context.Background(), &C.Metadata{
|
||||||
NetWork: C.UDP,
|
NetWork: C.UDP,
|
||||||
DstIP: localIP,
|
DstIP: localIP,
|
||||||
DstPort: "10001",
|
DstPort: "10001",
|
||||||
|
|
20
test/config/trojan-ws.json
Normal file
20
test/config/trojan-ws.json
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
{
|
||||||
|
"run_type": "server",
|
||||||
|
"local_addr": "0.0.0.0",
|
||||||
|
"local_port": 10002,
|
||||||
|
"disable_http_check": true,
|
||||||
|
"password": [
|
||||||
|
"example"
|
||||||
|
],
|
||||||
|
"websocket": {
|
||||||
|
"enabled": true,
|
||||||
|
"path": "/",
|
||||||
|
"host": "example.org"
|
||||||
|
},
|
||||||
|
"ssl": {
|
||||||
|
"verify": true,
|
||||||
|
"cert": "/fullchain.pem",
|
||||||
|
"key": "/privkey.pem",
|
||||||
|
"sni": "example.org"
|
||||||
|
}
|
||||||
|
}
|
10
test/go.mod
10
test/go.mod
|
@ -23,7 +23,7 @@ require (
|
||||||
github.com/gofrs/uuid v4.0.0+incompatible // indirect
|
github.com/gofrs/uuid v4.0.0+incompatible // indirect
|
||||||
github.com/gogo/protobuf v1.3.2 // indirect
|
github.com/gogo/protobuf v1.3.2 // indirect
|
||||||
github.com/golang/protobuf v1.5.0 // indirect
|
github.com/golang/protobuf v1.5.0 // indirect
|
||||||
github.com/google/btree v1.0.0 // indirect
|
github.com/google/btree v1.0.1 // indirect
|
||||||
github.com/gorilla/mux v1.8.0 // indirect
|
github.com/gorilla/mux v1.8.0 // indirect
|
||||||
github.com/gorilla/websocket v1.4.2 // indirect
|
github.com/gorilla/websocket v1.4.2 // indirect
|
||||||
github.com/insomniacslk/dhcp v0.0.0-20210827173440-b95caade3eac // indirect
|
github.com/insomniacslk/dhcp v0.0.0-20210827173440-b95caade3eac // indirect
|
||||||
|
@ -32,21 +32,25 @@ require (
|
||||||
github.com/morikuni/aec v1.0.0 // indirect
|
github.com/morikuni/aec v1.0.0 // indirect
|
||||||
github.com/opencontainers/go-digest v1.0.0 // indirect
|
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||||
github.com/opencontainers/image-spec v1.0.1 // indirect
|
github.com/opencontainers/image-spec v1.0.1 // indirect
|
||||||
|
github.com/oschwald/geoip2-golang v1.5.0 // indirect
|
||||||
|
github.com/oschwald/maxminddb-golang v1.8.0 // indirect
|
||||||
github.com/pkg/errors v0.9.1 // indirect
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
github.com/sirupsen/logrus v1.8.1 // indirect
|
github.com/sirupsen/logrus v1.8.1 // indirect
|
||||||
github.com/u-root/uio v0.0.0-20210528114334-82958018845c // indirect
|
github.com/u-root/uio v0.0.0-20210528114334-82958018845c // indirect
|
||||||
github.com/xtls/go v0.0.0-20201118062508-3632bf3b7499 // indirect
|
github.com/xtls/go v0.0.0-20201118062508-3632bf3b7499 // indirect
|
||||||
|
github.com/yaling888/go-lwip v0.0.0-20210928231210-94b50cb51cc1 // indirect
|
||||||
|
go.etcd.io/bbolt v1.3.6 // indirect
|
||||||
go.uber.org/atomic v1.9.0 // indirect
|
go.uber.org/atomic v1.9.0 // indirect
|
||||||
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 // indirect
|
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 // indirect
|
||||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
|
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
|
||||||
golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34 // indirect
|
golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34 // indirect
|
||||||
golang.org/x/text v0.3.6 // indirect
|
golang.org/x/text v0.3.6 // indirect
|
||||||
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect
|
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect
|
||||||
google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7 // indirect
|
google.golang.org/genproto v0.0.0-20210312152112-fc591d9ea70f // indirect
|
||||||
google.golang.org/grpc v1.40.0 // indirect
|
google.golang.org/grpc v1.40.0 // indirect
|
||||||
google.golang.org/protobuf v1.27.1 // indirect
|
google.golang.org/protobuf v1.27.1 // indirect
|
||||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect
|
||||||
gvisor.dev/gvisor v0.0.0-20210519191755-bd7eb2c99ba9 // indirect
|
gvisor.dev/gvisor v0.0.0-20210922003438-b39716d116fd // indirect
|
||||||
)
|
)
|
||||||
|
|
85
test/go.sum
85
test/go.sum
|
@ -15,7 +15,9 @@ cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZ
|
||||||
cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
|
cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
|
||||||
cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
|
cloud.google.com/go v0.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.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY=
|
cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk=
|
||||||
|
cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg=
|
||||||
|
cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8=
|
||||||
cloud.google.com/go/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=
|
||||||
|
@ -82,6 +84,7 @@ github.com/Microsoft/hcsshim/test v0.0.0-20210227013316-43a75bb4edd3/go.mod h1:m
|
||||||
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
|
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
|
||||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||||
github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
|
github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
|
||||||
|
github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
|
||||||
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
|
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
|
||||||
github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
|
github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
|
||||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
|
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
|
||||||
|
@ -95,6 +98,7 @@ github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kd
|
||||||
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
|
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
|
||||||
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
|
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
|
||||||
github.com/aws/aws-sdk-go v1.15.11/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0=
|
github.com/aws/aws-sdk-go v1.15.11/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0=
|
||||||
|
github.com/bazelbuild/rules_go v0.27.0/go.mod h1:MC23Dc/wkXEyk3Wpq6lCqz0ZAYOZDw2DR5y3N1q2i7M=
|
||||||
github.com/beorn7/perks v0.0.0-20160804104726-4c0e84591b9a/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
github.com/beorn7/perks v0.0.0-20160804104726-4c0e84591b9a/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 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=
|
||||||
|
@ -103,6 +107,7 @@ github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kB
|
||||||
github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA=
|
github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA=
|
||||||
github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA=
|
github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA=
|
||||||
github.com/blang/semver v3.1.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
|
github.com/blang/semver v3.1.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
|
||||||
|
github.com/blang/semver v3.5.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
|
||||||
github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
|
github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
|
||||||
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4=
|
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4=
|
||||||
github.com/bshuster-repo/logrus-logstash-hook v0.4.1/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk=
|
github.com/bshuster-repo/logrus-logstash-hook v0.4.1/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk=
|
||||||
|
@ -188,6 +193,7 @@ github.com/containerd/go-runc v0.0.0-20200220073739-7016d3ce2328/go.mod h1:PpyHr
|
||||||
github.com/containerd/go-runc v0.0.0-20201020171139-16b287bc67d0/go.mod h1:cNU0ZbCgCQVZK4lgG3P+9tn9/PaJNmoDXPpoJhDR+Ok=
|
github.com/containerd/go-runc v0.0.0-20201020171139-16b287bc67d0/go.mod h1:cNU0ZbCgCQVZK4lgG3P+9tn9/PaJNmoDXPpoJhDR+Ok=
|
||||||
github.com/containerd/go-runc v1.0.0/go.mod h1:cNU0ZbCgCQVZK4lgG3P+9tn9/PaJNmoDXPpoJhDR+Ok=
|
github.com/containerd/go-runc v1.0.0/go.mod h1:cNU0ZbCgCQVZK4lgG3P+9tn9/PaJNmoDXPpoJhDR+Ok=
|
||||||
github.com/containerd/imgcrypt v1.0.1/go.mod h1:mdd8cEPW7TPgNG4FpuP3sGBiQ7Yi/zak9TYCG3juvb0=
|
github.com/containerd/imgcrypt v1.0.1/go.mod h1:mdd8cEPW7TPgNG4FpuP3sGBiQ7Yi/zak9TYCG3juvb0=
|
||||||
|
github.com/containerd/imgcrypt v1.0.3/go.mod h1:v4X3p/H0lzcvVE0r7whbRYjYuK9Y2KEJnL08tXT63Is=
|
||||||
github.com/containerd/imgcrypt v1.0.4-0.20210301171431-0ae5c75f59ba/go.mod h1:6TNsg0ctmizkrOgXRNQjAPFWpMYRWuiB6dSF4Pfa5SA=
|
github.com/containerd/imgcrypt v1.0.4-0.20210301171431-0ae5c75f59ba/go.mod h1:6TNsg0ctmizkrOgXRNQjAPFWpMYRWuiB6dSF4Pfa5SA=
|
||||||
github.com/containerd/imgcrypt v1.1.1-0.20210312161619-7ed62a527887/go.mod h1:5AZJNI6sLHJljKuI9IHnw1pWqo/F0nGDOuR9zgTs7ow=
|
github.com/containerd/imgcrypt v1.1.1-0.20210312161619-7ed62a527887/go.mod h1:5AZJNI6sLHJljKuI9IHnw1pWqo/F0nGDOuR9zgTs7ow=
|
||||||
github.com/containerd/imgcrypt v1.1.1/go.mod h1:xpLnwiQmEUJPvQoAapeb2SNCxz7Xr6PJrXQb0Dpc4ms=
|
github.com/containerd/imgcrypt v1.1.1/go.mod h1:xpLnwiQmEUJPvQoAapeb2SNCxz7Xr6PJrXQb0Dpc4ms=
|
||||||
|
@ -213,8 +219,10 @@ github.com/containernetworking/cni v0.7.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ
|
||||||
github.com/containernetworking/cni v0.8.0/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY=
|
github.com/containernetworking/cni v0.8.0/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY=
|
||||||
github.com/containernetworking/cni v0.8.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY=
|
github.com/containernetworking/cni v0.8.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY=
|
||||||
github.com/containernetworking/plugins v0.8.6/go.mod h1:qnw5mN19D8fIwkqW7oHHYDHVlzhJpcY6TQxn/fUyDDM=
|
github.com/containernetworking/plugins v0.8.6/go.mod h1:qnw5mN19D8fIwkqW7oHHYDHVlzhJpcY6TQxn/fUyDDM=
|
||||||
|
github.com/containernetworking/plugins v0.8.7/go.mod h1:R7lXeZaBzpfqapcAbHRW8/CYwm0dHzbz0XEjofx0uB0=
|
||||||
github.com/containernetworking/plugins v0.9.1/go.mod h1:xP/idU2ldlzN6m4p5LmGiwRDjeJr6FLK6vuiUwoH7P8=
|
github.com/containernetworking/plugins v0.9.1/go.mod h1:xP/idU2ldlzN6m4p5LmGiwRDjeJr6FLK6vuiUwoH7P8=
|
||||||
github.com/containers/ocicrypt v1.0.1/go.mod h1:MeJDzk1RJHv89LjsH0Sp5KTY3ZYkjXO/C+bKAeWFIrc=
|
github.com/containers/ocicrypt v1.0.1/go.mod h1:MeJDzk1RJHv89LjsH0Sp5KTY3ZYkjXO/C+bKAeWFIrc=
|
||||||
|
github.com/containers/ocicrypt v1.0.3/go.mod h1:CUBa+8MRNL/VkpxYIpaMtgn1WgXGyvPQj8jcy0EVG6g=
|
||||||
github.com/containers/ocicrypt v1.1.0/go.mod h1:b8AOe0YR67uU8OqfVNcznfFpAzu3rdgUV4GP9qXPfu4=
|
github.com/containers/ocicrypt v1.1.0/go.mod h1:b8AOe0YR67uU8OqfVNcznfFpAzu3rdgUV4GP9qXPfu4=
|
||||||
github.com/containers/ocicrypt v1.1.1/go.mod h1:Dm55fwWm1YZAjYRaJ94z2mfZikIyIN4B0oB3dj3jFxY=
|
github.com/containers/ocicrypt v1.1.1/go.mod h1:Dm55fwWm1YZAjYRaJ94z2mfZikIyIN4B0oB3dj3jFxY=
|
||||||
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
|
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
|
||||||
|
@ -308,14 +316,18 @@ github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V
|
||||||
github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
|
github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
|
||||||
github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
|
github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
|
||||||
github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0=
|
github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0=
|
||||||
|
github.com/go-openapi/jsonpointer v0.17.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M=
|
||||||
github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg=
|
github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg=
|
||||||
github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
|
github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
|
||||||
github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg=
|
github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg=
|
||||||
|
github.com/go-openapi/jsonreference v0.17.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I=
|
||||||
github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc=
|
github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc=
|
||||||
github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8=
|
github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8=
|
||||||
github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc=
|
github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc=
|
||||||
|
github.com/go-openapi/spec v0.19.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI=
|
||||||
github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo=
|
github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo=
|
||||||
github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I=
|
github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I=
|
||||||
|
github.com/go-openapi/swag v0.17.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg=
|
||||||
github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
|
github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
|
||||||
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
|
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
|
||||||
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=
|
||||||
|
@ -329,6 +341,7 @@ github.com/gofrs/uuid v4.0.0+incompatible h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPh
|
||||||
github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
||||||
github.com/gogo/googleapis v1.2.0/go.mod h1:Njal3psf3qN6dwBtQfUmBZh2ybovJ0tlu3o/AC7HYjU=
|
github.com/gogo/googleapis v1.2.0/go.mod h1:Njal3psf3qN6dwBtQfUmBZh2ybovJ0tlu3o/AC7HYjU=
|
||||||
github.com/gogo/googleapis v1.4.0/go.mod h1:5YRNX2z1oM5gXdAkurHa942MDgEJyk02w4OecKY87+c=
|
github.com/gogo/googleapis v1.4.0/go.mod h1:5YRNX2z1oM5gXdAkurHa942MDgEJyk02w4OecKY87+c=
|
||||||
|
github.com/gogo/googleapis v1.4.1/go.mod h1:2lpHqI5OcWCtVElxXnPt+s8oJvMpySlOyM6xDCrzib4=
|
||||||
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.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
||||||
github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
|
github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
|
||||||
|
@ -349,6 +362,7 @@ 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/protobuf v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
|
@ -367,8 +381,9 @@ github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw
|
||||||
github.com/golang/protobuf v1.5.0 h1:LUVKkCeviFUMKqHa4tXIIij/lbhnMbP7Fn5wKdKkRh4=
|
github.com/golang/protobuf v1.5.0 h1:LUVKkCeviFUMKqHa4tXIIij/lbhnMbP7Fn5wKdKkRh4=
|
||||||
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/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 h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo=
|
|
||||||
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/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4=
|
||||||
|
github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA=
|
||||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
|
@ -377,6 +392,7 @@ 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 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
|
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
|
||||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
|
@ -396,8 +412,10 @@ github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hf
|
||||||
github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||||
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
github.com/google/pprof v0.0.0-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-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||||
github.com/google/pprof v0.0.0-20210115211752-39141e76b647/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||||
|
github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||||
|
github.com/google/pprof v0.0.0-20210423192551-a2663126120b/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/subcommands v1.0.2-0.20190508160503-636abe8753b8/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk=
|
github.com/google/subcommands v1.0.2-0.20190508160503-636abe8753b8/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk=
|
||||||
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
|
@ -407,6 +425,7 @@ github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+
|
||||||
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/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
|
github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
|
||||||
|
github.com/googleapis/gnostic v0.4.0/go.mod h1:on+2t9HRStVgn95RSsFWFz+6Q0Snyqv1awfrALZdbtU=
|
||||||
github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg=
|
github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg=
|
||||||
github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8=
|
github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8=
|
||||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||||
|
@ -439,6 +458,7 @@ github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:
|
||||||
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/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
|
github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
|
||||||
github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
|
github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
|
||||||
|
github.com/imdario/mergo v0.3.9/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
|
||||||
github.com/imdario/mergo v0.3.10/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
|
github.com/imdario/mergo v0.3.10/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
|
||||||
github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
|
github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
|
||||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||||
|
@ -483,6 +503,7 @@ github.com/kr328/tun2socket v0.0.0-20210412191540-3d56c47e2d99 h1:dkEFEnGUg2z/FA
|
||||||
github.com/kr328/tun2socket v0.0.0-20210412191540-3d56c47e2d99/go.mod h1:FWfSixjrLgtK+dHkDoN6lHMNhvER24gnjUZd/wt8Z9o=
|
github.com/kr328/tun2socket v0.0.0-20210412191540-3d56c47e2d99/go.mod h1:FWfSixjrLgtK+dHkDoN6lHMNhvER24gnjUZd/wt8Z9o=
|
||||||
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||||
github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||||
|
github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||||
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||||
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||||
github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs=
|
github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs=
|
||||||
|
@ -545,6 +566,7 @@ github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGV
|
||||||
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||||
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||||
|
github.com/onsi/gomega v1.10.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA=
|
||||||
github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc=
|
github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc=
|
||||||
github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
|
github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
|
||||||
github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
|
github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
|
||||||
|
@ -559,6 +581,7 @@ github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/go.mod h1:qT5X
|
||||||
github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
||||||
github.com/opencontainers/runc v1.0.0-rc8.0.20190926000215-3e425f80a8c9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
github.com/opencontainers/runc v1.0.0-rc8.0.20190926000215-3e425f80a8c9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
||||||
github.com/opencontainers/runc v1.0.0-rc9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
github.com/opencontainers/runc v1.0.0-rc9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
||||||
|
github.com/opencontainers/runc v1.0.0-rc90/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
||||||
github.com/opencontainers/runc v1.0.0-rc93/go.mod h1:3NOsor4w32B2tC0Zbl8Knk4Wg84SM2ImC1fxBuqJ/H0=
|
github.com/opencontainers/runc v1.0.0-rc93/go.mod h1:3NOsor4w32B2tC0Zbl8Knk4Wg84SM2ImC1fxBuqJ/H0=
|
||||||
github.com/opencontainers/runc v1.0.1/go.mod h1:aTaHFFwQXuA71CiyxOdFFIorAoemI04suvGRQFzWTD0=
|
github.com/opencontainers/runc v1.0.1/go.mod h1:aTaHFFwQXuA71CiyxOdFFIorAoemI04suvGRQFzWTD0=
|
||||||
github.com/opencontainers/runtime-spec v0.1.2-0.20190507144316-5b71a03e2700/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
github.com/opencontainers/runtime-spec v0.1.2-0.20190507144316-5b71a03e2700/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||||
|
@ -571,6 +594,10 @@ github.com/opencontainers/runtime-tools v0.0.0-20181011054405-1d69bd0f9c39/go.mo
|
||||||
github.com/opencontainers/selinux v1.6.0/go.mod h1:VVGKuOLlE7v4PJyT6h7mNWvq1rzqiriPsEqVhc+svHE=
|
github.com/opencontainers/selinux v1.6.0/go.mod h1:VVGKuOLlE7v4PJyT6h7mNWvq1rzqiriPsEqVhc+svHE=
|
||||||
github.com/opencontainers/selinux v1.8.0/go.mod h1:RScLhm78qiWa2gbVCcGkC7tCGdgk3ogry1nUQF8Evvo=
|
github.com/opencontainers/selinux v1.8.0/go.mod h1:RScLhm78qiWa2gbVCcGkC7tCGdgk3ogry1nUQF8Evvo=
|
||||||
github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8=
|
github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8=
|
||||||
|
github.com/oschwald/geoip2-golang v1.5.0 h1:igg2yQIrrcRccB1ytFXqBfOHCjXWIoMv85lVJ1ONZzw=
|
||||||
|
github.com/oschwald/geoip2-golang v1.5.0/go.mod h1:xdvYt5xQzB8ORWFqPnqMwZpCpgNagttWdoZLlJQzg7s=
|
||||||
|
github.com/oschwald/maxminddb-golang v1.8.0 h1:Uh/DSnGoxsyp/KYbY1AuP0tYEwfs0sCph9p/UMXK/Hk=
|
||||||
|
github.com/oschwald/maxminddb-golang v1.8.0/go.mod h1:RXZtst0N6+FY/3qCNmZMBApR19cdQj43/NM9VkrNAis=
|
||||||
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
|
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
|
||||||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||||
github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc=
|
github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc=
|
||||||
|
@ -586,6 +613,7 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
|
||||||
github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA=
|
github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA=
|
||||||
github.com/prometheus/client_golang v0.0.0-20180209125602-c332b6f63c06/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
github.com/prometheus/client_golang v0.0.0-20180209125602-c332b6f63c06/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 v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM=
|
||||||
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
|
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
|
||||||
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
|
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
|
||||||
github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g=
|
github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g=
|
||||||
|
@ -597,12 +625,14 @@ github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:
|
||||||
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-20180110214958-89604d197083/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
github.com/prometheus/common v0.0.0-20180110214958-89604d197083/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
||||||
github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
||||||
|
github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
||||||
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||||
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||||
github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc=
|
github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc=
|
||||||
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/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/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.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||||
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||||
github.com/prometheus/procfs v0.0.0-20190522114515-bc1a522cf7b1/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
github.com/prometheus/procfs v0.0.0-20190522114515-bc1a522cf7b1/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||||
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||||
|
@ -693,6 +723,8 @@ github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q
|
||||||
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
|
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
|
||||||
github.com/xtls/go v0.0.0-20201118062508-3632bf3b7499 h1:QHESTXtfgc1ABV+ArlbPVqUx9Ht5I0dDkYhxYoXFxNo=
|
github.com/xtls/go v0.0.0-20201118062508-3632bf3b7499 h1:QHESTXtfgc1ABV+ArlbPVqUx9Ht5I0dDkYhxYoXFxNo=
|
||||||
github.com/xtls/go v0.0.0-20201118062508-3632bf3b7499/go.mod h1:5TB2+k58gx4A4g2Nf5miSHNDF6CuAzHKpWBooLAshTs=
|
github.com/xtls/go v0.0.0-20201118062508-3632bf3b7499/go.mod h1:5TB2+k58gx4A4g2Nf5miSHNDF6CuAzHKpWBooLAshTs=
|
||||||
|
github.com/yaling888/go-lwip v0.0.0-20210928231210-94b50cb51cc1 h1:bhAo5qI3SrfsNP0/91NJ5Rl4cqauE4CeNRplsIuRZTE=
|
||||||
|
github.com/yaling888/go-lwip v0.0.0-20210928231210-94b50cb51cc1/go.mod h1:Y+f95PkWh183q1oDJxdlxTHa2mpdHG5zvBhV0TUhhSY=
|
||||||
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=
|
||||||
|
@ -703,6 +735,8 @@ github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go
|
||||||
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||||
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||||
go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
|
go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
|
||||||
|
go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU=
|
||||||
|
go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4=
|
||||||
go.etcd.io/etcd v0.5.0-alpha.5.0.20200910180754-dd1b699fc489/go.mod h1:yVHk9ub3CSBatqGNg7GRmsnfLWtoW60w4eDYfh7vHDg=
|
go.etcd.io/etcd v0.5.0-alpha.5.0.20200910180754-dd1b699fc489/go.mod h1:yVHk9ub3CSBatqGNg7GRmsnfLWtoW60w4eDYfh7vHDg=
|
||||||
go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk=
|
go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk=
|
||||||
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
||||||
|
@ -711,6 +745,7 @@ 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.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||||
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||||
|
@ -734,6 +769,7 @@ golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975/go.mod h1:LzIPMQfyMNhhGPh
|
||||||
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-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
|
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||||
golang.org/x/crypto v0.0.0-20210317152858-513c2a44f670/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
golang.org/x/crypto v0.0.0-20210317152858-513c2a44f670/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||||
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||||
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 h1:HWj/xjIHfjYU5nVXpTM0s39J9CbLn7Cc5a7IC5rwsMQ=
|
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 h1:HWj/xjIHfjYU5nVXpTM0s39J9CbLn7Cc5a7IC5rwsMQ=
|
||||||
|
@ -770,12 +806,15 @@ golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzB
|
||||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.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/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-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-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20181005035420-146acd28ed58/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/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-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-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=
|
||||||
|
@ -814,7 +853,9 @@ golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwY
|
||||||
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-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||||
|
golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
|
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.0.0-20210903162142-ad29c8ab022f h1:w6wWR0H+nyVpbSAQbzVEIACVyr/h8l/BEkY6Sokc7Eg=
|
golang.org/x/net v0.0.0-20210903162142-ad29c8ab022f h1:w6wWR0H+nyVpbSAQbzVEIACVyr/h8l/BEkY6Sokc7Eg=
|
||||||
golang.org/x/net v0.0.0-20210903162142-ad29c8ab022f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20210903162142-ad29c8ab022f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
|
@ -826,6 +867,10 @@ golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4Iltr
|
||||||
golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||||
golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
golang.org/x/oauth2 v0.0.0-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-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-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-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=
|
||||||
|
@ -877,6 +922,7 @@ golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||||
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/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-20191210023423-ac6580df4449/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191210023423-ac6580df4449/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20191224085550-c709ea063b76/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=
|
||||||
|
@ -903,6 +949,7 @@ golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||||
golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200916030750-2334cc1a136f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200916030750-2334cc1a136f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200922070232-aee5d888a860/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200922070232-aee5d888a860/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20201009025420-dfb3f7c4e634/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201009025420-dfb3f7c4e634/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20201101102859-da207088b7d1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201101102859-da207088b7d1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
@ -911,9 +958,13 @@ golang.org/x/sys v0.0.0-20201117170446-d9b008d0a637/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-20201202213521-69691e467435/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201202213521-69691e467435/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/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-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210314195730-07df6a141424/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210324051608-47abb6519492/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-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
@ -922,6 +973,7 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||||
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/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-20210906170528-6f6e22806c34 h1:GkvMjFtXUmahfDtashnc1mnrCtuBVcwse5QV2lUk/tI=
|
golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34 h1:GkvMjFtXUmahfDtashnc1mnrCtuBVcwse5QV2lUk/tI=
|
||||||
golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/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-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
@ -930,6 +982,7 @@ golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3
|
||||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
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.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
|
golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
|
||||||
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/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
|
@ -989,8 +1042,9 @@ golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc
|
||||||
golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE=
|
golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE=
|
||||||
golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
golang.org/x/tools v0.0.0-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-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-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/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=
|
||||||
|
@ -1016,6 +1070,9 @@ google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSr
|
||||||
google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
|
google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
|
||||||
google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg=
|
google.golang.org/api v0.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.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU=
|
||||||
|
google.golang.org/api v0.42.0/go.mod h1:+Oj4s6ch2SEGtPjGqfUfZonBH0GjQH89gTeKKAEGZKI=
|
||||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||||
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||||
|
@ -1060,8 +1117,13 @@ google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6D
|
||||||
google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a/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-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7 h1:n7yjMkxUgbEahYENvAGVlxMUW8TF/KEavLez31znfDw=
|
google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/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-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
|
google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
|
google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
|
google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
|
google.golang.org/genproto v0.0.0-20210312152112-fc591d9ea70f h1:YRBxgxUW6GFi+AKsn8WGA9k1SZohK+gGuEqdeT5aoNQ=
|
||||||
|
google.golang.org/genproto v0.0.0-20210312152112-fc591d9ea70f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
||||||
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=
|
||||||
|
@ -1082,8 +1144,9 @@ google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM
|
||||||
google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
|
google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
|
||||||
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
|
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
|
||||||
google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8=
|
google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8=
|
||||||
google.golang.org/grpc v1.36.0-dev.0.20210208035533-9280052d3665/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
google.golang.org/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.39.0-dev.0.20210518002758-2713b77e8526/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=
|
||||||
google.golang.org/grpc v1.40.0 h1:AGJ0Ih4mHjSeibYkFGh1dD9KJ/eOtZ93I6hoHhukQ5Q=
|
google.golang.org/grpc v1.40.0 h1:AGJ0Ih4mHjSeibYkFGh1dD9KJ/eOtZ93I6hoHhukQ5Q=
|
||||||
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/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||||
|
@ -1096,7 +1159,6 @@ google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2
|
||||||
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||||
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
|
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
|
||||||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||||
google.golang.org/protobuf v1.25.1-0.20201020201750-d3470999428b/go.mod h1:hFxJC2f0epmp1elRCiEGJTKAWbwxZ2nvqZdHl3FQXCY=
|
|
||||||
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 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ=
|
||||||
|
@ -1136,8 +1198,8 @@ gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81
|
||||||
gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk=
|
gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk=
|
||||||
gotest.tools/v3 v3.0.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0=
|
gotest.tools/v3 v3.0.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0=
|
||||||
gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8=
|
gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8=
|
||||||
gvisor.dev/gvisor v0.0.0-20210519191755-bd7eb2c99ba9 h1:7Xn0JTQiWLxAKGI5FCtQH4DVnQ4K7tBZ6hVSgitTZH8=
|
gvisor.dev/gvisor v0.0.0-20210922003438-b39716d116fd h1:m5QXicYwyY+W9EHMzkVxCEmeiD4O+XJeHOGb2wEOgP8=
|
||||||
gvisor.dev/gvisor v0.0.0-20210519191755-bd7eb2c99ba9/go.mod h1:ucHEMlckp+S/YzKEpwwAyGBhAh807Wxq/8Erc6gFxCE=
|
gvisor.dev/gvisor v0.0.0-20210922003438-b39716d116fd/go.mod h1:m1RK/gef4nU1CWOFscQWVk7iUgGH2Hz9Ee+lgeCzOBo=
|
||||||
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=
|
||||||
|
@ -1162,6 +1224,7 @@ k8s.io/client-go v0.16.13/go.mod h1:UKvVT4cajC2iN7DCjLgT0KVY/cbY6DGdUCyRiIfws5M=
|
||||||
k8s.io/client-go v0.20.1/go.mod h1:/zcHdt1TeWSd5HoUe6elJmHSQ6uLLgp4bIJHVEuy+/Y=
|
k8s.io/client-go v0.20.1/go.mod h1:/zcHdt1TeWSd5HoUe6elJmHSQ6uLLgp4bIJHVEuy+/Y=
|
||||||
k8s.io/client-go v0.20.4/go.mod h1:LiMv25ND1gLUdBeYxBIwKpkSC5IsozMMmOOeSJboP+k=
|
k8s.io/client-go v0.20.4/go.mod h1:LiMv25ND1gLUdBeYxBIwKpkSC5IsozMMmOOeSJboP+k=
|
||||||
k8s.io/client-go v0.20.6/go.mod h1:nNQMnOvEUEsOzRRFIIkdmYOjAZrC8bgq0ExboWSU1I0=
|
k8s.io/client-go v0.20.6/go.mod h1:nNQMnOvEUEsOzRRFIIkdmYOjAZrC8bgq0ExboWSU1I0=
|
||||||
|
k8s.io/component-base v0.16.13/go.mod h1:cNe9ZU2A6tqBG0gPQ4/T/KolI9Cv2NA1+7uvmkA7Cyc=
|
||||||
k8s.io/component-base v0.20.1/go.mod h1:guxkoJnNoh8LNrbtiQOlyp2Y2XFCZQmrcg2n/DeYNLk=
|
k8s.io/component-base v0.20.1/go.mod h1:guxkoJnNoh8LNrbtiQOlyp2Y2XFCZQmrcg2n/DeYNLk=
|
||||||
k8s.io/component-base v0.20.4/go.mod h1:t4p9EdiagbVCJKrQ1RsA5/V4rFQNDfRlevJajlGwgjI=
|
k8s.io/component-base v0.20.4/go.mod h1:t4p9EdiagbVCJKrQ1RsA5/V4rFQNDfRlevJajlGwgjI=
|
||||||
k8s.io/component-base v0.20.6/go.mod h1:6f1MPBAeI+mvuts3sIdtpjljHWBQ2cIy38oBIWMYnrM=
|
k8s.io/component-base v0.20.6/go.mod h1:6f1MPBAeI+mvuts3sIdtpjljHWBQ2cIy38oBIWMYnrM=
|
||||||
|
|
|
@ -93,6 +93,44 @@ func TestClash_TrojanGrpc(t *testing.T) {
|
||||||
testSuit(t, proxy)
|
testSuit(t, proxy)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestClash_TrojanWebsocket(t *testing.T) {
|
||||||
|
cfg := &container.Config{
|
||||||
|
Image: ImageTrojanGo,
|
||||||
|
ExposedPorts: defaultExposedPorts,
|
||||||
|
}
|
||||||
|
hostCfg := &container.HostConfig{
|
||||||
|
PortBindings: defaultPortBindings,
|
||||||
|
Binds: []string{
|
||||||
|
fmt.Sprintf("%s:/etc/trojan-go/config.json", C.Path.Resolve("trojan-ws.json")),
|
||||||
|
fmt.Sprintf("%s:/fullchain.pem", C.Path.Resolve("example.org.pem")),
|
||||||
|
fmt.Sprintf("%s:/privkey.pem", C.Path.Resolve("example.org-key.pem")),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
id, err := startContainer(cfg, hostCfg, "trojan-ws")
|
||||||
|
if err != nil {
|
||||||
|
assert.FailNow(t, err.Error())
|
||||||
|
}
|
||||||
|
defer cleanContainer(id)
|
||||||
|
|
||||||
|
proxy, err := outbound.NewTrojan(outbound.TrojanOption{
|
||||||
|
Name: "trojan",
|
||||||
|
Server: localIP.String(),
|
||||||
|
Port: 10002,
|
||||||
|
Password: "example",
|
||||||
|
SNI: "example.org",
|
||||||
|
SkipCertVerify: true,
|
||||||
|
UDP: true,
|
||||||
|
Network: "ws",
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
assert.FailNow(t, err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
time.Sleep(waitTime)
|
||||||
|
testSuit(t, proxy)
|
||||||
|
}
|
||||||
|
|
||||||
func Benchmark_Trojan(b *testing.B) {
|
func Benchmark_Trojan(b *testing.B) {
|
||||||
cfg := &container.Config{
|
cfg := &container.Config{
|
||||||
Image: ImageTrojan,
|
Image: ImageTrojan,
|
||||||
|
|
|
@ -304,13 +304,13 @@ func TestClash_VmessWebsocketTLS(t *testing.T) {
|
||||||
|
|
||||||
func TestClash_VmessGrpc(t *testing.T) {
|
func TestClash_VmessGrpc(t *testing.T) {
|
||||||
cfg := &container.Config{
|
cfg := &container.Config{
|
||||||
Image: ImageXray,
|
Image: ImageVmess,
|
||||||
ExposedPorts: defaultExposedPorts,
|
ExposedPorts: defaultExposedPorts,
|
||||||
}
|
}
|
||||||
hostCfg := &container.HostConfig{
|
hostCfg := &container.HostConfig{
|
||||||
PortBindings: defaultPortBindings,
|
PortBindings: defaultPortBindings,
|
||||||
Binds: []string{
|
Binds: []string{
|
||||||
fmt.Sprintf("%s:/etc/xray/config.json", C.Path.Resolve("vmess-grpc.json")),
|
fmt.Sprintf("%s:/etc/v2ray/config.json", C.Path.Resolve("vmess-grpc.json")),
|
||||||
fmt.Sprintf("%s:/etc/ssl/v2ray/fullchain.pem", C.Path.Resolve("example.org.pem")),
|
fmt.Sprintf("%s:/etc/ssl/v2ray/fullchain.pem", C.Path.Resolve("example.org.pem")),
|
||||||
fmt.Sprintf("%s:/etc/ssl/v2ray/privkey.pem", C.Path.Resolve("example.org-key.pem")),
|
fmt.Sprintf("%s:/etc/ssl/v2ray/privkey.pem", C.Path.Resolve("example.org-key.pem")),
|
||||||
},
|
},
|
||||||
|
|
|
@ -27,12 +27,10 @@ var (
|
||||||
ErrSmallBuffer = errors.New("buffer too small")
|
ErrSmallBuffer = errors.New("buffer too small")
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var defaultHeader = http.Header{
|
||||||
defaultHeader = http.Header{
|
"content-type": []string{"application/grpc"},
|
||||||
"content-type": []string{"application/grpc"},
|
"user-agent": []string{"grpc-go/1.36.0"},
|
||||||
"user-agent": []string{"grpc-go/1.36.0"},
|
}
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
type DialFn = func(network, addr string) (net.Conn, error)
|
type DialFn = func(network, addr string) (net.Conn, error)
|
||||||
|
|
||||||
|
|
|
@ -78,6 +78,7 @@ func (to *TLSObfs) Read(b []byte) (int, error) {
|
||||||
// type + ver = 3
|
// type + ver = 3
|
||||||
return to.read(b, 3)
|
return to.read(b, 3)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (to *TLSObfs) Write(b []byte) (int, error) {
|
func (to *TLSObfs) Write(b []byte) (int, error) {
|
||||||
length := len(b)
|
length := len(b)
|
||||||
for i := 0; i < length; i += chunkSize {
|
for i := 0; i < length; i += chunkSize {
|
||||||
|
|
|
@ -20,6 +20,7 @@ func (sc *snellCipher) SaltSize() int { return 16 }
|
||||||
func (sc *snellCipher) Encrypter(salt []byte) (cipher.AEAD, error) {
|
func (sc *snellCipher) Encrypter(salt []byte) (cipher.AEAD, error) {
|
||||||
return sc.makeAEAD(snellKDF(sc.psk, salt, sc.KeySize()))
|
return sc.makeAEAD(snellKDF(sc.psk, salt, sc.KeySize()))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sc *snellCipher) Decrypter(salt []byte) (cipher.AEAD, error) {
|
func (sc *snellCipher) Decrypter(salt []byte) (cipher.AEAD, error) {
|
||||||
return sc.makeAEAD(snellKDF(sc.psk, salt, sc.KeySize()))
|
return sc.makeAEAD(snellKDF(sc.psk, salt, sc.KeySize()))
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,9 +30,7 @@ const (
|
||||||
Version byte = 1
|
Version byte = 1
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var endSignal = []byte{}
|
||||||
endSignal = []byte{}
|
|
||||||
)
|
|
||||||
|
|
||||||
type Snell struct {
|
type Snell struct {
|
||||||
net.Conn
|
net.Conn
|
||||||
|
|
|
@ -184,7 +184,7 @@ func isReservedIP(ip net.IP) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
func readUntilNull(r io.Reader) ([]byte, error) {
|
func readUntilNull(r io.Reader) ([]byte, error) {
|
||||||
var buf = &bytes.Buffer{}
|
buf := &bytes.Buffer{}
|
||||||
var data [1]byte
|
var data [1]byte
|
||||||
|
|
||||||
for {
|
for {
|
||||||
|
|
|
@ -14,8 +14,10 @@ import (
|
||||||
"github.com/Dreamacro/clash/transport/ssr/tools"
|
"github.com/Dreamacro/clash/transport/ssr/tools"
|
||||||
)
|
)
|
||||||
|
|
||||||
type hmacMethod func(key, data []byte) []byte
|
type (
|
||||||
type hashDigestMethod func([]byte) []byte
|
hmacMethod func(key, data []byte) []byte
|
||||||
|
hashDigestMethod func([]byte) []byte
|
||||||
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
register("auth_aes128_sha1", newAuthAES128SHA1, 9)
|
register("auth_aes128_sha1", newAuthAES128SHA1, 9)
|
||||||
|
|
|
@ -8,10 +8,12 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
|
"net/http"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/Dreamacro/clash/common/pool"
|
"github.com/Dreamacro/clash/common/pool"
|
||||||
"github.com/Dreamacro/clash/transport/socks5"
|
"github.com/Dreamacro/clash/transport/socks5"
|
||||||
|
"github.com/Dreamacro/clash/transport/vmess"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -20,8 +22,10 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
defaultALPN = []string{"h2", "http/1.1"}
|
defaultALPN = []string{"h2", "http/1.1"}
|
||||||
crlf = []byte{'\r', '\n'}
|
defaultWebsocketALPN = []string{"http/1.1"}
|
||||||
|
|
||||||
|
crlf = []byte{'\r', '\n'}
|
||||||
)
|
)
|
||||||
|
|
||||||
type Command = byte
|
type Command = byte
|
||||||
|
@ -38,6 +42,13 @@ type Option struct {
|
||||||
SkipCertVerify bool
|
SkipCertVerify bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type WebsocketOption struct {
|
||||||
|
Host string
|
||||||
|
Port string
|
||||||
|
Path string
|
||||||
|
Headers http.Header
|
||||||
|
}
|
||||||
|
|
||||||
type Trojan struct {
|
type Trojan struct {
|
||||||
option *Option
|
option *Option
|
||||||
hexPassword []byte
|
hexPassword []byte
|
||||||
|
@ -64,6 +75,29 @@ func (t *Trojan) StreamConn(conn net.Conn) (net.Conn, error) {
|
||||||
return tlsConn, nil
|
return tlsConn, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *Trojan) StreamWebsocketConn(conn net.Conn, wsOptions *WebsocketOption) (net.Conn, error) {
|
||||||
|
alpn := defaultWebsocketALPN
|
||||||
|
if len(t.option.ALPN) != 0 {
|
||||||
|
alpn = t.option.ALPN
|
||||||
|
}
|
||||||
|
|
||||||
|
tlsConfig := &tls.Config{
|
||||||
|
NextProtos: alpn,
|
||||||
|
MinVersion: tls.VersionTLS12,
|
||||||
|
InsecureSkipVerify: t.option.SkipCertVerify,
|
||||||
|
ServerName: t.option.ServerName,
|
||||||
|
}
|
||||||
|
|
||||||
|
return vmess.StreamWebsocketConn(conn, &vmess.WebsocketConfig{
|
||||||
|
Host: wsOptions.Host,
|
||||||
|
Port: wsOptions.Port,
|
||||||
|
Path: wsOptions.Path,
|
||||||
|
Headers: wsOptions.Headers,
|
||||||
|
TLS: true,
|
||||||
|
TLSConfig: tlsConfig,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func (t *Trojan) WriteHeader(w io.Writer, command Command, socks5Addr []byte) error {
|
func (t *Trojan) WriteHeader(w io.Writer, command Command, socks5Addr []byte) error {
|
||||||
buf := pool.GetBuffer()
|
buf := pool.GetBuffer()
|
||||||
defer pool.PutBuffer(buf)
|
defer pool.PutBuffer(buf)
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package obfs
|
package obfs
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/tls"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
|
@ -26,12 +27,22 @@ func NewV2rayObfs(conn net.Conn, option *Option) (net.Conn, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
config := &vmess.WebsocketConfig{
|
config := &vmess.WebsocketConfig{
|
||||||
Host: option.Host,
|
Host: option.Host,
|
||||||
Port: option.Port,
|
Port: option.Port,
|
||||||
Path: option.Path,
|
Path: option.Path,
|
||||||
TLS: option.TLS,
|
Headers: header,
|
||||||
Headers: header,
|
}
|
||||||
SkipCertVerify: option.SkipCertVerify,
|
|
||||||
|
if option.TLS {
|
||||||
|
config.TLS = true
|
||||||
|
config.TLSConfig = &tls.Config{
|
||||||
|
ServerName: option.Host,
|
||||||
|
InsecureSkipVerify: option.SkipCertVerify,
|
||||||
|
NextProtos: []string{"http/1.1"},
|
||||||
|
}
|
||||||
|
if host := config.Headers.Get("Host"); host != "" {
|
||||||
|
config.TLSConfig.ServerName = host
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
|
|
|
@ -92,7 +92,7 @@ func sealVMessAEADHeader(key [16]byte, data []byte, t time.Time) []byte {
|
||||||
payloadHeaderAEADEncrypted = payloadHeaderAEAD.Seal(nil, payloadHeaderAEADNonce, data, generatedAuthID[:])
|
payloadHeaderAEADEncrypted = payloadHeaderAEAD.Seal(nil, payloadHeaderAEADNonce, data, generatedAuthID[:])
|
||||||
}
|
}
|
||||||
|
|
||||||
var outputBuffer = &bytes.Buffer{}
|
outputBuffer := &bytes.Buffer{}
|
||||||
|
|
||||||
outputBuffer.Write(generatedAuthID[:])
|
outputBuffer.Write(generatedAuthID[:])
|
||||||
outputBuffer.Write(payloadHeaderLengthAEADEncrypted)
|
outputBuffer.Write(payloadHeaderLengthAEADEncrypted)
|
||||||
|
|
|
@ -28,6 +28,7 @@ type websocketConn struct {
|
||||||
rMux sync.Mutex
|
rMux sync.Mutex
|
||||||
wMux sync.Mutex
|
wMux sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
type websocketWithEarlyDataConn struct {
|
type websocketWithEarlyDataConn struct {
|
||||||
net.Conn
|
net.Conn
|
||||||
underlay net.Conn
|
underlay net.Conn
|
||||||
|
@ -44,8 +45,7 @@ type WebsocketConfig struct {
|
||||||
Path string
|
Path string
|
||||||
Headers http.Header
|
Headers http.Header
|
||||||
TLS bool
|
TLS bool
|
||||||
SkipCertVerify bool
|
TLSConfig *tls.Config
|
||||||
ServerName string
|
|
||||||
MaxEarlyData int
|
MaxEarlyData int
|
||||||
EarlyDataHeaderName string
|
EarlyDataHeaderName string
|
||||||
}
|
}
|
||||||
|
@ -253,17 +253,7 @@ func streamWebsocketConn(conn net.Conn, c *WebsocketConfig, earlyData *bytes.Buf
|
||||||
scheme := "ws"
|
scheme := "ws"
|
||||||
if c.TLS {
|
if c.TLS {
|
||||||
scheme = "wss"
|
scheme = "wss"
|
||||||
dialer.TLSClientConfig = &tls.Config{
|
dialer.TLSClientConfig = c.TLSConfig
|
||||||
ServerName: c.Host,
|
|
||||||
InsecureSkipVerify: c.SkipCertVerify,
|
|
||||||
NextProtos: []string{"http/1.1"},
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.ServerName != "" {
|
|
||||||
dialer.TLSClientConfig.ServerName = c.ServerName
|
|
||||||
} else if host := c.Headers.Get("Host"); host != "" {
|
|
||||||
dialer.TLSClientConfig.ServerName = host
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uri := url.URL{
|
uri := url.URL{
|
||||||
|
|
|
@ -8,15 +8,13 @@ import (
|
||||||
|
|
||||||
type TunnelMode int
|
type TunnelMode int
|
||||||
|
|
||||||
var (
|
// ModeMapping is a mapping for Mode enum
|
||||||
// ModeMapping is a mapping for Mode enum
|
var ModeMapping = map[string]TunnelMode{
|
||||||
ModeMapping = map[string]TunnelMode{
|
Global.String(): Global,
|
||||||
Global.String(): Global,
|
Rule.String(): Rule,
|
||||||
Rule.String(): Rule,
|
Script.String(): Script,
|
||||||
Script.String(): Script,
|
Direct.String(): Direct,
|
||||||
Direct.String(): Direct,
|
}
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
const (
|
||||||
Global TunnelMode = iota
|
Global TunnelMode = iota
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package tunnel
|
package tunnel
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
@ -13,7 +14,7 @@ import (
|
||||||
S "github.com/Dreamacro/clash/component/script"
|
S "github.com/Dreamacro/clash/component/script"
|
||||||
C "github.com/Dreamacro/clash/constant"
|
C "github.com/Dreamacro/clash/constant"
|
||||||
"github.com/Dreamacro/clash/constant/provider"
|
"github.com/Dreamacro/clash/constant/provider"
|
||||||
"github.com/Dreamacro/clash/context"
|
icontext "github.com/Dreamacro/clash/context"
|
||||||
"github.com/Dreamacro/clash/log"
|
"github.com/Dreamacro/clash/log"
|
||||||
R "github.com/Dreamacro/clash/rule"
|
R "github.com/Dreamacro/clash/rule"
|
||||||
"github.com/Dreamacro/clash/tunnel/statistic"
|
"github.com/Dreamacro/clash/tunnel/statistic"
|
||||||
|
@ -136,8 +137,10 @@ func preHandleMetadata(metadata *C.Metadata) error {
|
||||||
if exist {
|
if exist {
|
||||||
metadata.Host = host
|
metadata.Host = host
|
||||||
metadata.AddrType = C.AtypDomainName
|
metadata.AddrType = C.AtypDomainName
|
||||||
|
metadata.DNSMode = C.DNSMapping
|
||||||
if resolver.FakeIPEnabled() {
|
if resolver.FakeIPEnabled() {
|
||||||
metadata.DstIP = nil
|
metadata.DstIP = nil
|
||||||
|
metadata.DNSMode = C.DNSFakeIP
|
||||||
} else if node := resolver.DefaultHosts.Search(host); node != nil {
|
} else if node := resolver.DefaultHosts.Search(host); node != nil {
|
||||||
// redir-host should lookup the hosts
|
// redir-host should lookup the hosts
|
||||||
metadata.DstIP = node.Data.(net.IP)
|
metadata.DstIP = node.Data.(net.IP)
|
||||||
|
@ -215,14 +218,16 @@ func handleUDPConn(packet *inbound.PacketAdapter) {
|
||||||
cond.Broadcast()
|
cond.Broadcast()
|
||||||
}()
|
}()
|
||||||
|
|
||||||
ctx := context.NewPacketConnContext(metadata)
|
pCtx := icontext.NewPacketConnContext(metadata)
|
||||||
proxy, rule, err := resolveMetadata(ctx, metadata)
|
proxy, rule, err := resolveMetadata(pCtx, metadata)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warnln("[UDP] Parse metadata failed: %s", err.Error())
|
log.Warnln("[UDP] Parse metadata failed: %s", err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
rawPc, err := proxy.DialUDP(metadata)
|
ctx, cancel := context.WithTimeout(context.Background(), C.DefaultUDPTimeout)
|
||||||
|
defer cancel()
|
||||||
|
rawPc, err := proxy.ListenPacketContext(ctx, metadata.Pure())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if rule == nil {
|
if rule == nil {
|
||||||
log.Warnln("[UDP] dial %s to %s error: %s", proxy.Name(), metadata.RemoteAddress(), err.Error())
|
log.Warnln("[UDP] dial %s to %s error: %s", proxy.Name(), metadata.RemoteAddress(), err.Error())
|
||||||
|
@ -231,7 +236,7 @@ func handleUDPConn(packet *inbound.PacketAdapter) {
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ctx.InjectPacketConn(rawPc)
|
pCtx.InjectPacketConn(rawPc)
|
||||||
pc := statistic.NewUDPTracker(rawPc, statistic.DefaultManager, metadata, rule)
|
pc := statistic.NewUDPTracker(rawPc, statistic.DefaultManager, metadata, rule)
|
||||||
|
|
||||||
switch true {
|
switch true {
|
||||||
|
@ -254,10 +259,10 @@ func handleUDPConn(packet *inbound.PacketAdapter) {
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleTCPConn(ctx C.ConnContext) {
|
func handleTCPConn(connCtx C.ConnContext) {
|
||||||
defer ctx.Conn().Close()
|
defer connCtx.Conn().Close()
|
||||||
|
|
||||||
metadata := ctx.Metadata()
|
metadata := connCtx.Metadata()
|
||||||
if !metadata.Valid() {
|
if !metadata.Valid() {
|
||||||
log.Warnln("[Metadata] not valid: %#v", metadata)
|
log.Warnln("[Metadata] not valid: %#v", metadata)
|
||||||
return
|
return
|
||||||
|
@ -268,13 +273,15 @@ func handleTCPConn(ctx C.ConnContext) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
proxy, rule, err := resolveMetadata(ctx, metadata)
|
proxy, rule, err := resolveMetadata(connCtx, metadata)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warnln("[Metadata] parse failed: %s", err.Error())
|
log.Warnln("[Metadata] parse failed: %s", err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
remoteConn, err := proxy.Dial(metadata)
|
ctx, cancel := context.WithTimeout(context.Background(), C.DefaultTCPTimeout)
|
||||||
|
defer cancel()
|
||||||
|
remoteConn, err := proxy.DialContext(ctx, metadata.Pure())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if rule == nil {
|
if rule == nil {
|
||||||
log.Warnln("[TCP] dial %s to %s error: %s", proxy.Name(), metadata.RemoteAddress(), err.Error())
|
log.Warnln("[TCP] dial %s to %s error: %s", proxy.Name(), metadata.RemoteAddress(), err.Error())
|
||||||
|
@ -299,7 +306,7 @@ func handleTCPConn(ctx C.ConnContext) {
|
||||||
log.Infoln("[TCP] %s(%s) --> %s doesn't match any rule using DIRECT", metadata.SourceAddress(), metadata.Process, metadata.RemoteAddress())
|
log.Infoln("[TCP] %s(%s) --> %s doesn't match any rule using DIRECT", metadata.SourceAddress(), metadata.Process, metadata.RemoteAddress())
|
||||||
}
|
}
|
||||||
|
|
||||||
handleSocket(ctx, remoteConn)
|
handleSocket(connCtx, remoteConn)
|
||||||
}
|
}
|
||||||
|
|
||||||
func shouldResolveIP(rule C.Rule, metadata *C.Metadata) bool {
|
func shouldResolveIP(rule C.Rule, metadata *C.Metadata) bool {
|
||||||
|
@ -359,7 +366,6 @@ func match(metadata *C.Metadata) (C.Proxy, C.Rule, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//return proxies["DIRECT"], nil, nil
|
|
||||||
return proxies["REJECT"], nil, nil
|
return proxies["REJECT"], nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -376,7 +382,6 @@ func matchScript(metadata *C.Metadata) (C.Proxy, error) {
|
||||||
preProcessCacheFinder.Match(metadata)
|
preProcessCacheFinder.Match(metadata)
|
||||||
|
|
||||||
adapter, err := S.CallPyMainFunction(metadata)
|
adapter, err := S.CallPyMainFunction(metadata)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue