Merge from remote branch
This commit is contained in:
4
.github/workflows/docker.yml
vendored
4
.github/workflows/docker.yml
vendored
@ -46,7 +46,7 @@ jobs:
|
|||||||
uses: docker/build-push-action@v2
|
uses: docker/build-push-action@v2
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
platforms: linux/amd64,linux/arm/v7,linux/arm64
|
platforms: linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64
|
||||||
push: true
|
push: true
|
||||||
tags: 'dreamacro/clash:dev,ghcr.io/dreamacro/clash:dev'
|
tags: 'dreamacro/clash:dev,ghcr.io/dreamacro/clash:dev'
|
||||||
|
|
||||||
@ -71,6 +71,6 @@ jobs:
|
|||||||
uses: docker/build-push-action@v2
|
uses: docker/build-push-action@v2
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
platforms: linux/amd64,linux/arm/v7,linux/arm64
|
platforms: linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64
|
||||||
push: true
|
push: true
|
||||||
tags: ${{steps.tags.outputs.result}}
|
tags: ${{steps.tags.outputs.result}}
|
||||||
|
14
.golangci.yaml
Normal file
14
.golangci.yaml
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
linters:
|
||||||
|
disable-all: true
|
||||||
|
enable:
|
||||||
|
- gofumpt
|
||||||
|
- megacheck
|
||||||
|
- govet
|
||||||
|
- gci
|
||||||
|
|
||||||
|
linters-settings:
|
||||||
|
gci:
|
||||||
|
sections:
|
||||||
|
- standard
|
||||||
|
- prefix(github.com/Dreamacro/clash)
|
||||||
|
- default
|
2
Makefile
2
Makefile
@ -117,7 +117,7 @@ vet:
|
|||||||
go vet ./...
|
go vet ./...
|
||||||
|
|
||||||
lint:
|
lint:
|
||||||
golangci-lint run --disable-all -E govet -E gofumpt -E megacheck ./...
|
golangci-lint run ./...
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -rf $(BINDIR)/*
|
rm -rf $(BINDIR)/*
|
@ -10,6 +10,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/Dreamacro/clash/common/queue"
|
"github.com/Dreamacro/clash/common/queue"
|
||||||
|
"github.com/Dreamacro/clash/component/dialer"
|
||||||
C "github.com/Dreamacro/clash/constant"
|
C "github.com/Dreamacro/clash/constant"
|
||||||
|
|
||||||
"go.uber.org/atomic"
|
"go.uber.org/atomic"
|
||||||
@ -34,8 +35,8 @@ 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, opts ...dialer.Option) (C.Conn, error) {
|
||||||
conn, err := p.ProxyAdapter.DialContext(ctx, metadata)
|
conn, err := p.ProxyAdapter.DialContext(ctx, metadata, opts...)
|
||||||
p.alive.Store(err == nil)
|
p.alive.Store(err == nil)
|
||||||
return conn, err
|
return conn, err
|
||||||
}
|
}
|
||||||
@ -48,8 +49,8 @@ func (p *Proxy) DialUDP(metadata *C.Metadata) (C.PacketConn, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ListenPacketContext implements C.ProxyAdapter
|
// ListenPacketContext implements C.ProxyAdapter
|
||||||
func (p *Proxy) ListenPacketContext(ctx context.Context, metadata *C.Metadata) (C.PacketConn, error) {
|
func (p *Proxy) ListenPacketContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (C.PacketConn, error) {
|
||||||
pc, err := p.ProxyAdapter.ListenPacketContext(ctx, metadata)
|
pc, err := p.ProxyAdapter.ListenPacketContext(ctx, metadata, opts...)
|
||||||
p.alive.Store(err == nil)
|
p.alive.Store(err == nil)
|
||||||
return pc, err
|
return pc, err
|
||||||
}
|
}
|
||||||
|
@ -6,14 +6,17 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"net"
|
"net"
|
||||||
|
|
||||||
|
"github.com/Dreamacro/clash/component/dialer"
|
||||||
C "github.com/Dreamacro/clash/constant"
|
C "github.com/Dreamacro/clash/constant"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Base struct {
|
type Base struct {
|
||||||
name string
|
name string
|
||||||
addr string
|
addr string
|
||||||
|
iface string
|
||||||
tp C.AdapterType
|
tp C.AdapterType
|
||||||
udp bool
|
udp bool
|
||||||
|
rmark int
|
||||||
}
|
}
|
||||||
|
|
||||||
// Name implements C.ProxyAdapter
|
// Name implements C.ProxyAdapter
|
||||||
@ -32,7 +35,7 @@ func (b *Base) StreamConn(c net.Conn, metadata *C.Metadata) (net.Conn, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ListenPacketContext implements C.ProxyAdapter
|
// ListenPacketContext implements C.ProxyAdapter
|
||||||
func (b *Base) ListenPacketContext(ctx context.Context, metadata *C.Metadata) (C.PacketConn, error) {
|
func (b *Base) ListenPacketContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (C.PacketConn, error) {
|
||||||
return nil, errors.New("no support")
|
return nil, errors.New("no support")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -58,8 +61,42 @@ func (b *Base) Unwrap(metadata *C.Metadata) C.Proxy {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewBase(name string, addr string, tp C.AdapterType, udp bool) *Base {
|
// DialOptions return []dialer.Option from struct
|
||||||
return &Base{name, addr, tp, udp}
|
func (b *Base) DialOptions(opts ...dialer.Option) []dialer.Option {
|
||||||
|
if b.iface != "" {
|
||||||
|
opts = append(opts, dialer.WithInterface(b.iface))
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.rmark != 0 {
|
||||||
|
opts = append(opts, dialer.WithRoutingMark(b.rmark))
|
||||||
|
}
|
||||||
|
|
||||||
|
return opts
|
||||||
|
}
|
||||||
|
|
||||||
|
type BasicOption struct {
|
||||||
|
Interface string `proxy:"interface-name,omitempty" group:"interface-name,omitempty"`
|
||||||
|
RoutingMark int `proxy:"routing-mark,omitempty" group:"routing-mark,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type BaseOption struct {
|
||||||
|
Name string
|
||||||
|
Addr string
|
||||||
|
Type C.AdapterType
|
||||||
|
UDP bool
|
||||||
|
Interface string
|
||||||
|
RoutingMark int
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewBase(opt BaseOption) *Base {
|
||||||
|
return &Base{
|
||||||
|
name: opt.Name,
|
||||||
|
addr: opt.Addr,
|
||||||
|
tp: opt.Type,
|
||||||
|
udp: opt.UDP,
|
||||||
|
iface: opt.Interface,
|
||||||
|
rmark: opt.RoutingMark,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type conn struct {
|
type conn struct {
|
||||||
|
@ -13,8 +13,8 @@ type Direct struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// DialContext implements C.ProxyAdapter
|
// DialContext implements C.ProxyAdapter
|
||||||
func (d *Direct) DialContext(ctx context.Context, metadata *C.Metadata) (C.Conn, error) {
|
func (d *Direct) DialContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (C.Conn, error) {
|
||||||
c, err := dialer.DialContext(ctx, "tcp", metadata.RemoteAddress())
|
c, err := dialer.DialContext(ctx, "tcp", metadata.RemoteAddress(), d.Base.DialOptions(opts...)...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -23,8 +23,8 @@ func (d *Direct) DialContext(ctx context.Context, metadata *C.Metadata) (C.Conn,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ListenPacketContext implements C.ProxyAdapter
|
// ListenPacketContext implements C.ProxyAdapter
|
||||||
func (d *Direct) ListenPacketContext(ctx context.Context, metadata *C.Metadata) (C.PacketConn, error) {
|
func (d *Direct) ListenPacketContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (C.PacketConn, error) {
|
||||||
pc, err := dialer.ListenPacket(ctx, "udp", "")
|
pc, err := dialer.ListenPacket(ctx, "udp", "", d.Base.DialOptions(opts...)...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,7 @@ type Http struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type HttpOption struct {
|
type HttpOption struct {
|
||||||
|
BasicOption
|
||||||
Name string `proxy:"name"`
|
Name string `proxy:"name"`
|
||||||
Server string `proxy:"server"`
|
Server string `proxy:"server"`
|
||||||
Port int `proxy:"port"`
|
Port int `proxy:"port"`
|
||||||
@ -53,8 +54,8 @@ func (h *Http) StreamConn(c net.Conn, metadata *C.Metadata) (net.Conn, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// DialContext implements C.ProxyAdapter
|
// DialContext implements C.ProxyAdapter
|
||||||
func (h *Http) DialContext(ctx context.Context, metadata *C.Metadata) (_ C.Conn, err error) {
|
func (h *Http) DialContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (_ C.Conn, err error) {
|
||||||
c, err := dialer.DialContext(ctx, "tcp", h.addr)
|
c, err := dialer.DialContext(ctx, "tcp", h.addr, h.Base.DialOptions(opts...)...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("%s connect error: %w", h.addr, err)
|
return nil, fmt.Errorf("%s connect error: %w", h.addr, err)
|
||||||
}
|
}
|
||||||
@ -134,6 +135,7 @@ func NewHttp(option HttpOption) *Http {
|
|||||||
name: option.Name,
|
name: option.Name,
|
||||||
addr: net.JoinHostPort(option.Server, strconv.Itoa(option.Port)),
|
addr: net.JoinHostPort(option.Server, strconv.Itoa(option.Port)),
|
||||||
tp: C.Http,
|
tp: C.Http,
|
||||||
|
iface: option.Interface,
|
||||||
},
|
},
|
||||||
user: option.UserName,
|
user: option.UserName,
|
||||||
pass: option.Password,
|
pass: option.Password,
|
||||||
|
@ -2,11 +2,11 @@ package outbound
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/Dreamacro/clash/component/dialer"
|
||||||
C "github.com/Dreamacro/clash/constant"
|
C "github.com/Dreamacro/clash/constant"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -15,13 +15,13 @@ type Reject struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// DialContext implements C.ProxyAdapter
|
// DialContext implements C.ProxyAdapter
|
||||||
func (r *Reject) DialContext(ctx context.Context, metadata *C.Metadata) (C.Conn, error) {
|
func (r *Reject) DialContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (C.Conn, error) {
|
||||||
return NewConn(&NopConn{}, r), nil
|
return NewConn(&nopConn{}, r), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListenPacketContext implements C.ProxyAdapter
|
// ListenPacketContext implements C.ProxyAdapter
|
||||||
func (r *Reject) ListenPacketContext(ctx context.Context, metadata *C.Metadata) (C.PacketConn, error) {
|
func (r *Reject) ListenPacketContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (C.PacketConn, error) {
|
||||||
return nil, errors.New("match reject rule")
|
return newPacketConn(&nopPacketConn{}, r), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewReject() *Reject {
|
func NewReject() *Reject {
|
||||||
@ -34,30 +34,29 @@ func NewReject() *Reject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type NopConn struct{}
|
type nopConn struct{}
|
||||||
|
|
||||||
func (rw *NopConn) Read(b []byte) (int, error) {
|
func (rw *nopConn) Read(b []byte) (int, error) {
|
||||||
return 0, io.EOF
|
return 0, io.EOF
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rw *NopConn) Write(b []byte) (int, error) {
|
func (rw *nopConn) Write(b []byte) (int, error) {
|
||||||
return 0, io.EOF
|
return 0, io.EOF
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close is fake function for net.Conn
|
func (rw *nopConn) Close() error { return nil }
|
||||||
func (rw *NopConn) Close() error { return nil }
|
func (rw *nopConn) LocalAddr() net.Addr { return nil }
|
||||||
|
func (rw *nopConn) RemoteAddr() net.Addr { return nil }
|
||||||
|
func (rw *nopConn) SetDeadline(time.Time) error { return nil }
|
||||||
|
func (rw *nopConn) SetReadDeadline(time.Time) error { return nil }
|
||||||
|
func (rw *nopConn) SetWriteDeadline(time.Time) error { return nil }
|
||||||
|
|
||||||
// LocalAddr is fake function for net.Conn
|
type nopPacketConn struct{}
|
||||||
func (rw *NopConn) LocalAddr() net.Addr { return nil }
|
|
||||||
|
|
||||||
// RemoteAddr is fake function for net.Conn
|
func (npc *nopPacketConn) WriteTo(b []byte, addr net.Addr) (n int, err error) { return len(b), nil }
|
||||||
func (rw *NopConn) RemoteAddr() net.Addr { return nil }
|
func (npc *nopPacketConn) ReadFrom(b []byte) (int, net.Addr, error) { return 0, nil, io.EOF }
|
||||||
|
func (npc *nopPacketConn) Close() error { return nil }
|
||||||
// SetDeadline is fake function for net.Conn
|
func (npc *nopPacketConn) LocalAddr() net.Addr { return &net.UDPAddr{IP: net.IPv4zero, Port: 0} }
|
||||||
func (rw *NopConn) SetDeadline(time.Time) error { return nil }
|
func (npc *nopPacketConn) SetDeadline(time.Time) error { return nil }
|
||||||
|
func (npc *nopPacketConn) SetReadDeadline(time.Time) error { return nil }
|
||||||
// SetReadDeadline is fake function for net.Conn
|
func (npc *nopPacketConn) SetWriteDeadline(time.Time) error { return nil }
|
||||||
func (rw *NopConn) SetReadDeadline(time.Time) error { return nil }
|
|
||||||
|
|
||||||
// SetWriteDeadline is fake function for net.Conn
|
|
||||||
func (rw *NopConn) SetWriteDeadline(time.Time) error { return nil }
|
|
||||||
|
@ -28,6 +28,7 @@ type ShadowSocks struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ShadowSocksOption struct {
|
type ShadowSocksOption struct {
|
||||||
|
BasicOption
|
||||||
Name string `proxy:"name"`
|
Name string `proxy:"name"`
|
||||||
Server string `proxy:"server"`
|
Server string `proxy:"server"`
|
||||||
Port int `proxy:"port"`
|
Port int `proxy:"port"`
|
||||||
@ -74,8 +75,8 @@ func (ss *ShadowSocks) StreamConn(c net.Conn, metadata *C.Metadata) (net.Conn, e
|
|||||||
}
|
}
|
||||||
|
|
||||||
// DialContext implements C.ProxyAdapter
|
// DialContext implements C.ProxyAdapter
|
||||||
func (ss *ShadowSocks) DialContext(ctx context.Context, metadata *C.Metadata) (_ C.Conn, err error) {
|
func (ss *ShadowSocks) DialContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (_ C.Conn, err error) {
|
||||||
c, err := dialer.DialContext(ctx, "tcp", ss.addr)
|
c, err := dialer.DialContext(ctx, "tcp", ss.addr, ss.Base.DialOptions(opts...)...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("%s connect error: %w", ss.addr, err)
|
return nil, fmt.Errorf("%s connect error: %w", ss.addr, err)
|
||||||
}
|
}
|
||||||
@ -88,8 +89,8 @@ func (ss *ShadowSocks) DialContext(ctx context.Context, metadata *C.Metadata) (_
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ListenPacketContext implements C.ProxyAdapter
|
// ListenPacketContext implements C.ProxyAdapter
|
||||||
func (ss *ShadowSocks) ListenPacketContext(ctx context.Context, metadata *C.Metadata) (C.PacketConn, error) {
|
func (ss *ShadowSocks) ListenPacketContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (C.PacketConn, error) {
|
||||||
pc, err := dialer.ListenPacket(ctx, "udp", "")
|
pc, err := dialer.ListenPacket(ctx, "udp", "", ss.Base.DialOptions(opts...)...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -158,6 +159,7 @@ func NewShadowSocks(option ShadowSocksOption) (*ShadowSocks, error) {
|
|||||||
addr: addr,
|
addr: addr,
|
||||||
tp: C.Shadowsocks,
|
tp: C.Shadowsocks,
|
||||||
udp: option.UDP,
|
udp: option.UDP,
|
||||||
|
iface: option.Interface,
|
||||||
},
|
},
|
||||||
cipher: ciph,
|
cipher: ciph,
|
||||||
|
|
||||||
|
@ -24,6 +24,7 @@ type ShadowSocksR struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ShadowSocksROption struct {
|
type ShadowSocksROption struct {
|
||||||
|
BasicOption
|
||||||
Name string `proxy:"name"`
|
Name string `proxy:"name"`
|
||||||
Server string `proxy:"server"`
|
Server string `proxy:"server"`
|
||||||
Port int `proxy:"port"`
|
Port int `proxy:"port"`
|
||||||
@ -59,8 +60,8 @@ func (ssr *ShadowSocksR) StreamConn(c net.Conn, metadata *C.Metadata) (net.Conn,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// DialContext implements C.ProxyAdapter
|
// DialContext implements C.ProxyAdapter
|
||||||
func (ssr *ShadowSocksR) DialContext(ctx context.Context, metadata *C.Metadata) (_ C.Conn, err error) {
|
func (ssr *ShadowSocksR) DialContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (_ C.Conn, err error) {
|
||||||
c, err := dialer.DialContext(ctx, "tcp", ssr.addr)
|
c, err := dialer.DialContext(ctx, "tcp", ssr.addr, ssr.Base.DialOptions(opts...)...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("%s connect error: %w", ssr.addr, err)
|
return nil, fmt.Errorf("%s connect error: %w", ssr.addr, err)
|
||||||
}
|
}
|
||||||
@ -73,8 +74,8 @@ func (ssr *ShadowSocksR) DialContext(ctx context.Context, metadata *C.Metadata)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ListenPacketContext implements C.ProxyAdapter
|
// ListenPacketContext implements C.ProxyAdapter
|
||||||
func (ssr *ShadowSocksR) ListenPacketContext(ctx context.Context, metadata *C.Metadata) (C.PacketConn, error) {
|
func (ssr *ShadowSocksR) ListenPacketContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (C.PacketConn, error) {
|
||||||
pc, err := dialer.ListenPacket(ctx, "udp", "")
|
pc, err := dialer.ListenPacket(ctx, "udp", "", ssr.Base.DialOptions(opts...)...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -140,6 +141,7 @@ func NewShadowSocksR(option ShadowSocksROption) (*ShadowSocksR, error) {
|
|||||||
addr: addr,
|
addr: addr,
|
||||||
tp: C.ShadowsocksR,
|
tp: C.ShadowsocksR,
|
||||||
udp: option.UDP,
|
udp: option.UDP,
|
||||||
|
iface: option.Interface,
|
||||||
},
|
},
|
||||||
cipher: coreCiph,
|
cipher: coreCiph,
|
||||||
obfs: obfs,
|
obfs: obfs,
|
||||||
|
@ -22,10 +22,12 @@ type Snell struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type SnellOption struct {
|
type SnellOption struct {
|
||||||
|
BasicOption
|
||||||
Name string `proxy:"name"`
|
Name string `proxy:"name"`
|
||||||
Server string `proxy:"server"`
|
Server string `proxy:"server"`
|
||||||
Port int `proxy:"port"`
|
Port int `proxy:"port"`
|
||||||
Psk string `proxy:"psk"`
|
Psk string `proxy:"psk"`
|
||||||
|
UDP bool `proxy:"udp,omitempty"`
|
||||||
Version int `proxy:"version,omitempty"`
|
Version int `proxy:"version,omitempty"`
|
||||||
ObfsOpts map[string]interface{} `proxy:"obfs-opts,omitempty"`
|
ObfsOpts map[string]interface{} `proxy:"obfs-opts,omitempty"`
|
||||||
}
|
}
|
||||||
@ -51,20 +53,20 @@ func streamConn(c net.Conn, option streamOption) *snell.Snell {
|
|||||||
// StreamConn implements C.ProxyAdapter
|
// StreamConn implements C.ProxyAdapter
|
||||||
func (s *Snell) StreamConn(c net.Conn, metadata *C.Metadata) (net.Conn, error) {
|
func (s *Snell) StreamConn(c net.Conn, metadata *C.Metadata) (net.Conn, error) {
|
||||||
c = streamConn(c, streamOption{s.psk, s.version, s.addr, s.obfsOption})
|
c = streamConn(c, streamOption{s.psk, s.version, s.addr, s.obfsOption})
|
||||||
port, _ := strconv.Atoi(metadata.DstPort)
|
port, _ := strconv.ParseUint(metadata.DstPort, 10, 16)
|
||||||
err := snell.WriteHeader(c, metadata.String(), uint(port), s.version)
|
err := snell.WriteHeader(c, metadata.String(), uint(port), s.version)
|
||||||
return c, err
|
return c, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// DialContext implements C.ProxyAdapter
|
// DialContext implements C.ProxyAdapter
|
||||||
func (s *Snell) DialContext(ctx context.Context, metadata *C.Metadata) (_ C.Conn, err error) {
|
func (s *Snell) DialContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (_ C.Conn, err error) {
|
||||||
if s.version == snell.Version2 {
|
if s.version == snell.Version2 && len(opts) == 0 {
|
||||||
c, err := s.pool.Get()
|
c, err := s.pool.Get()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
port, _ := strconv.Atoi(metadata.DstPort)
|
port, _ := strconv.ParseUint(metadata.DstPort, 10, 16)
|
||||||
if err = snell.WriteHeader(c, metadata.String(), uint(port), s.version); err != nil {
|
if err = snell.WriteHeader(c, metadata.String(), uint(port), s.version); err != nil {
|
||||||
c.Close()
|
c.Close()
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -72,7 +74,7 @@ func (s *Snell) DialContext(ctx context.Context, metadata *C.Metadata) (_ C.Conn
|
|||||||
return NewConn(c, s), err
|
return NewConn(c, s), err
|
||||||
}
|
}
|
||||||
|
|
||||||
c, err := dialer.DialContext(ctx, "tcp", s.addr)
|
c, err := dialer.DialContext(ctx, "tcp", s.addr, s.Base.DialOptions(opts...)...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("%s connect error: %w", s.addr, err)
|
return nil, fmt.Errorf("%s connect error: %w", s.addr, err)
|
||||||
}
|
}
|
||||||
@ -84,6 +86,24 @@ func (s *Snell) DialContext(ctx context.Context, metadata *C.Metadata) (_ C.Conn
|
|||||||
return NewConn(c, s), err
|
return NewConn(c, s), err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ListenPacketContext implements C.ProxyAdapter
|
||||||
|
func (s *Snell) ListenPacketContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (C.PacketConn, error) {
|
||||||
|
c, err := dialer.DialContext(ctx, "tcp", s.addr, s.Base.DialOptions(opts...)...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
tcpKeepAlive(c)
|
||||||
|
c = streamConn(c, streamOption{s.psk, s.version, s.addr, s.obfsOption})
|
||||||
|
|
||||||
|
err = snell.WriteUDPHeader(c, s.version)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
pc := snell.PacketConn(c)
|
||||||
|
return newPacketConn(pc, s), nil
|
||||||
|
}
|
||||||
|
|
||||||
func NewSnell(option SnellOption) (*Snell, error) {
|
func NewSnell(option SnellOption) (*Snell, error) {
|
||||||
addr := net.JoinHostPort(option.Server, strconv.Itoa(option.Port))
|
addr := net.JoinHostPort(option.Server, strconv.Itoa(option.Port))
|
||||||
psk := []byte(option.Psk)
|
psk := []byte(option.Psk)
|
||||||
@ -105,7 +125,13 @@ func NewSnell(option SnellOption) (*Snell, error) {
|
|||||||
if option.Version == 0 {
|
if option.Version == 0 {
|
||||||
option.Version = snell.DefaultSnellVersion
|
option.Version = snell.DefaultSnellVersion
|
||||||
}
|
}
|
||||||
if option.Version != snell.Version1 && option.Version != snell.Version2 {
|
switch option.Version {
|
||||||
|
case snell.Version1, snell.Version2:
|
||||||
|
if option.UDP {
|
||||||
|
return nil, fmt.Errorf("snell version %d not support UDP", option.Version)
|
||||||
|
}
|
||||||
|
case snell.Version3:
|
||||||
|
default:
|
||||||
return nil, fmt.Errorf("snell version error: %d", option.Version)
|
return nil, fmt.Errorf("snell version error: %d", option.Version)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -114,6 +140,8 @@ func NewSnell(option SnellOption) (*Snell, error) {
|
|||||||
name: option.Name,
|
name: option.Name,
|
||||||
addr: addr,
|
addr: addr,
|
||||||
tp: C.Snell,
|
tp: C.Snell,
|
||||||
|
udp: option.UDP,
|
||||||
|
iface: option.Interface,
|
||||||
},
|
},
|
||||||
psk: psk,
|
psk: psk,
|
||||||
obfsOption: obfsOption,
|
obfsOption: obfsOption,
|
||||||
@ -122,7 +150,7 @@ func NewSnell(option SnellOption) (*Snell, error) {
|
|||||||
|
|
||||||
if option.Version == snell.Version2 {
|
if option.Version == snell.Version2 {
|
||||||
s.pool = snell.NewPool(func(ctx context.Context) (*snell.Snell, error) {
|
s.pool = snell.NewPool(func(ctx context.Context) (*snell.Snell, error) {
|
||||||
c, err := dialer.DialContext(ctx, "tcp", addr)
|
c, err := dialer.DialContext(ctx, "tcp", addr, s.Base.DialOptions()...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,7 @@ type Socks5 struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Socks5Option struct {
|
type Socks5Option struct {
|
||||||
|
BasicOption
|
||||||
Name string `proxy:"name"`
|
Name string `proxy:"name"`
|
||||||
Server string `proxy:"server"`
|
Server string `proxy:"server"`
|
||||||
Port int `proxy:"port"`
|
Port int `proxy:"port"`
|
||||||
@ -59,8 +60,8 @@ func (ss *Socks5) StreamConn(c net.Conn, metadata *C.Metadata) (net.Conn, error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// DialContext implements C.ProxyAdapter
|
// DialContext implements C.ProxyAdapter
|
||||||
func (ss *Socks5) DialContext(ctx context.Context, metadata *C.Metadata) (_ C.Conn, err error) {
|
func (ss *Socks5) DialContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (_ C.Conn, err error) {
|
||||||
c, err := dialer.DialContext(ctx, "tcp", ss.addr)
|
c, err := dialer.DialContext(ctx, "tcp", ss.addr, ss.Base.DialOptions(opts...)...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("%s connect error: %w", ss.addr, err)
|
return nil, fmt.Errorf("%s connect error: %w", ss.addr, err)
|
||||||
}
|
}
|
||||||
@ -77,8 +78,8 @@ func (ss *Socks5) DialContext(ctx context.Context, metadata *C.Metadata) (_ C.Co
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ListenPacketContext implements C.ProxyAdapter
|
// ListenPacketContext implements C.ProxyAdapter
|
||||||
func (ss *Socks5) ListenPacketContext(ctx context.Context, metadata *C.Metadata) (_ C.PacketConn, err error) {
|
func (ss *Socks5) ListenPacketContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (_ C.PacketConn, err error) {
|
||||||
c, err := dialer.DialContext(ctx, "tcp", ss.addr)
|
c, err := dialer.DialContext(ctx, "tcp", ss.addr, ss.Base.DialOptions(opts...)...)
|
||||||
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)
|
||||||
return
|
return
|
||||||
@ -107,7 +108,7 @@ func (ss *Socks5) ListenPacketContext(ctx context.Context, metadata *C.Metadata)
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
pc, err := dialer.ListenPacket(ctx, "udp", "")
|
pc, err := dialer.ListenPacket(ctx, "udp", "", ss.Base.DialOptions(opts...)...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -152,6 +153,7 @@ func NewSocks5(option Socks5Option) *Socks5 {
|
|||||||
addr: net.JoinHostPort(option.Server, strconv.Itoa(option.Port)),
|
addr: net.JoinHostPort(option.Server, strconv.Itoa(option.Port)),
|
||||||
tp: C.Socks5,
|
tp: C.Socks5,
|
||||||
udp: option.UDP,
|
udp: option.UDP,
|
||||||
|
iface: option.Interface,
|
||||||
},
|
},
|
||||||
user: option.UserName,
|
user: option.UserName,
|
||||||
pass: option.Password,
|
pass: option.Password,
|
||||||
|
@ -28,6 +28,7 @@ type Trojan struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type TrojanOption struct {
|
type TrojanOption struct {
|
||||||
|
BasicOption
|
||||||
Name string `proxy:"name"`
|
Name string `proxy:"name"`
|
||||||
Server string `proxy:"server"`
|
Server string `proxy:"server"`
|
||||||
Port int `proxy:"port"`
|
Port int `proxy:"port"`
|
||||||
@ -86,9 +87,9 @@ func (t *Trojan) StreamConn(c net.Conn, metadata *C.Metadata) (net.Conn, error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// DialContext implements C.ProxyAdapter
|
// DialContext implements C.ProxyAdapter
|
||||||
func (t *Trojan) DialContext(ctx context.Context, metadata *C.Metadata) (_ C.Conn, err error) {
|
func (t *Trojan) DialContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (_ C.Conn, err error) {
|
||||||
// gun transport
|
// gun transport
|
||||||
if t.transport != nil {
|
if t.transport != nil && len(opts) == 0 {
|
||||||
c, err := gun.StreamGunWithTransport(t.transport, t.gunConfig)
|
c, err := gun.StreamGunWithTransport(t.transport, t.gunConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -102,7 +103,7 @@ func (t *Trojan) DialContext(ctx context.Context, metadata *C.Metadata) (_ C.Con
|
|||||||
return NewConn(c, t), nil
|
return NewConn(c, t), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
c, err := dialer.DialContext(ctx, "tcp", t.addr)
|
c, err := dialer.DialContext(ctx, "tcp", t.addr, t.Base.DialOptions(opts...)...)
|
||||||
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)
|
||||||
}
|
}
|
||||||
@ -119,18 +120,18 @@ func (t *Trojan) DialContext(ctx context.Context, metadata *C.Metadata) (_ C.Con
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ListenPacketContext implements C.ProxyAdapter
|
// ListenPacketContext implements C.ProxyAdapter
|
||||||
func (t *Trojan) ListenPacketContext(ctx context.Context, metadata *C.Metadata) (_ C.PacketConn, err error) {
|
func (t *Trojan) ListenPacketContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (_ C.PacketConn, err error) {
|
||||||
var c net.Conn
|
var c net.Conn
|
||||||
|
|
||||||
// grpc transport
|
// grpc transport
|
||||||
if t.transport != nil {
|
if t.transport != nil && len(opts) == 0 {
|
||||||
c, err = gun.StreamGunWithTransport(t.transport, t.gunConfig)
|
c, err = gun.StreamGunWithTransport(t.transport, t.gunConfig)
|
||||||
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)
|
||||||
} else {
|
} else {
|
||||||
c, err = dialer.DialContext(ctx, "tcp", t.addr)
|
c, err = dialer.DialContext(ctx, "tcp", t.addr, t.Base.DialOptions(opts...)...)
|
||||||
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)
|
||||||
}
|
}
|
||||||
@ -171,6 +172,7 @@ func NewTrojan(option TrojanOption) (*Trojan, error) {
|
|||||||
addr: addr,
|
addr: addr,
|
||||||
tp: C.Trojan,
|
tp: C.Trojan,
|
||||||
udp: option.UDP,
|
udp: option.UDP,
|
||||||
|
iface: option.Interface,
|
||||||
},
|
},
|
||||||
instance: trojan.New(tOption),
|
instance: trojan.New(tOption),
|
||||||
option: &option,
|
option: &option,
|
||||||
@ -178,7 +180,7 @@ func NewTrojan(option TrojanOption) (*Trojan, error) {
|
|||||||
|
|
||||||
if option.Network == "grpc" {
|
if option.Network == "grpc" {
|
||||||
dialFn := func(network, addr string) (net.Conn, error) {
|
dialFn := func(network, addr string) (net.Conn, error) {
|
||||||
c, err := dialer.DialContext(context.Background(), "tcp", t.addr)
|
c, err := dialer.DialContext(context.Background(), "tcp", t.addr, t.Base.DialOptions()...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("%s connect error: %s", t.addr, err.Error())
|
return nil, fmt.Errorf("%s connect error: %s", t.addr, err.Error())
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,7 @@ func tcpKeepAlive(c net.Conn) {
|
|||||||
func serializesSocksAddr(metadata *C.Metadata) []byte {
|
func serializesSocksAddr(metadata *C.Metadata) []byte {
|
||||||
var buf [][]byte
|
var buf [][]byte
|
||||||
aType := uint8(metadata.AddrType)
|
aType := uint8(metadata.AddrType)
|
||||||
p, _ := strconv.Atoi(metadata.DstPort)
|
p, _ := strconv.ParseUint(metadata.DstPort, 10, 16)
|
||||||
port := []byte{uint8(p >> 8), uint8(p & 0xff)}
|
port := []byte{uint8(p >> 8), uint8(p & 0xff)}
|
||||||
switch metadata.AddrType {
|
switch metadata.AddrType {
|
||||||
case socks5.AtypDomainName:
|
case socks5.AtypDomainName:
|
||||||
|
@ -15,6 +15,7 @@ import (
|
|||||||
"github.com/Dreamacro/clash/transport/gun"
|
"github.com/Dreamacro/clash/transport/gun"
|
||||||
"github.com/Dreamacro/clash/transport/vless"
|
"github.com/Dreamacro/clash/transport/vless"
|
||||||
"github.com/Dreamacro/clash/transport/vmess"
|
"github.com/Dreamacro/clash/transport/vmess"
|
||||||
|
|
||||||
"golang.org/x/net/http2"
|
"golang.org/x/net/http2"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -30,6 +31,7 @@ type Vless struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type VlessOption struct {
|
type VlessOption struct {
|
||||||
|
BasicOption
|
||||||
Name string `proxy:"name"`
|
Name string `proxy:"name"`
|
||||||
Server string `proxy:"server"`
|
Server string `proxy:"server"`
|
||||||
Port int `proxy:"port"`
|
Port int `proxy:"port"`
|
||||||
@ -181,9 +183,9 @@ func (v *Vless) isXTLSEnabled() bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// DialContext implements C.ProxyAdapter
|
// DialContext implements C.ProxyAdapter
|
||||||
func (v *Vless) DialContext(ctx context.Context, metadata *C.Metadata) (_ C.Conn, err error) {
|
func (v *Vless) DialContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (_ C.Conn, err error) {
|
||||||
// gun transport
|
// gun transport
|
||||||
if v.transport != nil {
|
if v.transport != nil && len(opts) == 0 {
|
||||||
c, err := gun.StreamGunWithTransport(v.transport, v.gunConfig)
|
c, err := gun.StreamGunWithTransport(v.transport, v.gunConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -198,7 +200,7 @@ func (v *Vless) DialContext(ctx context.Context, metadata *C.Metadata) (_ C.Conn
|
|||||||
return NewConn(c, v), nil
|
return NewConn(c, v), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
c, err := dialer.DialContext(ctx, "tcp", v.addr)
|
c, err := dialer.DialContext(ctx, "tcp", v.addr, v.Base.DialOptions(opts...)...)
|
||||||
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())
|
||||||
}
|
}
|
||||||
@ -209,8 +211,8 @@ func (v *Vless) 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 *Vless) DialUDP(metadata *C.Metadata) (_ C.PacketConn, err error) {
|
func (v *Vless) ListenPacketContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (_ 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)
|
||||||
@ -222,7 +224,7 @@ func (v *Vless) DialUDP(metadata *C.Metadata) (_ C.PacketConn, err error) {
|
|||||||
|
|
||||||
var c net.Conn
|
var c net.Conn
|
||||||
// gun transport
|
// gun transport
|
||||||
if v.transport != nil {
|
if v.transport != nil && len(opts) == 0 {
|
||||||
c, err = gun.StreamGunWithTransport(v.transport, v.gunConfig)
|
c, err = gun.StreamGunWithTransport(v.transport, v.gunConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -231,9 +233,7 @@ func (v *Vless) DialUDP(metadata *C.Metadata) (_ C.PacketConn, err error) {
|
|||||||
|
|
||||||
c, err = v.client.StreamConn(c, parseVlessAddr(metadata))
|
c, err = v.client.StreamConn(c, parseVlessAddr(metadata))
|
||||||
} else {
|
} else {
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), C.DefaultTCPTimeout)
|
c, err = dialer.DialContext(ctx, "tcp", v.addr, v.Base.DialOptions(opts...)...)
|
||||||
defer cancel()
|
|
||||||
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())
|
||||||
}
|
}
|
||||||
@ -244,7 +244,7 @@ func (v *Vless) DialUDP(metadata *C.Metadata) (_ C.PacketConn, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("new vmess client error: %v", err)
|
return nil, fmt.Errorf("new vless client error: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return newPacketConn(&vlessPacketConn{Conn: c, rAddr: metadata.UDPAddr()}, v), nil
|
return newPacketConn(&vlessPacketConn{Conn: c, rAddr: metadata.UDPAddr()}, v), nil
|
||||||
@ -293,6 +293,10 @@ func (uc *vlessPacketConn) ReadFrom(b []byte) (int, net.Addr, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func NewVless(option VlessOption) (*Vless, error) {
|
func NewVless(option VlessOption) (*Vless, error) {
|
||||||
|
if !option.TLS {
|
||||||
|
return nil, fmt.Errorf("TLS must be true with vless")
|
||||||
|
}
|
||||||
|
|
||||||
var addons *vless.Addons
|
var addons *vless.Addons
|
||||||
if option.Network != "ws" && len(option.Flow) >= 16 {
|
if option.Network != "ws" && len(option.Flow) >= 16 {
|
||||||
option.Flow = option.Flow[:16]
|
option.Flow = option.Flow[:16]
|
||||||
@ -306,8 +310,6 @@ func NewVless(option VlessOption) (*Vless, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
option.TLS = true
|
|
||||||
|
|
||||||
client, err := vless.NewClient(option.UUID, addons, option.FlowShow)
|
client, err := vless.NewClient(option.UUID, addons, option.FlowShow)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -319,6 +321,7 @@ func NewVless(option VlessOption) (*Vless, error) {
|
|||||||
addr: net.JoinHostPort(option.Server, strconv.Itoa(option.Port)),
|
addr: net.JoinHostPort(option.Server, strconv.Itoa(option.Port)),
|
||||||
tp: C.Vless,
|
tp: C.Vless,
|
||||||
udp: option.UDP,
|
udp: option.UDP,
|
||||||
|
iface: option.Interface,
|
||||||
},
|
},
|
||||||
client: client,
|
client: client,
|
||||||
option: &option,
|
option: &option,
|
||||||
@ -331,7 +334,7 @@ func NewVless(option VlessOption) (*Vless, error) {
|
|||||||
}
|
}
|
||||||
case "grpc":
|
case "grpc":
|
||||||
dialFn := func(network, addr string) (net.Conn, error) {
|
dialFn := func(network, addr string) (net.Conn, error) {
|
||||||
c, err := dialer.DialContext(context.Background(), "tcp", v.addr)
|
c, err := dialer.DialContext(context.Background(), "tcp", v.addr, v.Base.DialOptions()...)
|
||||||
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())
|
||||||
}
|
}
|
||||||
@ -344,7 +347,7 @@ func NewVless(option VlessOption) (*Vless, error) {
|
|||||||
Host: v.option.ServerName,
|
Host: v.option.ServerName,
|
||||||
}
|
}
|
||||||
tlsConfig := &tls.Config{
|
tlsConfig := &tls.Config{
|
||||||
InsecureSkipVerify: false,
|
InsecureSkipVerify: v.option.SkipCertVerify,
|
||||||
ServerName: v.option.ServerName,
|
ServerName: v.option.ServerName,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,6 +31,7 @@ type Vmess struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type VmessOption struct {
|
type VmessOption struct {
|
||||||
|
BasicOption
|
||||||
Name string `proxy:"name"`
|
Name string `proxy:"name"`
|
||||||
Server string `proxy:"server"`
|
Server string `proxy:"server"`
|
||||||
Port int `proxy:"port"`
|
Port int `proxy:"port"`
|
||||||
@ -46,10 +47,6 @@ type VmessOption struct {
|
|||||||
HTTP2Opts HTTP2Options `proxy:"h2-opts,omitempty"`
|
HTTP2Opts HTTP2Options `proxy:"h2-opts,omitempty"`
|
||||||
GrpcOpts GrpcOptions `proxy:"grpc-opts,omitempty"`
|
GrpcOpts GrpcOptions `proxy:"grpc-opts,omitempty"`
|
||||||
WSOpts WSOptions `proxy:"ws-opts,omitempty"`
|
WSOpts WSOptions `proxy:"ws-opts,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 {
|
||||||
@ -79,13 +76,6 @@ func (v *Vmess) StreamConn(c net.Conn, metadata *C.Metadata) (net.Conn, error) {
|
|||||||
var err error
|
var err error
|
||||||
switch v.option.Network {
|
switch v.option.Network {
|
||||||
case "ws":
|
case "ws":
|
||||||
if v.option.WSOpts.Path == "" {
|
|
||||||
v.option.WSOpts.Path = v.option.WSPath
|
|
||||||
}
|
|
||||||
if len(v.option.WSOpts.Headers) == 0 {
|
|
||||||
v.option.WSOpts.Headers = v.option.WSHeaders
|
|
||||||
}
|
|
||||||
|
|
||||||
host, port, _ := net.SplitHostPort(v.addr)
|
host, port, _ := net.SplitHostPort(v.addr)
|
||||||
wsOpts := &vmess.WebsocketConfig{
|
wsOpts := &vmess.WebsocketConfig{
|
||||||
Host: host,
|
Host: host,
|
||||||
@ -195,9 +185,9 @@ func (v *Vmess) StreamConn(c net.Conn, metadata *C.Metadata) (net.Conn, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// DialContext implements C.ProxyAdapter
|
// DialContext implements C.ProxyAdapter
|
||||||
func (v *Vmess) DialContext(ctx context.Context, metadata *C.Metadata) (_ C.Conn, err error) {
|
func (v *Vmess) DialContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (_ C.Conn, err error) {
|
||||||
// gun transport
|
// gun transport
|
||||||
if v.transport != nil {
|
if v.transport != nil && len(opts) == 0 {
|
||||||
c, err := gun.StreamGunWithTransport(v.transport, v.gunConfig)
|
c, err := gun.StreamGunWithTransport(v.transport, v.gunConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -212,7 +202,7 @@ func (v *Vmess) DialContext(ctx context.Context, metadata *C.Metadata) (_ C.Conn
|
|||||||
return NewConn(c, v), nil
|
return NewConn(c, v), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
c, err := dialer.DialContext(ctx, "tcp", v.addr)
|
c, err := dialer.DialContext(ctx, "tcp", v.addr, v.Base.DialOptions(opts...)...)
|
||||||
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())
|
||||||
}
|
}
|
||||||
@ -224,7 +214,7 @@ func (v *Vmess) DialContext(ctx context.Context, metadata *C.Metadata) (_ C.Conn
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ListenPacketContext implements C.ProxyAdapter
|
// ListenPacketContext implements C.ProxyAdapter
|
||||||
func (v *Vmess) ListenPacketContext(ctx context.Context, metadata *C.Metadata) (_ C.PacketConn, err error) {
|
func (v *Vmess) ListenPacketContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (_ 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)
|
||||||
@ -236,7 +226,7 @@ func (v *Vmess) ListenPacketContext(ctx context.Context, metadata *C.Metadata) (
|
|||||||
|
|
||||||
var c net.Conn
|
var c net.Conn
|
||||||
// gun transport
|
// gun transport
|
||||||
if v.transport != nil {
|
if v.transport != nil && len(opts) == 0 {
|
||||||
c, err = gun.StreamGunWithTransport(v.transport, v.gunConfig)
|
c, err = gun.StreamGunWithTransport(v.transport, v.gunConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -245,7 +235,7 @@ func (v *Vmess) ListenPacketContext(ctx context.Context, metadata *C.Metadata) (
|
|||||||
|
|
||||||
c, err = v.client.StreamConn(c, parseVmessAddr(metadata))
|
c, err = v.client.StreamConn(c, parseVmessAddr(metadata))
|
||||||
} else {
|
} else {
|
||||||
c, err = dialer.DialContext(ctx, "tcp", v.addr)
|
c, err = dialer.DialContext(ctx, "tcp", v.addr, v.Base.DialOptions(opts...)...)
|
||||||
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())
|
||||||
}
|
}
|
||||||
@ -289,6 +279,7 @@ func NewVmess(option VmessOption) (*Vmess, error) {
|
|||||||
addr: net.JoinHostPort(option.Server, strconv.Itoa(option.Port)),
|
addr: net.JoinHostPort(option.Server, strconv.Itoa(option.Port)),
|
||||||
tp: C.Vmess,
|
tp: C.Vmess,
|
||||||
udp: option.UDP,
|
udp: option.UDP,
|
||||||
|
iface: option.Interface,
|
||||||
},
|
},
|
||||||
client: client,
|
client: client,
|
||||||
option: &option,
|
option: &option,
|
||||||
@ -301,7 +292,7 @@ func NewVmess(option VmessOption) (*Vmess, error) {
|
|||||||
}
|
}
|
||||||
case "grpc":
|
case "grpc":
|
||||||
dialFn := func(network, addr string) (net.Conn, error) {
|
dialFn := func(network, addr string) (net.Conn, error) {
|
||||||
c, err := dialer.DialContext(context.Background(), "tcp", v.addr)
|
c, err := dialer.DialContext(context.Background(), "tcp", v.addr, v.Base.DialOptions()...)
|
||||||
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())
|
||||||
}
|
}
|
||||||
@ -351,7 +342,7 @@ func parseVmessAddr(metadata *C.Metadata) *vmess.DstAddr {
|
|||||||
copy(addr[1:], []byte(metadata.Host))
|
copy(addr[1:], []byte(metadata.Host))
|
||||||
}
|
}
|
||||||
|
|
||||||
port, _ := strconv.Atoi(metadata.DstPort)
|
port, _ := strconv.ParseUint(metadata.DstPort, 10, 16)
|
||||||
return &vmess.DstAddr{
|
return &vmess.DstAddr{
|
||||||
UDP: metadata.NetWork == C.UDP,
|
UDP: metadata.NetWork == C.UDP,
|
||||||
AddrType: addrType,
|
AddrType: addrType,
|
||||||
|
@ -6,6 +6,7 @@ import (
|
|||||||
|
|
||||||
"github.com/Dreamacro/clash/adapter/outbound"
|
"github.com/Dreamacro/clash/adapter/outbound"
|
||||||
"github.com/Dreamacro/clash/common/singledo"
|
"github.com/Dreamacro/clash/common/singledo"
|
||||||
|
"github.com/Dreamacro/clash/component/dialer"
|
||||||
C "github.com/Dreamacro/clash/constant"
|
C "github.com/Dreamacro/clash/constant"
|
||||||
"github.com/Dreamacro/clash/constant/provider"
|
"github.com/Dreamacro/clash/constant/provider"
|
||||||
)
|
)
|
||||||
@ -23,9 +24,9 @@ func (f *Fallback) Now() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// DialContext implements C.ProxyAdapter
|
// DialContext implements C.ProxyAdapter
|
||||||
func (f *Fallback) DialContext(ctx context.Context, metadata *C.Metadata) (C.Conn, error) {
|
func (f *Fallback) DialContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (C.Conn, error) {
|
||||||
proxy := f.findAliveProxy(true)
|
proxy := f.findAliveProxy(true)
|
||||||
c, err := proxy.DialContext(ctx, metadata)
|
c, err := proxy.DialContext(ctx, metadata, f.Base.DialOptions(opts...)...)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
c.AppendToChains(f)
|
c.AppendToChains(f)
|
||||||
}
|
}
|
||||||
@ -33,9 +34,9 @@ func (f *Fallback) DialContext(ctx context.Context, metadata *C.Metadata) (C.Con
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ListenPacketContext implements C.ProxyAdapter
|
// ListenPacketContext implements C.ProxyAdapter
|
||||||
func (f *Fallback) ListenPacketContext(ctx context.Context, metadata *C.Metadata) (C.PacketConn, error) {
|
func (f *Fallback) ListenPacketContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (C.PacketConn, error) {
|
||||||
proxy := f.findAliveProxy(true)
|
proxy := f.findAliveProxy(true)
|
||||||
pc, err := proxy.ListenPacketContext(ctx, metadata)
|
pc, err := proxy.ListenPacketContext(ctx, metadata, f.Base.DialOptions(opts...)...)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
pc.AppendToChains(f)
|
pc.AppendToChains(f)
|
||||||
}
|
}
|
||||||
@ -90,11 +91,16 @@ func (f *Fallback) findAliveProxy(touch bool) C.Proxy {
|
|||||||
return proxies[0]
|
return proxies[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewFallback(options *GroupCommonOption, providers []provider.ProxyProvider) *Fallback {
|
func NewFallback(option *GroupCommonOption, providers []provider.ProxyProvider) *Fallback {
|
||||||
return &Fallback{
|
return &Fallback{
|
||||||
Base: outbound.NewBase(options.Name, "", C.Fallback, false),
|
Base: outbound.NewBase(outbound.BaseOption{
|
||||||
|
Name: option.Name,
|
||||||
|
Type: C.Fallback,
|
||||||
|
Interface: option.Interface,
|
||||||
|
RoutingMark: option.RoutingMark,
|
||||||
|
}),
|
||||||
single: singledo.NewSingle(defaultGetProxiesDuration),
|
single: singledo.NewSingle(defaultGetProxiesDuration),
|
||||||
providers: providers,
|
providers: providers,
|
||||||
disableUDP: options.DisableUDP,
|
disableUDP: option.DisableUDP,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@ import (
|
|||||||
"github.com/Dreamacro/clash/adapter/outbound"
|
"github.com/Dreamacro/clash/adapter/outbound"
|
||||||
"github.com/Dreamacro/clash/common/murmur3"
|
"github.com/Dreamacro/clash/common/murmur3"
|
||||||
"github.com/Dreamacro/clash/common/singledo"
|
"github.com/Dreamacro/clash/common/singledo"
|
||||||
|
"github.com/Dreamacro/clash/component/dialer"
|
||||||
C "github.com/Dreamacro/clash/constant"
|
C "github.com/Dreamacro/clash/constant"
|
||||||
"github.com/Dreamacro/clash/constant/provider"
|
"github.com/Dreamacro/clash/constant/provider"
|
||||||
|
|
||||||
@ -69,7 +70,7 @@ func jumpHash(key uint64, buckets int32) int32 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// DialContext implements C.ProxyAdapter
|
// DialContext implements C.ProxyAdapter
|
||||||
func (lb *LoadBalance) DialContext(ctx context.Context, metadata *C.Metadata) (c C.Conn, err error) {
|
func (lb *LoadBalance) DialContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (c C.Conn, err error) {
|
||||||
defer func() {
|
defer func() {
|
||||||
if err == nil {
|
if err == nil {
|
||||||
c.AppendToChains(lb)
|
c.AppendToChains(lb)
|
||||||
@ -78,12 +79,12 @@ func (lb *LoadBalance) DialContext(ctx context.Context, metadata *C.Metadata) (c
|
|||||||
|
|
||||||
proxy := lb.Unwrap(metadata)
|
proxy := lb.Unwrap(metadata)
|
||||||
|
|
||||||
c, err = proxy.DialContext(ctx, metadata)
|
c, err = proxy.DialContext(ctx, metadata, lb.Base.DialOptions(opts...)...)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListenPacketContext implements C.ProxyAdapter
|
// ListenPacketContext implements C.ProxyAdapter
|
||||||
func (lb *LoadBalance) ListenPacketContext(ctx context.Context, metadata *C.Metadata) (pc C.PacketConn, err error) {
|
func (lb *LoadBalance) ListenPacketContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (pc C.PacketConn, err error) {
|
||||||
defer func() {
|
defer func() {
|
||||||
if err == nil {
|
if err == nil {
|
||||||
pc.AppendToChains(lb)
|
pc.AppendToChains(lb)
|
||||||
@ -91,7 +92,7 @@ func (lb *LoadBalance) ListenPacketContext(ctx context.Context, metadata *C.Meta
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
proxy := lb.Unwrap(metadata)
|
proxy := lb.Unwrap(metadata)
|
||||||
return proxy.ListenPacketContext(ctx, metadata)
|
return proxy.ListenPacketContext(ctx, metadata, lb.Base.DialOptions(opts...)...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SupportUDP implements C.ProxyAdapter
|
// SupportUDP implements C.ProxyAdapter
|
||||||
@ -158,7 +159,7 @@ func (lb *LoadBalance) MarshalJSON() ([]byte, error) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewLoadBalance(options *GroupCommonOption, providers []provider.ProxyProvider, strategy string) (lb *LoadBalance, err error) {
|
func NewLoadBalance(option *GroupCommonOption, providers []provider.ProxyProvider, strategy string) (lb *LoadBalance, err error) {
|
||||||
var strategyFn strategyFn
|
var strategyFn strategyFn
|
||||||
switch strategy {
|
switch strategy {
|
||||||
case "consistent-hashing":
|
case "consistent-hashing":
|
||||||
@ -169,10 +170,15 @@ func NewLoadBalance(options *GroupCommonOption, providers []provider.ProxyProvid
|
|||||||
return nil, fmt.Errorf("%w: %s", errStrategy, strategy)
|
return nil, fmt.Errorf("%w: %s", errStrategy, strategy)
|
||||||
}
|
}
|
||||||
return &LoadBalance{
|
return &LoadBalance{
|
||||||
Base: outbound.NewBase(options.Name, "", C.LoadBalance, false),
|
Base: outbound.NewBase(outbound.BaseOption{
|
||||||
|
Name: option.Name,
|
||||||
|
Type: C.LoadBalance,
|
||||||
|
Interface: option.Interface,
|
||||||
|
RoutingMark: option.RoutingMark,
|
||||||
|
}),
|
||||||
single: singledo.NewSingle(defaultGetProxiesDuration),
|
single: singledo.NewSingle(defaultGetProxiesDuration),
|
||||||
providers: providers,
|
providers: providers,
|
||||||
strategyFn: strategyFn,
|
strategyFn: strategyFn,
|
||||||
disableUDP: options.DisableUDP,
|
disableUDP: option.DisableUDP,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/Dreamacro/clash/adapter/outbound"
|
||||||
"github.com/Dreamacro/clash/adapter/provider"
|
"github.com/Dreamacro/clash/adapter/provider"
|
||||||
"github.com/Dreamacro/clash/common/structure"
|
"github.com/Dreamacro/clash/common/structure"
|
||||||
C "github.com/Dreamacro/clash/constant"
|
C "github.com/Dreamacro/clash/constant"
|
||||||
@ -15,10 +16,11 @@ var (
|
|||||||
errType = errors.New("unsupport type")
|
errType = errors.New("unsupport type")
|
||||||
errMissProxy = errors.New("`use` or `proxies` missing")
|
errMissProxy = errors.New("`use` or `proxies` missing")
|
||||||
errMissHealthCheck = errors.New("`url` or `interval` missing")
|
errMissHealthCheck = errors.New("`url` or `interval` missing")
|
||||||
errDuplicateProvider = errors.New("`duplicate provider name")
|
errDuplicateProvider = errors.New("duplicate provider name")
|
||||||
)
|
)
|
||||||
|
|
||||||
type GroupCommonOption struct {
|
type GroupCommonOption struct {
|
||||||
|
outbound.BasicOption
|
||||||
Name string `group:"name"`
|
Name string `group:"name"`
|
||||||
Type string `group:"type"`
|
Type string `group:"type"`
|
||||||
Proxies []string `group:"proxies,omitempty"`
|
Proxies []string `group:"proxies,omitempty"`
|
||||||
@ -57,16 +59,6 @@ func ParseProxyGroup(config map[string]interface{}, proxyMap map[string]C.Proxy,
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// if Use not empty, drop health check options
|
|
||||||
if len(groupOption.Use) != 0 {
|
|
||||||
hc := provider.NewHealthCheck(ps, "", 0, true)
|
|
||||||
pd, err := provider.NewCompatibleProvider(groupName, ps, hc)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
providers = append(providers, pd)
|
|
||||||
} else {
|
|
||||||
if _, ok := providersMap[groupName]; ok {
|
if _, ok := providersMap[groupName]; ok {
|
||||||
return nil, errDuplicateProvider
|
return nil, errDuplicateProvider
|
||||||
}
|
}
|
||||||
@ -96,7 +88,6 @@ func ParseProxyGroup(config map[string]interface{}, proxyMap map[string]C.Proxy,
|
|||||||
providersMap[groupName] = pd
|
providersMap[groupName] = pd
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if len(groupOption.Use) != 0 {
|
if len(groupOption.Use) != 0 {
|
||||||
list, err := getProviders(providersMap, groupOption.Use)
|
list, err := getProviders(providersMap, groupOption.Use)
|
||||||
|
@ -19,7 +19,7 @@ type Relay struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// DialContext implements C.ProxyAdapter
|
// DialContext implements C.ProxyAdapter
|
||||||
func (r *Relay) DialContext(ctx context.Context, metadata *C.Metadata) (C.Conn, error) {
|
func (r *Relay) DialContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (C.Conn, error) {
|
||||||
var proxies []C.Proxy
|
var proxies []C.Proxy
|
||||||
for _, proxy := range r.proxies(metadata, true) {
|
for _, proxy := range r.proxies(metadata, true) {
|
||||||
if proxy.Type() != C.Direct {
|
if proxy.Type() != C.Direct {
|
||||||
@ -29,15 +29,15 @@ func (r *Relay) DialContext(ctx context.Context, metadata *C.Metadata) (C.Conn,
|
|||||||
|
|
||||||
switch len(proxies) {
|
switch len(proxies) {
|
||||||
case 0:
|
case 0:
|
||||||
return outbound.NewDirect().DialContext(ctx, metadata)
|
return outbound.NewDirect().DialContext(ctx, metadata, r.Base.DialOptions(opts...)...)
|
||||||
case 1:
|
case 1:
|
||||||
return proxies[0].DialContext(ctx, metadata)
|
return proxies[0].DialContext(ctx, metadata, r.Base.DialOptions(opts...)...)
|
||||||
}
|
}
|
||||||
|
|
||||||
first := proxies[0]
|
first := proxies[0]
|
||||||
last := proxies[len(proxies)-1]
|
last := proxies[len(proxies)-1]
|
||||||
|
|
||||||
c, err := dialer.DialContext(ctx, "tcp", first.Addr())
|
c, err := dialer.DialContext(ctx, "tcp", first.Addr(), r.Base.DialOptions(opts...)...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("%s connect error: %w", first.Addr(), err)
|
return nil, fmt.Errorf("%s connect error: %w", first.Addr(), err)
|
||||||
}
|
}
|
||||||
@ -100,9 +100,14 @@ func (r *Relay) proxies(metadata *C.Metadata, touch bool) []C.Proxy {
|
|||||||
return proxies
|
return proxies
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewRelay(options *GroupCommonOption, providers []provider.ProxyProvider) *Relay {
|
func NewRelay(option *GroupCommonOption, providers []provider.ProxyProvider) *Relay {
|
||||||
return &Relay{
|
return &Relay{
|
||||||
Base: outbound.NewBase(options.Name, "", C.Relay, false),
|
Base: outbound.NewBase(outbound.BaseOption{
|
||||||
|
Name: option.Name,
|
||||||
|
Type: C.Relay,
|
||||||
|
Interface: option.Interface,
|
||||||
|
RoutingMark: option.RoutingMark,
|
||||||
|
}),
|
||||||
single: singledo.NewSingle(defaultGetProxiesDuration),
|
single: singledo.NewSingle(defaultGetProxiesDuration),
|
||||||
providers: providers,
|
providers: providers,
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ import (
|
|||||||
|
|
||||||
"github.com/Dreamacro/clash/adapter/outbound"
|
"github.com/Dreamacro/clash/adapter/outbound"
|
||||||
"github.com/Dreamacro/clash/common/singledo"
|
"github.com/Dreamacro/clash/common/singledo"
|
||||||
|
"github.com/Dreamacro/clash/component/dialer"
|
||||||
C "github.com/Dreamacro/clash/constant"
|
C "github.com/Dreamacro/clash/constant"
|
||||||
"github.com/Dreamacro/clash/constant/provider"
|
"github.com/Dreamacro/clash/constant/provider"
|
||||||
)
|
)
|
||||||
@ -20,8 +21,8 @@ type Selector struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// DialContext implements C.ProxyAdapter
|
// DialContext implements C.ProxyAdapter
|
||||||
func (s *Selector) DialContext(ctx context.Context, metadata *C.Metadata) (C.Conn, error) {
|
func (s *Selector) DialContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (C.Conn, error) {
|
||||||
c, err := s.selectedProxy(true).DialContext(ctx, metadata)
|
c, err := s.selectedProxy(true).DialContext(ctx, metadata, s.Base.DialOptions(opts...)...)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
c.AppendToChains(s)
|
c.AppendToChains(s)
|
||||||
}
|
}
|
||||||
@ -29,8 +30,8 @@ func (s *Selector) DialContext(ctx context.Context, metadata *C.Metadata) (C.Con
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ListenPacketContext implements C.ProxyAdapter
|
// ListenPacketContext implements C.ProxyAdapter
|
||||||
func (s *Selector) ListenPacketContext(ctx context.Context, metadata *C.Metadata) (C.PacketConn, error) {
|
func (s *Selector) ListenPacketContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (C.PacketConn, error) {
|
||||||
pc, err := s.selectedProxy(true).ListenPacketContext(ctx, metadata)
|
pc, err := s.selectedProxy(true).ListenPacketContext(ctx, metadata, s.Base.DialOptions(opts...)...)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
pc.AppendToChains(s)
|
pc.AppendToChains(s)
|
||||||
}
|
}
|
||||||
@ -96,13 +97,18 @@ func (s *Selector) selectedProxy(touch bool) C.Proxy {
|
|||||||
return elm.(C.Proxy)
|
return elm.(C.Proxy)
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewSelector(options *GroupCommonOption, providers []provider.ProxyProvider) *Selector {
|
func NewSelector(option *GroupCommonOption, providers []provider.ProxyProvider) *Selector {
|
||||||
selected := providers[0].Proxies()[0].Name()
|
selected := providers[0].Proxies()[0].Name()
|
||||||
return &Selector{
|
return &Selector{
|
||||||
Base: outbound.NewBase(options.Name, "", C.Selector, false),
|
Base: outbound.NewBase(outbound.BaseOption{
|
||||||
|
Name: option.Name,
|
||||||
|
Type: C.Selector,
|
||||||
|
Interface: option.Interface,
|
||||||
|
RoutingMark: option.RoutingMark,
|
||||||
|
}),
|
||||||
single: singledo.NewSingle(defaultGetProxiesDuration),
|
single: singledo.NewSingle(defaultGetProxiesDuration),
|
||||||
providers: providers,
|
providers: providers,
|
||||||
selected: selected,
|
selected: selected,
|
||||||
disableUDP: options.DisableUDP,
|
disableUDP: option.DisableUDP,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ import (
|
|||||||
|
|
||||||
"github.com/Dreamacro/clash/adapter/outbound"
|
"github.com/Dreamacro/clash/adapter/outbound"
|
||||||
"github.com/Dreamacro/clash/common/singledo"
|
"github.com/Dreamacro/clash/common/singledo"
|
||||||
|
"github.com/Dreamacro/clash/component/dialer"
|
||||||
C "github.com/Dreamacro/clash/constant"
|
C "github.com/Dreamacro/clash/constant"
|
||||||
"github.com/Dreamacro/clash/constant/provider"
|
"github.com/Dreamacro/clash/constant/provider"
|
||||||
)
|
)
|
||||||
@ -34,8 +35,8 @@ func (u *URLTest) Now() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// DialContext implements C.ProxyAdapter
|
// DialContext implements C.ProxyAdapter
|
||||||
func (u *URLTest) DialContext(ctx context.Context, metadata *C.Metadata) (c C.Conn, err error) {
|
func (u *URLTest) DialContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (c C.Conn, err error) {
|
||||||
c, err = u.fast(true).DialContext(ctx, metadata)
|
c, err = u.fast(true).DialContext(ctx, metadata, u.Base.DialOptions(opts...)...)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
c.AppendToChains(u)
|
c.AppendToChains(u)
|
||||||
}
|
}
|
||||||
@ -43,8 +44,8 @@ func (u *URLTest) DialContext(ctx context.Context, metadata *C.Metadata) (c C.Co
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ListenPacketContext implements C.ProxyAdapter
|
// ListenPacketContext implements C.ProxyAdapter
|
||||||
func (u *URLTest) ListenPacketContext(ctx context.Context, metadata *C.Metadata) (C.PacketConn, error) {
|
func (u *URLTest) ListenPacketContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (C.PacketConn, error) {
|
||||||
pc, err := u.fast(true).ListenPacketContext(ctx, metadata)
|
pc, err := u.fast(true).ListenPacketContext(ctx, metadata, u.Base.DialOptions(opts...)...)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
pc.AppendToChains(u)
|
pc.AppendToChains(u)
|
||||||
}
|
}
|
||||||
@ -133,13 +134,18 @@ func parseURLTestOption(config map[string]interface{}) []urlTestOption {
|
|||||||
return opts
|
return opts
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewURLTest(commonOptions *GroupCommonOption, providers []provider.ProxyProvider, options ...urlTestOption) *URLTest {
|
func NewURLTest(option *GroupCommonOption, providers []provider.ProxyProvider, options ...urlTestOption) *URLTest {
|
||||||
urlTest := &URLTest{
|
urlTest := &URLTest{
|
||||||
Base: outbound.NewBase(commonOptions.Name, "", C.URLTest, false),
|
Base: outbound.NewBase(outbound.BaseOption{
|
||||||
|
Name: option.Name,
|
||||||
|
Type: C.URLTest,
|
||||||
|
Interface: option.Interface,
|
||||||
|
RoutingMark: option.RoutingMark,
|
||||||
|
}),
|
||||||
single: singledo.NewSingle(defaultGetProxiesDuration),
|
single: singledo.NewSingle(defaultGetProxiesDuration),
|
||||||
fastSingle: singledo.NewSingle(time.Second * 10),
|
fastSingle: singledo.NewSingle(time.Second * 10),
|
||||||
providers: providers,
|
providers: providers,
|
||||||
disableUDP: commonOptions.DisableUDP,
|
disableUDP: option.DisableUDP,
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, option := range options {
|
for _, option := range options {
|
||||||
|
@ -102,6 +102,7 @@ func (f *fetcher) Update() (interface{}, bool, error) {
|
|||||||
hash := md5.Sum(buf)
|
hash := md5.Sum(buf)
|
||||||
if bytes.Equal(f.hash[:], hash[:]) {
|
if bytes.Equal(f.hash[:], hash[:]) {
|
||||||
f.updatedAt = &now
|
f.updatedAt = &now
|
||||||
|
os.Chtimes(f.vehicle.Path(), now, now)
|
||||||
return nil, true, nil
|
return nil, true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,6 +24,7 @@ type proxyProviderSchema struct {
|
|||||||
Path string `provider:"path"`
|
Path string `provider:"path"`
|
||||||
URL string `provider:"url,omitempty"`
|
URL string `provider:"url,omitempty"`
|
||||||
Interval int `provider:"interval,omitempty"`
|
Interval int `provider:"interval,omitempty"`
|
||||||
|
Filter string `provider:"filter,omitempty"`
|
||||||
HealthCheck healthCheckSchema `provider:"health-check,omitempty"`
|
HealthCheck healthCheckSchema `provider:"health-check,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -58,5 +59,6 @@ func ParseProxyProvider(name string, mapping map[string]interface{}) (types.Prox
|
|||||||
}
|
}
|
||||||
|
|
||||||
interval := time.Duration(uint(schema.Interval)) * time.Second
|
interval := time.Duration(uint(schema.Interval)) * time.Second
|
||||||
return NewProxySetProvider(name, interval, vehicle, hc), nil
|
filter := schema.Filter
|
||||||
|
return NewProxySetProvider(name, interval, filter, vehicle, hc)
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"regexp"
|
||||||
"runtime"
|
"runtime"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -82,33 +83,6 @@ func (pp *proxySetProvider) ProxiesWithTouch() []C.Proxy {
|
|||||||
return pp.Proxies()
|
return pp.Proxies()
|
||||||
}
|
}
|
||||||
|
|
||||||
func proxiesParse(buf []byte) (interface{}, error) {
|
|
||||||
schema := &ProxySchema{}
|
|
||||||
|
|
||||||
if err := yaml.Unmarshal(buf, schema); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if schema.Proxies == nil {
|
|
||||||
return nil, errors.New("file must have a `proxies` field")
|
|
||||||
}
|
|
||||||
|
|
||||||
proxies := []C.Proxy{}
|
|
||||||
for idx, mapping := range schema.Proxies {
|
|
||||||
proxy, err := adapter.ParseProxy(mapping)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("proxy %d error: %w", idx, err)
|
|
||||||
}
|
|
||||||
proxies = append(proxies, proxy)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(proxies) == 0 {
|
|
||||||
return nil, errors.New("file doesn't have any valid proxy")
|
|
||||||
}
|
|
||||||
|
|
||||||
return proxies, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (pp *proxySetProvider) setProxies(proxies []C.Proxy) {
|
func (pp *proxySetProvider) setProxies(proxies []C.Proxy) {
|
||||||
pp.proxies = proxies
|
pp.proxies = proxies
|
||||||
pp.healthCheck.setProxy(proxies)
|
pp.healthCheck.setProxy(proxies)
|
||||||
@ -122,7 +96,12 @@ func stopProxyProvider(pd *ProxySetProvider) {
|
|||||||
pd.fetcher.Destroy()
|
pd.fetcher.Destroy()
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewProxySetProvider(name string, interval time.Duration, vehicle types.Vehicle, hc *HealthCheck) *ProxySetProvider {
|
func NewProxySetProvider(name string, interval time.Duration, filter string, vehicle types.Vehicle, hc *HealthCheck) (*ProxySetProvider, error) {
|
||||||
|
filterReg, err := regexp.Compile(filter)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("invalid filter regex: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
if hc.auto() {
|
if hc.auto() {
|
||||||
go hc.process()
|
go hc.process()
|
||||||
}
|
}
|
||||||
@ -137,12 +116,45 @@ func NewProxySetProvider(name string, interval time.Duration, vehicle types.Vehi
|
|||||||
pd.setProxies(ret)
|
pd.setProxies(ret)
|
||||||
}
|
}
|
||||||
|
|
||||||
fetcher := newFetcher(name, interval, vehicle, proxiesParse, onUpdate)
|
proxiesParseAndFilter := func(buf []byte) (interface{}, error) {
|
||||||
|
schema := &ProxySchema{}
|
||||||
|
|
||||||
|
if err := yaml.Unmarshal(buf, schema); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if schema.Proxies == nil {
|
||||||
|
return nil, errors.New("file must have a `proxies` field")
|
||||||
|
}
|
||||||
|
|
||||||
|
proxies := []C.Proxy{}
|
||||||
|
for idx, mapping := range schema.Proxies {
|
||||||
|
if name, ok := mapping["name"]; ok && len(filter) > 0 && !filterReg.MatchString(name.(string)) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
proxy, err := adapter.ParseProxy(mapping)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("proxy %d error: %w", idx, err)
|
||||||
|
}
|
||||||
|
proxies = append(proxies, proxy)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(proxies) == 0 {
|
||||||
|
if len(filter) > 0 {
|
||||||
|
return nil, errors.New("doesn't match any proxy, please check your filter")
|
||||||
|
}
|
||||||
|
return nil, errors.New("file doesn't have any proxy")
|
||||||
|
}
|
||||||
|
|
||||||
|
return proxies, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
fetcher := newFetcher(name, interval, vehicle, proxiesParseAndFilter, onUpdate)
|
||||||
pd.fetcher = fetcher
|
pd.fetcher = fetcher
|
||||||
|
|
||||||
wrapper := &ProxySetProvider{pd}
|
wrapper := &ProxySetProvider{pd}
|
||||||
runtime.SetFinalizer(wrapper, stopProxyProvider)
|
runtime.SetFinalizer(wrapper, stopProxyProvider)
|
||||||
return wrapper
|
return wrapper, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// for auto gc
|
// for auto gc
|
||||||
|
@ -5,6 +5,11 @@ const (
|
|||||||
// but the maximum packet size of vmess/shadowsocks is about 16 KiB
|
// but the maximum packet size of vmess/shadowsocks is about 16 KiB
|
||||||
// so define a buffer of 20 KiB to reduce the memory of each TCP relay
|
// so define a buffer of 20 KiB to reduce the memory of each TCP relay
|
||||||
RelayBufferSize = 20 * 1024
|
RelayBufferSize = 20 * 1024
|
||||||
|
|
||||||
|
// RelayBufferSize uses 20KiB, but due to the allocator it will actually
|
||||||
|
// request 32Kib. Most UDPs are smaller than the MTU, and the TUN's MTU
|
||||||
|
// set to 9000, so the UDP Buffer size set to 16Kib
|
||||||
|
UDPBufferSize = 16 * 1024
|
||||||
)
|
)
|
||||||
|
|
||||||
func Get(size int) []byte {
|
func Get(size int) []byte {
|
||||||
|
@ -37,6 +37,12 @@ func (d *Decoder) Decode(src map[string]interface{}, dst interface{}) error {
|
|||||||
v := reflect.ValueOf(dst).Elem()
|
v := reflect.ValueOf(dst).Elem()
|
||||||
for idx := 0; idx < v.NumField(); idx++ {
|
for idx := 0; idx < v.NumField(); idx++ {
|
||||||
field := t.Field(idx)
|
field := t.Field(idx)
|
||||||
|
if field.Anonymous {
|
||||||
|
if err := d.decodeStruct(field.Name, src, v.Field(idx)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
tag := field.Tag.Get(d.option.TagName)
|
tag := field.Tag.Get(d.option.TagName)
|
||||||
str := strings.SplitN(tag, ",", 2)
|
str := strings.SplitN(tag, ",", 2)
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
package structure
|
package structure
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"reflect"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -39,12 +40,8 @@ func TestStructure_Basic(t *testing.T) {
|
|||||||
|
|
||||||
s := &Baz{}
|
s := &Baz{}
|
||||||
err := decoder.Decode(rawMap, s)
|
err := decoder.Decode(rawMap, s)
|
||||||
if err != nil {
|
assert.Nil(t, err)
|
||||||
t.Fatal(err.Error())
|
assert.Equal(t, goal, s)
|
||||||
}
|
|
||||||
if !reflect.DeepEqual(s, goal) {
|
|
||||||
t.Fatalf("bad: %#v", s)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestStructure_Slice(t *testing.T) {
|
func TestStructure_Slice(t *testing.T) {
|
||||||
@ -60,12 +57,8 @@ func TestStructure_Slice(t *testing.T) {
|
|||||||
|
|
||||||
s := &BazSlice{}
|
s := &BazSlice{}
|
||||||
err := decoder.Decode(rawMap, s)
|
err := decoder.Decode(rawMap, s)
|
||||||
if err != nil {
|
assert.Nil(t, err)
|
||||||
t.Fatal(err.Error())
|
assert.Equal(t, goal, s)
|
||||||
}
|
|
||||||
if !reflect.DeepEqual(s, goal) {
|
|
||||||
t.Fatalf("bad: %#v", s)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestStructure_Optional(t *testing.T) {
|
func TestStructure_Optional(t *testing.T) {
|
||||||
@ -79,12 +72,8 @@ func TestStructure_Optional(t *testing.T) {
|
|||||||
|
|
||||||
s := &BazOptional{}
|
s := &BazOptional{}
|
||||||
err := decoder.Decode(rawMap, s)
|
err := decoder.Decode(rawMap, s)
|
||||||
if err != nil {
|
assert.Nil(t, err)
|
||||||
t.Fatal(err.Error())
|
assert.Equal(t, goal, s)
|
||||||
}
|
|
||||||
if !reflect.DeepEqual(s, goal) {
|
|
||||||
t.Fatalf("bad: %#v", s)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestStructure_MissingKey(t *testing.T) {
|
func TestStructure_MissingKey(t *testing.T) {
|
||||||
@ -94,18 +83,14 @@ func TestStructure_MissingKey(t *testing.T) {
|
|||||||
|
|
||||||
s := &Baz{}
|
s := &Baz{}
|
||||||
err := decoder.Decode(rawMap, s)
|
err := decoder.Decode(rawMap, s)
|
||||||
if err == nil {
|
assert.NotNilf(t, err, "should throw error: %#v", s)
|
||||||
t.Fatalf("should throw error: %#v", s)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestStructure_ParamError(t *testing.T) {
|
func TestStructure_ParamError(t *testing.T) {
|
||||||
rawMap := map[string]interface{}{}
|
rawMap := map[string]interface{}{}
|
||||||
s := Baz{}
|
s := Baz{}
|
||||||
err := decoder.Decode(rawMap, s)
|
err := decoder.Decode(rawMap, s)
|
||||||
if err == nil {
|
assert.NotNilf(t, err, "should throw error: %#v", s)
|
||||||
t.Fatalf("should throw error: %#v", s)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestStructure_SliceTypeError(t *testing.T) {
|
func TestStructure_SliceTypeError(t *testing.T) {
|
||||||
@ -116,9 +101,7 @@ func TestStructure_SliceTypeError(t *testing.T) {
|
|||||||
|
|
||||||
s := &BazSlice{}
|
s := &BazSlice{}
|
||||||
err := decoder.Decode(rawMap, s)
|
err := decoder.Decode(rawMap, s)
|
||||||
if err == nil {
|
assert.NotNilf(t, err, "should throw error: %#v", s)
|
||||||
t.Fatalf("should throw error: %#v", s)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestStructure_WeakType(t *testing.T) {
|
func TestStructure_WeakType(t *testing.T) {
|
||||||
@ -134,10 +117,23 @@ func TestStructure_WeakType(t *testing.T) {
|
|||||||
|
|
||||||
s := &BazSlice{}
|
s := &BazSlice{}
|
||||||
err := weakTypeDecoder.Decode(rawMap, s)
|
err := weakTypeDecoder.Decode(rawMap, s)
|
||||||
if err != nil {
|
assert.Nil(t, err)
|
||||||
t.Fatal(err.Error())
|
assert.Equal(t, goal, s)
|
||||||
}
|
}
|
||||||
if !reflect.DeepEqual(s, goal) {
|
|
||||||
t.Fatalf("bad: %#v", s)
|
func TestStructure_Nest(t *testing.T) {
|
||||||
}
|
rawMap := map[string]interface{}{
|
||||||
|
"foo": 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
goal := BazOptional{
|
||||||
|
Foo: 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
s := &struct {
|
||||||
|
BazOptional
|
||||||
|
}{}
|
||||||
|
err := decoder.Decode(rawMap, s)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, s.BazOptional, goal)
|
||||||
}
|
}
|
||||||
|
@ -4,9 +4,9 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"golang.org/x/sys/unix"
|
|
||||||
|
|
||||||
"github.com/Dreamacro/clash/component/iface"
|
"github.com/Dreamacro/clash/component/iface"
|
||||||
|
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
)
|
)
|
||||||
|
|
||||||
type controlFn = func(network, address string, c syscall.RawConn) error
|
type controlFn = func(network, address string, c syscall.RawConn) error
|
||||||
@ -27,14 +27,21 @@ func bindControl(ifaceIdx int, chain controlFn) controlFn {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.Control(func(fd uintptr) {
|
var innerErr error
|
||||||
|
err = c.Control(func(fd uintptr) {
|
||||||
switch network {
|
switch network {
|
||||||
case "tcp4", "udp4":
|
case "tcp4", "udp4":
|
||||||
unix.SetsockoptInt(int(fd), unix.IPPROTO_IP, unix.IP_BOUND_IF, ifaceIdx)
|
innerErr = unix.SetsockoptInt(int(fd), unix.IPPROTO_IP, unix.IP_BOUND_IF, ifaceIdx)
|
||||||
case "tcp6", "udp6":
|
case "tcp6", "udp6":
|
||||||
unix.SetsockoptInt(int(fd), unix.IPPROTO_IPV6, unix.IPV6_BOUND_IF, ifaceIdx)
|
innerErr = unix.SetsockoptInt(int(fd), unix.IPPROTO_IPV6, unix.IPV6_BOUND_IF, ifaceIdx)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
if innerErr != nil {
|
||||||
|
err = innerErr
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,9 +25,16 @@ func bindControl(ifaceName string, chain controlFn) controlFn {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.Control(func(fd uintptr) {
|
var innerErr error
|
||||||
unix.BindToDevice(int(fd), ifaceName)
|
err = c.Control(func(fd uintptr) {
|
||||||
|
innerErr = unix.BindToDevice(int(fd), ifaceName)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
if innerErr != nil {
|
||||||
|
err = innerErr
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,15 +58,15 @@ func bindIfaceToDialer(ifaceName string, dialer *net.Dialer, network string, des
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
local := 0
|
local := uint64(0)
|
||||||
if dialer.LocalAddr != nil {
|
if dialer.LocalAddr != nil {
|
||||||
_, port, err := net.SplitHostPort(dialer.LocalAddr.String())
|
_, port, err := net.SplitHostPort(dialer.LocalAddr.String())
|
||||||
if err == nil {
|
if err == nil {
|
||||||
local, _ = strconv.Atoi(port)
|
local, _ = strconv.ParseUint(port, 10, 16)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
addr, err := lookupLocalAddr(ifaceName, network, destination, local)
|
addr, err := lookupLocalAddr(ifaceName, network, destination, int(local))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -82,9 +82,9 @@ func bindIfaceToListenConfig(ifaceName string, _ *net.ListenConfig, network, add
|
|||||||
port = "0"
|
port = "0"
|
||||||
}
|
}
|
||||||
|
|
||||||
local, _ := strconv.Atoi(port)
|
local, _ := strconv.ParseUint(port, 10, 16)
|
||||||
|
|
||||||
addr, err := lookupLocalAddr(ifaceName, network, nil, local)
|
addr, err := lookupLocalAddr(ifaceName, network, nil, int(local))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
@ -36,13 +36,14 @@ func DialContext(ctx context.Context, network, address string, options ...Option
|
|||||||
}
|
}
|
||||||
|
|
||||||
func ListenPacket(ctx context.Context, network, address string, options ...Option) (net.PacketConn, error) {
|
func ListenPacket(ctx context.Context, network, address string, options ...Option) (net.PacketConn, error) {
|
||||||
cfg := &config{}
|
cfg := &option{
|
||||||
|
interfaceName: DefaultInterface.Load(),
|
||||||
|
routingMark: int(DefaultRoutingMark.Load()),
|
||||||
|
}
|
||||||
|
|
||||||
if !cfg.skipDefault {
|
|
||||||
for _, o := range DefaultOptions {
|
for _, o := range DefaultOptions {
|
||||||
o(cfg)
|
o(cfg)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
for _, o := range options {
|
for _, o := range options {
|
||||||
o(cfg)
|
o(cfg)
|
||||||
@ -59,18 +60,22 @@ func ListenPacket(ctx context.Context, network, address string, options ...Optio
|
|||||||
if cfg.addrReuse {
|
if cfg.addrReuse {
|
||||||
addrReuseToListenConfig(lc)
|
addrReuseToListenConfig(lc)
|
||||||
}
|
}
|
||||||
|
if cfg.routingMark != 0 {
|
||||||
|
bindMarkToListenConfig(cfg.routingMark, lc, network, address)
|
||||||
|
}
|
||||||
|
|
||||||
return lc.ListenPacket(ctx, network, address)
|
return lc.ListenPacket(ctx, network, address)
|
||||||
}
|
}
|
||||||
|
|
||||||
func dialContext(ctx context.Context, network string, destination net.IP, port string, options []Option) (net.Conn, error) {
|
func dialContext(ctx context.Context, network string, destination net.IP, port string, options []Option) (net.Conn, error) {
|
||||||
opt := &config{}
|
opt := &option{
|
||||||
|
interfaceName: DefaultInterface.Load(),
|
||||||
|
routingMark: int(DefaultRoutingMark.Load()),
|
||||||
|
}
|
||||||
|
|
||||||
if !opt.skipDefault {
|
|
||||||
for _, o := range DefaultOptions {
|
for _, o := range DefaultOptions {
|
||||||
o(opt)
|
o(opt)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
for _, o := range options {
|
for _, o := range options {
|
||||||
o(opt)
|
o(opt)
|
||||||
@ -82,6 +87,9 @@ func dialContext(ctx context.Context, network string, destination net.IP, port s
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if opt.routingMark != 0 {
|
||||||
|
bindMarkToDialer(opt.routingMark, dialer, network, destination)
|
||||||
|
}
|
||||||
|
|
||||||
return dialer.DialContext(ctx, network, net.JoinHostPort(destination.String(), port))
|
return dialer.DialContext(ctx, network, net.JoinHostPort(destination.String(), port))
|
||||||
}
|
}
|
||||||
|
44
component/dialer/mark_linux.go
Normal file
44
component/dialer/mark_linux.go
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
//go:build linux
|
||||||
|
// +build linux
|
||||||
|
|
||||||
|
package dialer
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"syscall"
|
||||||
|
)
|
||||||
|
|
||||||
|
func bindMarkToDialer(mark int, dialer *net.Dialer, _ string, _ net.IP) {
|
||||||
|
dialer.Control = bindMarkToControl(mark, dialer.Control)
|
||||||
|
}
|
||||||
|
|
||||||
|
func bindMarkToListenConfig(mark int, lc *net.ListenConfig, _, address string) {
|
||||||
|
lc.Control = bindMarkToControl(mark, lc.Control)
|
||||||
|
}
|
||||||
|
|
||||||
|
func bindMarkToControl(mark int, chain controlFn) controlFn {
|
||||||
|
return func(network, address string, c syscall.RawConn) (err error) {
|
||||||
|
defer func() {
|
||||||
|
if err == nil && chain != nil {
|
||||||
|
err = chain(network, address, c)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
ipStr, _, err := net.SplitHostPort(address)
|
||||||
|
if err == nil {
|
||||||
|
ip := net.ParseIP(ipStr)
|
||||||
|
if ip != nil && !ip.IsGlobalUnicast() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.Control(func(fd uintptr) {
|
||||||
|
switch network {
|
||||||
|
case "tcp4", "udp4":
|
||||||
|
syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_MARK, mark)
|
||||||
|
case "tcp6", "udp6":
|
||||||
|
syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_MARK, mark)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
27
component/dialer/mark_nonlinux.go
Normal file
27
component/dialer/mark_nonlinux.go
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
//go:build !linux
|
||||||
|
// +build !linux
|
||||||
|
|
||||||
|
package dialer
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"github.com/Dreamacro/clash/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
var printMarkWarnOnce sync.Once
|
||||||
|
|
||||||
|
func printMarkWarn() {
|
||||||
|
printMarkWarnOnce.Do(func() {
|
||||||
|
log.Warnln("Routing mark on socket is not supported on current platform")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func bindMarkToDialer(mark int, dialer *net.Dialer, _ string, _ net.IP) {
|
||||||
|
printMarkWarn()
|
||||||
|
}
|
||||||
|
|
||||||
|
func bindMarkToListenConfig(mark int, lc *net.ListenConfig, _, address string) {
|
||||||
|
printMarkWarn()
|
||||||
|
}
|
@ -1,29 +1,35 @@
|
|||||||
package dialer
|
package dialer
|
||||||
|
|
||||||
var DefaultOptions []Option
|
import "go.uber.org/atomic"
|
||||||
|
|
||||||
type config struct {
|
var (
|
||||||
skipDefault bool
|
DefaultOptions []Option
|
||||||
|
DefaultInterface = atomic.NewString("")
|
||||||
|
DefaultRoutingMark = atomic.NewInt32(0)
|
||||||
|
)
|
||||||
|
|
||||||
|
type option struct {
|
||||||
interfaceName string
|
interfaceName string
|
||||||
addrReuse bool
|
addrReuse bool
|
||||||
|
routingMark int
|
||||||
}
|
}
|
||||||
|
|
||||||
type Option func(opt *config)
|
type Option func(opt *option)
|
||||||
|
|
||||||
func WithInterface(name string) Option {
|
func WithInterface(name string) Option {
|
||||||
return func(opt *config) {
|
return func(opt *option) {
|
||||||
opt.interfaceName = name
|
opt.interfaceName = name
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func WithAddrReuse(reuse bool) Option {
|
func WithAddrReuse(reuse bool) Option {
|
||||||
return func(opt *config) {
|
return func(opt *option) {
|
||||||
opt.addrReuse = reuse
|
opt.addrReuse = reuse
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func WithSkipDefault(skip bool) Option {
|
func WithRoutingMark(mark int) Option {
|
||||||
return func(opt *config) {
|
return func(opt *option) {
|
||||||
opt.skipDefault = skip
|
opt.routingMark = mark
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -38,6 +38,12 @@ func (c *cachefileStore) PutByIP(ip net.IP, host string) {
|
|||||||
c.cache.PutFakeip(ip.To4(), []byte(host))
|
c.cache.PutFakeip(ip.To4(), []byte(host))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DelByIP implements store.DelByIP
|
||||||
|
func (c *cachefileStore) DelByIP(ip net.IP) {
|
||||||
|
ip = ip.To4()
|
||||||
|
c.cache.DelFakeipPair(ip, c.cache.GetFakeip(ip.To4()))
|
||||||
|
}
|
||||||
|
|
||||||
// Exist implements store.Exist
|
// Exist implements store.Exist
|
||||||
func (c *cachefileStore) Exist(ip net.IP) bool {
|
func (c *cachefileStore) Exist(ip net.IP) bool {
|
||||||
_, exist := c.GetByIP(ip)
|
_, exist := c.GetByIP(ip)
|
||||||
|
@ -46,6 +46,15 @@ func (m *memoryStore) PutByIP(ip net.IP, host string) {
|
|||||||
m.cache.Set(ipToUint(ip.To4()), host)
|
m.cache.Set(ipToUint(ip.To4()), host)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DelByIP implements store.DelByIP
|
||||||
|
func (m *memoryStore) DelByIP(ip net.IP) {
|
||||||
|
ipNum := ipToUint(ip.To4())
|
||||||
|
if elm, exist := m.cache.Get(ipNum); exist {
|
||||||
|
m.cache.Delete(elm.(string))
|
||||||
|
}
|
||||||
|
m.cache.Delete(ipNum)
|
||||||
|
}
|
||||||
|
|
||||||
// Exist implements store.Exist
|
// Exist implements store.Exist
|
||||||
func (m *memoryStore) Exist(ip net.IP) bool {
|
func (m *memoryStore) Exist(ip net.IP) bool {
|
||||||
return m.cache.Exist(ipToUint(ip.To4()))
|
return m.cache.Exist(ipToUint(ip.To4()))
|
||||||
|
@ -15,6 +15,7 @@ type store interface {
|
|||||||
PutByHost(host string, ip net.IP)
|
PutByHost(host string, ip net.IP)
|
||||||
GetByIP(ip net.IP) (string, bool)
|
GetByIP(ip net.IP) (string, bool)
|
||||||
PutByIP(ip net.IP, host string)
|
PutByIP(ip net.IP, host string)
|
||||||
|
DelByIP(ip net.IP)
|
||||||
Exist(ip net.IP) bool
|
Exist(ip net.IP) bool
|
||||||
CloneTo(store)
|
CloneTo(store)
|
||||||
}
|
}
|
||||||
@ -97,6 +98,9 @@ func (p *Pool) get(host string) net.IP {
|
|||||||
p.offset = (p.offset + 1) % (p.max - p.min)
|
p.offset = (p.offset + 1) % (p.max - p.min)
|
||||||
// Avoid infinite loops
|
// Avoid infinite loops
|
||||||
if p.offset == current {
|
if p.offset == current {
|
||||||
|
p.offset = (p.offset + 1) % (p.max - p.min)
|
||||||
|
ip := uintToIP(p.min + p.offset - 1)
|
||||||
|
p.store.DelByIP(ip)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package fakeip
|
package fakeip
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
@ -75,7 +76,7 @@ func TestPool_Basic(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestPool_CycleUsed(t *testing.T) {
|
func TestPool_CycleUsed(t *testing.T) {
|
||||||
_, ipnet, _ := net.ParseCIDR("192.168.0.1/30")
|
_, ipnet, _ := net.ParseCIDR("192.168.0.1/29")
|
||||||
pools, tempfile, err := createPools(Options{
|
pools, tempfile, err := createPools(Options{
|
||||||
IPNet: ipnet,
|
IPNet: ipnet,
|
||||||
Size: 10,
|
Size: 10,
|
||||||
@ -84,9 +85,15 @@ func TestPool_CycleUsed(t *testing.T) {
|
|||||||
defer os.Remove(tempfile)
|
defer os.Remove(tempfile)
|
||||||
|
|
||||||
for _, pool := range pools {
|
for _, pool := range pools {
|
||||||
first := pool.Lookup("foo.com")
|
foo := pool.Lookup("foo.com")
|
||||||
same := pool.Lookup("baz.com")
|
bar := pool.Lookup("bar.com")
|
||||||
assert.True(t, first.Equal(same))
|
for i := 0; i < 3; i++ {
|
||||||
|
pool.Lookup(fmt.Sprintf("%d.com", i))
|
||||||
|
}
|
||||||
|
baz := pool.Lookup("baz.com")
|
||||||
|
next := pool.Lookup("foo.com")
|
||||||
|
assert.True(t, foo.Equal(baz))
|
||||||
|
assert.True(t, next.Equal(bar))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@ import (
|
|||||||
"github.com/Dreamacro/clash/component/geodata/router"
|
"github.com/Dreamacro/clash/component/geodata/router"
|
||||||
C "github.com/Dreamacro/clash/constant"
|
C "github.com/Dreamacro/clash/constant"
|
||||||
"github.com/Dreamacro/clash/log"
|
"github.com/Dreamacro/clash/log"
|
||||||
|
|
||||||
"google.golang.org/protobuf/proto"
|
"google.golang.org/protobuf/proto"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -9,6 +9,7 @@ import (
|
|||||||
"github.com/Dreamacro/clash/component/geodata"
|
"github.com/Dreamacro/clash/component/geodata"
|
||||||
"github.com/Dreamacro/clash/component/geodata/router"
|
"github.com/Dreamacro/clash/component/geodata/router"
|
||||||
C "github.com/Dreamacro/clash/constant"
|
C "github.com/Dreamacro/clash/constant"
|
||||||
|
|
||||||
"google.golang.org/protobuf/proto"
|
"google.golang.org/protobuf/proto"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
package cachefile
|
package cachefile
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"encoding/gob"
|
|
||||||
"os"
|
"os"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
@ -90,6 +88,31 @@ func (c *CacheFile) PutFakeip(key, value []byte) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *CacheFile) DelFakeipPair(ip, host []byte) error {
|
||||||
|
if c.DB == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
err := c.DB.Batch(func(t *bbolt.Tx) error {
|
||||||
|
bucket, err := t.CreateBucketIfNotExists(bucketFakeip)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = bucket.Delete(ip)
|
||||||
|
if len(host) > 0 {
|
||||||
|
if err := bucket.Delete(host); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
})
|
||||||
|
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 {
|
func (c *CacheFile) GetFakeip(key []byte) []byte {
|
||||||
if c.DB == nil {
|
if c.DB == nil {
|
||||||
return nil
|
return nil
|
||||||
@ -113,9 +136,7 @@ func (c *CacheFile) Close() error {
|
|||||||
return c.DB.Close()
|
return c.DB.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: remove migrateCache until 2022
|
func initCache() {
|
||||||
func migrateCache() {
|
|
||||||
defer func() {
|
|
||||||
options := bbolt.Options{Timeout: time.Second}
|
options := bbolt.Options{Timeout: time.Second}
|
||||||
db, err := bbolt.Open(C.Path.Cache(), fileMode, &options)
|
db, err := bbolt.Open(C.Path.Cache(), fileMode, &options)
|
||||||
switch err {
|
switch err {
|
||||||
@ -134,48 +155,11 @@ func migrateCache() {
|
|||||||
defaultCache = &CacheFile{
|
defaultCache = &CacheFile{
|
||||||
DB: db,
|
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{
|
|
||||||
Selected: map[string]string{},
|
|
||||||
}
|
|
||||||
bufReader := bytes.NewBuffer(buf)
|
|
||||||
gob.NewDecoder(bufReader).Decode(model)
|
|
||||||
|
|
||||||
// write to new cache file
|
|
||||||
db, err := bbolt.Open(C.Path.Cache(), fileMode, nil)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer db.Close()
|
|
||||||
|
|
||||||
db.Batch(func(t *bbolt.Tx) error {
|
|
||||||
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(migrateCache)
|
initOnce.Do(initCache)
|
||||||
|
|
||||||
return defaultCache
|
return defaultCache
|
||||||
}
|
}
|
||||||
|
@ -109,13 +109,13 @@ func (t *DomainTrie) search(node *Node, parts []string) *Node {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if c := node.getChild(parts[len(parts)-1]); c != nil {
|
if c := node.getChild(parts[len(parts)-1]); c != nil {
|
||||||
if n := t.search(c, parts[:len(parts)-1]); n != nil {
|
if n := t.search(c, parts[:len(parts)-1]); n != nil && n.Data != nil {
|
||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if c := node.getChild(wildcard); c != nil {
|
if c := node.getChild(wildcard); c != nil {
|
||||||
if n := t.search(c, parts[:len(parts)-1]); n != nil {
|
if n := t.search(c, parts[:len(parts)-1]); n != nil && n.Data != nil {
|
||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -97,3 +97,11 @@ func TestTrie_Boundary(t *testing.T) {
|
|||||||
assert.NotNil(t, tree.Insert("..dev", localIP))
|
assert.NotNil(t, tree.Insert("..dev", localIP))
|
||||||
assert.Nil(t, tree.Search("dev"))
|
assert.Nil(t, tree.Search("dev"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestTrie_WildcardBoundary(t *testing.T) {
|
||||||
|
tree := New()
|
||||||
|
tree.Insert("+.*", localIP)
|
||||||
|
tree.Insert("stun.*.*.*", localIP)
|
||||||
|
|
||||||
|
assert.NotNil(t, tree.Search("example.com"))
|
||||||
|
}
|
||||||
|
@ -2,8 +2,8 @@ package trie
|
|||||||
|
|
||||||
// Node is the trie's node
|
// Node is the trie's node
|
||||||
type Node struct {
|
type Node struct {
|
||||||
Data interface{}
|
|
||||||
children map[string]*Node
|
children map[string]*Node
|
||||||
|
Data interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *Node) getChild(s string) *Node {
|
func (n *Node) getChild(s string) *Node {
|
||||||
|
@ -34,6 +34,7 @@ type General struct {
|
|||||||
LogLevel log.LogLevel `json:"log-level"`
|
LogLevel log.LogLevel `json:"log-level"`
|
||||||
IPv6 bool `json:"ipv6"`
|
IPv6 bool `json:"ipv6"`
|
||||||
Interface string `json:"-"`
|
Interface string `json:"-"`
|
||||||
|
RoutingMark int `json:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Inbound
|
// Inbound
|
||||||
@ -82,7 +83,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"`
|
StoreFakeIP bool `yaml:"store-fake-ip"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tun config
|
// Tun config
|
||||||
@ -148,6 +149,7 @@ type RawConfig struct {
|
|||||||
ExternalUI string `yaml:"external-ui"`
|
ExternalUI string `yaml:"external-ui"`
|
||||||
Secret string `yaml:"secret"`
|
Secret string `yaml:"secret"`
|
||||||
Interface string `yaml:"interface-name"`
|
Interface string `yaml:"interface-name"`
|
||||||
|
RoutingMark int `yaml:"routing-mark"`
|
||||||
|
|
||||||
ProxyProvider map[string]map[string]interface{} `yaml:"proxy-providers"`
|
ProxyProvider map[string]map[string]interface{} `yaml:"proxy-providers"`
|
||||||
Hosts map[string]string `yaml:"hosts"`
|
Hosts map[string]string `yaml:"hosts"`
|
||||||
@ -288,6 +290,7 @@ func parseGeneral(cfg *RawConfig) (*General, error) {
|
|||||||
LogLevel: cfg.LogLevel,
|
LogLevel: cfg.LogLevel,
|
||||||
IPv6: cfg.IPv6,
|
IPv6: cfg.IPv6,
|
||||||
Interface: cfg.Interface,
|
Interface: cfg.Interface,
|
||||||
|
RoutingMark: cfg.RoutingMark,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,6 +5,8 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/Dreamacro/clash/component/dialer"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Adapter Type
|
// Adapter Type
|
||||||
@ -31,6 +33,7 @@ const (
|
|||||||
const (
|
const (
|
||||||
DefaultTCPTimeout = 5 * time.Second
|
DefaultTCPTimeout = 5 * time.Second
|
||||||
DefaultUDPTimeout = DefaultTCPTimeout
|
DefaultUDPTimeout = DefaultTCPTimeout
|
||||||
|
DefaultTLSTimeout = DefaultTCPTimeout
|
||||||
)
|
)
|
||||||
|
|
||||||
type Connection interface {
|
type Connection interface {
|
||||||
@ -91,9 +94,8 @@ type ProxyAdapter interface {
|
|||||||
|
|
||||||
// DialContext return a C.Conn with protocol which
|
// DialContext return a C.Conn with protocol which
|
||||||
// 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, opts ...dialer.Option) (Conn, error)
|
||||||
|
ListenPacketContext(ctx context.Context, metadata *Metadata, opts ...dialer.Option) (PacketConn, error)
|
||||||
ListenPacketContext(ctx context.Context, metadata *Metadata) (PacketConn, error)
|
|
||||||
|
|
||||||
// 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
|
||||||
|
@ -114,10 +114,10 @@ func (m *Metadata) UDPAddr() *net.UDPAddr {
|
|||||||
if m.NetWork != UDP || m.DstIP == nil {
|
if m.NetWork != UDP || m.DstIP == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
port, _ := strconv.Atoi(m.DstPort)
|
port, _ := strconv.ParseUint(m.DstPort, 10, 16)
|
||||||
return &net.UDPAddr{
|
return &net.UDPAddr{
|
||||||
IP: m.DstIP,
|
IP: m.DstIP,
|
||||||
Port: port,
|
Port: int(port),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
16
constant/mime/mime.go
Normal file
16
constant/mime/mime.go
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
package mime
|
||||||
|
|
||||||
|
import (
|
||||||
|
"mime"
|
||||||
|
)
|
||||||
|
|
||||||
|
var consensusMimes = map[string]string{
|
||||||
|
// rfc4329: text/javascript is obsolete, so we need to overwrite mime's builtin
|
||||||
|
".js": "application/javascript; charset=utf-8",
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
for ext, typ := range consensusMimes {
|
||||||
|
mime.AddExtensionType(ext, typ)
|
||||||
|
}
|
||||||
|
}
|
@ -47,11 +47,11 @@ func (s *Server) SetHandler(handler handler) {
|
|||||||
s.handler = handler
|
s.handler = handler
|
||||||
}
|
}
|
||||||
|
|
||||||
func ReCreateServer(addr string, resolver *Resolver, mapper *ResolverEnhancer) error {
|
func ReCreateServer(addr string, resolver *Resolver, mapper *ResolverEnhancer) {
|
||||||
if addr == address && resolver != nil {
|
if addr == address && resolver != nil {
|
||||||
handler := NewHandler(resolver, mapper)
|
handler := NewHandler(resolver, mapper)
|
||||||
server.SetHandler(handler)
|
server.SetHandler(handler)
|
||||||
return nil
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if server.Server != nil {
|
if server.Server != nil {
|
||||||
@ -60,24 +60,37 @@ func ReCreateServer(addr string, resolver *Resolver, mapper *ResolverEnhancer) e
|
|||||||
address = ""
|
address = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if addr == "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var err error
|
||||||
|
defer func() {
|
||||||
|
if err != nil {
|
||||||
|
log.Errorln("Start DNS server error: %s", err.Error())
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
_, port, err := net.SplitHostPort(addr)
|
_, port, err := net.SplitHostPort(addr)
|
||||||
if port == "0" || port == "" || err != nil {
|
if port == "0" || port == "" || err != nil {
|
||||||
return nil
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
udpAddr, err := net.ResolveUDPAddr("udp", addr)
|
udpAddr, err := net.ResolveUDPAddr("udp", addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
p, err := net.ListenUDP("udp", udpAddr)
|
p, err := net.ListenUDP("udp", udpAddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err = sockopt.UDPReuseaddr(p)
|
err = sockopt.UDPReuseaddr(p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warnln("Failed to Reuse UDP Address: %s", err)
|
log.Warnln("Failed to Reuse UDP Address: %s", err)
|
||||||
|
|
||||||
|
err = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
address = addr
|
address = addr
|
||||||
@ -88,5 +101,6 @@ func ReCreateServer(addr string, resolver *Resolver, mapper *ResolverEnhancer) e
|
|||||||
go func() {
|
go func() {
|
||||||
server.ActivateAndServe()
|
server.ActivateAndServe()
|
||||||
}()
|
}()
|
||||||
return nil
|
|
||||||
|
log.Infoln("DNS server listening at: %s", p.LocalAddr().String())
|
||||||
}
|
}
|
||||||
|
19
go.mod
19
go.mod
@ -4,23 +4,23 @@ go 1.17
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/Dreamacro/go-shadowsocks2 v0.1.7
|
github.com/Dreamacro/go-shadowsocks2 v0.1.7
|
||||||
github.com/go-chi/chi/v5 v5.0.4
|
github.com/go-chi/chi/v5 v5.0.7
|
||||||
github.com/go-chi/cors v1.2.0
|
github.com/go-chi/cors v1.2.0
|
||||||
github.com/go-chi/render v1.0.1
|
github.com/go-chi/render v1.0.1
|
||||||
github.com/gofrs/uuid v4.0.0+incompatible
|
github.com/gofrs/uuid v4.2.0+incompatible
|
||||||
github.com/gorilla/websocket v1.4.2
|
github.com/gorilla/websocket v1.4.2
|
||||||
github.com/insomniacslk/dhcp v0.0.0-20210827173440-b95caade3eac
|
github.com/insomniacslk/dhcp v0.0.0-20211214070828-5297eed8f489
|
||||||
github.com/kr328/tun2socket v0.0.0-20210412191540-3d56c47e2d99
|
github.com/kr328/tun2socket v0.0.0-20210412191540-3d56c47e2d99
|
||||||
github.com/miekg/dns v1.1.43
|
github.com/miekg/dns v1.1.45
|
||||||
github.com/oschwald/geoip2-golang v1.5.0
|
github.com/oschwald/geoip2-golang v1.5.0
|
||||||
github.com/sirupsen/logrus v1.8.1
|
github.com/sirupsen/logrus v1.8.1
|
||||||
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-20210920065950-d4af136d3672
|
||||||
go.etcd.io/bbolt v1.3.6
|
go.etcd.io/bbolt v1.3.6
|
||||||
go.uber.org/atomic v1.9.0
|
go.uber.org/atomic v1.9.0
|
||||||
go.uber.org/automaxprocs v1.4.0
|
go.uber.org/automaxprocs v1.4.0
|
||||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519
|
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3
|
||||||
golang.org/x/net v0.0.0-20211029160332-540bb53d3b2e
|
golang.org/x/net v0.0.0-20211216030914-fe4d6282115f
|
||||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
|
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
|
||||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e
|
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e
|
||||||
golang.zx2c4.com/wireguard/windows v0.5.1
|
golang.zx2c4.com/wireguard/windows v0.5.1
|
||||||
@ -36,7 +36,10 @@ require (
|
|||||||
github.com/oschwald/maxminddb-golang v1.8.0 // indirect
|
github.com/oschwald/maxminddb-golang v1.8.0 // indirect
|
||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
github.com/u-root/uio v0.0.0-20210528114334-82958018845c // indirect
|
github.com/u-root/uio v0.0.0-20210528114334-82958018845c // indirect
|
||||||
golang.org/x/text v0.3.8-0.20211029042148-bb1c79828956 // indirect
|
golang.org/x/mod v0.5.1 // indirect
|
||||||
|
golang.org/x/text v0.3.8-0.20211004125949-5bd84dd9b33b // indirect
|
||||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0 // indirect
|
golang.org/x/time v0.0.0-20191024005414-555d28b269f0 // indirect
|
||||||
|
golang.org/x/tools v0.1.9 // indirect
|
||||||
|
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect
|
||||||
)
|
)
|
||||||
|
39
go.sum
39
go.sum
@ -124,8 +124,8 @@ github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM
|
|||||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||||
github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||||
github.com/go-chi/chi/v5 v5.0.4 h1:5e494iHzsYBiyXQAHHuI4tyJS9M3V84OuX3ufIIGHFo=
|
github.com/go-chi/chi/v5 v5.0.7 h1:rDTPXLDHGATaeHvVlLcR4Qe0zftYethFucbjVQ1PxU8=
|
||||||
github.com/go-chi/chi/v5 v5.0.4/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
|
github.com/go-chi/chi/v5 v5.0.7/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
|
||||||
github.com/go-chi/cors v1.2.0 h1:tV1g1XENQ8ku4Bq3K9ub2AtgG+p16SmzeMSGTwrOKdE=
|
github.com/go-chi/cors v1.2.0 h1:tV1g1XENQ8ku4Bq3K9ub2AtgG+p16SmzeMSGTwrOKdE=
|
||||||
github.com/go-chi/cors v1.2.0/go.mod h1:sSbTewc+6wYHBBCW7ytsFSn836hqM7JxpglAy2Vzc58=
|
github.com/go-chi/cors v1.2.0/go.mod h1:sSbTewc+6wYHBBCW7ytsFSn836hqM7JxpglAy2Vzc58=
|
||||||
github.com/go-chi/render v1.0.1 h1:4/5tis2cKaNdnv9zFLfXzcquC9HbeZgCnxGnKrltBS8=
|
github.com/go-chi/render v1.0.1 h1:4/5tis2cKaNdnv9zFLfXzcquC9HbeZgCnxGnKrltBS8=
|
||||||
@ -144,8 +144,8 @@ github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dp
|
|||||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||||
github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||||
github.com/gofrs/flock v0.8.0/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
|
github.com/gofrs/flock v0.8.0/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
|
||||||
github.com/gofrs/uuid v4.0.0+incompatible h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPhW6m+TnJw=
|
github.com/gofrs/uuid v4.2.0+incompatible h1:yyYWMnhkhrKwwr8gAOcOCYxOOscHgDS9yZgBrnJfGa0=
|
||||||
github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
github.com/gofrs/uuid v4.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
||||||
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=
|
||||||
@ -237,8 +237,8 @@ github.com/hugelgupf/socketpair v0.0.0-20190730060125-05d35a94e714/go.mod h1:2Go
|
|||||||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||||
github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
|
github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
|
||||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||||
github.com/insomniacslk/dhcp v0.0.0-20210827173440-b95caade3eac h1:IO6EfdRnPhxgKOsk9DbewdtQZHKZKnGlW7QCUttvNys=
|
github.com/insomniacslk/dhcp v0.0.0-20211214070828-5297eed8f489 h1:jhdHqd7DxBrzfuFSoPxjD6nUVaV/1RIn9aHA0WCf/as=
|
||||||
github.com/insomniacslk/dhcp v0.0.0-20210827173440-b95caade3eac/go.mod h1:h+MxyHxRg9NH3terB1nfRIUaQEcI0XOVkdR9LNBlp8E=
|
github.com/insomniacslk/dhcp v0.0.0-20211214070828-5297eed8f489/go.mod h1:h+MxyHxRg9NH3terB1nfRIUaQEcI0XOVkdR9LNBlp8E=
|
||||||
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
||||||
github.com/jsimonetti/rtnetlink v0.0.0-20190606172950-9527aa82566a/go.mod h1:Oz+70psSo5OFh8DBl0Zv2ACw7Esh6pPUphlvZG9x7uw=
|
github.com/jsimonetti/rtnetlink v0.0.0-20190606172950-9527aa82566a/go.mod h1:Oz+70psSo5OFh8DBl0Zv2ACw7Esh6pPUphlvZG9x7uw=
|
||||||
github.com/jsimonetti/rtnetlink v0.0.0-20200117123717-f846d4f6c1f4/go.mod h1:WGuG/smIU4J/54PblvSbh+xvCZmpJnFgr3ds6Z55XMQ=
|
github.com/jsimonetti/rtnetlink v0.0.0-20200117123717-f846d4f6c1f4/go.mod h1:WGuG/smIU4J/54PblvSbh+xvCZmpJnFgr3ds6Z55XMQ=
|
||||||
@ -279,8 +279,8 @@ github.com/mdlayher/netlink v1.1.0/go.mod h1:H4WCitaheIsdF9yOYu8CFmCgQthAPIWZmcK
|
|||||||
github.com/mdlayher/netlink v1.1.1/go.mod h1:WTYpFb/WTvlRJAyKhZL5/uy69TDDpHHu2VZmb2XgV7o=
|
github.com/mdlayher/netlink v1.1.1/go.mod h1:WTYpFb/WTvlRJAyKhZL5/uy69TDDpHHu2VZmb2XgV7o=
|
||||||
github.com/mdlayher/raw v0.0.0-20190606142536-fef19f00fc18/go.mod h1:7EpbotpCmVZcu+KCX4g9WaRNuu11uyhiW7+Le1dKawg=
|
github.com/mdlayher/raw v0.0.0-20190606142536-fef19f00fc18/go.mod h1:7EpbotpCmVZcu+KCX4g9WaRNuu11uyhiW7+Le1dKawg=
|
||||||
github.com/mdlayher/raw v0.0.0-20191009151244-50f2db8cc065/go.mod h1:7EpbotpCmVZcu+KCX4g9WaRNuu11uyhiW7+Le1dKawg=
|
github.com/mdlayher/raw v0.0.0-20191009151244-50f2db8cc065/go.mod h1:7EpbotpCmVZcu+KCX4g9WaRNuu11uyhiW7+Le1dKawg=
|
||||||
github.com/miekg/dns v1.1.43 h1:JKfpVSCB84vrAmHzyrsxB5NAr5kLoMXZArPSw7Qlgyg=
|
github.com/miekg/dns v1.1.45 h1:g5fRIhm9nx7g8osrAvgb16QJfmyMsyOCb+J7LSv+Qzk=
|
||||||
github.com/miekg/dns v1.1.43/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4=
|
github.com/miekg/dns v1.1.45/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME=
|
||||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
@ -373,8 +373,8 @@ github.com/vishvananda/netlink v1.0.1-0.20190930145447-2ec5bdc52b86/go.mod h1:+S
|
|||||||
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
|
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
|
||||||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
||||||
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-20210920065950-d4af136d3672 h1:4mkzGhKqt3JO1BWYjtD3iRFyAx4ow67hmSqOcGjuxqQ=
|
||||||
github.com/xtls/go v0.0.0-20201118062508-3632bf3b7499/go.mod h1:5TB2+k58gx4A4g2Nf5miSHNDF6CuAzHKpWBooLAshTs=
|
github.com/xtls/go v0.0.0-20210920065950-d4af136d3672/go.mod h1:YGGVbz9cOxyKFUmhW7LGaLZaMA0cPlHJinvAmVxEMSU=
|
||||||
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=
|
||||||
@ -408,8 +408,10 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
|
|||||||
golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
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-20210921155107-089bfa567519 h1:7I4JAnoQBe7ZtJcBaYHi5UtiO8tQHbUSXxL+pnGRANg=
|
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
|
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 h1:0es+/5331RGQPcXlMfP+WrnIIS6dNnNRe0WB02W0F4M=
|
||||||
|
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||||
@ -442,6 +444,7 @@ 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.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
|
golang.org/x/mod v0.5.1 h1:OJxoQ/rynoF0dcCdI7cLPktw/hR2cueqYfjm43oqK38=
|
||||||
golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
|
golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
|
||||||
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=
|
||||||
@ -483,11 +486,13 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY
|
|||||||
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-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-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||||
|
golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.0.0-20211020060615-d418f374d309/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20211020060615-d418f374d309/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.0.0-20211029160332-540bb53d3b2e h1:2lVrcCMRP9p7tfk4KUpV1ESqtf49jpihlUtYnSj67k4=
|
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.0.0-20211029160332-540bb53d3b2e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20211216030914-fe4d6282115f h1:hEYJvxw1lSnWIl8X9ofsYMklzaDs90JI2az5YMd4fPM=
|
||||||
|
golang.org/x/net v0.0.0-20211216030914-fe4d6282115f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
@ -560,13 +565,14 @@ golang.org/x/sys v0.0.0-20201101102859-da207088b7d1/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-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-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-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-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210525143221-35b2ab0089ea/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210525143221-35b2ab0089ea/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e h1:fLOSk5Q00efkSvAm+4xcoXD+RRmLmmulPn5I3Y9F2EM=
|
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e h1:fLOSk5Q00efkSvAm+4xcoXD+RRmLmmulPn5I3Y9F2EM=
|
||||||
@ -581,9 +587,8 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
|||||||
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
|
golang.org/x/text v0.3.8-0.20211004125949-5bd84dd9b33b h1:NXqSWXSRUSCaFuvitrWtU169I3876zRTalMRbfd6LL0=
|
||||||
golang.org/x/text v0.3.8-0.20211004125949-5bd84dd9b33b/go.mod h1:EFNZuWvGYxIRUEX+K8UmCFwYmZjqcrnq15ZuVldZkZ0=
|
golang.org/x/text v0.3.8-0.20211004125949-5bd84dd9b33b/go.mod h1:EFNZuWvGYxIRUEX+K8UmCFwYmZjqcrnq15ZuVldZkZ0=
|
||||||
golang.org/x/text v0.3.8-0.20211029042148-bb1c79828956 h1:xw/3G76i8BwoCoEZ8RzhVpFrHEz4Qm9D7zPckwa7KVM=
|
|
||||||
golang.org/x/text v0.3.8-0.20211029042148-bb1c79828956/go.mod h1:EFNZuWvGYxIRUEX+K8UmCFwYmZjqcrnq15ZuVldZkZ0=
|
|
||||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0 h1:/5xXl8Y5W96D+TtHSlonuFqGHIWVuyCkGJLwGh9JJFs=
|
golang.org/x/time v0.0.0-20191024005414-555d28b269f0 h1:/5xXl8Y5W96D+TtHSlonuFqGHIWVuyCkGJLwGh9JJFs=
|
||||||
@ -635,7 +640,9 @@ golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc
|
|||||||
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||||
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.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||||
|
golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||||
golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo=
|
golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo=
|
||||||
|
golang.org/x/tools v0.1.9 h1:j9KsMiaP1c3B0OTQGth0/k+miLGTgLsAFUCrF2vLcF8=
|
||||||
golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU=
|
golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU=
|
||||||
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=
|
||||||
|
@ -152,14 +152,7 @@ func updateDNS(c *config.DNS, general *config.General) {
|
|||||||
resolver.DefaultLocalServer = dns.NewLocalServer(r, m)
|
resolver.DefaultLocalServer = dns.NewLocalServer(r, m)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := dns.ReCreateServer(c.Listen, r, m); err != nil {
|
dns.ReCreateServer(c.Listen, r, m)
|
||||||
log.Errorln("Start DNS server error: %s", err.Error())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.Listen != "" {
|
|
||||||
log.Infoln("DNS server listening at: %s", c.Listen)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateHosts(tree *trie.DomainTrie) {
|
func updateHosts(tree *trie.DomainTrie) {
|
||||||
@ -175,6 +168,7 @@ func updateRules(rules []C.Rule) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func updateGeneral(general *config.General, force bool) {
|
func updateGeneral(general *config.General, force bool) {
|
||||||
|
log.SetLevel(log.DEBUG)
|
||||||
tunnel.SetMode(general.Mode)
|
tunnel.SetMode(general.Mode)
|
||||||
resolver.DisableIPv6 = !general.IPv6
|
resolver.DisableIPv6 = !general.IPv6
|
||||||
|
|
||||||
@ -191,12 +185,10 @@ func updateGeneral(general *config.General, force bool) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if general.Interface != "" {
|
|
||||||
dialer.DefaultOptions = []dialer.Option{dialer.WithInterface(general.Interface)}
|
|
||||||
log.Infoln("Use interface name: %s", general.Interface)
|
log.Infoln("Use interface name: %s", general.Interface)
|
||||||
} else {
|
|
||||||
dialer.DefaultOptions = nil
|
dialer.DefaultInterface.Store(general.Interface)
|
||||||
}
|
dialer.DefaultRoutingMark.Store(int32(general.RoutingMark))
|
||||||
|
|
||||||
iface.FlushCache()
|
iface.FlushCache()
|
||||||
|
|
||||||
@ -214,30 +206,12 @@ func updateGeneral(general *config.General, force bool) {
|
|||||||
tcpIn := tunnel.TCPIn()
|
tcpIn := tunnel.TCPIn()
|
||||||
udpIn := tunnel.UDPIn()
|
udpIn := tunnel.UDPIn()
|
||||||
|
|
||||||
if err := P.ReCreateHTTP(general.Port, tcpIn); err != nil {
|
P.ReCreateHTTP(general.Port, tcpIn)
|
||||||
log.Errorln("Start HTTP server error: %s", err.Error())
|
P.ReCreateSocks(general.SocksPort, tcpIn, udpIn)
|
||||||
}
|
P.ReCreateRedir(general.RedirPort, tcpIn, udpIn)
|
||||||
|
P.ReCreateTProxy(general.TProxyPort, tcpIn, udpIn)
|
||||||
if err := P.ReCreateSocks(general.SocksPort, tcpIn, udpIn); err != nil {
|
P.ReCreateMixed(general.MixedPort, tcpIn, udpIn)
|
||||||
log.Errorln("Start SOCKS server error: %s", err.Error())
|
P.ReCreateTun(general.Tun, tcpIn, udpIn)
|
||||||
}
|
|
||||||
|
|
||||||
if err := P.ReCreateRedir(general.RedirPort, tcpIn, udpIn); err != nil {
|
|
||||||
log.Errorln("Start Redir server error: %s", err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := P.ReCreateTProxy(general.TProxyPort, tcpIn, udpIn); err != nil {
|
|
||||||
log.Errorln("Start TProxy server error: %s", err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := P.ReCreateMixed(general.MixedPort, tcpIn, udpIn); err != nil {
|
|
||||||
log.Errorln("Start Mixed(http and socks) server error: %s", err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := P.ReCreateTun(general.Tun, tcpIn, udpIn); err != nil {
|
|
||||||
log.Errorln("Start Tun interface error: %s", err.Error())
|
|
||||||
os.Exit(2)
|
|
||||||
}
|
|
||||||
|
|
||||||
log.SetLevel(general.LogLevel)
|
log.SetLevel(general.LogLevel)
|
||||||
}
|
}
|
||||||
|
@ -79,15 +79,7 @@ func patchConfigs(w http.ResponseWriter, r *http.Request) {
|
|||||||
P.ReCreateMixed(pointerOrDefault(general.MixedPort, ports.MixedPort), tcpIn, udpIn)
|
P.ReCreateMixed(pointerOrDefault(general.MixedPort, ports.MixedPort), tcpIn, udpIn)
|
||||||
|
|
||||||
if general.Tun != nil {
|
if general.Tun != nil {
|
||||||
err := P.ReCreateTun(*general.Tun, nil, nil)
|
P.ReCreateTun(*general.Tun, tcpIn, udpIn)
|
||||||
if err == nil {
|
|
||||||
log.Infoln("Recreate tun success.")
|
|
||||||
} else {
|
|
||||||
log.Errorln("Recreate tun failed: %s", err.Error())
|
|
||||||
render.Status(r, http.StatusBadRequest)
|
|
||||||
render.JSON(w, r, newError(err.Error()))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if general.Mode != nil {
|
if general.Mode != nil {
|
||||||
|
@ -9,6 +9,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
C "github.com/Dreamacro/clash/constant"
|
C "github.com/Dreamacro/clash/constant"
|
||||||
|
_ "github.com/Dreamacro/clash/constant/mime"
|
||||||
"github.com/Dreamacro/clash/log"
|
"github.com/Dreamacro/clash/log"
|
||||||
"github.com/Dreamacro/clash/tunnel/statistic"
|
"github.com/Dreamacro/clash/tunnel/statistic"
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@ package proxy
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
"os"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strconv"
|
"strconv"
|
||||||
"sync"
|
"sync"
|
||||||
@ -80,38 +81,50 @@ func SetBindAddress(host string) {
|
|||||||
bindAddress = host
|
bindAddress = host
|
||||||
}
|
}
|
||||||
|
|
||||||
func ReCreateHTTP(port int, tcpIn chan<- C.ConnContext) error {
|
func ReCreateHTTP(port int, tcpIn chan<- C.ConnContext) {
|
||||||
httpMux.Lock()
|
httpMux.Lock()
|
||||||
defer httpMux.Unlock()
|
defer httpMux.Unlock()
|
||||||
|
|
||||||
|
var err error
|
||||||
|
defer func() {
|
||||||
|
if err != nil {
|
||||||
|
log.Errorln("Start HTTP server error: %s", err.Error())
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
addr := genAddr(bindAddress, port, allowLan)
|
addr := genAddr(bindAddress, port, allowLan)
|
||||||
|
|
||||||
if httpListener != nil {
|
if httpListener != nil {
|
||||||
if httpListener.RawAddress() == addr {
|
if httpListener.RawAddress() == addr {
|
||||||
return nil
|
return
|
||||||
}
|
}
|
||||||
httpListener.Close()
|
httpListener.Close()
|
||||||
httpListener = nil
|
httpListener = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if portIsZero(addr) {
|
if portIsZero(addr) {
|
||||||
return nil
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var err error
|
|
||||||
httpListener, err = http.New(addr, tcpIn)
|
httpListener, err = http.New(addr, tcpIn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Infoln("HTTP proxy listening at: %s", httpListener.Address())
|
log.Infoln("HTTP proxy listening at: %s", httpListener.Address())
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func ReCreateSocks(port int, tcpIn chan<- C.ConnContext, udpIn chan<- *inbound.PacketAdapter) error {
|
func ReCreateSocks(port int, tcpIn chan<- C.ConnContext, udpIn chan<- *inbound.PacketAdapter) {
|
||||||
socksMux.Lock()
|
socksMux.Lock()
|
||||||
defer socksMux.Unlock()
|
defer socksMux.Unlock()
|
||||||
|
|
||||||
|
var err error
|
||||||
|
defer func() {
|
||||||
|
if err != nil {
|
||||||
|
log.Errorln("Start SOCKS server error: %s", err.Error())
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
addr := genAddr(bindAddress, port, allowLan)
|
addr := genAddr(bindAddress, port, allowLan)
|
||||||
|
|
||||||
shouldTCPIgnore := false
|
shouldTCPIgnore := false
|
||||||
@ -136,40 +149,46 @@ func ReCreateSocks(port int, tcpIn chan<- C.ConnContext, udpIn chan<- *inbound.P
|
|||||||
}
|
}
|
||||||
|
|
||||||
if shouldTCPIgnore && shouldUDPIgnore {
|
if shouldTCPIgnore && shouldUDPIgnore {
|
||||||
return nil
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if portIsZero(addr) {
|
if portIsZero(addr) {
|
||||||
return nil
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
tcpListener, err := socks.New(addr, tcpIn)
|
tcpListener, err := socks.New(addr, tcpIn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
udpListener, err := socks.NewUDP(addr, udpIn)
|
udpListener, err := socks.NewUDP(addr, udpIn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
tcpListener.Close()
|
tcpListener.Close()
|
||||||
return err
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
socksListener = tcpListener
|
socksListener = tcpListener
|
||||||
socksUDPListener = udpListener
|
socksUDPListener = udpListener
|
||||||
|
|
||||||
log.Infoln("SOCKS proxy listening at: %s", socksListener.Address())
|
log.Infoln("SOCKS proxy listening at: %s", socksListener.Address())
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func ReCreateRedir(port int, tcpIn chan<- C.ConnContext, udpIn chan<- *inbound.PacketAdapter) error {
|
func ReCreateRedir(port int, tcpIn chan<- C.ConnContext, udpIn chan<- *inbound.PacketAdapter) {
|
||||||
redirMux.Lock()
|
redirMux.Lock()
|
||||||
defer redirMux.Unlock()
|
defer redirMux.Unlock()
|
||||||
|
|
||||||
|
var err error
|
||||||
|
defer func() {
|
||||||
|
if err != nil {
|
||||||
|
log.Errorln("Start Redir server error: %s", err.Error())
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
addr := genAddr(bindAddress, port, allowLan)
|
addr := genAddr(bindAddress, port, allowLan)
|
||||||
|
|
||||||
if redirListener != nil {
|
if redirListener != nil {
|
||||||
if redirListener.RawAddress() == addr {
|
if redirListener.RawAddress() == addr {
|
||||||
return nil
|
return
|
||||||
}
|
}
|
||||||
redirListener.Close()
|
redirListener.Close()
|
||||||
redirListener = nil
|
redirListener = nil
|
||||||
@ -177,20 +196,19 @@ func ReCreateRedir(port int, tcpIn chan<- C.ConnContext, udpIn chan<- *inbound.P
|
|||||||
|
|
||||||
if redirUDPListener != nil {
|
if redirUDPListener != nil {
|
||||||
if redirUDPListener.RawAddress() == addr {
|
if redirUDPListener.RawAddress() == addr {
|
||||||
return nil
|
return
|
||||||
}
|
}
|
||||||
redirUDPListener.Close()
|
redirUDPListener.Close()
|
||||||
redirUDPListener = nil
|
redirUDPListener = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if portIsZero(addr) {
|
if portIsZero(addr) {
|
||||||
return nil
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var err error
|
|
||||||
redirListener, err = redir.New(addr, tcpIn)
|
redirListener, err = redir.New(addr, tcpIn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
redirUDPListener, err = tproxy.NewUDP(addr, udpIn)
|
redirUDPListener, err = tproxy.NewUDP(addr, udpIn)
|
||||||
@ -199,18 +217,24 @@ func ReCreateRedir(port int, tcpIn chan<- C.ConnContext, udpIn chan<- *inbound.P
|
|||||||
}
|
}
|
||||||
|
|
||||||
log.Infoln("Redirect proxy listening at: %s", redirListener.Address())
|
log.Infoln("Redirect proxy listening at: %s", redirListener.Address())
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func ReCreateTProxy(port int, tcpIn chan<- C.ConnContext, udpIn chan<- *inbound.PacketAdapter) error {
|
func ReCreateTProxy(port int, tcpIn chan<- C.ConnContext, udpIn chan<- *inbound.PacketAdapter) {
|
||||||
tproxyMux.Lock()
|
tproxyMux.Lock()
|
||||||
defer tproxyMux.Unlock()
|
defer tproxyMux.Unlock()
|
||||||
|
|
||||||
|
var err error
|
||||||
|
defer func() {
|
||||||
|
if err != nil {
|
||||||
|
log.Errorln("Start TProxy server error: %s", err.Error())
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
addr := genAddr(bindAddress, port, allowLan)
|
addr := genAddr(bindAddress, port, allowLan)
|
||||||
|
|
||||||
if tproxyListener != nil {
|
if tproxyListener != nil {
|
||||||
if tproxyListener.RawAddress() == addr {
|
if tproxyListener.RawAddress() == addr {
|
||||||
return nil
|
return
|
||||||
}
|
}
|
||||||
tproxyListener.Close()
|
tproxyListener.Close()
|
||||||
tproxyListener = nil
|
tproxyListener = nil
|
||||||
@ -218,20 +242,19 @@ func ReCreateTProxy(port int, tcpIn chan<- C.ConnContext, udpIn chan<- *inbound.
|
|||||||
|
|
||||||
if tproxyUDPListener != nil {
|
if tproxyUDPListener != nil {
|
||||||
if tproxyUDPListener.RawAddress() == addr {
|
if tproxyUDPListener.RawAddress() == addr {
|
||||||
return nil
|
return
|
||||||
}
|
}
|
||||||
tproxyUDPListener.Close()
|
tproxyUDPListener.Close()
|
||||||
tproxyUDPListener = nil
|
tproxyUDPListener = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if portIsZero(addr) {
|
if portIsZero(addr) {
|
||||||
return nil
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var err error
|
|
||||||
tproxyListener, err = tproxy.New(addr, tcpIn)
|
tproxyListener, err = tproxy.New(addr, tcpIn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
tproxyUDPListener, err = tproxy.NewUDP(addr, udpIn)
|
tproxyUDPListener, err = tproxy.NewUDP(addr, udpIn)
|
||||||
@ -240,13 +263,19 @@ func ReCreateTProxy(port int, tcpIn chan<- C.ConnContext, udpIn chan<- *inbound.
|
|||||||
}
|
}
|
||||||
|
|
||||||
log.Infoln("TProxy server listening at: %s", tproxyListener.Address())
|
log.Infoln("TProxy server listening at: %s", tproxyListener.Address())
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func ReCreateMixed(port int, tcpIn chan<- C.ConnContext, udpIn chan<- *inbound.PacketAdapter) error {
|
func ReCreateMixed(port int, tcpIn chan<- C.ConnContext, udpIn chan<- *inbound.PacketAdapter) {
|
||||||
mixedMux.Lock()
|
mixedMux.Lock()
|
||||||
defer mixedMux.Unlock()
|
defer mixedMux.Unlock()
|
||||||
|
|
||||||
|
var err error
|
||||||
|
defer func() {
|
||||||
|
if err != nil {
|
||||||
|
log.Errorln("Start Mixed(http+socks) server error: %s", err.Error())
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
addr := genAddr(bindAddress, port, allowLan)
|
addr := genAddr(bindAddress, port, allowLan)
|
||||||
|
|
||||||
shouldTCPIgnore := false
|
shouldTCPIgnore := false
|
||||||
@ -270,46 +299,52 @@ func ReCreateMixed(port int, tcpIn chan<- C.ConnContext, udpIn chan<- *inbound.P
|
|||||||
}
|
}
|
||||||
|
|
||||||
if shouldTCPIgnore && shouldUDPIgnore {
|
if shouldTCPIgnore && shouldUDPIgnore {
|
||||||
return nil
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if portIsZero(addr) {
|
if portIsZero(addr) {
|
||||||
return nil
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var err error
|
|
||||||
mixedListener, err = mixed.New(addr, tcpIn)
|
mixedListener, err = mixed.New(addr, tcpIn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
mixedUDPLister, err = socks.NewUDP(addr, udpIn)
|
mixedUDPLister, err = socks.NewUDP(addr, udpIn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
mixedListener.Close()
|
mixedListener.Close()
|
||||||
return err
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Infoln("Mixed(http+socks) proxy listening at: %s", mixedListener.Address())
|
log.Infoln("Mixed(http+socks) proxy listening at: %s", mixedListener.Address())
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func ReCreateTun(conf config.Tun, tcpIn chan<- C.ConnContext, udpIn chan<- *inbound.PacketAdapter) error {
|
func ReCreateTun(conf config.Tun, tcpIn chan<- C.ConnContext, udpIn chan<- *inbound.PacketAdapter) {
|
||||||
tunMux.Lock()
|
tunMux.Lock()
|
||||||
defer tunMux.Unlock()
|
defer tunMux.Unlock()
|
||||||
|
|
||||||
|
var err error
|
||||||
|
defer func() {
|
||||||
|
if err != nil {
|
||||||
|
log.Errorln("Start TUN interface error: %s", err.Error())
|
||||||
|
os.Exit(2)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
if tunAdapter != nil {
|
if tunAdapter != nil {
|
||||||
tunAdapter.Close()
|
tunAdapter.Close()
|
||||||
tunAdapter = nil
|
tunAdapter = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if !conf.Enable {
|
if !conf.Enable {
|
||||||
return nil
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var err error
|
|
||||||
tunAdapter, err = tun.New(conf, tcpIn, udpIn)
|
tunAdapter, err = tun.New(conf, tcpIn, udpIn)
|
||||||
|
if err != nil {
|
||||||
return err
|
log.Warnln("Failed to start TUN interface: %s", err.Error())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetPorts return the ports of proxy servers
|
// GetPorts return the ports of proxy servers
|
||||||
|
@ -49,7 +49,7 @@ func NewUDP(addr string, in chan<- *inbound.PacketAdapter) (*UDPListener, error)
|
|||||||
}
|
}
|
||||||
go func() {
|
go func() {
|
||||||
for {
|
for {
|
||||||
buf := pool.Get(pool.RelayBufferSize)
|
buf := pool.Get(pool.UDPBufferSize)
|
||||||
n, remoteAddr, err := l.ReadFrom(buf)
|
n, remoteAddr, err := l.ReadFrom(buf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
pool.Put(buf)
|
pool.Put(buf)
|
||||||
|
@ -57,7 +57,7 @@ func NewUDP(addr string, in chan<- *inbound.PacketAdapter) (*UDPListener, error)
|
|||||||
go func() {
|
go func() {
|
||||||
oob := make([]byte, 1024)
|
oob := make([]byte, 1024)
|
||||||
for {
|
for {
|
||||||
buf := pool.Get(pool.RelayBufferSize)
|
buf := pool.Get(pool.UDPBufferSize)
|
||||||
n, oobn, _, lAddr, err := c.ReadMsgUDP(buf, oob)
|
n, oobn, _, lAddr, err := c.ReadMsgUDP(buf, oob)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
pool.Put(buf)
|
pool.Put(buf)
|
||||||
|
@ -14,10 +14,10 @@ import (
|
|||||||
"syscall"
|
"syscall"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/Dreamacro/clash/common/pool"
|
||||||
|
|
||||||
"golang.org/x/net/ipv6"
|
"golang.org/x/net/ipv6"
|
||||||
"golang.org/x/sys/unix"
|
"golang.org/x/sys/unix"
|
||||||
|
|
||||||
"github.com/Dreamacro/clash/common/pool"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -2,6 +2,7 @@ package commons
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/Dreamacro/clash/component/resolver"
|
"github.com/Dreamacro/clash/component/resolver"
|
||||||
|
|
||||||
D "github.com/miekg/dns"
|
D "github.com/miekg/dns"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -17,6 +17,7 @@ import (
|
|||||||
"github.com/Dreamacro/clash/listener/tun/ipstack"
|
"github.com/Dreamacro/clash/listener/tun/ipstack"
|
||||||
"github.com/Dreamacro/clash/log"
|
"github.com/Dreamacro/clash/log"
|
||||||
"github.com/Dreamacro/clash/transport/socks5"
|
"github.com/Dreamacro/clash/transport/socks5"
|
||||||
|
|
||||||
"gvisor.dev/gvisor/pkg/tcpip"
|
"gvisor.dev/gvisor/pkg/tcpip"
|
||||||
"gvisor.dev/gvisor/pkg/tcpip/adapters/gonet"
|
"gvisor.dev/gvisor/pkg/tcpip/adapters/gonet"
|
||||||
"gvisor.dev/gvisor/pkg/tcpip/buffer"
|
"gvisor.dev/gvisor/pkg/tcpip/buffer"
|
||||||
|
@ -6,6 +6,7 @@ import (
|
|||||||
|
|
||||||
"github.com/Dreamacro/clash/dns"
|
"github.com/Dreamacro/clash/dns"
|
||||||
"github.com/Dreamacro/clash/log"
|
"github.com/Dreamacro/clash/log"
|
||||||
|
|
||||||
D "github.com/miekg/dns"
|
D "github.com/miekg/dns"
|
||||||
"gvisor.dev/gvisor/pkg/tcpip"
|
"gvisor.dev/gvisor/pkg/tcpip"
|
||||||
"gvisor.dev/gvisor/pkg/tcpip/adapters/gonet"
|
"gvisor.dev/gvisor/pkg/tcpip/adapters/gonet"
|
||||||
|
@ -5,6 +5,7 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
|
|
||||||
"github.com/Dreamacro/clash/component/resolver"
|
"github.com/Dreamacro/clash/component/resolver"
|
||||||
|
|
||||||
"gvisor.dev/gvisor/pkg/tcpip"
|
"gvisor.dev/gvisor/pkg/tcpip"
|
||||||
"gvisor.dev/gvisor/pkg/tcpip/buffer"
|
"gvisor.dev/gvisor/pkg/tcpip/buffer"
|
||||||
"gvisor.dev/gvisor/pkg/tcpip/header"
|
"gvisor.dev/gvisor/pkg/tcpip/header"
|
||||||
|
@ -7,6 +7,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
D "github.com/Dreamacro/clash/listener/tun/ipstack/commons"
|
D "github.com/Dreamacro/clash/listener/tun/ipstack/commons"
|
||||||
|
|
||||||
"github.com/kr328/tun2socket/binding"
|
"github.com/kr328/tun2socket/binding"
|
||||||
"github.com/kr328/tun2socket/redirect"
|
"github.com/kr328/tun2socket/redirect"
|
||||||
)
|
)
|
||||||
|
@ -4,10 +4,10 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"github.com/kr328/tun2socket/binding"
|
|
||||||
|
|
||||||
C "github.com/Dreamacro/clash/constant"
|
C "github.com/Dreamacro/clash/constant"
|
||||||
"github.com/Dreamacro/clash/context"
|
"github.com/Dreamacro/clash/context"
|
||||||
|
|
||||||
|
"github.com/kr328/tun2socket/binding"
|
||||||
)
|
)
|
||||||
|
|
||||||
func handleTCP(conn net.Conn, endpoint *binding.Endpoint, tcpIn chan<- C.ConnContext) {
|
func handleTCP(conn net.Conn, endpoint *binding.Endpoint, tcpIn chan<- C.ConnContext) {
|
||||||
|
@ -11,6 +11,7 @@ import (
|
|||||||
"github.com/Dreamacro/clash/listener/tun/dev"
|
"github.com/Dreamacro/clash/listener/tun/dev"
|
||||||
"github.com/Dreamacro/clash/listener/tun/ipstack"
|
"github.com/Dreamacro/clash/listener/tun/ipstack"
|
||||||
"github.com/Dreamacro/clash/log"
|
"github.com/Dreamacro/clash/log"
|
||||||
|
|
||||||
"github.com/kr328/tun2socket"
|
"github.com/kr328/tun2socket"
|
||||||
"github.com/kr328/tun2socket/binding"
|
"github.com/kr328/tun2socket/binding"
|
||||||
"github.com/kr328/tun2socket/redirect"
|
"github.com/kr328/tun2socket/redirect"
|
||||||
|
@ -8,6 +8,7 @@ import (
|
|||||||
"github.com/Dreamacro/clash/common/pool"
|
"github.com/Dreamacro/clash/common/pool"
|
||||||
C "github.com/Dreamacro/clash/constant"
|
C "github.com/Dreamacro/clash/constant"
|
||||||
"github.com/Dreamacro/clash/transport/socks5"
|
"github.com/Dreamacro/clash/transport/socks5"
|
||||||
|
|
||||||
"github.com/kr328/tun2socket/binding"
|
"github.com/kr328/tun2socket/binding"
|
||||||
"github.com/kr328/tun2socket/redirect"
|
"github.com/kr328/tun2socket/redirect"
|
||||||
)
|
)
|
||||||
|
@ -5,10 +5,9 @@ import (
|
|||||||
|
|
||||||
"github.com/Dreamacro/clash/component/geodata"
|
"github.com/Dreamacro/clash/component/geodata"
|
||||||
"github.com/Dreamacro/clash/component/geodata/router"
|
"github.com/Dreamacro/clash/component/geodata/router"
|
||||||
|
_ "github.com/Dreamacro/clash/component/geodata/standard"
|
||||||
C "github.com/Dreamacro/clash/constant"
|
C "github.com/Dreamacro/clash/constant"
|
||||||
"github.com/Dreamacro/clash/log"
|
"github.com/Dreamacro/clash/log"
|
||||||
|
|
||||||
_ "github.com/Dreamacro/clash/component/geodata/standard"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type GEOSITE struct {
|
type GEOSITE struct {
|
||||||
|
@ -32,7 +32,7 @@ const (
|
|||||||
ImageVmess = "v2fly/v2fly-core:latest"
|
ImageVmess = "v2fly/v2fly-core:latest"
|
||||||
ImageTrojan = "trojangfw/trojan:latest"
|
ImageTrojan = "trojangfw/trojan:latest"
|
||||||
ImageTrojanGo = "p4gefau1t/trojan-go:latest"
|
ImageTrojanGo = "p4gefau1t/trojan-go:latest"
|
||||||
ImageSnell = "icpz/snell-server:latest"
|
ImageSnell = "ghcr.io/icpz/snell-server:latest"
|
||||||
ImageXray = "teddysun/xray:latest"
|
ImageXray = "teddysun/xray:latest"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
29
test/go.mod
29
test/go.mod
@ -3,12 +3,12 @@ module clash-test
|
|||||||
go 1.17
|
go 1.17
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/Dreamacro/clash v1.6.6-0.20210905062555-c7b718f6512d
|
github.com/Dreamacro/clash v1.7.2-0.20211108085948-bd2ea2b917aa
|
||||||
github.com/docker/docker v20.10.8+incompatible
|
github.com/docker/docker v20.10.12+incompatible
|
||||||
github.com/docker/go-connections v0.4.0
|
github.com/docker/go-connections v0.4.0
|
||||||
github.com/miekg/dns v1.1.43
|
github.com/miekg/dns v1.1.45
|
||||||
github.com/stretchr/testify v1.7.0
|
github.com/stretchr/testify v1.7.0
|
||||||
golang.org/x/net v0.0.0-20211029160332-540bb53d3b2e
|
golang.org/x/net v0.0.0-20211216030914-fe4d6282115f
|
||||||
)
|
)
|
||||||
|
|
||||||
replace github.com/Dreamacro/clash => ../
|
replace github.com/Dreamacro/clash => ../
|
||||||
@ -16,39 +16,42 @@ replace github.com/Dreamacro/clash => ../
|
|||||||
require (
|
require (
|
||||||
github.com/Dreamacro/go-shadowsocks2 v0.1.7 // indirect
|
github.com/Dreamacro/go-shadowsocks2 v0.1.7 // indirect
|
||||||
github.com/Microsoft/go-winio v0.5.1 // indirect
|
github.com/Microsoft/go-winio v0.5.1 // indirect
|
||||||
github.com/containerd/containerd v1.5.5 // indirect
|
github.com/containerd/containerd v1.5.8 // indirect
|
||||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
github.com/docker/distribution v2.7.1+incompatible // indirect
|
github.com/docker/distribution v2.7.1+incompatible // indirect
|
||||||
github.com/docker/go-units v0.4.0 // indirect
|
github.com/docker/go-units v0.4.0 // indirect
|
||||||
github.com/gofrs/uuid v4.0.0+incompatible // indirect
|
github.com/gofrs/uuid v4.2.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.2 // indirect
|
github.com/golang/protobuf v1.5.2 // indirect
|
||||||
github.com/google/btree v1.0.1 // 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-20211214070828-5297eed8f489 // indirect
|
||||||
github.com/kr328/tun2socket v0.0.0-20210412191540-3d56c47e2d99 // indirect
|
github.com/kr328/tun2socket v0.0.0-20210412191540-3d56c47e2d99 // indirect
|
||||||
github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 // indirect
|
github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 // indirect
|
||||||
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.2 // indirect
|
||||||
github.com/oschwald/geoip2-golang v1.5.0 // indirect
|
github.com/oschwald/geoip2-golang v1.5.0 // indirect
|
||||||
github.com/oschwald/maxminddb-golang v1.8.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-20210920065950-d4af136d3672 // indirect
|
||||||
go.etcd.io/bbolt v1.3.6 // 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-20210921155107-089bfa567519 // indirect
|
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 // indirect
|
||||||
|
golang.org/x/mod v0.5.1 // 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-20211216021012-1d35b9e2eb4e // indirect
|
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e // indirect
|
||||||
golang.org/x/text v0.3.8-0.20211029042148-bb1c79828956 // indirect
|
golang.org/x/text v0.3.8-0.20211004125949-5bd84dd9b33b // indirect
|
||||||
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect
|
golang.org/x/time v0.0.0-20211116232009-f0f3c7e86c11 // indirect
|
||||||
|
golang.org/x/tools v0.1.9 // indirect
|
||||||
|
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
|
||||||
golang.zx2c4.com/wireguard/windows v0.5.1 // indirect
|
golang.zx2c4.com/wireguard/windows v0.5.1 // indirect
|
||||||
google.golang.org/genproto v0.0.0-20210722135532-667f2b7c528f // indirect
|
google.golang.org/genproto v0.0.0-20210722135532-667f2b7c528f // indirect
|
||||||
google.golang.org/grpc v1.42.0-dev.0.20211020220737-f00baa6c3c84 // indirect
|
google.golang.org/grpc v1.43.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
|
||||||
|
64
test/go.sum
64
test/go.sum
@ -75,7 +75,7 @@ github.com/Microsoft/hcsshim v0.8.9/go.mod h1:5692vkUqntj1idxauYlpoINNKeqCiG6Sg3
|
|||||||
github.com/Microsoft/hcsshim v0.8.14/go.mod h1:NtVKoYxQuTLx6gEq0L96c9Ju4JbRJ4nY2ow3VK6a9Lg=
|
github.com/Microsoft/hcsshim v0.8.14/go.mod h1:NtVKoYxQuTLx6gEq0L96c9Ju4JbRJ4nY2ow3VK6a9Lg=
|
||||||
github.com/Microsoft/hcsshim v0.8.15/go.mod h1:x38A4YbHbdxJtc0sF6oIz+RG0npwSCAvn69iY6URG00=
|
github.com/Microsoft/hcsshim v0.8.15/go.mod h1:x38A4YbHbdxJtc0sF6oIz+RG0npwSCAvn69iY6URG00=
|
||||||
github.com/Microsoft/hcsshim v0.8.16/go.mod h1:o5/SZqmR7x9JNKsW3pu+nqHm0MF8vbA+VxGOoXdC600=
|
github.com/Microsoft/hcsshim v0.8.16/go.mod h1:o5/SZqmR7x9JNKsW3pu+nqHm0MF8vbA+VxGOoXdC600=
|
||||||
github.com/Microsoft/hcsshim v0.8.18/go.mod h1:+w2gRZ5ReXQhFOrvSQeNfhrYB/dg3oDwTOcER2fw4I4=
|
github.com/Microsoft/hcsshim v0.8.23/go.mod h1:4zegtUJth7lAvFyc6cH2gGQ5B3OFQim01nnU2M8jKDg=
|
||||||
github.com/Microsoft/hcsshim/test v0.0.0-20201218223536-d3e5debf77da/go.mod h1:5hlzMzRKMLyo42nCZ9oml8AdTlq/0cvIaBv6tK1RehU=
|
github.com/Microsoft/hcsshim/test v0.0.0-20201218223536-d3e5debf77da/go.mod h1:5hlzMzRKMLyo42nCZ9oml8AdTlq/0cvIaBv6tK1RehU=
|
||||||
github.com/Microsoft/hcsshim/test v0.0.0-20210227013316-43a75bb4edd3/go.mod h1:mw7qgWloBUl75W/gVH3cQszUg1+gUITj7D6NY7ywVnY=
|
github.com/Microsoft/hcsshim/test v0.0.0-20210227013316-43a75bb4edd3/go.mod h1:mw7qgWloBUl75W/gVH3cQszUg1+gUITj7D6NY7ywVnY=
|
||||||
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=
|
||||||
@ -111,6 +111,7 @@ github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd/go.mod h1:2oa8n
|
|||||||
github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0BsqsP2LwDJ9aOkm/6J86V6lyAXCoQWGw3K50=
|
github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0BsqsP2LwDJ9aOkm/6J86V6lyAXCoQWGw3K50=
|
||||||
github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE=
|
github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE=
|
||||||
github.com/cenkalti/backoff v1.1.1-0.20190506075156-2146c9339422/go.mod h1:b6Nc7NRH5C4aCISLry0tLnTjcuTEvoiqcWDdsU0sOGM=
|
github.com/cenkalti/backoff v1.1.1-0.20190506075156-2146c9339422/go.mod h1:b6Nc7NRH5C4aCISLry0tLnTjcuTEvoiqcWDdsU0sOGM=
|
||||||
|
github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
|
||||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||||
@ -161,13 +162,13 @@ github.com/containerd/containerd v1.3.9/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMX
|
|||||||
github.com/containerd/containerd v1.4.0-beta.2.0.20200729163537-40b22ef07410/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
|
github.com/containerd/containerd v1.4.0-beta.2.0.20200729163537-40b22ef07410/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
|
||||||
github.com/containerd/containerd v1.4.1/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
|
github.com/containerd/containerd v1.4.1/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
|
||||||
github.com/containerd/containerd v1.4.3/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
|
github.com/containerd/containerd v1.4.3/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
|
||||||
|
github.com/containerd/containerd v1.4.9/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
|
||||||
github.com/containerd/containerd v1.5.0-beta.1/go.mod h1:5HfvG1V2FsKesEGQ17k5/T7V960Tmcumvqn8Mc+pCYQ=
|
github.com/containerd/containerd v1.5.0-beta.1/go.mod h1:5HfvG1V2FsKesEGQ17k5/T7V960Tmcumvqn8Mc+pCYQ=
|
||||||
github.com/containerd/containerd v1.5.0-beta.3/go.mod h1:/wr9AVtEM7x9c+n0+stptlo/uBBoBORwEx6ardVcmKU=
|
github.com/containerd/containerd v1.5.0-beta.3/go.mod h1:/wr9AVtEM7x9c+n0+stptlo/uBBoBORwEx6ardVcmKU=
|
||||||
github.com/containerd/containerd v1.5.0-beta.4/go.mod h1:GmdgZd2zA2GYIBZ0w09ZvgqEq8EfBp/m3lcVZIvPHhI=
|
github.com/containerd/containerd v1.5.0-beta.4/go.mod h1:GmdgZd2zA2GYIBZ0w09ZvgqEq8EfBp/m3lcVZIvPHhI=
|
||||||
github.com/containerd/containerd v1.5.0-rc.0/go.mod h1:V/IXoMqNGgBlabz3tHD2TWDoTJseu1FGOKuoA4nNb2s=
|
github.com/containerd/containerd v1.5.0-rc.0/go.mod h1:V/IXoMqNGgBlabz3tHD2TWDoTJseu1FGOKuoA4nNb2s=
|
||||||
github.com/containerd/containerd v1.5.1/go.mod h1:0DOxVqwDy2iZvrZp2JUx/E+hS0UNTVn7dJnIOwtYR4g=
|
github.com/containerd/containerd v1.5.8 h1:NmkCC1/QxyZFBny8JogwLpOy2f+VEbO/f6bV2Mqtwuw=
|
||||||
github.com/containerd/containerd v1.5.5 h1:q1gxsZsGZ8ddVe98yO6pR21b5xQSMiR61lD0W96pgQo=
|
github.com/containerd/containerd v1.5.8/go.mod h1:YdFSv5bTFLpG2HIYmfqDpSYYTDX+mc5qtSuYx1YUb/s=
|
||||||
github.com/containerd/containerd v1.5.5/go.mod h1:oSTh0QpT1w6jYcGmbiSbxv9OSQYaa88mPyWIuU79zyo=
|
|
||||||
github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
|
github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
|
||||||
github.com/containerd/continuity v0.0.0-20190815185530-f2a389ac0a02/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
|
github.com/containerd/continuity v0.0.0-20190815185530-f2a389ac0a02/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
|
||||||
github.com/containerd/continuity v0.0.0-20191127005431-f65d91d395eb/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
|
github.com/containerd/continuity v0.0.0-20191127005431-f65d91d395eb/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
|
||||||
@ -201,6 +202,7 @@ github.com/containerd/ttrpc v0.0.0-20190828172938-92c8520ef9f8/go.mod h1:PvCDdDG
|
|||||||
github.com/containerd/ttrpc v0.0.0-20191028202541-4f1b8fe65a5c/go.mod h1:LPm1u0xBw8r8NOKoOdNMeVHSawSsltak+Ihv+etqsE8=
|
github.com/containerd/ttrpc v0.0.0-20191028202541-4f1b8fe65a5c/go.mod h1:LPm1u0xBw8r8NOKoOdNMeVHSawSsltak+Ihv+etqsE8=
|
||||||
github.com/containerd/ttrpc v1.0.1/go.mod h1:UAxOpgT9ziI0gJrmKvgcZivgxOp8iFPSk8httJEt98Y=
|
github.com/containerd/ttrpc v1.0.1/go.mod h1:UAxOpgT9ziI0gJrmKvgcZivgxOp8iFPSk8httJEt98Y=
|
||||||
github.com/containerd/ttrpc v1.0.2/go.mod h1:UAxOpgT9ziI0gJrmKvgcZivgxOp8iFPSk8httJEt98Y=
|
github.com/containerd/ttrpc v1.0.2/go.mod h1:UAxOpgT9ziI0gJrmKvgcZivgxOp8iFPSk8httJEt98Y=
|
||||||
|
github.com/containerd/ttrpc v1.1.0/go.mod h1:XX4ZTnoOId4HklF4edwc4DcqskFZuvXB1Evzy5KFQpQ=
|
||||||
github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd/go.mod h1:Cm3kwCdlkCfMSHURc+r6fwoGH6/F1hH3S4sg0rLFWPc=
|
github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd/go.mod h1:Cm3kwCdlkCfMSHURc+r6fwoGH6/F1hH3S4sg0rLFWPc=
|
||||||
github.com/containerd/typeurl v0.0.0-20190911142611-5eb25027c9fd/go.mod h1:GeKYzf2pQcqv7tJ0AoCuuhtnqhva5LNU3U+OyKxxJpk=
|
github.com/containerd/typeurl v0.0.0-20190911142611-5eb25027c9fd/go.mod h1:GeKYzf2pQcqv7tJ0AoCuuhtnqhva5LNU3U+OyKxxJpk=
|
||||||
github.com/containerd/typeurl v1.0.1/go.mod h1:TB1hUtrpaiO88KEK56ijojHS1+NeF0izUACaJW2mdXg=
|
github.com/containerd/typeurl v1.0.1/go.mod h1:TB1hUtrpaiO88KEK56ijojHS1+NeF0izUACaJW2mdXg=
|
||||||
@ -255,8 +257,8 @@ github.com/docker/distribution v0.0.0-20190905152932-14b96e55d84c/go.mod h1:0+TT
|
|||||||
github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||||
github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug=
|
github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug=
|
||||||
github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||||
github.com/docker/docker v20.10.8+incompatible h1:RVqD337BgQicVCzYrrlhLDWhq6OAD2PJDUg2LsEUvKM=
|
github.com/docker/docker v20.10.12+incompatible h1:CEeNmFM0QZIsJCZKMkZx0ZcahTiewkrgiwfYD+dfl1U=
|
||||||
github.com/docker/docker v20.10.8+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
github.com/docker/docker v20.10.12+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||||
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
|
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
|
||||||
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
|
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
|
||||||
github.com/docker/go-events v0.0.0-20170721190031-9461782956ad/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA=
|
github.com/docker/go-events v0.0.0-20170721190031-9461782956ad/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA=
|
||||||
@ -293,7 +295,7 @@ github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa/go.mod h1:KnogPXt
|
|||||||
github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY=
|
github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY=
|
||||||
github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||||
github.com/go-chi/chi/v5 v5.0.4/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
|
github.com/go-chi/chi/v5 v5.0.7/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
|
||||||
github.com/go-chi/cors v1.2.0/go.mod h1:sSbTewc+6wYHBBCW7ytsFSn836hqM7JxpglAy2Vzc58=
|
github.com/go-chi/cors v1.2.0/go.mod h1:sSbTewc+6wYHBBCW7ytsFSn836hqM7JxpglAy2Vzc58=
|
||||||
github.com/go-chi/render v1.0.1/go.mod h1:pq4Rr7HbnsdaeHagklXub+p6Wd16Af5l9koip1OvJns=
|
github.com/go-chi/render v1.0.1/go.mod h1:pq4Rr7HbnsdaeHagklXub+p6Wd16Af5l9koip1OvJns=
|
||||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||||
@ -324,8 +326,8 @@ github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6
|
|||||||
github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||||
github.com/gofrs/flock v0.8.0/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
|
github.com/gofrs/flock v0.8.0/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
|
||||||
github.com/gofrs/uuid v4.0.0+incompatible h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPhW6m+TnJw=
|
github.com/gofrs/uuid v4.2.0+incompatible h1:yyYWMnhkhrKwwr8gAOcOCYxOOscHgDS9yZgBrnJfGa0=
|
||||||
github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
github.com/gofrs/uuid v4.2.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/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||||
@ -438,9 +440,10 @@ github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJ
|
|||||||
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.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/imdario/mergo v0.3.12/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=
|
||||||
github.com/insomniacslk/dhcp v0.0.0-20210827173440-b95caade3eac h1:IO6EfdRnPhxgKOsk9DbewdtQZHKZKnGlW7QCUttvNys=
|
github.com/insomniacslk/dhcp v0.0.0-20211214070828-5297eed8f489 h1:jhdHqd7DxBrzfuFSoPxjD6nUVaV/1RIn9aHA0WCf/as=
|
||||||
github.com/insomniacslk/dhcp v0.0.0-20210827173440-b95caade3eac/go.mod h1:h+MxyHxRg9NH3terB1nfRIUaQEcI0XOVkdR9LNBlp8E=
|
github.com/insomniacslk/dhcp v0.0.0-20211214070828-5297eed8f489/go.mod h1:h+MxyHxRg9NH3terB1nfRIUaQEcI0XOVkdR9LNBlp8E=
|
||||||
github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56/go.mod h1:ymszkNOg6tORTn+6F6j+Jc8TOr5osrynvN6ivFWZ2GA=
|
github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56/go.mod h1:ymszkNOg6tORTn+6F6j+Jc8TOr5osrynvN6ivFWZ2GA=
|
||||||
github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
||||||
github.com/jmespath/go-jmespath v0.0.0-20160803190731-bd40a432e4c7/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
github.com/jmespath/go-jmespath v0.0.0-20160803190731-bd40a432e4c7/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
||||||
@ -500,8 +503,8 @@ github.com/mdlayher/netlink v1.1.0/go.mod h1:H4WCitaheIsdF9yOYu8CFmCgQthAPIWZmcK
|
|||||||
github.com/mdlayher/netlink v1.1.1/go.mod h1:WTYpFb/WTvlRJAyKhZL5/uy69TDDpHHu2VZmb2XgV7o=
|
github.com/mdlayher/netlink v1.1.1/go.mod h1:WTYpFb/WTvlRJAyKhZL5/uy69TDDpHHu2VZmb2XgV7o=
|
||||||
github.com/mdlayher/raw v0.0.0-20190606142536-fef19f00fc18/go.mod h1:7EpbotpCmVZcu+KCX4g9WaRNuu11uyhiW7+Le1dKawg=
|
github.com/mdlayher/raw v0.0.0-20190606142536-fef19f00fc18/go.mod h1:7EpbotpCmVZcu+KCX4g9WaRNuu11uyhiW7+Le1dKawg=
|
||||||
github.com/mdlayher/raw v0.0.0-20191009151244-50f2db8cc065/go.mod h1:7EpbotpCmVZcu+KCX4g9WaRNuu11uyhiW7+Le1dKawg=
|
github.com/mdlayher/raw v0.0.0-20191009151244-50f2db8cc065/go.mod h1:7EpbotpCmVZcu+KCX4g9WaRNuu11uyhiW7+Le1dKawg=
|
||||||
github.com/miekg/dns v1.1.43 h1:JKfpVSCB84vrAmHzyrsxB5NAr5kLoMXZArPSw7Qlgyg=
|
github.com/miekg/dns v1.1.45 h1:g5fRIhm9nx7g8osrAvgb16QJfmyMsyOCb+J7LSv+Qzk=
|
||||||
github.com/miekg/dns v1.1.43/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4=
|
github.com/miekg/dns v1.1.45/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME=
|
||||||
github.com/miekg/pkcs11 v1.0.3/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs=
|
github.com/miekg/pkcs11 v1.0.3/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs=
|
||||||
github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4=
|
github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4=
|
||||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||||
@ -552,15 +555,16 @@ github.com/opencontainers/go-digest v1.0.0-rc1.0.20180430190053-c9281466c8b2/go.
|
|||||||
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
||||||
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
||||||
github.com/opencontainers/image-spec v1.0.0/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
github.com/opencontainers/image-spec v1.0.0/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
||||||
github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI=
|
|
||||||
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
||||||
|
github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM=
|
||||||
|
github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
||||||
github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
||||||
github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
github.com/opencontainers/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-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.2/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=
|
||||||
github.com/opencontainers/runtime-spec v1.0.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
github.com/opencontainers/runtime-spec v1.0.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||||
github.com/opencontainers/runtime-spec v1.0.2-0.20190207185410-29686dbc5559/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
github.com/opencontainers/runtime-spec v1.0.2-0.20190207185410-29686dbc5559/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||||
@ -695,8 +699,8 @@ github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:
|
|||||||
github.com/xeipuuv/gojsonschema v0.0.0-20180618132009-1d523034197f/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs=
|
github.com/xeipuuv/gojsonschema v0.0.0-20180618132009-1d523034197f/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs=
|
||||||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
||||||
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-20210920065950-d4af136d3672 h1:4mkzGhKqt3JO1BWYjtD3iRFyAx4ow67hmSqOcGjuxqQ=
|
||||||
github.com/xtls/go v0.0.0-20201118062508-3632bf3b7499/go.mod h1:5TB2+k58gx4A4g2Nf5miSHNDF6CuAzHKpWBooLAshTs=
|
github.com/xtls/go v0.0.0-20210920065950-d4af136d3672/go.mod h1:YGGVbz9cOxyKFUmhW7LGaLZaMA0cPlHJinvAmVxEMSU=
|
||||||
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=
|
||||||
@ -744,8 +748,10 @@ golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPh
|
|||||||
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-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-20210921155107-089bfa567519 h1:7I4JAnoQBe7ZtJcBaYHi5UtiO8tQHbUSXxL+pnGRANg=
|
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
|
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 h1:0es+/5331RGQPcXlMfP+WrnIIS6dNnNRe0WB02W0F4M=
|
||||||
|
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||||
@ -778,6 +784,7 @@ 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.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
|
golang.org/x/mod v0.5.1 h1:OJxoQ/rynoF0dcCdI7cLPktw/hR2cueqYfjm43oqK38=
|
||||||
golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
|
golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
|
||||||
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=
|
||||||
@ -825,11 +832,13 @@ golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwY
|
|||||||
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-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-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||||
|
golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.0.0-20211020060615-d418f374d309/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20211020060615-d418f374d309/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.0.0-20211029160332-540bb53d3b2e h1:2lVrcCMRP9p7tfk4KUpV1ESqtf49jpihlUtYnSj67k4=
|
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.0.0-20211029160332-540bb53d3b2e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20211216030914-fe4d6282115f h1:hEYJvxw1lSnWIl8X9ofsYMklzaDs90JI2az5YMd4fPM=
|
||||||
|
golang.org/x/net v0.0.0-20211216030914-fe4d6282115f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
@ -924,7 +933,6 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||||||
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-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-20210303074136-134d130e1a04/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-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
@ -933,7 +941,9 @@ golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||||||
golang.org/x/sys v0.0.0-20210525143221-35b2ab0089ea/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210525143221-35b2ab0089ea/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e h1:fLOSk5Q00efkSvAm+4xcoXD+RRmLmmulPn5I3Y9F2EM=
|
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e h1:fLOSk5Q00efkSvAm+4xcoXD+RRmLmmulPn5I3Y9F2EM=
|
||||||
@ -949,16 +959,15 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
|||||||
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
|
golang.org/x/text v0.3.8-0.20211004125949-5bd84dd9b33b h1:NXqSWXSRUSCaFuvitrWtU169I3876zRTalMRbfd6LL0=
|
||||||
golang.org/x/text v0.3.8-0.20211004125949-5bd84dd9b33b/go.mod h1:EFNZuWvGYxIRUEX+K8UmCFwYmZjqcrnq15ZuVldZkZ0=
|
golang.org/x/text v0.3.8-0.20211004125949-5bd84dd9b33b/go.mod h1:EFNZuWvGYxIRUEX+K8UmCFwYmZjqcrnq15ZuVldZkZ0=
|
||||||
golang.org/x/text v0.3.8-0.20211029042148-bb1c79828956 h1:xw/3G76i8BwoCoEZ8RzhVpFrHEz4Qm9D7zPckwa7KVM=
|
|
||||||
golang.org/x/text v0.3.8-0.20211029042148-bb1c79828956/go.mod h1:EFNZuWvGYxIRUEX+K8UmCFwYmZjqcrnq15ZuVldZkZ0=
|
|
||||||
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=
|
||||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac h1:7zkz7BUtwNFFqcowJ+RIgu2MaV/MapERkDIy+mwPyjs=
|
golang.org/x/time v0.0.0-20211116232009-f0f3c7e86c11 h1:GZokNIeuVkl3aZHJchRrr13WCsols02MLUcz1U9is6M=
|
||||||
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20211116232009-f0f3c7e86c11/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
@ -1008,7 +1017,9 @@ golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc
|
|||||||
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||||
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.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||||
|
golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||||
golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo=
|
golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo=
|
||||||
|
golang.org/x/tools v0.1.9 h1:j9KsMiaP1c3B0OTQGth0/k+miLGTgLsAFUCrF2vLcF8=
|
||||||
golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU=
|
golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU=
|
||||||
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=
|
||||||
@ -1097,8 +1108,9 @@ google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTp
|
|||||||
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.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/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=
|
google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=
|
||||||
google.golang.org/grpc v1.42.0-dev.0.20211020220737-f00baa6c3c84 h1:hZAzgyItS2MPyqvdC8wQZI99ZLGP9Vwijyfr0dmYWc4=
|
|
||||||
google.golang.org/grpc v1.42.0-dev.0.20211020220737-f00baa6c3c84/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
|
google.golang.org/grpc v1.42.0-dev.0.20211020220737-f00baa6c3c84/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
|
||||||
|
google.golang.org/grpc v1.43.0 h1:Eeu7bZtDZ2DpRCsLhUlcrLnvYaMK1Gz86a+hMVvELmM=
|
||||||
|
google.golang.org/grpc v1.43.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
|
||||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||||
|
@ -120,6 +120,42 @@ func TestClash_Snell(t *testing.T) {
|
|||||||
testSuit(t, proxy)
|
testSuit(t, proxy)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestClash_Snellv3(t *testing.T) {
|
||||||
|
cfg := &container.Config{
|
||||||
|
Image: ImageSnell,
|
||||||
|
ExposedPorts: defaultExposedPorts,
|
||||||
|
Cmd: []string{"-c", "/config.conf"},
|
||||||
|
}
|
||||||
|
hostCfg := &container.HostConfig{
|
||||||
|
PortBindings: defaultPortBindings,
|
||||||
|
Binds: []string{fmt.Sprintf("%s:/config.conf", C.Path.Resolve("snell.conf"))},
|
||||||
|
}
|
||||||
|
|
||||||
|
id, err := startContainer(cfg, hostCfg, "snell")
|
||||||
|
if err != nil {
|
||||||
|
assert.FailNow(t, err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Cleanup(func() {
|
||||||
|
cleanContainer(id)
|
||||||
|
})
|
||||||
|
|
||||||
|
proxy, err := outbound.NewSnell(outbound.SnellOption{
|
||||||
|
Name: "snell",
|
||||||
|
Server: localIP.String(),
|
||||||
|
Port: 10002,
|
||||||
|
Psk: "password",
|
||||||
|
UDP: true,
|
||||||
|
Version: 3,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
assert.FailNow(t, err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
time.Sleep(waitTime)
|
||||||
|
testSuit(t, proxy)
|
||||||
|
}
|
||||||
|
|
||||||
func Benchmark_Snell(b *testing.B) {
|
func Benchmark_Snell(b *testing.B) {
|
||||||
cfg := &container.Config{
|
cfg := &container.Config{
|
||||||
Image: ImageSnell,
|
Image: ImageSnell,
|
||||||
|
@ -5,6 +5,7 @@ package gun
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
|
"context"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"errors"
|
"errors"
|
||||||
@ -17,6 +18,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/Dreamacro/clash/common/pool"
|
"github.com/Dreamacro/clash/common/pool"
|
||||||
|
C "github.com/Dreamacro/clash/constant"
|
||||||
|
|
||||||
"go.uber.org/atomic"
|
"go.uber.org/atomic"
|
||||||
"golang.org/x/net/http2"
|
"golang.org/x/net/http2"
|
||||||
@ -173,7 +175,11 @@ func NewHTTP2Client(dialFn DialFn, tlsConfig *tls.Config) *http2.Transport {
|
|||||||
}
|
}
|
||||||
|
|
||||||
cn := tls.Client(pconn, cfg)
|
cn := tls.Client(pconn, cfg)
|
||||||
if err := cn.Handshake(); err != nil {
|
|
||||||
|
// fix tls handshake not timeout
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), C.DefaultTLSTimeout)
|
||||||
|
defer cancel()
|
||||||
|
if err := cn.HandshakeContext(ctx); err != nil {
|
||||||
pconn.Close()
|
pconn.Close()
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -6,8 +6,10 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
|
"sync"
|
||||||
|
|
||||||
"github.com/Dreamacro/clash/common/pool"
|
"github.com/Dreamacro/clash/common/pool"
|
||||||
|
"github.com/Dreamacro/clash/transport/socks5"
|
||||||
|
|
||||||
"github.com/Dreamacro/go-shadowsocks2/shadowaead"
|
"github.com/Dreamacro/go-shadowsocks2/shadowaead"
|
||||||
)
|
)
|
||||||
@ -15,13 +17,19 @@ import (
|
|||||||
const (
|
const (
|
||||||
Version1 = 1
|
Version1 = 1
|
||||||
Version2 = 2
|
Version2 = 2
|
||||||
|
Version3 = 3
|
||||||
DefaultSnellVersion = Version1
|
DefaultSnellVersion = Version1
|
||||||
|
|
||||||
|
// max packet length
|
||||||
|
maxLength = 0x3FFF
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
CommandPing byte = 0
|
CommandPing byte = 0
|
||||||
CommandConnect byte = 1
|
CommandConnect byte = 1
|
||||||
CommandConnectV2 byte = 5
|
CommandConnectV2 byte = 5
|
||||||
|
CommandUDP byte = 6
|
||||||
|
CommondUDPForward byte = 1
|
||||||
|
|
||||||
CommandTunnel byte = 0
|
CommandTunnel byte = 0
|
||||||
CommandPong byte = 1
|
CommandPong byte = 1
|
||||||
@ -100,6 +108,16 @@ func WriteHeader(conn net.Conn, host string, port uint, version int) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func WriteUDPHeader(conn net.Conn, version int) error {
|
||||||
|
if version < Version3 {
|
||||||
|
return errors.New("unsupport UDP version")
|
||||||
|
}
|
||||||
|
|
||||||
|
// version, command, clientID length
|
||||||
|
_, err := conn.Write([]byte{Version, CommandUDP, 0x00})
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// HalfClose works only on version2
|
// HalfClose works only on version2
|
||||||
func HalfClose(conn net.Conn) error {
|
func HalfClose(conn net.Conn) error {
|
||||||
if _, err := conn.Write(endSignal); err != nil {
|
if _, err := conn.Write(endSignal); err != nil {
|
||||||
@ -114,10 +132,147 @@ func HalfClose(conn net.Conn) error {
|
|||||||
|
|
||||||
func StreamConn(conn net.Conn, psk []byte, version int) *Snell {
|
func StreamConn(conn net.Conn, psk []byte, version int) *Snell {
|
||||||
var cipher shadowaead.Cipher
|
var cipher shadowaead.Cipher
|
||||||
if version == Version2 {
|
if version != Version1 {
|
||||||
cipher = NewAES128GCM(psk)
|
cipher = NewAES128GCM(psk)
|
||||||
} else {
|
} else {
|
||||||
cipher = NewChacha20Poly1305(psk)
|
cipher = NewChacha20Poly1305(psk)
|
||||||
}
|
}
|
||||||
return &Snell{Conn: shadowaead.NewConn(conn, cipher)}
|
return &Snell{Conn: shadowaead.NewConn(conn, cipher)}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func PacketConn(conn net.Conn) net.PacketConn {
|
||||||
|
return &packetConn{
|
||||||
|
Conn: conn,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func writePacket(w io.Writer, socks5Addr, payload []byte) (int, error) {
|
||||||
|
buf := pool.GetBuffer()
|
||||||
|
defer pool.PutBuffer(buf)
|
||||||
|
|
||||||
|
// compose snell UDP address format (refer: icpz/snell-server-reversed)
|
||||||
|
// a brand new wheel to replace socks5 address format, well done Yachen
|
||||||
|
buf.WriteByte(CommondUDPForward)
|
||||||
|
switch socks5Addr[0] {
|
||||||
|
case socks5.AtypDomainName:
|
||||||
|
hostLen := socks5Addr[1]
|
||||||
|
buf.Write(socks5Addr[1 : 1+1+hostLen+2])
|
||||||
|
case socks5.AtypIPv4:
|
||||||
|
buf.Write([]byte{0x00, 0x04})
|
||||||
|
buf.Write(socks5Addr[1 : 1+net.IPv4len+2])
|
||||||
|
case socks5.AtypIPv6:
|
||||||
|
buf.Write([]byte{0x00, 0x06})
|
||||||
|
buf.Write(socks5Addr[1 : 1+net.IPv6len+2])
|
||||||
|
}
|
||||||
|
|
||||||
|
buf.Write(payload)
|
||||||
|
_, err := w.Write(buf.Bytes())
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return len(payload), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func WritePacket(w io.Writer, socks5Addr, payload []byte) (int, error) {
|
||||||
|
if len(payload) <= maxLength {
|
||||||
|
return writePacket(w, socks5Addr, payload)
|
||||||
|
}
|
||||||
|
|
||||||
|
offset := 0
|
||||||
|
total := len(payload)
|
||||||
|
for {
|
||||||
|
cursor := offset + maxLength
|
||||||
|
if cursor > total {
|
||||||
|
cursor = total
|
||||||
|
}
|
||||||
|
|
||||||
|
n, err := writePacket(w, socks5Addr, payload[offset:cursor])
|
||||||
|
if err != nil {
|
||||||
|
return offset + n, err
|
||||||
|
}
|
||||||
|
|
||||||
|
offset = cursor
|
||||||
|
if offset == total {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return total, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func ReadPacket(r io.Reader, payload []byte) (net.Addr, int, error) {
|
||||||
|
buf := pool.Get(pool.UDPBufferSize)
|
||||||
|
defer pool.Put(buf)
|
||||||
|
|
||||||
|
n, err := r.Read(buf)
|
||||||
|
headLen := 1
|
||||||
|
if err != nil {
|
||||||
|
return nil, 0, err
|
||||||
|
}
|
||||||
|
if n < headLen {
|
||||||
|
return nil, 0, errors.New("insufficient UDP length")
|
||||||
|
}
|
||||||
|
|
||||||
|
// parse snell UDP response address format
|
||||||
|
switch buf[0] {
|
||||||
|
case 0x04:
|
||||||
|
headLen += net.IPv4len + 2
|
||||||
|
if n < headLen {
|
||||||
|
err = errors.New("insufficient UDP length")
|
||||||
|
break
|
||||||
|
}
|
||||||
|
buf[0] = socks5.AtypIPv4
|
||||||
|
case 0x06:
|
||||||
|
headLen += net.IPv6len + 2
|
||||||
|
if n < headLen {
|
||||||
|
err = errors.New("insufficient UDP length")
|
||||||
|
break
|
||||||
|
}
|
||||||
|
buf[0] = socks5.AtypIPv6
|
||||||
|
default:
|
||||||
|
err = errors.New("ip version invalid")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
addr := socks5.SplitAddr(buf[0:])
|
||||||
|
if addr == nil {
|
||||||
|
return nil, 0, errors.New("remote address invalid")
|
||||||
|
}
|
||||||
|
uAddr := addr.UDPAddr()
|
||||||
|
|
||||||
|
length := len(payload)
|
||||||
|
if n-headLen < length {
|
||||||
|
length = n - headLen
|
||||||
|
}
|
||||||
|
copy(payload[:], buf[headLen:headLen+length])
|
||||||
|
|
||||||
|
return uAddr, length, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type packetConn struct {
|
||||||
|
net.Conn
|
||||||
|
rMux sync.Mutex
|
||||||
|
wMux sync.Mutex
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pc *packetConn) WriteTo(b []byte, addr net.Addr) (int, error) {
|
||||||
|
pc.wMux.Lock()
|
||||||
|
defer pc.wMux.Unlock()
|
||||||
|
|
||||||
|
return WritePacket(pc, socks5.ParseAddr(addr.String()), b)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pc *packetConn) ReadFrom(b []byte) (int, net.Addr, error) {
|
||||||
|
pc.rMux.Lock()
|
||||||
|
defer pc.rMux.Unlock()
|
||||||
|
|
||||||
|
addr, n, err := ReadPacket(pc.Conn, b)
|
||||||
|
if err != nil {
|
||||||
|
return 0, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return n, addr, nil
|
||||||
|
}
|
||||||
|
@ -154,7 +154,7 @@ func (a *authAES128) Encode(buf *bytes.Buffer, b []byte) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *authAES128) DecodePacket(b []byte) ([]byte, error) {
|
func (a *authAES128) DecodePacket(b []byte) ([]byte, error) {
|
||||||
if !bytes.Equal(a.hmac(a.userKey, b[:len(b)-4])[:4], b[len(b)-4:]) {
|
if !bytes.Equal(a.hmac(a.Key, b[:len(b)-4])[:4], b[len(b)-4:]) {
|
||||||
return nil, errAuthAES128ChksumError
|
return nil, errAuthAES128ChksumError
|
||||||
}
|
}
|
||||||
return b[:len(b)-4], nil
|
return b[:len(b)-4], nil
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package trojan
|
package trojan
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
@ -12,6 +13,7 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/Dreamacro/clash/common/pool"
|
"github.com/Dreamacro/clash/common/pool"
|
||||||
|
C "github.com/Dreamacro/clash/constant"
|
||||||
"github.com/Dreamacro/clash/transport/socks5"
|
"github.com/Dreamacro/clash/transport/socks5"
|
||||||
"github.com/Dreamacro/clash/transport/vmess"
|
"github.com/Dreamacro/clash/transport/vmess"
|
||||||
)
|
)
|
||||||
@ -68,7 +70,11 @@ func (t *Trojan) StreamConn(conn net.Conn) (net.Conn, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
tlsConn := tls.Client(conn, tlsConfig)
|
tlsConn := tls.Client(conn, tlsConfig)
|
||||||
if err := tlsConn.Handshake(); err != nil {
|
|
||||||
|
// fix tls handshake not timeout
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), C.DefaultTLSTimeout)
|
||||||
|
defer cancel()
|
||||||
|
if err := tlsConn.HandshakeContext(ctx); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,8 +1,11 @@
|
|||||||
package vless
|
package vless
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"net"
|
"net"
|
||||||
|
|
||||||
|
C "github.com/Dreamacro/clash/constant"
|
||||||
|
|
||||||
xtls "github.com/xtls/go"
|
xtls "github.com/xtls/go"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -20,6 +23,10 @@ func StreamXTLSConn(conn net.Conn, cfg *XTLSConfig) (net.Conn, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
xtlsConn := xtls.Client(conn, xtlsConfig)
|
xtlsConn := xtls.Client(conn, xtlsConfig)
|
||||||
err := xtlsConn.Handshake()
|
|
||||||
|
// fix xtls handshake not timeout
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), C.DefaultTLSTimeout)
|
||||||
|
defer cancel()
|
||||||
|
err := xtlsConn.HandshakeContext(ctx)
|
||||||
return xtlsConn, err
|
return xtlsConn, err
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,11 @@
|
|||||||
package vmess
|
package vmess
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"net"
|
"net"
|
||||||
|
|
||||||
|
C "github.com/Dreamacro/clash/constant"
|
||||||
)
|
)
|
||||||
|
|
||||||
type TLSConfig struct {
|
type TLSConfig struct {
|
||||||
@ -19,6 +22,10 @@ func StreamTLSConn(conn net.Conn, cfg *TLSConfig) (net.Conn, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
tlsConn := tls.Client(conn, tlsConfig)
|
tlsConn := tls.Client(conn, tlsConfig)
|
||||||
err := tlsConn.Handshake()
|
|
||||||
|
// fix tls handshake not timeout
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), C.DefaultTLSTimeout)
|
||||||
|
defer cancel()
|
||||||
|
err := tlsConn.HandshakeContext(ctx)
|
||||||
return tlsConn, err
|
return tlsConn, err
|
||||||
}
|
}
|
||||||
|
@ -39,7 +39,7 @@ func handleUDPToRemote(packet C.UDPPacket, pc C.PacketConn, metadata *C.Metadata
|
|||||||
}
|
}
|
||||||
|
|
||||||
func handleUDPToLocal(packet C.UDPPacket, pc net.PacketConn, key string, fAddr net.Addr) {
|
func handleUDPToLocal(packet C.UDPPacket, pc net.PacketConn, key string, fAddr net.Addr) {
|
||||||
buf := pool.Get(pool.RelayBufferSize)
|
buf := pool.Get(pool.UDPBufferSize)
|
||||||
defer pool.Put(buf)
|
defer pool.Put(buf)
|
||||||
defer natTable.Delete(key)
|
defer natTable.Delete(key)
|
||||||
defer pc.Close()
|
defer pc.Close()
|
||||||
|
Reference in New Issue
Block a user