From f96ebab99f21004c0f4d2e723ce2be23a8e326f7 Mon Sep 17 00:00:00 2001 From: Dreamacro <8615343+Dreamacro@users.noreply.github.com> Date: Thu, 13 May 2021 22:18:49 +0800 Subject: [PATCH 01/96] Chore: split component to transport --- adapters/inbound/packet.go | 2 +- adapters/inbound/socket.go | 2 +- adapters/inbound/util.go | 2 +- adapters/outbound/shadowsocks.go | 6 +++--- adapters/outbound/shadowsocksr.go | 4 ++-- adapters/outbound/snell.go | 4 ++-- adapters/outbound/socks5.go | 2 +- adapters/outbound/trojan.go | 4 ++-- adapters/outbound/util.go | 2 +- adapters/outbound/vmess.go | 4 ++-- proxy/mixed/mixed.go | 3 +-- proxy/redir/tcp_darwin.go | 2 +- proxy/redir/tproxy.go | 2 +- proxy/redir/udp.go | 2 +- proxy/socks/tcp.go | 2 +- proxy/socks/udp.go | 2 +- proxy/socks/utils.go | 2 +- {component => transport}/gun/gun.go | 0 {component => transport}/simple-obfs/http.go | 0 {component => transport}/simple-obfs/tls.go | 0 {component => transport}/snell/cipher.go | 0 {component => transport}/snell/pool.go | 0 {component => transport}/snell/snell.go | 0 {component => transport}/socks5/socks5.go | 0 {component => transport}/ssr/obfs/base.go | 0 {component => transport}/ssr/obfs/http_post.go | 0 {component => transport}/ssr/obfs/http_simple.go | 2 +- {component => transport}/ssr/obfs/obfs.go | 0 {component => transport}/ssr/obfs/plain.go | 0 {component => transport}/ssr/obfs/random_head.go | 0 {component => transport}/ssr/obfs/tls1.2_ticket_auth.go | 2 +- {component => transport}/ssr/protocol/auth_aes128_md5.go | 2 +- {component => transport}/ssr/protocol/auth_aes128_sha1.go | 2 +- {component => transport}/ssr/protocol/auth_chain_a.go | 2 +- {component => transport}/ssr/protocol/auth_chain_b.go | 2 +- {component => transport}/ssr/protocol/auth_sha1_v4.go | 2 +- {component => transport}/ssr/protocol/base.go | 0 {component => transport}/ssr/protocol/origin.go | 0 {component => transport}/ssr/protocol/packet.go | 2 +- {component => transport}/ssr/protocol/protocol.go | 0 {component => transport}/ssr/protocol/stream.go | 2 +- {component => transport}/ssr/tools/bufPool.go | 0 {component => transport}/ssr/tools/crypto.go | 0 {component => transport}/ssr/tools/random.go | 0 {component => transport}/trojan/trojan.go | 2 +- {component => transport}/v2ray-plugin/mux.go | 0 {component => transport}/v2ray-plugin/websocket.go | 2 +- {component => transport}/vmess/aead.go | 0 {component => transport}/vmess/chunk.go | 0 {component => transport}/vmess/conn.go | 0 {component => transport}/vmess/h2.go | 0 {component => transport}/vmess/header.go | 0 {component => transport}/vmess/http.go | 0 {component => transport}/vmess/tls.go | 0 {component => transport}/vmess/user.go | 0 {component => transport}/vmess/vmess.go | 0 {component => transport}/vmess/websocket.go | 0 57 files changed, 34 insertions(+), 35 deletions(-) rename {component => transport}/gun/gun.go (100%) rename {component => transport}/simple-obfs/http.go (100%) rename {component => transport}/simple-obfs/tls.go (100%) rename {component => transport}/snell/cipher.go (100%) rename {component => transport}/snell/pool.go (100%) rename {component => transport}/snell/snell.go (100%) rename {component => transport}/socks5/socks5.go (100%) rename {component => transport}/ssr/obfs/base.go (100%) rename {component => transport}/ssr/obfs/http_post.go (100%) rename {component => transport}/ssr/obfs/http_simple.go (99%) rename {component => transport}/ssr/obfs/obfs.go (100%) rename {component => transport}/ssr/obfs/plain.go (100%) rename {component => transport}/ssr/obfs/random_head.go (100%) rename {component => transport}/ssr/obfs/tls1.2_ticket_auth.go (99%) rename {component => transport}/ssr/protocol/auth_aes128_md5.go (87%) rename {component => transport}/ssr/protocol/auth_aes128_sha1.go (99%) rename {component => transport}/ssr/protocol/auth_chain_a.go (99%) rename {component => transport}/ssr/protocol/auth_chain_b.go (97%) rename {component => transport}/ssr/protocol/auth_sha1_v4.go (98%) rename {component => transport}/ssr/protocol/base.go (100%) rename {component => transport}/ssr/protocol/origin.go (100%) rename {component => transport}/ssr/protocol/packet.go (93%) rename {component => transport}/ssr/protocol/protocol.go (100%) rename {component => transport}/ssr/protocol/stream.go (94%) rename {component => transport}/ssr/tools/bufPool.go (100%) rename {component => transport}/ssr/tools/crypto.go (100%) rename {component => transport}/ssr/tools/random.go (100%) rename {component => transport}/trojan/trojan.go (98%) rename {component => transport}/v2ray-plugin/mux.go (100%) rename {component => transport}/v2ray-plugin/websocket.go (95%) rename {component => transport}/vmess/aead.go (100%) rename {component => transport}/vmess/chunk.go (100%) rename {component => transport}/vmess/conn.go (100%) rename {component => transport}/vmess/h2.go (100%) rename {component => transport}/vmess/header.go (100%) rename {component => transport}/vmess/http.go (100%) rename {component => transport}/vmess/tls.go (100%) rename {component => transport}/vmess/user.go (100%) rename {component => transport}/vmess/vmess.go (100%) rename {component => transport}/vmess/websocket.go (100%) diff --git a/adapters/inbound/packet.go b/adapters/inbound/packet.go index 001a579b8..80b136cd6 100644 --- a/adapters/inbound/packet.go +++ b/adapters/inbound/packet.go @@ -1,8 +1,8 @@ package inbound import ( - "github.com/Dreamacro/clash/component/socks5" C "github.com/Dreamacro/clash/constant" + "github.com/Dreamacro/clash/transport/socks5" ) // PacketAdapter is a UDP Packet adapter for socks/redir/tun diff --git a/adapters/inbound/socket.go b/adapters/inbound/socket.go index be772b7bc..be717017e 100644 --- a/adapters/inbound/socket.go +++ b/adapters/inbound/socket.go @@ -3,9 +3,9 @@ package inbound import ( "net" - "github.com/Dreamacro/clash/component/socks5" C "github.com/Dreamacro/clash/constant" "github.com/Dreamacro/clash/context" + "github.com/Dreamacro/clash/transport/socks5" ) // NewSocket receive TCP inbound and return ConnContext diff --git a/adapters/inbound/util.go b/adapters/inbound/util.go index 6241ac803..07577ec0e 100644 --- a/adapters/inbound/util.go +++ b/adapters/inbound/util.go @@ -6,8 +6,8 @@ import ( "strconv" "strings" - "github.com/Dreamacro/clash/component/socks5" C "github.com/Dreamacro/clash/constant" + "github.com/Dreamacro/clash/transport/socks5" ) func parseSocksAddr(target socks5.Addr) *C.Metadata { diff --git a/adapters/outbound/shadowsocks.go b/adapters/outbound/shadowsocks.go index edcd60abe..6dcfc2c08 100644 --- a/adapters/outbound/shadowsocks.go +++ b/adapters/outbound/shadowsocks.go @@ -10,10 +10,10 @@ import ( "github.com/Dreamacro/clash/common/structure" "github.com/Dreamacro/clash/component/dialer" - obfs "github.com/Dreamacro/clash/component/simple-obfs" - "github.com/Dreamacro/clash/component/socks5" - v2rayObfs "github.com/Dreamacro/clash/component/v2ray-plugin" C "github.com/Dreamacro/clash/constant" + obfs "github.com/Dreamacro/clash/transport/simple-obfs" + "github.com/Dreamacro/clash/transport/socks5" + v2rayObfs "github.com/Dreamacro/clash/transport/v2ray-plugin" "github.com/Dreamacro/go-shadowsocks2/core" ) diff --git a/adapters/outbound/shadowsocksr.go b/adapters/outbound/shadowsocksr.go index 6636d5ff9..635135fcd 100644 --- a/adapters/outbound/shadowsocksr.go +++ b/adapters/outbound/shadowsocksr.go @@ -8,9 +8,9 @@ import ( "strconv" "github.com/Dreamacro/clash/component/dialer" - "github.com/Dreamacro/clash/component/ssr/obfs" - "github.com/Dreamacro/clash/component/ssr/protocol" C "github.com/Dreamacro/clash/constant" + "github.com/Dreamacro/clash/transport/ssr/obfs" + "github.com/Dreamacro/clash/transport/ssr/protocol" "github.com/Dreamacro/go-shadowsocks2/core" "github.com/Dreamacro/go-shadowsocks2/shadowaead" diff --git a/adapters/outbound/snell.go b/adapters/outbound/snell.go index 0b65b272b..2dc16a511 100644 --- a/adapters/outbound/snell.go +++ b/adapters/outbound/snell.go @@ -8,9 +8,9 @@ import ( "github.com/Dreamacro/clash/common/structure" "github.com/Dreamacro/clash/component/dialer" - obfs "github.com/Dreamacro/clash/component/simple-obfs" - "github.com/Dreamacro/clash/component/snell" C "github.com/Dreamacro/clash/constant" + obfs "github.com/Dreamacro/clash/transport/simple-obfs" + "github.com/Dreamacro/clash/transport/snell" ) type Snell struct { diff --git a/adapters/outbound/socks5.go b/adapters/outbound/socks5.go index 377d7d173..466797de8 100644 --- a/adapters/outbound/socks5.go +++ b/adapters/outbound/socks5.go @@ -11,8 +11,8 @@ import ( "strconv" "github.com/Dreamacro/clash/component/dialer" - "github.com/Dreamacro/clash/component/socks5" C "github.com/Dreamacro/clash/constant" + "github.com/Dreamacro/clash/transport/socks5" ) type Socks5 struct { diff --git a/adapters/outbound/trojan.go b/adapters/outbound/trojan.go index cfd734499..929f44147 100644 --- a/adapters/outbound/trojan.go +++ b/adapters/outbound/trojan.go @@ -9,9 +9,9 @@ import ( "strconv" "github.com/Dreamacro/clash/component/dialer" - "github.com/Dreamacro/clash/component/gun" - "github.com/Dreamacro/clash/component/trojan" C "github.com/Dreamacro/clash/constant" + "github.com/Dreamacro/clash/transport/gun" + "github.com/Dreamacro/clash/transport/trojan" "golang.org/x/net/http2" ) diff --git a/adapters/outbound/util.go b/adapters/outbound/util.go index 932f741cc..cd60d3732 100644 --- a/adapters/outbound/util.go +++ b/adapters/outbound/util.go @@ -11,8 +11,8 @@ import ( "time" "github.com/Dreamacro/clash/component/resolver" - "github.com/Dreamacro/clash/component/socks5" C "github.com/Dreamacro/clash/constant" + "github.com/Dreamacro/clash/transport/socks5" ) const ( diff --git a/adapters/outbound/vmess.go b/adapters/outbound/vmess.go index 528db7f5c..246450aca 100644 --- a/adapters/outbound/vmess.go +++ b/adapters/outbound/vmess.go @@ -11,10 +11,10 @@ import ( "strings" "github.com/Dreamacro/clash/component/dialer" - "github.com/Dreamacro/clash/component/gun" "github.com/Dreamacro/clash/component/resolver" - "github.com/Dreamacro/clash/component/vmess" C "github.com/Dreamacro/clash/constant" + "github.com/Dreamacro/clash/transport/gun" + "github.com/Dreamacro/clash/transport/vmess" "golang.org/x/net/http2" ) diff --git a/proxy/mixed/mixed.go b/proxy/mixed/mixed.go index 3328724e1..b89748eea 100644 --- a/proxy/mixed/mixed.go +++ b/proxy/mixed/mixed.go @@ -5,11 +5,10 @@ import ( "time" "github.com/Dreamacro/clash/common/cache" - "github.com/Dreamacro/clash/component/socks5" "github.com/Dreamacro/clash/log" - "github.com/Dreamacro/clash/proxy/http" "github.com/Dreamacro/clash/proxy/socks" + "github.com/Dreamacro/clash/transport/socks5" ) type MixedListener struct { diff --git a/proxy/redir/tcp_darwin.go b/proxy/redir/tcp_darwin.go index 4e9ade1e5..5a2f331c3 100644 --- a/proxy/redir/tcp_darwin.go +++ b/proxy/redir/tcp_darwin.go @@ -5,7 +5,7 @@ import ( "syscall" "unsafe" - "github.com/Dreamacro/clash/component/socks5" + "github.com/Dreamacro/clash/transport/socks5" ) func parserPacket(c net.Conn) (socks5.Addr, error) { diff --git a/proxy/redir/tproxy.go b/proxy/redir/tproxy.go index e2846e4f0..576c4d37f 100644 --- a/proxy/redir/tproxy.go +++ b/proxy/redir/tproxy.go @@ -4,9 +4,9 @@ import ( "net" "github.com/Dreamacro/clash/adapters/inbound" - "github.com/Dreamacro/clash/component/socks5" C "github.com/Dreamacro/clash/constant" "github.com/Dreamacro/clash/log" + "github.com/Dreamacro/clash/transport/socks5" "github.com/Dreamacro/clash/tunnel" ) diff --git a/proxy/redir/udp.go b/proxy/redir/udp.go index 45a726e07..57bd3ff35 100644 --- a/proxy/redir/udp.go +++ b/proxy/redir/udp.go @@ -5,8 +5,8 @@ import ( adapters "github.com/Dreamacro/clash/adapters/inbound" "github.com/Dreamacro/clash/common/pool" - "github.com/Dreamacro/clash/component/socks5" C "github.com/Dreamacro/clash/constant" + "github.com/Dreamacro/clash/transport/socks5" "github.com/Dreamacro/clash/tunnel" ) diff --git a/proxy/socks/tcp.go b/proxy/socks/tcp.go index 0f6c4fb4f..116ea3f6b 100644 --- a/proxy/socks/tcp.go +++ b/proxy/socks/tcp.go @@ -6,10 +6,10 @@ import ( "net" adapters "github.com/Dreamacro/clash/adapters/inbound" - "github.com/Dreamacro/clash/component/socks5" C "github.com/Dreamacro/clash/constant" "github.com/Dreamacro/clash/log" authStore "github.com/Dreamacro/clash/proxy/auth" + "github.com/Dreamacro/clash/transport/socks5" "github.com/Dreamacro/clash/tunnel" ) diff --git a/proxy/socks/udp.go b/proxy/socks/udp.go index 38bc11313..a365353b8 100644 --- a/proxy/socks/udp.go +++ b/proxy/socks/udp.go @@ -6,9 +6,9 @@ import ( adapters "github.com/Dreamacro/clash/adapters/inbound" "github.com/Dreamacro/clash/common/pool" "github.com/Dreamacro/clash/common/sockopt" - "github.com/Dreamacro/clash/component/socks5" C "github.com/Dreamacro/clash/constant" "github.com/Dreamacro/clash/log" + "github.com/Dreamacro/clash/transport/socks5" "github.com/Dreamacro/clash/tunnel" ) diff --git a/proxy/socks/utils.go b/proxy/socks/utils.go index 797e0a220..28dfef723 100644 --- a/proxy/socks/utils.go +++ b/proxy/socks/utils.go @@ -4,7 +4,7 @@ import ( "net" "github.com/Dreamacro/clash/common/pool" - "github.com/Dreamacro/clash/component/socks5" + "github.com/Dreamacro/clash/transport/socks5" ) type packet struct { diff --git a/component/gun/gun.go b/transport/gun/gun.go similarity index 100% rename from component/gun/gun.go rename to transport/gun/gun.go diff --git a/component/simple-obfs/http.go b/transport/simple-obfs/http.go similarity index 100% rename from component/simple-obfs/http.go rename to transport/simple-obfs/http.go diff --git a/component/simple-obfs/tls.go b/transport/simple-obfs/tls.go similarity index 100% rename from component/simple-obfs/tls.go rename to transport/simple-obfs/tls.go diff --git a/component/snell/cipher.go b/transport/snell/cipher.go similarity index 100% rename from component/snell/cipher.go rename to transport/snell/cipher.go diff --git a/component/snell/pool.go b/transport/snell/pool.go similarity index 100% rename from component/snell/pool.go rename to transport/snell/pool.go diff --git a/component/snell/snell.go b/transport/snell/snell.go similarity index 100% rename from component/snell/snell.go rename to transport/snell/snell.go diff --git a/component/socks5/socks5.go b/transport/socks5/socks5.go similarity index 100% rename from component/socks5/socks5.go rename to transport/socks5/socks5.go diff --git a/component/ssr/obfs/base.go b/transport/ssr/obfs/base.go similarity index 100% rename from component/ssr/obfs/base.go rename to transport/ssr/obfs/base.go diff --git a/component/ssr/obfs/http_post.go b/transport/ssr/obfs/http_post.go similarity index 100% rename from component/ssr/obfs/http_post.go rename to transport/ssr/obfs/http_post.go diff --git a/component/ssr/obfs/http_simple.go b/transport/ssr/obfs/http_simple.go similarity index 99% rename from component/ssr/obfs/http_simple.go rename to transport/ssr/obfs/http_simple.go index 86dea9475..26fb31247 100644 --- a/component/ssr/obfs/http_simple.go +++ b/transport/ssr/obfs/http_simple.go @@ -10,7 +10,7 @@ import ( "strings" "github.com/Dreamacro/clash/common/pool" - "github.com/Dreamacro/clash/component/ssr/tools" + "github.com/Dreamacro/clash/transport/ssr/tools" ) func init() { diff --git a/component/ssr/obfs/obfs.go b/transport/ssr/obfs/obfs.go similarity index 100% rename from component/ssr/obfs/obfs.go rename to transport/ssr/obfs/obfs.go diff --git a/component/ssr/obfs/plain.go b/transport/ssr/obfs/plain.go similarity index 100% rename from component/ssr/obfs/plain.go rename to transport/ssr/obfs/plain.go diff --git a/component/ssr/obfs/random_head.go b/transport/ssr/obfs/random_head.go similarity index 100% rename from component/ssr/obfs/random_head.go rename to transport/ssr/obfs/random_head.go diff --git a/component/ssr/obfs/tls1.2_ticket_auth.go b/transport/ssr/obfs/tls1.2_ticket_auth.go similarity index 99% rename from component/ssr/obfs/tls1.2_ticket_auth.go rename to transport/ssr/obfs/tls1.2_ticket_auth.go index f3c5b456d..d9141121c 100644 --- a/component/ssr/obfs/tls1.2_ticket_auth.go +++ b/transport/ssr/obfs/tls1.2_ticket_auth.go @@ -10,7 +10,7 @@ import ( "time" "github.com/Dreamacro/clash/common/pool" - "github.com/Dreamacro/clash/component/ssr/tools" + "github.com/Dreamacro/clash/transport/ssr/tools" ) func init() { diff --git a/component/ssr/protocol/auth_aes128_md5.go b/transport/ssr/protocol/auth_aes128_md5.go similarity index 87% rename from component/ssr/protocol/auth_aes128_md5.go rename to transport/ssr/protocol/auth_aes128_md5.go index 08e350c46..d3bc94172 100644 --- a/component/ssr/protocol/auth_aes128_md5.go +++ b/transport/ssr/protocol/auth_aes128_md5.go @@ -1,6 +1,6 @@ package protocol -import "github.com/Dreamacro/clash/component/ssr/tools" +import "github.com/Dreamacro/clash/transport/ssr/tools" func init() { register("auth_aes128_md5", newAuthAES128MD5, 9) diff --git a/component/ssr/protocol/auth_aes128_sha1.go b/transport/ssr/protocol/auth_aes128_sha1.go similarity index 99% rename from component/ssr/protocol/auth_aes128_sha1.go rename to transport/ssr/protocol/auth_aes128_sha1.go index 503834562..65bcd7416 100644 --- a/component/ssr/protocol/auth_aes128_sha1.go +++ b/transport/ssr/protocol/auth_aes128_sha1.go @@ -10,8 +10,8 @@ import ( "strings" "github.com/Dreamacro/clash/common/pool" - "github.com/Dreamacro/clash/component/ssr/tools" "github.com/Dreamacro/clash/log" + "github.com/Dreamacro/clash/transport/ssr/tools" ) type hmacMethod func(key, data []byte) []byte diff --git a/component/ssr/protocol/auth_chain_a.go b/transport/ssr/protocol/auth_chain_a.go similarity index 99% rename from component/ssr/protocol/auth_chain_a.go rename to transport/ssr/protocol/auth_chain_a.go index db51e1048..4ce55c1a6 100644 --- a/component/ssr/protocol/auth_chain_a.go +++ b/transport/ssr/protocol/auth_chain_a.go @@ -12,8 +12,8 @@ import ( "strings" "github.com/Dreamacro/clash/common/pool" - "github.com/Dreamacro/clash/component/ssr/tools" "github.com/Dreamacro/clash/log" + "github.com/Dreamacro/clash/transport/ssr/tools" "github.com/Dreamacro/go-shadowsocks2/core" ) diff --git a/component/ssr/protocol/auth_chain_b.go b/transport/ssr/protocol/auth_chain_b.go similarity index 97% rename from component/ssr/protocol/auth_chain_b.go rename to transport/ssr/protocol/auth_chain_b.go index 2f3f8f17a..857b2a3aa 100644 --- a/component/ssr/protocol/auth_chain_b.go +++ b/transport/ssr/protocol/auth_chain_b.go @@ -4,7 +4,7 @@ import ( "net" "sort" - "github.com/Dreamacro/clash/component/ssr/tools" + "github.com/Dreamacro/clash/transport/ssr/tools" ) func init() { diff --git a/component/ssr/protocol/auth_sha1_v4.go b/transport/ssr/protocol/auth_sha1_v4.go similarity index 98% rename from component/ssr/protocol/auth_sha1_v4.go rename to transport/ssr/protocol/auth_sha1_v4.go index 0f24c360c..30392c9e7 100644 --- a/component/ssr/protocol/auth_sha1_v4.go +++ b/transport/ssr/protocol/auth_sha1_v4.go @@ -9,7 +9,7 @@ import ( "net" "github.com/Dreamacro/clash/common/pool" - "github.com/Dreamacro/clash/component/ssr/tools" + "github.com/Dreamacro/clash/transport/ssr/tools" ) func init() { diff --git a/component/ssr/protocol/base.go b/transport/ssr/protocol/base.go similarity index 100% rename from component/ssr/protocol/base.go rename to transport/ssr/protocol/base.go diff --git a/component/ssr/protocol/origin.go b/transport/ssr/protocol/origin.go similarity index 100% rename from component/ssr/protocol/origin.go rename to transport/ssr/protocol/origin.go diff --git a/component/ssr/protocol/packet.go b/transport/ssr/protocol/packet.go similarity index 93% rename from component/ssr/protocol/packet.go rename to transport/ssr/protocol/packet.go index 1577c7885..621dc8c8f 100644 --- a/component/ssr/protocol/packet.go +++ b/transport/ssr/protocol/packet.go @@ -4,7 +4,7 @@ import ( "bytes" "net" - "github.com/Dreamacro/clash/component/ssr/tools" + "github.com/Dreamacro/clash/transport/ssr/tools" ) type PacketConn struct { diff --git a/component/ssr/protocol/protocol.go b/transport/ssr/protocol/protocol.go similarity index 100% rename from component/ssr/protocol/protocol.go rename to transport/ssr/protocol/protocol.go diff --git a/component/ssr/protocol/stream.go b/transport/ssr/protocol/stream.go similarity index 94% rename from component/ssr/protocol/stream.go rename to transport/ssr/protocol/stream.go index 53f53ead4..25d46f74a 100644 --- a/component/ssr/protocol/stream.go +++ b/transport/ssr/protocol/stream.go @@ -5,7 +5,7 @@ import ( "net" "github.com/Dreamacro/clash/common/pool" - "github.com/Dreamacro/clash/component/ssr/tools" + "github.com/Dreamacro/clash/transport/ssr/tools" ) type Conn struct { diff --git a/component/ssr/tools/bufPool.go b/transport/ssr/tools/bufPool.go similarity index 100% rename from component/ssr/tools/bufPool.go rename to transport/ssr/tools/bufPool.go diff --git a/component/ssr/tools/crypto.go b/transport/ssr/tools/crypto.go similarity index 100% rename from component/ssr/tools/crypto.go rename to transport/ssr/tools/crypto.go diff --git a/component/ssr/tools/random.go b/transport/ssr/tools/random.go similarity index 100% rename from component/ssr/tools/random.go rename to transport/ssr/tools/random.go diff --git a/component/trojan/trojan.go b/transport/trojan/trojan.go similarity index 98% rename from component/trojan/trojan.go rename to transport/trojan/trojan.go index ef440d62b..88cc95fb1 100644 --- a/component/trojan/trojan.go +++ b/transport/trojan/trojan.go @@ -11,7 +11,7 @@ import ( "net" "sync" - "github.com/Dreamacro/clash/component/socks5" + "github.com/Dreamacro/clash/transport/socks5" ) const ( diff --git a/component/v2ray-plugin/mux.go b/transport/v2ray-plugin/mux.go similarity index 100% rename from component/v2ray-plugin/mux.go rename to transport/v2ray-plugin/mux.go diff --git a/component/v2ray-plugin/websocket.go b/transport/v2ray-plugin/websocket.go similarity index 95% rename from component/v2ray-plugin/websocket.go rename to transport/v2ray-plugin/websocket.go index fbd1f3e32..9feaf2c2f 100644 --- a/component/v2ray-plugin/websocket.go +++ b/transport/v2ray-plugin/websocket.go @@ -5,7 +5,7 @@ import ( "net" "net/http" - "github.com/Dreamacro/clash/component/vmess" + "github.com/Dreamacro/clash/transport/vmess" ) // Option is options of websocket obfs diff --git a/component/vmess/aead.go b/transport/vmess/aead.go similarity index 100% rename from component/vmess/aead.go rename to transport/vmess/aead.go diff --git a/component/vmess/chunk.go b/transport/vmess/chunk.go similarity index 100% rename from component/vmess/chunk.go rename to transport/vmess/chunk.go diff --git a/component/vmess/conn.go b/transport/vmess/conn.go similarity index 100% rename from component/vmess/conn.go rename to transport/vmess/conn.go diff --git a/component/vmess/h2.go b/transport/vmess/h2.go similarity index 100% rename from component/vmess/h2.go rename to transport/vmess/h2.go diff --git a/component/vmess/header.go b/transport/vmess/header.go similarity index 100% rename from component/vmess/header.go rename to transport/vmess/header.go diff --git a/component/vmess/http.go b/transport/vmess/http.go similarity index 100% rename from component/vmess/http.go rename to transport/vmess/http.go diff --git a/component/vmess/tls.go b/transport/vmess/tls.go similarity index 100% rename from component/vmess/tls.go rename to transport/vmess/tls.go diff --git a/component/vmess/user.go b/transport/vmess/user.go similarity index 100% rename from component/vmess/user.go rename to transport/vmess/user.go diff --git a/component/vmess/vmess.go b/transport/vmess/vmess.go similarity index 100% rename from component/vmess/vmess.go rename to transport/vmess/vmess.go diff --git a/component/vmess/websocket.go b/transport/vmess/websocket.go similarity index 100% rename from component/vmess/websocket.go rename to transport/vmess/websocket.go From 4e5898197aed4e944f8ad9d2139c24ffd0ad6a95 Mon Sep 17 00:00:00 2001 From: Dreamacro <8615343+Dreamacro@users.noreply.github.com> Date: Thu, 13 May 2021 22:39:33 +0800 Subject: [PATCH 02/96] Fix: build broken --- proxy/redir/tcp_freebsd.go | 2 +- proxy/redir/tcp_linux.go | 2 +- proxy/redir/tcp_other.go | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/proxy/redir/tcp_freebsd.go b/proxy/redir/tcp_freebsd.go index f9cdf5a6a..12c4ba6ae 100644 --- a/proxy/redir/tcp_freebsd.go +++ b/proxy/redir/tcp_freebsd.go @@ -6,7 +6,7 @@ import ( "syscall" "unsafe" - "github.com/Dreamacro/clash/component/socks5" + "github.com/Dreamacro/clash/transport/socks5" ) const ( diff --git a/proxy/redir/tcp_linux.go b/proxy/redir/tcp_linux.go index ac3a455c3..e802319cd 100644 --- a/proxy/redir/tcp_linux.go +++ b/proxy/redir/tcp_linux.go @@ -6,7 +6,7 @@ import ( "syscall" "unsafe" - "github.com/Dreamacro/clash/component/socks5" + "github.com/Dreamacro/clash/transport/socks5" ) const ( diff --git a/proxy/redir/tcp_other.go b/proxy/redir/tcp_other.go index 21743ec08..50968e9ab 100644 --- a/proxy/redir/tcp_other.go +++ b/proxy/redir/tcp_other.go @@ -6,7 +6,7 @@ import ( "errors" "net" - "github.com/Dreamacro/clash/component/socks5" + "github.com/Dreamacro/clash/transport/socks5" ) func parserPacket(conn net.Conn) (socks5.Addr, error) { From 06fdd3abe0ab610a57ce88c448e59003d3c13368 Mon Sep 17 00:00:00 2001 From: Dreamacro <8615343+Dreamacro@users.noreply.github.com> Date: Sun, 16 May 2021 20:05:41 +0800 Subject: [PATCH 03/96] Fix: vmess http should use Host header on request --- transport/vmess/http.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/transport/vmess/http.go b/transport/vmess/http.go index 5c1a5bd1c..1c09e215a 100644 --- a/transport/vmess/http.go +++ b/transport/vmess/http.go @@ -52,7 +52,12 @@ func (hc *httpConn) Write(b []byte) (int, error) { } path := hc.cfg.Path[rand.Intn(len(hc.cfg.Path))] - u := fmt.Sprintf("http://%s%s", hc.cfg.Host, path) + host := hc.cfg.Host + if header := hc.cfg.Headers["Host"]; len(header) != 0 { + host = header[rand.Intn(len(header))] + } + + u := fmt.Sprintf("http://%s%s", host, path) req, _ := http.NewRequest("GET", u, bytes.NewBuffer(b)) for key, list := range hc.cfg.Headers { req.Header.Set(key, list[rand.Intn(len(list))]) From d5e52bed433c73369e4571cd42b469ddae4afb56 Mon Sep 17 00:00:00 2001 From: Dreamacro <8615343+Dreamacro@users.noreply.github.com> Date: Mon, 17 May 2021 20:33:00 +0800 Subject: [PATCH 04/96] Feature: add protocol test --- test/README.md | 49 +++ test/clash_test.go | 635 ++++++++++++++++++++++++++++++++ test/config/example.org-key.pem | 28 ++ test/config/example.org.pem | 25 ++ test/config/snell-http.conf | 4 + test/config/snell-tls.conf | 4 + test/config/snell.conf | 3 + test/config/trojan-grpc.json | 40 ++ test/config/trojan.json | 40 ++ test/config/vmess-aead.json | 28 ++ test/config/vmess-grpc.json | 40 ++ test/config/vmess-http.json | 55 +++ test/config/vmess-http2.json | 43 +++ test/config/vmess-tls.json | 37 ++ test/config/vmess-ws-tls.json | 34 ++ test/config/vmess-ws.json | 26 ++ test/config/vmess.json | 28 ++ test/dns_test.go | 103 ++++++ test/docker_test.go | 45 +++ test/go.mod | 26 ++ test/go.sum | 202 ++++++++++ test/snell_test.go | 121 ++++++ test/ss_test.go | 172 +++++++++ test/trojan_test.go | 94 +++++ test/util_test.go | 70 ++++ test/vmess_test.go | 347 +++++++++++++++++ 26 files changed, 2299 insertions(+) create mode 100644 test/README.md create mode 100644 test/clash_test.go create mode 100644 test/config/example.org-key.pem create mode 100644 test/config/example.org.pem create mode 100644 test/config/snell-http.conf create mode 100644 test/config/snell-tls.conf create mode 100644 test/config/snell.conf create mode 100644 test/config/trojan-grpc.json create mode 100644 test/config/trojan.json create mode 100644 test/config/vmess-aead.json create mode 100644 test/config/vmess-grpc.json create mode 100644 test/config/vmess-http.json create mode 100644 test/config/vmess-http2.json create mode 100644 test/config/vmess-tls.json create mode 100644 test/config/vmess-ws-tls.json create mode 100644 test/config/vmess-ws.json create mode 100644 test/config/vmess.json create mode 100644 test/dns_test.go create mode 100644 test/docker_test.go create mode 100644 test/go.mod create mode 100644 test/go.sum create mode 100644 test/snell_test.go create mode 100644 test/ss_test.go create mode 100644 test/trojan_test.go create mode 100644 test/util_test.go create mode 100644 test/vmess_test.go diff --git a/test/README.md b/test/README.md new file mode 100644 index 000000000..dec9999c2 --- /dev/null +++ b/test/README.md @@ -0,0 +1,49 @@ +## Clash testing suit + +### Protocol testing suit + +* TCP pingpong test +* UDP pingpong test +* TCP large data test +* UDP large data test + +### Protocols + +- [x] Shadowsocks + - [x] Normal + - [x] ObfsHTTP + - [x] ObfsTLS + - [x] ObfsV2rayPlugin +- [x] Vmess + - [x] Normal + - [x] AEAD + - [x] HTTP + - [x] HTTP2 + - [x] TLS + - [x] Websocket + - [x] Websocket TLS + - [x] gRPC +- [x] Trojan + - [x] Normal + - [x] gRPC +- [x] Snell + - [x] Normal + - [x] ObfsHTTP + - [x] ObfsTLS + +### Features + +- [ ] DNS + - [x] DNS Server + - [x] FakeIP + - [x] Host + +### Command + +Prerequisite + +* docker (support Linux and macOS) + +``` +$ go test -p 1 -v +``` diff --git a/test/clash_test.go b/test/clash_test.go new file mode 100644 index 000000000..e835b0fec --- /dev/null +++ b/test/clash_test.go @@ -0,0 +1,635 @@ +package main + +import ( + "context" + "crypto/md5" + "crypto/rand" + "errors" + "fmt" + "io" + "net" + "os" + "path/filepath" + "runtime" + "sync" + "testing" + "time" + + C "github.com/Dreamacro/clash/constant" + "github.com/Dreamacro/clash/hub/executor" + "github.com/Dreamacro/clash/transport/socks5" + + "github.com/docker/docker/api/types" + "github.com/docker/docker/client" + "github.com/docker/go-connections/nat" + "github.com/stretchr/testify/assert" +) + +const ( + ImageShadowsocks = "mritd/shadowsocks:latest" + ImageVmess = "v2fly/v2fly-core:latest" + ImageTrojan = "trojangfw/trojan:latest" + ImageSnell = "icpz/snell-server:latest" + ImageXray = "teddysun/xray:latest" +) + +var ( + waitTime = time.Second + localIP = net.ParseIP("127.0.0.1") + + defaultExposedPorts = nat.PortSet{ + "10002/tcp": struct{}{}, + "10002/udp": struct{}{}, + } + defaultPortBindings = nat.PortMap{ + "10002/tcp": []nat.PortBinding{ + {HostPort: "10002", HostIP: "0.0.0.0"}, + }, + "10002/udp": []nat.PortBinding{ + {HostPort: "10002", HostIP: "0.0.0.0"}, + }, + } +) + +func init() { + if runtime.GOOS == "darwin" { + isDarwin = true + } + + currentDir, err := os.Getwd() + if err != nil { + panic(err) + } + homeDir := filepath.Join(currentDir, "config") + C.SetHomeDir(homeDir) + + if isDarwin { + localIP, err = defaultRouteIP() + if err != nil { + panic(err) + } + } + + c, err := client.NewClientWithOpts(client.FromEnv) + if err != nil { + panic(err) + } + defer c.Close() + + list, err := c.ImageList(context.Background(), types.ImageListOptions{All: true}) + if err != nil { + panic(err) + } + + imageExist := func(image string) bool { + for _, item := range list { + for _, tag := range item.RepoTags { + if image == tag { + return true + } + } + } + return false + } + + images := []string{ + ImageShadowsocks, + ImageVmess, + ImageTrojan, + ImageSnell, + ImageXray, + } + + for _, image := range images { + if imageExist(image) { + continue + } + + imageStream, err := c.ImagePull(context.Background(), image, types.ImagePullOptions{}) + if err != nil { + panic(err) + } + + io.Copy(io.Discard, imageStream) + } +} + +var clean = ` +port: 0 +socks-port: 0 +mixed-port: 0 +redir-port: 0 +tproxy-port: 0 +dns: + enable: false +` + +func cleanup() { + parseAndApply(clean) +} + +func parseAndApply(cfgStr string) error { + cfg, err := executor.ParseWithBytes([]byte(cfgStr)) + if err != nil { + return err + } + + executor.ApplyConfig(cfg, true) + return nil +} + +func newPingPongPair() (chan []byte, chan []byte, func(t *testing.T) error) { + pingCh := make(chan []byte) + pongCh := make(chan []byte) + test := func(t *testing.T) error { + defer close(pingCh) + defer close(pongCh) + pingOpen := false + pongOpen := false + var recv []byte + + for { + if pingOpen && pongOpen { + break + } + + select { + case recv, pingOpen = <-pingCh: + assert.True(t, pingOpen) + assert.Equal(t, []byte("ping"), recv) + case recv, pongOpen = <-pongCh: + assert.True(t, pongOpen) + assert.Equal(t, []byte("pong"), recv) + case <-time.After(10 * time.Second): + return errors.New("timeout") + } + } + return nil + } + + return pingCh, pongCh, test +} + +func newLargeDataPair() (chan hashPair, chan hashPair, func(t *testing.T) error) { + pingCh := make(chan hashPair) + pongCh := make(chan hashPair) + test := func(t *testing.T) error { + defer close(pingCh) + defer close(pongCh) + pingOpen := false + pongOpen := false + var serverPair hashPair + var clientPair hashPair + + for { + if pingOpen && pongOpen { + break + } + + select { + case serverPair, pingOpen = <-pingCh: + assert.True(t, pingOpen) + case clientPair, pongOpen = <-pongCh: + assert.True(t, pongOpen) + case <-time.After(10 * time.Second): + return errors.New("timeout") + } + } + + assert.Equal(t, serverPair.recvHash, clientPair.sendHash) + assert.Equal(t, serverPair.sendHash, clientPair.recvHash) + + return nil + } + + return pingCh, pongCh, test +} + +func testPingPongWithSocksPort(t *testing.T, port int) { + pingCh, pongCh, test := newPingPongPair() + go func() { + l, err := net.Listen("tcp", ":10001") + if err != nil { + assert.FailNow(t, err.Error()) + } + + c, err := l.Accept() + if err != nil { + assert.FailNow(t, err.Error()) + } + + buf := make([]byte, 4) + if _, err := io.ReadFull(c, buf); err != nil { + assert.FailNow(t, err.Error()) + } + + pingCh <- buf + if _, err := c.Write([]byte("pong")); err != nil { + assert.FailNow(t, err.Error()) + } + l.Close() + }() + + go func() { + c, err := net.Dial("tcp", fmt.Sprintf("127.0.0.1:%d", port)) + if err != nil { + assert.FailNow(t, err.Error()) + } + + if _, err := socks5.ClientHandshake(c, socks5.ParseAddr("127.0.0.1:10001"), socks5.CmdConnect, nil); err != nil { + assert.FailNow(t, err.Error()) + } + + if _, err := c.Write([]byte("ping")); err != nil { + assert.FailNow(t, err.Error()) + } + + buf := make([]byte, 4) + if _, err := io.ReadFull(c, buf); err != nil { + assert.FailNow(t, err.Error()) + } + + pongCh <- buf + c.Close() + }() + + test(t) +} + +func testPingPongWithConn(t *testing.T, c net.Conn) error { + l, err := net.Listen("tcp", ":10001") + if err != nil { + return err + } + defer l.Close() + + pingCh, pongCh, test := newPingPongPair() + go func() { + c, err := l.Accept() + if err != nil { + return + } + + buf := make([]byte, 4) + if _, err := io.ReadFull(c, buf); err != nil { + return + } + + pingCh <- buf + if _, err := c.Write([]byte("pong")); err != nil { + return + } + }() + + go func() { + if _, err := c.Write([]byte("ping")); err != nil { + return + } + + buf := make([]byte, 4) + if _, err := io.ReadFull(c, buf); err != nil { + return + } + + pongCh <- buf + }() + + return test(t) +} + +func testPingPongWithPacketConn(t *testing.T, pc net.PacketConn) error { + l, err := net.ListenPacket("udp", ":10001") + if err != nil { + return err + } + defer l.Close() + + rAddr := &net.UDPAddr{IP: localIP, Port: 10001} + + pingCh, pongCh, test := newPingPongPair() + go func() { + buf := make([]byte, 1024) + n, rAddr, err := l.ReadFrom(buf) + if err != nil { + return + } + + pingCh <- buf[:n] + if _, err := l.WriteTo([]byte("pong"), rAddr); err != nil { + return + } + }() + + go func() { + if _, err := pc.WriteTo([]byte("ping"), rAddr); err != nil { + return + } + + buf := make([]byte, 1024) + n, _, err := pc.ReadFrom(buf) + if err != nil { + return + } + + pongCh <- buf[:n] + }() + + return test(t) +} + +type hashPair struct { + sendHash map[int][]byte + recvHash map[int][]byte +} + +func testLargeDataWithConn(t *testing.T, c net.Conn) error { + l, err := net.Listen("tcp", ":10001") + if err != nil { + return err + } + defer l.Close() + + times := 100 + chunkSize := int64(64 * 1024) + + pingCh, pongCh, test := newLargeDataPair() + writeRandData := func(conn net.Conn) (map[int][]byte, error) { + buf := make([]byte, chunkSize) + hashMap := map[int][]byte{} + for i := 0; i < times; i++ { + if _, err := rand.Read(buf[1:]); err != nil { + return nil, err + } + buf[0] = byte(i) + + hash := md5.Sum(buf) + hashMap[i] = hash[:] + + if _, err := conn.Write(buf); err != nil { + return nil, err + } + } + + return hashMap, nil + } + + go func() { + c, err := l.Accept() + if err != nil { + return + } + + hashMap := map[int][]byte{} + buf := make([]byte, chunkSize) + + for i := 0; i < times; i++ { + _, err := io.ReadFull(c, buf) + if err != nil { + t.Log(err.Error()) + return + } + + hash := md5.Sum(buf) + hashMap[int(buf[0])] = hash[:] + } + + sendHash, err := writeRandData(c) + if err != nil { + t.Log(err.Error()) + return + } + + pingCh <- hashPair{ + sendHash: sendHash, + recvHash: hashMap, + } + }() + + go func() { + sendHash, err := writeRandData(c) + if err != nil { + t.Log(err.Error()) + return + } + + hashMap := map[int][]byte{} + buf := make([]byte, chunkSize) + + for i := 0; i < times; i++ { + _, err := io.ReadFull(c, buf) + if err != nil { + t.Log(err.Error()) + return + } + + hash := md5.Sum(buf) + hashMap[int(buf[0])] = hash[:] + } + + pongCh <- hashPair{ + sendHash: sendHash, + recvHash: hashMap, + } + }() + + return test(t) +} + +func testLargeDataWithPacketConn(t *testing.T, pc net.PacketConn) error { + l, err := net.ListenPacket("udp", ":10001") + if err != nil { + return err + } + defer l.Close() + + rAddr := &net.UDPAddr{IP: localIP, Port: 10001} + + times := 50 + chunkSize := int64(1024) + + pingCh, pongCh, test := newLargeDataPair() + writeRandData := func(pc net.PacketConn, addr net.Addr) (map[int][]byte, error) { + hashMap := map[int][]byte{} + mux := sync.Mutex{} + for i := 0; i < times; i++ { + go func(idx int) { + buf := make([]byte, chunkSize) + if _, err := rand.Read(buf[1:]); err != nil { + t.Log(err.Error()) + return + } + buf[0] = byte(idx) + + hash := md5.Sum(buf) + mux.Lock() + hashMap[idx] = hash[:] + mux.Unlock() + + if _, err := pc.WriteTo(buf, addr); err != nil { + t.Log(err.Error()) + return + } + }(i) + } + + return hashMap, nil + } + + go func() { + var rAddr net.Addr + hashMap := map[int][]byte{} + buf := make([]byte, 64*1024) + + for i := 0; i < times; i++ { + _, rAddr, err = l.ReadFrom(buf) + if err != nil { + t.Log(err.Error()) + return + } + + hash := md5.Sum(buf[:chunkSize]) + hashMap[int(buf[0])] = hash[:] + } + + sendHash, err := writeRandData(l, rAddr) + if err != nil { + t.Log(err.Error()) + return + } + + pingCh <- hashPair{ + sendHash: sendHash, + recvHash: hashMap, + } + }() + + go func() { + sendHash, err := writeRandData(pc, rAddr) + if err != nil { + t.Log(err.Error()) + return + } + + hashMap := map[int][]byte{} + buf := make([]byte, 64*1024) + + for i := 0; i < times; i++ { + _, _, err := pc.ReadFrom(buf) + if err != nil { + t.Log(err.Error()) + return + } + + hash := md5.Sum(buf[:chunkSize]) + hashMap[int(buf[0])] = hash[:] + } + + pongCh <- hashPair{ + sendHash: sendHash, + recvHash: hashMap, + } + }() + + return test(t) +} + +func testPacketConnTimeout(t *testing.T, pc net.PacketConn) error { + err := pc.SetReadDeadline(time.Now().Add(time.Millisecond * 300)) + assert.NoError(t, err) + + errCh := make(chan error, 1) + go func() { + buf := make([]byte, 1024) + _, _, err := pc.ReadFrom(buf) + errCh <- err + }() + + select { + case <-errCh: + return nil + case <-time.After(time.Second * 10): + return errors.New("timeout") + } +} + +func testSuit(t *testing.T, proxy C.ProxyAdapter) { + conn, err := proxy.DialContext(context.Background(), &C.Metadata{ + Host: localIP.String(), + DstPort: "10001", + AddrType: socks5.AtypDomainName, + }) + if err != nil { + assert.FailNow(t, err.Error()) + } + defer conn.Close() + assert.NoError(t, testPingPongWithConn(t, conn)) + + conn, err = proxy.DialContext(context.Background(), &C.Metadata{ + Host: localIP.String(), + DstPort: "10001", + AddrType: socks5.AtypDomainName, + }) + if err != nil { + assert.FailNow(t, err.Error()) + } + defer conn.Close() + assert.NoError(t, testLargeDataWithConn(t, conn)) + + if !proxy.SupportUDP() { + return + } + + pc, err := proxy.DialUDP(&C.Metadata{ + NetWork: C.UDP, + DstIP: localIP, + DstPort: "10001", + AddrType: socks5.AtypIPv4, + }) + if err != nil { + assert.FailNow(t, err.Error()) + } + defer pc.Close() + + assert.NoError(t, testPingPongWithPacketConn(t, pc)) + + pc, err = proxy.DialUDP(&C.Metadata{ + NetWork: C.UDP, + DstIP: localIP, + DstPort: "10001", + AddrType: socks5.AtypIPv4, + }) + if err != nil { + assert.FailNow(t, err.Error()) + } + defer pc.Close() + + assert.NoError(t, testLargeDataWithPacketConn(t, pc)) + + pc, err = proxy.DialUDP(&C.Metadata{ + NetWork: C.UDP, + DstIP: localIP, + DstPort: "10001", + AddrType: socks5.AtypIPv4, + }) + if err != nil { + assert.FailNow(t, err.Error()) + } + defer pc.Close() + + assert.NoError(t, testPacketConnTimeout(t, pc)) +} + +func TestClash_Basic(t *testing.T) { + basic := ` +mixed-port: 10000 +log-level: silent +` + + if err := parseAndApply(basic); err != nil { + assert.FailNow(t, err.Error()) + } + defer cleanup() + + time.Sleep(waitTime) + testPingPongWithSocksPort(t, 10000) +} diff --git a/test/config/example.org-key.pem b/test/config/example.org-key.pem new file mode 100644 index 000000000..dbe9a3db3 --- /dev/null +++ b/test/config/example.org-key.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDQ+c++LkDTdaw5 +5spCu9MWMcvVdrYBZZ5qZy7DskphSUSQp25cIu34GJXVPNxtbWx1CQCmdLlwqXvo +PfUt5/pz9qsfhdAbzFduZQgGd7GTQOTJBDrAhm2+iVsQyGHHhF68muN+SgT+AtRE +sJyZoHNYtjjWEIHQ++FHEDqwUVnj6Ut99LHlyfCjOZ5+WyBiKCjyMNots/gDep7R +i4X2kMTqNMIIqPUcAaP5EQk41bJbFhKe915qN9b1dRISKFKmiWeOsxgTB/O/EaL5 +LsBYwZ/BiIMDk30aZvzRJeloasIR3z4hrKQqBfB0lfeIdiPpJIs5rXJQEiWH89ge +gplsLbfrAgMBAAECggEBAKpMGaZzDPMF/v8Ee6lcZM2+cMyZPALxa+JsCakCvyh+ +y7hSKVY+RM0cQ+YM/djTBkJtvrDniEMuasI803PAitI7nwJGSuyMXmehP6P9oKFO +jeLeZn6ETiSqzKJlmYE89vMeCevdqCnT5mW/wy5Smg0eGj0gIJpM2S3PJPSQpv9Z +ots0JXkwooJcpGWzlwPkjSouY2gDbE4Coi+jmYLNjA1k5RbggcutnUCZZkJ6yMNv +H52VjnkffpAFHRouK/YgF+5nbMyyw5YTLOyTWBq7qfBMsXynkWLU73GC/xDZa3yG +o/Ph2knXCjgLmCRessTOObdOXedjnGWIjiqF8fVboDECgYEA6x5CteYiwthDBULZ +CG5nE9VKkRHJYdArm+VjmGbzK51tKli112avmU4r3ol907+mEa4tWLkPqdZrrL49 +aHltuHizZJixJcw0rcI302ot/Ov0gkF9V55gnAQS/Kemvx9FHWm5NHdYvbObzj33 +bYRLJBtJWzYg9M8Bw9ZrUnegc/MCgYEA44kq5OSYCbyu3eaX8XHTtFhuQHNFjwl7 +Xk/Oel6PVZzmt+oOlDHnOfGSB/KpR3YXxFRngiiPZzbrOwFyPGe7HIfg03HAXiJh +ivEfrPHbQqQUI/4b44GpDy6bhNtz777ivFGYEt21vpwd89rFiye+RkqF8eL/evxO +pUayDZYvwikCgYEA07wFoZ/lkAiHmpZPsxsRcrfzFd+pto9splEWtumHdbCo3ajT +4W5VFr9iHF8/VFDT8jokFjFaXL1/bCpKTOqFl8oC68XiSkKy8gPkmFyXm5y2LhNi +GGTFZdr5alRkgttbN5i9M/WCkhvMZRhC2Xp43MRB9IUzeqNtWHqhXbvjYGcCgYEA +vTMOztviLJ6PjYa0K5lp31l0+/SeD21j/y0/VPOSHi9kjeN7EfFZAw6DTkaSShDB +fIhutYVCkSHSgfMW6XGb3gKCiW/Z9KyEDYOowicuGgDTmoYu7IOhbzVjLhtJET7Z +zJvQZ0eiW4f3RBFTF/4JMuu+6z7FD6ADSV06qx+KQNkCgYBw26iQxmT5e/4kVv8X +DzBJ1HuliKBnnzZA1YRjB4H8F6Yrq+9qur1Lurez4YlbkGV8yPFt+Iu82ViUWL28 +9T7Jgp3TOpf8qOqsWFv8HldpEZbE0Tcib4x6s+zOg/aw0ac/xOPY1sCVFB81VODP +XCar+uxMBXI1zbXqd9QdEwy4Ig== +-----END PRIVATE KEY----- diff --git a/test/config/example.org.pem b/test/config/example.org.pem new file mode 100644 index 000000000..9b99259a3 --- /dev/null +++ b/test/config/example.org.pem @@ -0,0 +1,25 @@ +-----BEGIN CERTIFICATE----- +MIIESzCCArOgAwIBAgIQIi5xRZvFZaSweWU9Y5mExjANBgkqhkiG9w0BAQsFADCB +hzEeMBwGA1UEChMVbWtjZXJ0IGRldmVsb3BtZW50IENBMS4wLAYDVQQLDCVkcmVh +bWFjcm9ARHJlYW1hY3JvLmxvY2FsIChEcmVhbWFjcm8pMTUwMwYDVQQDDCxta2Nl +cnQgZHJlYW1hY3JvQERyZWFtYWNyby5sb2NhbCAoRHJlYW1hY3JvKTAeFw0yMTAz +MTcxNDQwMzZaFw0yMzA2MTcxNDQwMzZaMFkxJzAlBgNVBAoTHm1rY2VydCBkZXZl +bG9wbWVudCBjZXJ0aWZpY2F0ZTEuMCwGA1UECwwlZHJlYW1hY3JvQERyZWFtYWNy +by5sb2NhbCAoRHJlYW1hY3JvKTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC +ggEBAND5z74uQNN1rDnmykK70xYxy9V2tgFlnmpnLsOySmFJRJCnblwi7fgYldU8 +3G1tbHUJAKZ0uXCpe+g99S3n+nP2qx+F0BvMV25lCAZ3sZNA5MkEOsCGbb6JWxDI +YceEXrya435KBP4C1ESwnJmgc1i2ONYQgdD74UcQOrBRWePpS330seXJ8KM5nn5b +IGIoKPIw2i2z+AN6ntGLhfaQxOo0wgio9RwBo/kRCTjVslsWEp73Xmo31vV1EhIo +UqaJZ46zGBMH878RovkuwFjBn8GIgwOTfRpm/NEl6WhqwhHfPiGspCoF8HSV94h2 +I+kkizmtclASJYfz2B6CmWwtt+sCAwEAAaNgMF4wDgYDVR0PAQH/BAQDAgWgMBMG +A1UdJQQMMAoGCCsGAQUFBwMBMB8GA1UdIwQYMBaAFO800LQ6Pa85RH4EbMmFH6ln +F150MBYGA1UdEQQPMA2CC2V4YW1wbGUub3JnMA0GCSqGSIb3DQEBCwUAA4IBgQAP +TsF53h7bvJcUXT3Y9yZ2vnW6xr9r92tNnM1Gfo3D2Yyn9oLf2YrfJng6WZ04Fhqa +Wh0HOvE0n6yPNpm/Q7mh64DrgolZ8Ce5H4RTJDAabHU9XhEzfGSVtzRSFsz+szu1 +Y30IV+08DxxqMmNPspYdpAET2Lwyk2WhnARGiGw11CRkQCEkVEe6d702vS9UGBUz +Du6lmCYCm0SbFrZ0CGgmHSHoTcCtf3EjVam7dPg3yWiPbWjvhXxgip6hz9sCqkhG +WA5f+fPgSZ1I9U4i+uYnqjfrzwgC08RwUYordm15F6gPvXw+KVwDO8yUYQoEH0b6 +AFJtbzoAXDysvBC6kWYFFOr62EaisaEkELTS/NrPD9ux1eKbxcxHCwEtVjgC0CL6 +gAxEAQ+9maJMbrAFhsOBbGGFC+mMCGg4eEyx6+iMB0oQe0W7QFeRUAFi7Ptc/ocS +tZ9lbrfX1/wrcTTWIYWE+xH6oeb4fhs29kxjHcf2l+tQzmpl0aP3Z/bMW4BSB+w= +-----END CERTIFICATE----- diff --git a/test/config/snell-http.conf b/test/config/snell-http.conf new file mode 100644 index 000000000..f5130dc10 --- /dev/null +++ b/test/config/snell-http.conf @@ -0,0 +1,4 @@ +[snell-server] +listen = 0.0.0.0:10002 +psk = password +obfs = http diff --git a/test/config/snell-tls.conf b/test/config/snell-tls.conf new file mode 100644 index 000000000..bf8b51396 --- /dev/null +++ b/test/config/snell-tls.conf @@ -0,0 +1,4 @@ +[snell-server] +listen = 0.0.0.0:10002 +psk = password +obfs = tls diff --git a/test/config/snell.conf b/test/config/snell.conf new file mode 100644 index 000000000..40266391b --- /dev/null +++ b/test/config/snell.conf @@ -0,0 +1,3 @@ +[snell-server] +listen = 0.0.0.0:10002 +psk = password diff --git a/test/config/trojan-grpc.json b/test/config/trojan-grpc.json new file mode 100644 index 000000000..eb0dcc990 --- /dev/null +++ b/test/config/trojan-grpc.json @@ -0,0 +1,40 @@ +{ + "inbounds": [ + { + "port": 10002, + "listen": "0.0.0.0", + "protocol": "trojan", + "settings": { + "clients": [ + { + "password": "example", + "email": "grpc@example.com" + } + ] + }, + "streamSettings": { + "network": "grpc", + "security": "tls", + "tlsSettings": { + "certificates": [ + { + "certificateFile": "/etc/ssl/v2ray/fullchain.pem", + "keyFile": "/etc/ssl/v2ray/privkey.pem" + } + ] + }, + "grpcSettings": { + "serviceName": "example" + } + } + } + ], + "outbounds": [ + { + "protocol": "freedom" + } + ], + "log": { + "loglevel": "debug" + } +} \ No newline at end of file diff --git a/test/config/trojan.json b/test/config/trojan.json new file mode 100644 index 000000000..18e33a980 --- /dev/null +++ b/test/config/trojan.json @@ -0,0 +1,40 @@ +{ + "run_type": "server", + "local_addr": "0.0.0.0", + "local_port": 10002, + "password": [ + "password" + ], + "log_level": 1, + "ssl": { + "cert": "/path/to/certificate.crt", + "key": "/path/to/private.key", + "key_password": "", + "cipher": "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384", + "cipher_tls13": "TLS_AES_128_GCM_SHA256:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_256_GCM_SHA384", + "prefer_server_cipher": true, + "alpn": [ + "http/1.1" + ], + "alpn_port_override": { + "h2": 81 + }, + "reuse_session": true, + "session_ticket": false, + "session_timeout": 600, + "plain_http_response": "", + "curves": "", + "dhparam": "" + }, + "tcp": { + "prefer_ipv4": false, + "no_delay": true, + "keep_alive": true, + "reuse_port": false, + "fast_open": false, + "fast_open_qlen": 20 + }, + "mysql": { + "enabled": false + } +} \ No newline at end of file diff --git a/test/config/vmess-aead.json b/test/config/vmess-aead.json new file mode 100644 index 000000000..27bc4757f --- /dev/null +++ b/test/config/vmess-aead.json @@ -0,0 +1,28 @@ +{ + "inbounds": [ + { + "port": 10002, + "listen": "0.0.0.0", + "protocol": "vmess", + "settings": { + "clients": [ + { + "id": "b831381d-6324-4d53-ad4f-8cda48b30811", + "alterId": 0 + } + ] + }, + "streamSettings": { + "network": "tcp" + } + } + ], + "outbounds": [ + { + "protocol": "freedom" + } + ], + "log": { + "loglevel": "debug" + } +} \ No newline at end of file diff --git a/test/config/vmess-grpc.json b/test/config/vmess-grpc.json new file mode 100644 index 000000000..1b3a8e9a7 --- /dev/null +++ b/test/config/vmess-grpc.json @@ -0,0 +1,40 @@ +{ + "inbounds": [ + { + "port": 10002, + "listen": "0.0.0.0", + "protocol": "vmess", + "settings": { + "clients": [ + { + "id": "b831381d-6324-4d53-ad4f-8cda48b30811", + "alterId": 32 + } + ] + }, + "streamSettings": { + "network": "grpc", + "security": "tls", + "tlsSettings": { + "certificates": [ + { + "certificateFile": "/etc/ssl/v2ray/fullchain.pem", + "keyFile": "/etc/ssl/v2ray/privkey.pem" + } + ] + }, + "grpcSettings": { + "serviceName": "example" + } + } + } + ], + "outbounds": [ + { + "protocol": "freedom" + } + ], + "log": { + "loglevel": "debug" + } +} \ No newline at end of file diff --git a/test/config/vmess-http.json b/test/config/vmess-http.json new file mode 100644 index 000000000..aa6c6c8ed --- /dev/null +++ b/test/config/vmess-http.json @@ -0,0 +1,55 @@ +{ + "inbounds": [ + { + "port": 10002, + "listen": "0.0.0.0", + "protocol": "vmess", + "settings": { + "clients": [ + { + "id": "b831381d-6324-4d53-ad4f-8cda48b30811", + "alterId": 32 + } + ] + }, + "streamSettings": { + "network": "tcp", + "tcpSettings": { + "header": { + "type": "http", + "response": { + "version": "1.1", + "status": "200", + "reason": "OK", + "headers": { + "Content-Type": [ + "application/octet-stream", + "video/mpeg", + "application/x-msdownload", + "text/html", + "application/x-shockwave-flash" + ], + "Transfer-Encoding": [ + "chunked" + ], + "Connection": [ + "keep-alive" + ], + "Pragma": "no-cache" + } + } + } + }, + "security": "none" + } + } + ], + "outbounds": [ + { + "protocol": "freedom" + } + ], + "log": { + "loglevel": "debug" + } +} \ No newline at end of file diff --git a/test/config/vmess-http2.json b/test/config/vmess-http2.json new file mode 100644 index 000000000..488737311 --- /dev/null +++ b/test/config/vmess-http2.json @@ -0,0 +1,43 @@ +{ + "inbounds": [ + { + "port": 10002, + "listen": "0.0.0.0", + "protocol": "vmess", + "settings": { + "clients": [ + { + "id": "b831381d-6324-4d53-ad4f-8cda48b30811", + "alterId": 32 + } + ] + }, + "streamSettings": { + "network": "http", + "security": "tls", + "tlsSettings": { + "certificates": [ + { + "certificateFile": "/etc/ssl/v2ray/fullchain.pem", + "keyFile": "/etc/ssl/v2ray/privkey.pem" + } + ] + }, + "httpSettings": { + "host": [ + "example.org" + ], + "path": "/test" + } + } + } + ], + "outbounds": [ + { + "protocol": "freedom" + } + ], + "log": { + "loglevel": "debug" + } +} \ No newline at end of file diff --git a/test/config/vmess-tls.json b/test/config/vmess-tls.json new file mode 100644 index 000000000..ae2fa489b --- /dev/null +++ b/test/config/vmess-tls.json @@ -0,0 +1,37 @@ +{ + "inbounds": [ + { + "port": 10002, + "listen": "0.0.0.0", + "protocol": "vmess", + "settings": { + "clients": [ + { + "id": "b831381d-6324-4d53-ad4f-8cda48b30811", + "alterId": 32 + } + ] + }, + "streamSettings": { + "network": "tcp", + "security": "tls", + "tlsSettings": { + "certificates": [ + { + "certificateFile": "/etc/ssl/v2ray/fullchain.pem", + "keyFile": "/etc/ssl/v2ray/privkey.pem" + } + ] + } + } + } + ], + "outbounds": [ + { + "protocol": "freedom" + } + ], + "log": { + "loglevel": "debug" + } +} \ No newline at end of file diff --git a/test/config/vmess-ws-tls.json b/test/config/vmess-ws-tls.json new file mode 100644 index 000000000..dda1e0c96 --- /dev/null +++ b/test/config/vmess-ws-tls.json @@ -0,0 +1,34 @@ +{ + "inbounds": [ + { + "port": 10002, + "listen": "0.0.0.0", + "protocol": "vmess", + "settings": { + "clients": [ + { + "id": "b831381d-6324-4d53-ad4f-8cda48b30811", + "alterId": 32 + } + ] + }, + "streamSettings": { + "network": "ws", + "security": "tls", + "tlsSettings": { + "certificates": [ + { + "certificateFile": "/etc/ssl/v2ray/fullchain.pem", + "keyFile": "/etc/ssl/v2ray/privkey.pem" + } + ] + } + } + } + ], + "outbounds": [ + { + "protocol": "freedom" + } + ] +} \ No newline at end of file diff --git a/test/config/vmess-ws.json b/test/config/vmess-ws.json new file mode 100644 index 000000000..94ace4e32 --- /dev/null +++ b/test/config/vmess-ws.json @@ -0,0 +1,26 @@ +{ + "inbounds": [ + { + "port": 10002, + "listen": "0.0.0.0", + "protocol": "vmess", + "settings": { + "clients": [ + { + "id": "b831381d-6324-4d53-ad4f-8cda48b30811", + "alterId": 32 + } + ] + }, + "streamSettings": { + "network": "ws", + "security": "none" + } + } + ], + "outbounds": [ + { + "protocol": "freedom" + } + ] +} \ No newline at end of file diff --git a/test/config/vmess.json b/test/config/vmess.json new file mode 100644 index 000000000..bcf53cd8c --- /dev/null +++ b/test/config/vmess.json @@ -0,0 +1,28 @@ +{ + "inbounds": [ + { + "port": 10002, + "listen": "0.0.0.0", + "protocol": "vmess", + "settings": { + "clients": [ + { + "id": "b831381d-6324-4d53-ad4f-8cda48b30811", + "alterId": 32 + } + ] + }, + "streamSettings": { + "network": "tcp" + } + } + ], + "outbounds": [ + { + "protocol": "freedom" + } + ], + "log": { + "loglevel": "debug" + } +} \ No newline at end of file diff --git a/test/dns_test.go b/test/dns_test.go new file mode 100644 index 000000000..dd07bda84 --- /dev/null +++ b/test/dns_test.go @@ -0,0 +1,103 @@ +package main + +import ( + "testing" + "time" + + "github.com/miekg/dns" + "github.com/stretchr/testify/assert" +) + +func exchange(address, domain string, tp uint16) ([]dns.RR, error) { + client := dns.Client{} + query := &dns.Msg{} + query.SetQuestion(dns.Fqdn(domain), tp) + + r, _, err := client.Exchange(query, address) + if err != nil { + return nil, err + } + return r.Answer, nil +} + +func TestClash_DNS(t *testing.T) { + basic := ` +log-level: silent +dns: + enable: true + listen: 0.0.0.0:8553 + nameserver: + - 119.29.29.29 +` + + if err := parseAndApply(basic); err != nil { + assert.FailNow(t, err.Error()) + } + defer cleanup() + + time.Sleep(waitTime) + + rr, err := exchange("127.0.0.1:8553", "1.1.1.1.nip.io", dns.TypeA) + assert.NoError(t, err) + if !assert.NotEmpty(t, rr) { + assert.FailNow(t, "record empty") + } + + record := rr[0].(*dns.A) + assert.Equal(t, record.A.String(), "1.1.1.1") + + rr, err = exchange("127.0.0.1:8553", "2606-4700-4700--1111.sslip.io", dns.TypeAAAA) + assert.NoError(t, err) + assert.Empty(t, rr) +} + +func TestClash_DNSHostAndFakeIP(t *testing.T) { + basic := ` +log-level: silent +hosts: + foo.clash.dev: 1.1.1.1 +dns: + enable: true + listen: 0.0.0.0:8553 + ipv6: true + enhanced-mode: fake-ip + fake-ip-range: 198.18.0.1/16 + fake-ip-filter: + - .sslip.io + nameserver: + - 119.29.29.29 +` + + if err := parseAndApply(basic); err != nil { + assert.FailNow(t, err.Error()) + } + defer cleanup() + + time.Sleep(waitTime) + + type domainPair struct { + domain string + ip string + } + + list := []domainPair{ + {"foo.org", "198.18.0.2"}, + {"bar.org", "198.18.0.3"}, + {"foo.org", "198.18.0.2"}, + {"foo.clash.dev", "1.1.1.1"}, + } + + for _, pair := range list { + rr, err := exchange("127.0.0.1:8553", pair.domain, dns.TypeA) + assert.NoError(t, err) + assert.NotEmpty(t, rr) + + record := rr[0].(*dns.A) + assert.Equal(t, record.A.String(), pair.ip) + } + + rr, err := exchange("127.0.0.1:8553", "2606-4700-4700--1111.sslip.io", dns.TypeAAAA) + assert.NoError(t, err) + assert.NotEmpty(t, rr) + assert.Equal(t, rr[0].(*dns.AAAA).AAAA.String(), "2606:4700:4700::1111") +} diff --git a/test/docker_test.go b/test/docker_test.go new file mode 100644 index 000000000..ce4c2de47 --- /dev/null +++ b/test/docker_test.go @@ -0,0 +1,45 @@ +package main + +import ( + "context" + + "github.com/docker/docker/api/types" + "github.com/docker/docker/api/types/container" + "github.com/docker/docker/client" +) + +var isDarwin = false + +func startContainer(cfg *container.Config, hostCfg *container.HostConfig, name string) (string, error) { + c, err := client.NewClientWithOpts(client.FromEnv) + if err != nil { + return "", err + } + defer c.Close() + + if !isDarwin { + hostCfg.NetworkMode = "host" + } + + container, err := c.ContainerCreate(context.Background(), cfg, hostCfg, nil, nil, name) + if err != nil { + return "", err + } + + if err = c.ContainerStart(context.Background(), container.ID, types.ContainerStartOptions{}); err != nil { + return "", err + } + + return container.ID, nil +} + +func cleanContainer(id string) error { + c, err := client.NewClientWithOpts(client.FromEnv) + if err != nil { + return err + } + defer c.Close() + + removeOpts := types.ContainerRemoveOptions{Force: true} + return c.ContainerRemove(context.Background(), id, removeOpts) +} diff --git a/test/go.mod b/test/go.mod new file mode 100644 index 000000000..1a5cb6763 --- /dev/null +++ b/test/go.mod @@ -0,0 +1,26 @@ +module clash-test + +go 1.16 + +require ( + github.com/Dreamacro/clash v1.6.1-0.20210516120541-06fdd3abe0ab + github.com/Microsoft/go-winio v0.4.16 // indirect + github.com/containerd/containerd v1.4.4 // indirect + github.com/docker/distribution v2.7.1+incompatible // indirect + github.com/docker/docker v20.10.6+incompatible + github.com/docker/go-connections v0.4.0 + github.com/docker/go-units v0.4.0 // indirect + github.com/gogo/protobuf v1.3.2 // indirect + github.com/google/go-cmp v0.5.5 // indirect + github.com/gorilla/mux v1.8.0 // indirect + github.com/miekg/dns v1.1.42 + github.com/moby/term v0.0.0-20201216013528-df9cb8a40635 // indirect + github.com/morikuni/aec v1.0.0 // indirect + github.com/opencontainers/go-digest v1.0.0 // indirect + github.com/opencontainers/image-spec v1.0.1 // indirect + github.com/stretchr/testify v1.7.0 + golang.org/x/net v0.0.0-20210510120150-4163338589ed + golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba // indirect + google.golang.org/grpc v1.36.0 // indirect + gotest.tools/v3 v3.0.3 // indirect +) diff --git a/test/go.sum b/test/go.sum new file mode 100644 index 000000000..2a641fb70 --- /dev/null +++ b/test/go.sum @@ -0,0 +1,202 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 h1:w+iIsaOQNcT7OZ575w+acHgRric5iCyQh+xv+KJ4HB8= +github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/Dreamacro/clash v1.6.1-0.20210516120541-06fdd3abe0ab h1:hfjxpY+73Xo6k+JHMkLlaOR3Tw5hG/YZxmDFyV9Y6sY= +github.com/Dreamacro/clash v1.6.1-0.20210516120541-06fdd3abe0ab/go.mod h1:Pz9GwWR244jrMSInQ0KUL02jMCe5xIJ+pkgzuNIy2Iw= +github.com/Dreamacro/go-shadowsocks2 v0.1.7 h1:8CtbE1HoPPMfrQZGXmlluq6dO2lL31W6WRRE8fabc4Q= +github.com/Dreamacro/go-shadowsocks2 v0.1.7/go.mod h1:8p5G4cAj5ZlXwUR+Ww63gfSikr8kvw8uw3TDwLAJpUc= +github.com/Microsoft/go-winio v0.4.16 h1:FtSW/jqD+l4ba5iPBj9CODVtgfYAD8w2wS923g/cFDk= +github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/containerd/containerd v1.4.4 h1:rtRG4N6Ct7GNssATwgpvMGfnjnwfjnu/Zs9W3Ikzq+M= +github.com/containerd/containerd v1.4.4/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/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/docker v20.10.6+incompatible h1:oXI3Vas8TI8Eu/EjH4srKHJBVqraSzJybhxY7Om9faQ= +github.com/docker/docker v20.10.6+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/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= +github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw= +github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/go-chi/chi/v5 v5.0.3/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= +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/gofrs/uuid v4.0.0+incompatible h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPhW6m+TnJw= +github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= +github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= +github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= +github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/miekg/dns v1.1.42 h1:gWGe42RGaIqXQZ+r3WUGEKBEtvPHY2SXo4dqixDNxuY= +github.com/miekg/dns v1.1.42/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4= +github.com/moby/term v0.0.0-20201216013528-df9cb8a40635 h1:rzf0wL0CHVc8CEsgyygG0Mn9CNCCPZqOPaz8RiiHYQk= +github.com/moby/term v0.0.0-20201216013528-df9cb8a40635/go.mod h1:FBS0z0QWA44HXygs7VXDUOGoN/1TV3RuWkLO04am3wc= +github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= +github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= +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/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/oschwald/geoip2-golang v1.5.0 h1:igg2yQIrrcRccB1ytFXqBfOHCjXWIoMv85lVJ1ONZzw= +github.com/oschwald/geoip2-golang v1.5.0/go.mod h1:xdvYt5xQzB8ORWFqPnqMwZpCpgNagttWdoZLlJQzg7s= +github.com/oschwald/maxminddb-golang v1.8.0 h1:Uh/DSnGoxsyp/KYbY1AuP0tYEwfs0sCph9p/UMXK/Hk= +github.com/oschwald/maxminddb-golang v1.8.0/go.mod h1:RXZtst0N6+FY/3qCNmZMBApR19cdQj43/NM9VkrNAis= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= +github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= +go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +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-20210506145944-38f3c27a63bf h1:B2n+Zi5QeYRDAEodEu72OS36gmTWjgpXr2+cWcBW90o= +golang.org/x/crypto v0.0.0-20210506145944-38f3c27a63bf/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +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/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/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-20210508051633-16afe75a6701/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210510120150-4163338589ed h1:p9UgmWI9wKpfYmgaV/IZKGdXc5qEK45tDwwwDyjS26I= +golang.org/x/net v0.0.0-20210510120150-4163338589ed/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191224085550-c709ea063b76/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200831180312-196b9ba8737a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210507161434-a76c4d0a0096 h1:5PbJGn5Sp3GEUjJ61aYbUP6RIo3Z3r2E4Tv9y2z8UHo= +golang.org/x/sys v0.0.0-20210507161434-a76c4d0a0096/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba h1:O8mE0/t419eoIwhTFpKVkHiTs/Igowgfkj25AcZrtiE= +golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 h1:+kGHl1aib/qcwaRi1CbqBZ1rk19r85MNUf8HaBghugY= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.36.0 h1:o1bcQ6imQMIOpdrO3SWf2z5RV72WbDwdXuK0MDlc8As= +google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= +gotest.tools/v3 v3.0.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0= +gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/test/snell_test.go b/test/snell_test.go new file mode 100644 index 000000000..0d9e059a0 --- /dev/null +++ b/test/snell_test.go @@ -0,0 +1,121 @@ +package main + +import ( + "fmt" + "testing" + "time" + + "github.com/Dreamacro/clash/adapters/outbound" + C "github.com/Dreamacro/clash/constant" + + "github.com/docker/docker/api/types/container" + "github.com/stretchr/testify/assert" +) + +func TestClash_SnellObfsHTTP(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-http.conf"))}, + } + + id, err := startContainer(cfg, hostCfg, "snell-http") + 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", + ObfsOpts: map[string]interface{}{ + "mode": "http", + }, + }) + if err != nil { + assert.FailNow(t, err.Error()) + } + + time.Sleep(waitTime) + testSuit(t, proxy) +} + +func TestClash_SnellObfsTLS(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-tls.conf"))}, + } + + id, err := startContainer(cfg, hostCfg, "snell-tls") + 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", + ObfsOpts: map[string]interface{}{ + "mode": "tls", + }, + }) + if err != nil { + assert.FailNow(t, err.Error()) + } + + time.Sleep(waitTime) + testSuit(t, proxy) +} + +func TestClash_Snell(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", + }) + if err != nil { + assert.FailNow(t, err.Error()) + } + + time.Sleep(waitTime) + testSuit(t, proxy) +} diff --git a/test/ss_test.go b/test/ss_test.go new file mode 100644 index 000000000..6876d3fb5 --- /dev/null +++ b/test/ss_test.go @@ -0,0 +1,172 @@ +package main + +import ( + "testing" + "time" + + "github.com/Dreamacro/clash/adapters/outbound" + + "github.com/docker/docker/api/types/container" + "github.com/stretchr/testify/assert" +) + +func TestClash_Shadowsocks(t *testing.T) { + cfg := &container.Config{ + Image: ImageShadowsocks, + Env: []string{"SS_MODULE=ss-server", "SS_CONFIG=-s 0.0.0.0 -u -v -p 10002 -m chacha20-ietf-poly1305 -k FzcLbKs2dY9mhL"}, + ExposedPorts: defaultExposedPorts, + } + hostCfg := &container.HostConfig{ + PortBindings: defaultPortBindings, + } + + id, err := startContainer(cfg, hostCfg, "ss") + if err != nil { + assert.FailNow(t, err.Error()) + } + + t.Cleanup(func() { + cleanContainer(id) + }) + + proxy, err := outbound.NewShadowSocks(outbound.ShadowSocksOption{ + Name: "ss", + Server: localIP.String(), + Port: 10002, + Password: "FzcLbKs2dY9mhL", + Cipher: "chacha20-ietf-poly1305", + UDP: true, + }) + if err != nil { + assert.FailNow(t, err.Error()) + } + + time.Sleep(waitTime) + testSuit(t, proxy) +} + +func TestClash_ShadowsocksObfsHTTP(t *testing.T) { + cfg := &container.Config{ + Image: ImageShadowsocks, + Env: []string{ + "SS_MODULE=ss-server", + "SS_CONFIG=-s 0.0.0.0 -u -p 10002 -m chacha20-ietf-poly1305 -k FzcLbKs2dY9mhL --plugin obfs-server --plugin-opts obfs=http", + }, + ExposedPorts: defaultExposedPorts, + } + hostCfg := &container.HostConfig{ + PortBindings: defaultPortBindings, + } + + id, err := startContainer(cfg, hostCfg, "ss-obfs-http") + if err != nil { + assert.FailNow(t, err.Error()) + } + + t.Cleanup(func() { + cleanContainer(id) + }) + + proxy, err := outbound.NewShadowSocks(outbound.ShadowSocksOption{ + Name: "ss", + Server: localIP.String(), + Port: 10002, + Password: "FzcLbKs2dY9mhL", + Cipher: "chacha20-ietf-poly1305", + UDP: true, + Plugin: "obfs", + PluginOpts: map[string]interface{}{ + "mode": "http", + }, + }) + if err != nil { + assert.FailNow(t, err.Error()) + } + + time.Sleep(waitTime) + testSuit(t, proxy) +} + +func TestClash_ShadowsocksObfsTLS(t *testing.T) { + cfg := &container.Config{ + Image: ImageShadowsocks, + Env: []string{ + "SS_MODULE=ss-server", + "SS_CONFIG=-s 0.0.0.0 -u -p 10002 -m chacha20-ietf-poly1305 -k FzcLbKs2dY9mhL --plugin obfs-server --plugin-opts obfs=tls", + }, + ExposedPorts: defaultExposedPorts, + } + hostCfg := &container.HostConfig{ + PortBindings: defaultPortBindings, + } + + id, err := startContainer(cfg, hostCfg, "ss-obfs-tls") + if err != nil { + assert.FailNow(t, err.Error()) + } + + t.Cleanup(func() { + cleanContainer(id) + }) + + proxy, err := outbound.NewShadowSocks(outbound.ShadowSocksOption{ + Name: "ss", + Server: localIP.String(), + Port: 10002, + Password: "FzcLbKs2dY9mhL", + Cipher: "chacha20-ietf-poly1305", + UDP: true, + Plugin: "obfs", + PluginOpts: map[string]interface{}{ + "mode": "tls", + }, + }) + if err != nil { + assert.FailNow(t, err.Error()) + } + + time.Sleep(waitTime) + testSuit(t, proxy) +} + +func TestClash_ShadowsocksV2RayPlugin(t *testing.T) { + cfg := &container.Config{ + Image: ImageShadowsocks, + Env: []string{ + "SS_MODULE=ss-server", + "SS_CONFIG=-s 0.0.0.0 -u -p 10002 -m chacha20-ietf-poly1305 -k FzcLbKs2dY9mhL --plugin v2ray-plugin --plugin-opts=server", + }, + ExposedPorts: defaultExposedPorts, + } + hostCfg := &container.HostConfig{ + PortBindings: defaultPortBindings, + } + + id, err := startContainer(cfg, hostCfg, "ss-v2ray-plugin") + if err != nil { + assert.FailNow(t, err.Error()) + } + + t.Cleanup(func() { + cleanContainer(id) + }) + + proxy, err := outbound.NewShadowSocks(outbound.ShadowSocksOption{ + Name: "ss", + Server: localIP.String(), + Port: 10002, + Password: "FzcLbKs2dY9mhL", + Cipher: "chacha20-ietf-poly1305", + UDP: true, + Plugin: "v2ray-plugin", + PluginOpts: map[string]interface{}{ + "mode": "websocket", + }, + }) + if err != nil { + assert.FailNow(t, err.Error()) + } + + time.Sleep(waitTime) + testSuit(t, proxy) +} diff --git a/test/trojan_test.go b/test/trojan_test.go new file mode 100644 index 000000000..c20f12792 --- /dev/null +++ b/test/trojan_test.go @@ -0,0 +1,94 @@ +package main + +import ( + "fmt" + "testing" + "time" + + "github.com/Dreamacro/clash/adapters/outbound" + C "github.com/Dreamacro/clash/constant" + + "github.com/docker/docker/api/types/container" + "github.com/stretchr/testify/assert" +) + +func TestClash_Trojan(t *testing.T) { + cfg := &container.Config{ + Image: ImageTrojan, + ExposedPorts: defaultExposedPorts, + } + hostCfg := &container.HostConfig{ + PortBindings: defaultPortBindings, + Binds: []string{ + fmt.Sprintf("%s:/config/config.json", C.Path.Resolve("trojan.json")), + fmt.Sprintf("%s:/path/to/certificate.crt", C.Path.Resolve("example.org.pem")), + fmt.Sprintf("%s:/path/to/private.key", C.Path.Resolve("example.org-key.pem")), + }, + } + + id, err := startContainer(cfg, hostCfg, "trojan") + if err != nil { + assert.FailNow(t, err.Error()) + } + + t.Cleanup(func() { + cleanContainer(id) + }) + + proxy, err := outbound.NewTrojan(outbound.TrojanOption{ + Name: "trojan", + Server: localIP.String(), + Port: 10002, + Password: "password", + SNI: "example.org", + SkipCertVerify: true, + UDP: true, + }) + if err != nil { + assert.FailNow(t, err.Error()) + } + + time.Sleep(waitTime) + testSuit(t, proxy) +} + +func TestClash_TrojanGrpc(t *testing.T) { + cfg := &container.Config{ + Image: ImageXray, + ExposedPorts: defaultExposedPorts, + } + hostCfg := &container.HostConfig{ + PortBindings: defaultPortBindings, + Binds: []string{ + fmt.Sprintf("%s:/etc/xray/config.json", C.Path.Resolve("trojan-grpc.json")), + fmt.Sprintf("%s:/etc/ssl/v2ray/fullchain.pem", C.Path.Resolve("example.org.pem")), + fmt.Sprintf("%s:/etc/ssl/v2ray/privkey.pem", C.Path.Resolve("example.org-key.pem")), + }, + } + + id, err := startContainer(cfg, hostCfg, "trojan-grpc") + if err != nil { + assert.FailNow(t, err.Error()) + } + defer cleanContainer(id) + + proxy, err := outbound.NewTrojan(outbound.TrojanOption{ + Name: "trojan", + Server: localIP.String(), + Port: 10002, + Password: "example", + SNI: "example.org", + SkipCertVerify: true, + UDP: true, + Network: "grpc", + GrpcOpts: outbound.GrpcOptions{ + GrpcServiceName: "example", + }, + }) + if err != nil { + assert.FailNow(t, err.Error()) + } + + time.Sleep(waitTime) + testSuit(t, proxy) +} diff --git a/test/util_test.go b/test/util_test.go new file mode 100644 index 000000000..ab9b8b2bf --- /dev/null +++ b/test/util_test.go @@ -0,0 +1,70 @@ +package main + +import ( + "errors" + "fmt" + "net" + "syscall" + + "golang.org/x/net/route" +) + +func defaultRouteIP() (net.IP, error) { + idx, err := defaultRouteInterfaceIndex() + if err != nil { + return nil, err + } + iface, err := net.InterfaceByIndex(idx) + if err != nil { + return nil, err + } + addrs, err := iface.Addrs() + if err != nil { + return nil, err + } + for _, addr := range addrs { + ip := addr.(*net.IPNet).IP + if ip.To4() != nil { + return ip, nil + } + } + + return nil, errors.New("no ipv4 addr") +} + +func defaultRouteInterfaceIndex() (int, error) { + rib, err := route.FetchRIB(syscall.AF_UNSPEC, syscall.NET_RT_DUMP2, 0) + if err != nil { + return 0, fmt.Errorf("route.FetchRIB: %w", err) + } + msgs, err := route.ParseRIB(syscall.NET_RT_IFLIST2, rib) + if err != nil { + return 0, fmt.Errorf("route.ParseRIB: %w", err) + } + for _, message := range msgs { + routeMessage := message.(*route.RouteMessage) + if routeMessage.Flags&(syscall.RTF_UP|syscall.RTF_GATEWAY|syscall.RTF_STATIC) == 0 { + continue + } + + addresses := routeMessage.Addrs + + destination, ok := addresses[0].(*route.Inet4Addr) + if !ok { + continue + } + + if destination.IP != [4]byte{0, 0, 0, 0} { + continue + } + + switch addresses[1].(type) { + case *route.Inet4Addr: + return routeMessage.Index, nil + default: + continue + } + } + + return 0, fmt.Errorf("ambiguous gateway interfaces found") +} diff --git a/test/vmess_test.go b/test/vmess_test.go new file mode 100644 index 000000000..cf539bf89 --- /dev/null +++ b/test/vmess_test.go @@ -0,0 +1,347 @@ +package main + +import ( + "fmt" + "testing" + "time" + + "github.com/Dreamacro/clash/adapters/outbound" + C "github.com/Dreamacro/clash/constant" + + "github.com/docker/docker/api/types/container" + "github.com/stretchr/testify/assert" +) + +func TestClash_Vmess(t *testing.T) { + configPath := C.Path.Resolve("vmess.json") + + cfg := &container.Config{ + Image: ImageVmess, + ExposedPorts: defaultExposedPorts, + } + hostCfg := &container.HostConfig{ + PortBindings: defaultPortBindings, + Binds: []string{fmt.Sprintf("%s:/etc/v2ray/config.json", configPath)}, + } + + id, err := startContainer(cfg, hostCfg, "vmess") + if err != nil { + assert.FailNow(t, err.Error()) + } + + t.Cleanup(func() { + cleanContainer(id) + }) + + proxy, err := outbound.NewVmess(outbound.VmessOption{ + Name: "vmess", + Server: localIP.String(), + Port: 10002, + UUID: "b831381d-6324-4d53-ad4f-8cda48b30811", + Cipher: "auto", + AlterID: 32, + UDP: true, + }) + if err != nil { + assert.FailNow(t, err.Error()) + } + + time.Sleep(waitTime) + testSuit(t, proxy) +} + +func TestClash_VmessAEAD(t *testing.T) { + configPath := C.Path.Resolve("vmess-aead.json") + + cfg := &container.Config{ + Image: ImageVmess, + ExposedPorts: defaultExposedPorts, + } + hostCfg := &container.HostConfig{ + PortBindings: defaultPortBindings, + Binds: []string{fmt.Sprintf("%s:/etc/v2ray/config.json", configPath)}, + } + + id, err := startContainer(cfg, hostCfg, "vmess-aead") + if err != nil { + assert.FailNow(t, err.Error()) + } + + t.Cleanup(func() { + cleanContainer(id) + }) + + proxy, err := outbound.NewVmess(outbound.VmessOption{ + Name: "vmess", + Server: localIP.String(), + Port: 10002, + UUID: "b831381d-6324-4d53-ad4f-8cda48b30811", + Cipher: "auto", + AlterID: 0, + UDP: true, + }) + if err != nil { + assert.FailNow(t, err.Error()) + } + + time.Sleep(waitTime) + testSuit(t, proxy) +} + +func TestClash_VmessTLS(t *testing.T) { + cfg := &container.Config{ + Image: ImageVmess, + ExposedPorts: defaultExposedPorts, + } + hostCfg := &container.HostConfig{ + PortBindings: defaultPortBindings, + Binds: []string{ + fmt.Sprintf("%s:/etc/v2ray/config.json", C.Path.Resolve("vmess-tls.json")), + fmt.Sprintf("%s:/etc/ssl/v2ray/fullchain.pem", C.Path.Resolve("example.org.pem")), + fmt.Sprintf("%s:/etc/ssl/v2ray/privkey.pem", C.Path.Resolve("example.org-key.pem")), + }, + } + + id, err := startContainer(cfg, hostCfg, "vmess-tls") + if err != nil { + assert.FailNow(t, err.Error()) + } + defer cleanContainer(id) + + proxy, err := outbound.NewVmess(outbound.VmessOption{ + Name: "vmess", + Server: localIP.String(), + Port: 10002, + UUID: "b831381d-6324-4d53-ad4f-8cda48b30811", + Cipher: "auto", + AlterID: 32, + TLS: true, + SkipCertVerify: true, + ServerName: "example.org", + UDP: true, + }) + if err != nil { + assert.FailNow(t, err.Error()) + } + + time.Sleep(waitTime) + testSuit(t, proxy) +} + +func TestClash_VmessHTTP2(t *testing.T) { + cfg := &container.Config{ + Image: ImageVmess, + ExposedPorts: defaultExposedPorts, + } + hostCfg := &container.HostConfig{ + PortBindings: defaultPortBindings, + Binds: []string{ + fmt.Sprintf("%s:/etc/v2ray/config.json", C.Path.Resolve("vmess-http2.json")), + fmt.Sprintf("%s:/etc/ssl/v2ray/fullchain.pem", C.Path.Resolve("example.org.pem")), + fmt.Sprintf("%s:/etc/ssl/v2ray/privkey.pem", C.Path.Resolve("example.org-key.pem")), + }, + } + + id, err := startContainer(cfg, hostCfg, "vmess-http2") + if err != nil { + assert.FailNow(t, err.Error()) + } + defer cleanContainer(id) + + proxy, err := outbound.NewVmess(outbound.VmessOption{ + Name: "vmess", + Server: localIP.String(), + Port: 10002, + UUID: "b831381d-6324-4d53-ad4f-8cda48b30811", + Cipher: "auto", + AlterID: 32, + Network: "h2", + TLS: true, + SkipCertVerify: true, + ServerName: "example.org", + UDP: true, + HTTP2Opts: outbound.HTTP2Options{ + Host: []string{"example.org"}, + Path: "/test", + }, + }) + if err != nil { + assert.FailNow(t, err.Error()) + } + + time.Sleep(waitTime) + testSuit(t, proxy) +} + +func TestClash_VmessHTTP(t *testing.T) { + cfg := &container.Config{ + Image: ImageVmess, + ExposedPorts: defaultExposedPorts, + } + hostCfg := &container.HostConfig{ + PortBindings: defaultPortBindings, + Binds: []string{ + fmt.Sprintf("%s:/etc/v2ray/config.json", C.Path.Resolve("vmess-http.json")), + }, + } + + id, err := startContainer(cfg, hostCfg, "vmess-http") + if err != nil { + assert.FailNow(t, err.Error()) + } + defer cleanContainer(id) + + proxy, err := outbound.NewVmess(outbound.VmessOption{ + Name: "vmess", + Server: localIP.String(), + Port: 10002, + UUID: "b831381d-6324-4d53-ad4f-8cda48b30811", + Cipher: "auto", + AlterID: 32, + Network: "http", + UDP: true, + HTTPOpts: outbound.HTTPOptions{ + Method: "GET", + Path: []string{"/"}, + Headers: map[string][]string{ + "Host": {"www.amazon.com"}, + "User-Agent": { + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.105 Safari/537.36 Edg/84.0.522.49", + }, + "Accept-Encoding": { + "gzip, deflate", + }, + "Connection": { + "keep-alive", + }, + "Pragma": {"no-cache"}, + }, + }, + }) + if err != nil { + assert.FailNow(t, err.Error()) + } + + time.Sleep(waitTime) + testSuit(t, proxy) +} + +func TestClash_VmessWebsocket(t *testing.T) { + cfg := &container.Config{ + Image: ImageVmess, + ExposedPorts: defaultExposedPorts, + } + hostCfg := &container.HostConfig{ + PortBindings: defaultPortBindings, + Binds: []string{ + fmt.Sprintf("%s:/etc/v2ray/config.json", C.Path.Resolve("vmess-ws.json")), + }, + } + + id, err := startContainer(cfg, hostCfg, "vmess-ws") + if err != nil { + assert.FailNow(t, err.Error()) + } + defer cleanContainer(id) + + proxy, err := outbound.NewVmess(outbound.VmessOption{ + Name: "vmess", + Server: localIP.String(), + Port: 10002, + UUID: "b831381d-6324-4d53-ad4f-8cda48b30811", + Cipher: "auto", + AlterID: 32, + Network: "ws", + UDP: true, + }) + if err != nil { + assert.FailNow(t, err.Error()) + } + + time.Sleep(waitTime) + testSuit(t, proxy) +} + +func TestClash_VmessWebsocketTLS(t *testing.T) { + cfg := &container.Config{ + Image: ImageVmess, + ExposedPorts: defaultExposedPorts, + } + hostCfg := &container.HostConfig{ + PortBindings: defaultPortBindings, + Binds: []string{ + fmt.Sprintf("%s:/etc/v2ray/config.json", C.Path.Resolve("vmess-ws-tls.json")), + fmt.Sprintf("%s:/etc/ssl/v2ray/fullchain.pem", C.Path.Resolve("example.org.pem")), + fmt.Sprintf("%s:/etc/ssl/v2ray/privkey.pem", C.Path.Resolve("example.org-key.pem")), + }, + } + + id, err := startContainer(cfg, hostCfg, "vmess-ws") + if err != nil { + assert.FailNow(t, err.Error()) + } + defer cleanContainer(id) + + proxy, err := outbound.NewVmess(outbound.VmessOption{ + Name: "vmess", + Server: localIP.String(), + Port: 10002, + UUID: "b831381d-6324-4d53-ad4f-8cda48b30811", + Cipher: "auto", + AlterID: 32, + Network: "ws", + TLS: true, + SkipCertVerify: true, + UDP: true, + }) + if err != nil { + assert.FailNow(t, err.Error()) + } + + time.Sleep(waitTime) + testSuit(t, proxy) +} + +func TestClash_VmessGrpc(t *testing.T) { + cfg := &container.Config{ + Image: ImageXray, + ExposedPorts: defaultExposedPorts, + } + hostCfg := &container.HostConfig{ + PortBindings: defaultPortBindings, + Binds: []string{ + fmt.Sprintf("%s:/etc/xray/config.json", C.Path.Resolve("vmess-grpc.json")), + fmt.Sprintf("%s:/etc/ssl/v2ray/fullchain.pem", C.Path.Resolve("example.org.pem")), + fmt.Sprintf("%s:/etc/ssl/v2ray/privkey.pem", C.Path.Resolve("example.org-key.pem")), + }, + } + + id, err := startContainer(cfg, hostCfg, "vmess-grpc") + if err != nil { + assert.FailNow(t, err.Error()) + } + defer cleanContainer(id) + + proxy, err := outbound.NewVmess(outbound.VmessOption{ + Name: "vmess", + Server: localIP.String(), + Port: 10002, + UUID: "b831381d-6324-4d53-ad4f-8cda48b30811", + Cipher: "auto", + AlterID: 32, + Network: "grpc", + TLS: true, + SkipCertVerify: true, + UDP: true, + ServerName: "example.org", + GrpcOpts: outbound.GrpcOptions{ + GrpcServiceName: "example", + }, + }) + if err != nil { + assert.FailNow(t, err.Error()) + } + + time.Sleep(waitTime) + testSuit(t, proxy) +} From 0778591524e180cc935176e772ede8d8a86c0f85 Mon Sep 17 00:00:00 2001 From: Rusty Pen Date: Wed, 19 May 2021 11:17:35 +0800 Subject: [PATCH 05/96] Feature: dns resolve domain through nameserver-policy (#1406) --- component/trie/domain.go | 6 +++--- config/config.go | 23 +++++++++++++++++++++++ dns/resolver.go | 35 +++++++++++++++++++++++++++++++++++ hub/executor/executor.go | 1 + 4 files changed, 62 insertions(+), 3 deletions(-) diff --git a/component/trie/domain.go b/component/trie/domain.go index c063686e0..b4de4a707 100644 --- a/component/trie/domain.go +++ b/component/trie/domain.go @@ -23,7 +23,7 @@ type DomainTrie struct { root *Node } -func validAndSplitDomain(domain string) ([]string, bool) { +func ValidAndSplitDomain(domain string) ([]string, bool) { if domain != "" && domain[len(domain)-1] == '.' { return nil, false } @@ -54,7 +54,7 @@ func validAndSplitDomain(domain string) ([]string, bool) { // 4. .example.com // 5. +.example.com func (t *DomainTrie) Insert(domain string, data interface{}) error { - parts, valid := validAndSplitDomain(domain) + parts, valid := ValidAndSplitDomain(domain) if !valid { return ErrInvalidDomain } @@ -91,7 +91,7 @@ func (t *DomainTrie) insert(parts []string, data interface{}) { // 2. wildcard domain // 2. dot wildcard domain func (t *DomainTrie) Search(domain string) *Node { - parts, valid := validAndSplitDomain(domain) + parts, valid := ValidAndSplitDomain(domain) if !valid || parts[0] == "" { return nil } diff --git a/config/config.go b/config/config.go index 51faac918..903316492 100644 --- a/config/config.go +++ b/config/config.go @@ -64,6 +64,7 @@ type DNS struct { DefaultNameserver []dns.NameServer `yaml:"default-nameserver"` FakeIPRange *fakeip.Pool Hosts *trie.DomainTrie + NameServerPolicy map[string]dns.NameServer } // FallbackFilter config @@ -106,6 +107,7 @@ type RawDNS struct { FakeIPRange string `yaml:"fake-ip-range"` FakeIPFilter []string `yaml:"fake-ip-filter"` DefaultNameserver []string `yaml:"default-nameserver"` + NameServerPolicy map[string]string `yaml:"nameserver-policy"` } type RawFallbackFilter struct { @@ -500,6 +502,23 @@ func parseNameServer(servers []string) ([]dns.NameServer, error) { return nameservers, nil } +func parseNameServerPolicy(nsPolicy map[string]string) (map[string]dns.NameServer, error) { + policy := map[string]dns.NameServer{} + + for domain, server := range nsPolicy { + nameservers, err := parseNameServer([]string{server}) + if err != nil { + return nil, err + } + if _, valid := trie.ValidAndSplitDomain(domain); !valid { + return nil, fmt.Errorf("DNS ResoverRule invalid domain: %s", domain) + } + policy[domain] = nameservers[0] + } + + return policy, nil +} + func parseFallbackIPCIDR(ips []string) ([]*net.IPNet, error) { ipNets := []*net.IPNet{} @@ -537,6 +556,10 @@ func parseDNS(cfg RawDNS, hosts *trie.DomainTrie) (*DNS, error) { return nil, err } + if dnsCfg.NameServerPolicy, err = parseNameServerPolicy(cfg.NameServerPolicy); err != nil { + return nil, err + } + if len(cfg.DefaultNameserver) == 0 { return nil, errors.New("default nameserver should have at least one nameserver") } diff --git a/dns/resolver.go b/dns/resolver.go index 0db6855dd..f57fec525 100644 --- a/dns/resolver.go +++ b/dns/resolver.go @@ -43,6 +43,7 @@ type Resolver struct { fallbackIPFilters []fallbackIPFilter group singleflight.Group lruCache *cache.LruCache + policy *trie.DomainTrie } // ResolveIP request with TypeA and TypeAAAA, priority return TypeA @@ -131,6 +132,9 @@ func (r *Resolver) exchangeWithoutCache(m *D.Msg) (msg *D.Msg, err error) { return r.ipExchange(m) } + if matched := r.matchPolicy(m); len(matched) != 0 { + return r.batchExchange(matched, m) + } return r.batchExchange(r.main, m) }) @@ -172,6 +176,24 @@ func (r *Resolver) batchExchange(clients []dnsClient, m *D.Msg) (msg *D.Msg, err return } +func (r *Resolver) matchPolicy(m *D.Msg) []dnsClient { + if r.policy == nil { + return nil + } + + domain := r.msgToDomain(m) + if domain == "" { + return nil + } + + record := r.policy.Search(domain) + if record == nil { + return nil + } + + return record.Data.([]dnsClient) +} + func (r *Resolver) shouldOnlyQueryFallback(m *D.Msg) bool { if r.fallback == nil || len(r.fallbackDomainFilters) == 0 { return false @@ -194,6 +216,11 @@ func (r *Resolver) shouldOnlyQueryFallback(m *D.Msg) bool { func (r *Resolver) ipExchange(m *D.Msg) (msg *D.Msg, err error) { + if matched := r.matchPolicy(m); len(matched) != 0 { + res := <-r.asyncExchange(matched, m) + return res.Msg, res.Error + } + onlyFallback := r.shouldOnlyQueryFallback(m) if onlyFallback { @@ -293,6 +320,7 @@ type Config struct { FallbackFilter FallbackFilter Pool *fakeip.Pool Hosts *trie.DomainTrie + Policy map[string]NameServer } func NewResolver(config Config) *Resolver { @@ -312,6 +340,13 @@ func NewResolver(config Config) *Resolver { r.fallback = transform(config.Fallback, defaultResolver) } + if len(config.Policy) != 0 { + r.policy = trie.New() + for domain, nameserver := range config.Policy { + r.policy.Insert(domain, transform([]NameServer{nameserver}, defaultResolver)) + } + } + fallbackIPFilters := []fallbackIPFilter{} if config.FallbackFilter.GeoIP { fallbackIPFilters = append(fallbackIPFilters, &geoipFilter{}) diff --git a/hub/executor/executor.go b/hub/executor/executor.go index bea2a1abd..caf75aff9 100644 --- a/hub/executor/executor.go +++ b/hub/executor/executor.go @@ -128,6 +128,7 @@ func updateDNS(c *config.DNS) { Domain: c.FallbackFilter.Domain, }, Default: c.DefaultNameserver, + Policy: c.NameServerPolicy, } r := dns.NewResolver(cfg) From 045edc188cd3f90e9aa95c0c6f02f89848cb4967 Mon Sep 17 00:00:00 2001 From: Dreamacro <8615343+Dreamacro@users.noreply.github.com> Date: Thu, 10 Jun 2021 14:05:56 +0800 Subject: [PATCH 06/96] Style: code style --- .../outbound/base.go => adapter/adapter.go | 126 +++++------------- {adapters => adapter}/inbound/http.go | 0 {adapters => adapter}/inbound/https.go | 0 {adapters => adapter}/inbound/packet.go | 0 {adapters => adapter}/inbound/socket.go | 0 {adapters => adapter}/inbound/util.go | 0 adapter/outbound/base.go | 100 ++++++++++++++ {adapters => adapter}/outbound/direct.go | 0 {adapters => adapter}/outbound/http.go | 0 {adapters => adapter}/outbound/reject.go | 0 {adapters => adapter}/outbound/shadowsocks.go | 8 -- .../outbound/shadowsocksr.go | 8 -- {adapters => adapter}/outbound/snell.go | 0 {adapters => adapter}/outbound/socks5.go | 2 +- {adapters => adapter}/outbound/trojan.go | 9 +- {adapters => adapter}/outbound/util.go | 34 ----- {adapters => adapter}/outbound/vmess.go | 2 +- {adapters => adapter}/outboundgroup/common.go | 2 +- .../outboundgroup/fallback.go | 4 +- .../outboundgroup/loadbalance.go | 4 +- {adapters => adapter}/outboundgroup/parser.go | 2 +- {adapters => adapter}/outboundgroup/relay.go | 4 +- .../outboundgroup/selector.go | 4 +- .../outboundgroup/urltest.go | 4 +- {adapters => adapter}/outboundgroup/util.go | 0 {adapters/outbound => adapter}/parser.go | 33 ++--- {adapters => adapter}/provider/fetcher.go | 0 {adapters => adapter}/provider/healthcheck.go | 0 {adapters => adapter}/provider/parser.go | 0 {adapters => adapter}/provider/provider.go | 4 +- {adapters => adapter}/provider/vehicle.go | 0 config/config.go | 19 +-- config/utils.go | 2 +- constant/adapters.go | 4 + hub/executor/executor.go | 8 +- hub/route/provider.go | 2 +- hub/route/proxies.go | 6 +- proxy/http/server.go | 6 +- proxy/redir/tcp.go | 2 +- proxy/redir/tproxy.go | 2 +- proxy/redir/udp.go | 4 +- proxy/socks/tcp.go | 4 +- proxy/socks/udp.go | 4 +- {rules => rule}/base.go | 0 {rules => rule}/domain.go | 0 {rules => rule}/domain_keyword.go | 0 {rules => rule}/domain_suffix.go | 0 {rules => rule}/final.go | 0 {rules => rule}/geoip.go | 0 {rules => rule}/ipcidr.go | 0 {rules => rule}/parser.go | 0 {rules => rule}/port.go | 0 {rules => rule}/process.go | 0 test/snell_test.go | 2 +- test/ss_test.go | 2 +- test/trojan_test.go | 2 +- test/vmess_test.go | 2 +- tunnel/connection.go | 2 +- tunnel/tunnel.go | 4 +- 59 files changed, 207 insertions(+), 220 deletions(-) rename adapters/outbound/base.go => adapter/adapter.go (61%) rename {adapters => adapter}/inbound/http.go (100%) rename {adapters => adapter}/inbound/https.go (100%) rename {adapters => adapter}/inbound/packet.go (100%) rename {adapters => adapter}/inbound/socket.go (100%) rename {adapters => adapter}/inbound/util.go (100%) create mode 100644 adapter/outbound/base.go rename {adapters => adapter}/outbound/direct.go (100%) rename {adapters => adapter}/outbound/http.go (100%) rename {adapters => adapter}/outbound/reject.go (100%) rename {adapters => adapter}/outbound/shadowsocks.go (96%) rename {adapters => adapter}/outbound/shadowsocksr.go (95%) rename {adapters => adapter}/outbound/snell.go (100%) rename {adapters => adapter}/outbound/socks5.go (98%) rename {adapters => adapter}/outbound/trojan.go (95%) rename {adapters => adapter}/outbound/util.go (76%) rename {adapters => adapter}/outbound/vmess.go (99%) rename {adapters => adapter}/outboundgroup/common.go (90%) rename {adapters => adapter}/outboundgroup/fallback.go (95%) rename {adapters => adapter}/outboundgroup/loadbalance.go (97%) rename {adapters => adapter}/outboundgroup/parser.go (98%) rename {adapters => adapter}/outboundgroup/relay.go (95%) rename {adapters => adapter}/outboundgroup/selector.go (96%) rename {adapters => adapter}/outboundgroup/urltest.go (97%) rename {adapters => adapter}/outboundgroup/util.go (100%) rename {adapters/outbound => adapter}/parser.go (63%) rename {adapters => adapter}/provider/fetcher.go (100%) rename {adapters => adapter}/provider/healthcheck.go (100%) rename {adapters => adapter}/provider/parser.go (100%) rename {adapters => adapter}/provider/provider.go (98%) rename {adapters => adapter}/provider/vehicle.go (100%) rename {rules => rule}/base.go (100%) rename {rules => rule}/domain.go (100%) rename {rules => rule}/domain_keyword.go (100%) rename {rules => rule}/domain_suffix.go (100%) rename {rules => rule}/final.go (100%) rename {rules => rule}/geoip.go (100%) rename {rules => rule}/ipcidr.go (100%) rename {rules => rule}/parser.go (100%) rename {rules => rule}/port.go (100%) rename {rules => rule}/process.go (100%) diff --git a/adapters/outbound/base.go b/adapter/adapter.go similarity index 61% rename from adapters/outbound/base.go rename to adapter/adapter.go index 6e16bbaed..f3503f04c 100644 --- a/adapters/outbound/base.go +++ b/adapter/adapter.go @@ -1,11 +1,12 @@ -package outbound +package adapter import ( "context" "encoding/json" - "errors" + "fmt" "net" "net/http" + "net/url" "time" "github.com/Dreamacro/clash/common/queue" @@ -14,97 +15,6 @@ import ( "go.uber.org/atomic" ) -type Base struct { - name string - addr string - tp C.AdapterType - udp bool -} - -// Name implements C.ProxyAdapter -func (b *Base) Name() string { - return b.name -} - -// Type implements C.ProxyAdapter -func (b *Base) Type() C.AdapterType { - return b.tp -} - -// StreamConn implements C.ProxyAdapter -func (b *Base) StreamConn(c net.Conn, metadata *C.Metadata) (net.Conn, error) { - return c, errors.New("no support") -} - -// DialUDP implements C.ProxyAdapter -func (b *Base) DialUDP(metadata *C.Metadata) (C.PacketConn, error) { - return nil, errors.New("no support") -} - -// SupportUDP implements C.ProxyAdapter -func (b *Base) SupportUDP() bool { - return b.udp -} - -// MarshalJSON implements C.ProxyAdapter -func (b *Base) MarshalJSON() ([]byte, error) { - return json.Marshal(map[string]string{ - "type": b.Type().String(), - }) -} - -// Addr implements C.ProxyAdapter -func (b *Base) Addr() string { - return b.addr -} - -// Unwrap implements C.ProxyAdapter -func (b *Base) Unwrap(metadata *C.Metadata) C.Proxy { - return nil -} - -func NewBase(name string, addr string, tp C.AdapterType, udp bool) *Base { - return &Base{name, addr, tp, udp} -} - -type conn struct { - net.Conn - chain C.Chain -} - -// Chains implements C.Connection -func (c *conn) Chains() C.Chain { - return c.chain -} - -// AppendToChains implements C.Connection -func (c *conn) AppendToChains(a C.ProxyAdapter) { - c.chain = append(c.chain, a.Name()) -} - -func NewConn(c net.Conn, a C.ProxyAdapter) C.Conn { - return &conn{c, []string{a.Name()}} -} - -type packetConn struct { - net.PacketConn - chain C.Chain -} - -// Chains implements C.Connection -func (c *packetConn) Chains() C.Chain { - return c.chain -} - -// AppendToChains implements C.Connection -func (c *packetConn) AppendToChains(a C.ProxyAdapter) { - c.chain = append(c.chain, a.Name()) -} - -func newPacketConn(pc net.PacketConn, a C.ProxyAdapter) C.PacketConn { - return &packetConn{pc, []string{a.Name()}} -} - type Proxy struct { C.ProxyAdapter history *queue.Queue @@ -118,7 +28,7 @@ func (p *Proxy) Alive() bool { // Dial implements C.Proxy func (p *Proxy) Dial(metadata *C.Metadata) (C.Conn, error) { - ctx, cancel := context.WithTimeout(context.Background(), tcpTimeout) + ctx, cancel := context.WithTimeout(context.Background(), C.DefaultTCPTimeout) defer cancel() return p.DialContext(ctx, metadata) } @@ -237,3 +147,31 @@ func (p *Proxy) URLTest(ctx context.Context, url string) (t uint16, err error) { func NewProxy(adapter C.ProxyAdapter) *Proxy { return &Proxy{adapter, queue.New(10), atomic.NewBool(true)} } + +func urlToMetadata(rawURL string) (addr C.Metadata, err error) { + u, err := url.Parse(rawURL) + if err != nil { + return + } + + port := u.Port() + if port == "" { + switch u.Scheme { + case "https": + port = "443" + case "http": + port = "80" + default: + err = fmt.Errorf("%s scheme not Support", rawURL) + return + } + } + + addr = C.Metadata{ + AddrType: C.AtypDomainName, + Host: u.Hostname(), + DstIP: nil, + DstPort: port, + } + return +} diff --git a/adapters/inbound/http.go b/adapter/inbound/http.go similarity index 100% rename from adapters/inbound/http.go rename to adapter/inbound/http.go diff --git a/adapters/inbound/https.go b/adapter/inbound/https.go similarity index 100% rename from adapters/inbound/https.go rename to adapter/inbound/https.go diff --git a/adapters/inbound/packet.go b/adapter/inbound/packet.go similarity index 100% rename from adapters/inbound/packet.go rename to adapter/inbound/packet.go diff --git a/adapters/inbound/socket.go b/adapter/inbound/socket.go similarity index 100% rename from adapters/inbound/socket.go rename to adapter/inbound/socket.go diff --git a/adapters/inbound/util.go b/adapter/inbound/util.go similarity index 100% rename from adapters/inbound/util.go rename to adapter/inbound/util.go diff --git a/adapter/outbound/base.go b/adapter/outbound/base.go new file mode 100644 index 000000000..a001d799e --- /dev/null +++ b/adapter/outbound/base.go @@ -0,0 +1,100 @@ +package outbound + +import ( + "encoding/json" + "errors" + "net" + + C "github.com/Dreamacro/clash/constant" +) + +type Base struct { + name string + addr string + tp C.AdapterType + udp bool +} + +// Name implements C.ProxyAdapter +func (b *Base) Name() string { + return b.name +} + +// Type implements C.ProxyAdapter +func (b *Base) Type() C.AdapterType { + return b.tp +} + +// StreamConn implements C.ProxyAdapter +func (b *Base) StreamConn(c net.Conn, metadata *C.Metadata) (net.Conn, error) { + return c, errors.New("no support") +} + +// DialUDP implements C.ProxyAdapter +func (b *Base) DialUDP(metadata *C.Metadata) (C.PacketConn, error) { + return nil, errors.New("no support") +} + +// SupportUDP implements C.ProxyAdapter +func (b *Base) SupportUDP() bool { + return b.udp +} + +// MarshalJSON implements C.ProxyAdapter +func (b *Base) MarshalJSON() ([]byte, error) { + return json.Marshal(map[string]string{ + "type": b.Type().String(), + }) +} + +// Addr implements C.ProxyAdapter +func (b *Base) Addr() string { + return b.addr +} + +// Unwrap implements C.ProxyAdapter +func (b *Base) Unwrap(metadata *C.Metadata) C.Proxy { + return nil +} + +func NewBase(name string, addr string, tp C.AdapterType, udp bool) *Base { + return &Base{name, addr, tp, udp} +} + +type conn struct { + net.Conn + chain C.Chain +} + +// Chains implements C.Connection +func (c *conn) Chains() C.Chain { + return c.chain +} + +// AppendToChains implements C.Connection +func (c *conn) AppendToChains(a C.ProxyAdapter) { + c.chain = append(c.chain, a.Name()) +} + +func NewConn(c net.Conn, a C.ProxyAdapter) C.Conn { + return &conn{c, []string{a.Name()}} +} + +type packetConn struct { + net.PacketConn + chain C.Chain +} + +// Chains implements C.Connection +func (c *packetConn) Chains() C.Chain { + return c.chain +} + +// AppendToChains implements C.Connection +func (c *packetConn) AppendToChains(a C.ProxyAdapter) { + c.chain = append(c.chain, a.Name()) +} + +func newPacketConn(pc net.PacketConn, a C.ProxyAdapter) C.PacketConn { + return &packetConn{pc, []string{a.Name()}} +} diff --git a/adapters/outbound/direct.go b/adapter/outbound/direct.go similarity index 100% rename from adapters/outbound/direct.go rename to adapter/outbound/direct.go diff --git a/adapters/outbound/http.go b/adapter/outbound/http.go similarity index 100% rename from adapters/outbound/http.go rename to adapter/outbound/http.go diff --git a/adapters/outbound/reject.go b/adapter/outbound/reject.go similarity index 100% rename from adapters/outbound/reject.go rename to adapter/outbound/reject.go diff --git a/adapters/outbound/shadowsocks.go b/adapter/outbound/shadowsocks.go similarity index 96% rename from adapters/outbound/shadowsocks.go rename to adapter/outbound/shadowsocks.go index 6dcfc2c08..0fb3ab9a8 100644 --- a/adapters/outbound/shadowsocks.go +++ b/adapter/outbound/shadowsocks.go @@ -2,7 +2,6 @@ package outbound import ( "context" - "encoding/json" "errors" "fmt" "net" @@ -105,13 +104,6 @@ func (ss *ShadowSocks) DialUDP(metadata *C.Metadata) (C.PacketConn, error) { return newPacketConn(&ssPacketConn{PacketConn: pc, rAddr: addr}, ss), nil } -// MarshalJSON implements C.ProxyAdapter -func (ss *ShadowSocks) MarshalJSON() ([]byte, error) { - return json.Marshal(map[string]string{ - "type": ss.Type().String(), - }) -} - func NewShadowSocks(option ShadowSocksOption) (*ShadowSocks, error) { addr := net.JoinHostPort(option.Server, strconv.Itoa(option.Port)) cipher := option.Cipher diff --git a/adapters/outbound/shadowsocksr.go b/adapter/outbound/shadowsocksr.go similarity index 95% rename from adapters/outbound/shadowsocksr.go rename to adapter/outbound/shadowsocksr.go index 635135fcd..b44f46e56 100644 --- a/adapters/outbound/shadowsocksr.go +++ b/adapter/outbound/shadowsocksr.go @@ -2,7 +2,6 @@ package outbound import ( "context" - "encoding/json" "fmt" "net" "strconv" @@ -91,13 +90,6 @@ func (ssr *ShadowSocksR) DialUDP(metadata *C.Metadata) (C.PacketConn, error) { return newPacketConn(&ssPacketConn{PacketConn: pc, rAddr: addr}, ssr), nil } -// MarshalJSON implements C.ProxyAdapter -func (ssr *ShadowSocksR) MarshalJSON() ([]byte, error) { - return json.Marshal(map[string]string{ - "type": ssr.Type().String(), - }) -} - func NewShadowSocksR(option ShadowSocksROption) (*ShadowSocksR, error) { addr := net.JoinHostPort(option.Server, strconv.Itoa(option.Port)) cipher := option.Cipher diff --git a/adapters/outbound/snell.go b/adapter/outbound/snell.go similarity index 100% rename from adapters/outbound/snell.go rename to adapter/outbound/snell.go diff --git a/adapters/outbound/socks5.go b/adapter/outbound/socks5.go similarity index 98% rename from adapters/outbound/socks5.go rename to adapter/outbound/socks5.go index 466797de8..26c7c06ad 100644 --- a/adapters/outbound/socks5.go +++ b/adapter/outbound/socks5.go @@ -79,7 +79,7 @@ func (ss *Socks5) DialContext(ctx context.Context, metadata *C.Metadata) (_ C.Co // DialUDP implements C.ProxyAdapter func (ss *Socks5) DialUDP(metadata *C.Metadata) (_ C.PacketConn, err error) { - ctx, cancel := context.WithTimeout(context.Background(), tcpTimeout) + ctx, cancel := context.WithTimeout(context.Background(), C.DefaultTCPTimeout) defer cancel() c, err := dialer.DialContext(ctx, "tcp", ss.addr) if err != nil { diff --git a/adapters/outbound/trojan.go b/adapter/outbound/trojan.go similarity index 95% rename from adapters/outbound/trojan.go rename to adapter/outbound/trojan.go index 929f44147..5d8527353 100644 --- a/adapters/outbound/trojan.go +++ b/adapter/outbound/trojan.go @@ -3,7 +3,6 @@ package outbound import ( "context" "crypto/tls" - "encoding/json" "fmt" "net" "strconv" @@ -101,7 +100,7 @@ func (t *Trojan) DialUDP(metadata *C.Metadata) (_ C.PacketConn, err error) { } defer safeConnClose(c, err) } else { - ctx, cancel := context.WithTimeout(context.Background(), tcpTimeout) + ctx, cancel := context.WithTimeout(context.Background(), C.DefaultTCPTimeout) defer cancel() c, err = dialer.DialContext(ctx, "tcp", t.addr) if err != nil { @@ -124,12 +123,6 @@ func (t *Trojan) DialUDP(metadata *C.Metadata) (_ C.PacketConn, err error) { return newPacketConn(pc, t), err } -func (t *Trojan) MarshalJSON() ([]byte, error) { - return json.Marshal(map[string]string{ - "type": t.Type().String(), - }) -} - func NewTrojan(option TrojanOption) (*Trojan, error) { addr := net.JoinHostPort(option.Server, strconv.Itoa(option.Port)) diff --git a/adapters/outbound/util.go b/adapter/outbound/util.go similarity index 76% rename from adapters/outbound/util.go rename to adapter/outbound/util.go index cd60d3732..4b81eb5d6 100644 --- a/adapters/outbound/util.go +++ b/adapter/outbound/util.go @@ -3,9 +3,7 @@ package outbound import ( "bytes" "crypto/tls" - "fmt" "net" - "net/url" "strconv" "sync" "time" @@ -15,43 +13,11 @@ import ( "github.com/Dreamacro/clash/transport/socks5" ) -const ( - tcpTimeout = 5 * time.Second -) - var ( globalClientSessionCache tls.ClientSessionCache once sync.Once ) -func urlToMetadata(rawURL string) (addr C.Metadata, err error) { - u, err := url.Parse(rawURL) - if err != nil { - return - } - - port := u.Port() - if port == "" { - switch u.Scheme { - case "https": - port = "443" - case "http": - port = "80" - default: - err = fmt.Errorf("%s scheme not Support", rawURL) - return - } - } - - addr = C.Metadata{ - AddrType: C.AtypDomainName, - Host: u.Hostname(), - DstIP: nil, - DstPort: port, - } - return -} - func tcpKeepAlive(c net.Conn) { if tcp, ok := c.(*net.TCPConn); ok { tcp.SetKeepAlive(true) diff --git a/adapters/outbound/vmess.go b/adapter/outbound/vmess.go similarity index 99% rename from adapters/outbound/vmess.go rename to adapter/outbound/vmess.go index 246450aca..672f767ba 100644 --- a/adapters/outbound/vmess.go +++ b/adapter/outbound/vmess.go @@ -222,7 +222,7 @@ func (v *Vmess) DialUDP(metadata *C.Metadata) (_ C.PacketConn, err error) { c, err = v.client.StreamConn(c, parseVmessAddr(metadata)) } else { - ctx, cancel := context.WithTimeout(context.Background(), tcpTimeout) + ctx, cancel := context.WithTimeout(context.Background(), C.DefaultTCPTimeout) defer cancel() c, err = dialer.DialContext(ctx, "tcp", v.addr) if err != nil { diff --git a/adapters/outboundgroup/common.go b/adapter/outboundgroup/common.go similarity index 90% rename from adapters/outboundgroup/common.go rename to adapter/outboundgroup/common.go index c5c719f29..31b8cb6bb 100644 --- a/adapters/outboundgroup/common.go +++ b/adapter/outboundgroup/common.go @@ -3,7 +3,7 @@ package outboundgroup import ( "time" - "github.com/Dreamacro/clash/adapters/provider" + "github.com/Dreamacro/clash/adapter/provider" C "github.com/Dreamacro/clash/constant" ) diff --git a/adapters/outboundgroup/fallback.go b/adapter/outboundgroup/fallback.go similarity index 95% rename from adapters/outboundgroup/fallback.go rename to adapter/outboundgroup/fallback.go index b3dbe0cb7..8b38f09ca 100644 --- a/adapters/outboundgroup/fallback.go +++ b/adapter/outboundgroup/fallback.go @@ -4,8 +4,8 @@ import ( "context" "encoding/json" - "github.com/Dreamacro/clash/adapters/outbound" - "github.com/Dreamacro/clash/adapters/provider" + "github.com/Dreamacro/clash/adapter/outbound" + "github.com/Dreamacro/clash/adapter/provider" "github.com/Dreamacro/clash/common/singledo" C "github.com/Dreamacro/clash/constant" ) diff --git a/adapters/outboundgroup/loadbalance.go b/adapter/outboundgroup/loadbalance.go similarity index 97% rename from adapters/outboundgroup/loadbalance.go rename to adapter/outboundgroup/loadbalance.go index b44fade17..7856a07d6 100644 --- a/adapters/outboundgroup/loadbalance.go +++ b/adapter/outboundgroup/loadbalance.go @@ -7,8 +7,8 @@ import ( "fmt" "net" - "github.com/Dreamacro/clash/adapters/outbound" - "github.com/Dreamacro/clash/adapters/provider" + "github.com/Dreamacro/clash/adapter/outbound" + "github.com/Dreamacro/clash/adapter/provider" "github.com/Dreamacro/clash/common/murmur3" "github.com/Dreamacro/clash/common/singledo" C "github.com/Dreamacro/clash/constant" diff --git a/adapters/outboundgroup/parser.go b/adapter/outboundgroup/parser.go similarity index 98% rename from adapters/outboundgroup/parser.go rename to adapter/outboundgroup/parser.go index 82ceaa798..d11040a5f 100644 --- a/adapters/outboundgroup/parser.go +++ b/adapter/outboundgroup/parser.go @@ -4,7 +4,7 @@ import ( "errors" "fmt" - "github.com/Dreamacro/clash/adapters/provider" + "github.com/Dreamacro/clash/adapter/provider" "github.com/Dreamacro/clash/common/structure" C "github.com/Dreamacro/clash/constant" ) diff --git a/adapters/outboundgroup/relay.go b/adapter/outboundgroup/relay.go similarity index 95% rename from adapters/outboundgroup/relay.go rename to adapter/outboundgroup/relay.go index 6583d3903..e4a897b8a 100644 --- a/adapters/outboundgroup/relay.go +++ b/adapter/outboundgroup/relay.go @@ -6,8 +6,8 @@ import ( "errors" "fmt" - "github.com/Dreamacro/clash/adapters/outbound" - "github.com/Dreamacro/clash/adapters/provider" + "github.com/Dreamacro/clash/adapter/outbound" + "github.com/Dreamacro/clash/adapter/provider" "github.com/Dreamacro/clash/common/singledo" "github.com/Dreamacro/clash/component/dialer" C "github.com/Dreamacro/clash/constant" diff --git a/adapters/outboundgroup/selector.go b/adapter/outboundgroup/selector.go similarity index 96% rename from adapters/outboundgroup/selector.go rename to adapter/outboundgroup/selector.go index 67afaaabe..c28b6f8cf 100644 --- a/adapters/outboundgroup/selector.go +++ b/adapter/outboundgroup/selector.go @@ -5,8 +5,8 @@ import ( "encoding/json" "errors" - "github.com/Dreamacro/clash/adapters/outbound" - "github.com/Dreamacro/clash/adapters/provider" + "github.com/Dreamacro/clash/adapter/outbound" + "github.com/Dreamacro/clash/adapter/provider" "github.com/Dreamacro/clash/common/singledo" C "github.com/Dreamacro/clash/constant" ) diff --git a/adapters/outboundgroup/urltest.go b/adapter/outboundgroup/urltest.go similarity index 97% rename from adapters/outboundgroup/urltest.go rename to adapter/outboundgroup/urltest.go index 52c5fef91..0f59d4be5 100644 --- a/adapters/outboundgroup/urltest.go +++ b/adapter/outboundgroup/urltest.go @@ -5,8 +5,8 @@ import ( "encoding/json" "time" - "github.com/Dreamacro/clash/adapters/outbound" - "github.com/Dreamacro/clash/adapters/provider" + "github.com/Dreamacro/clash/adapter/outbound" + "github.com/Dreamacro/clash/adapter/provider" "github.com/Dreamacro/clash/common/singledo" C "github.com/Dreamacro/clash/constant" ) diff --git a/adapters/outboundgroup/util.go b/adapter/outboundgroup/util.go similarity index 100% rename from adapters/outboundgroup/util.go rename to adapter/outboundgroup/util.go diff --git a/adapters/outbound/parser.go b/adapter/parser.go similarity index 63% rename from adapters/outbound/parser.go rename to adapter/parser.go index f0f894da3..62d152259 100644 --- a/adapters/outbound/parser.go +++ b/adapter/parser.go @@ -1,8 +1,9 @@ -package outbound +package adapter import ( "fmt" + "github.com/Dreamacro/clash/adapter/outbound" "github.com/Dreamacro/clash/common/structure" C "github.com/Dreamacro/clash/constant" ) @@ -20,36 +21,36 @@ func ParseProxy(mapping map[string]interface{}) (C.Proxy, error) { ) switch proxyType { case "ss": - ssOption := &ShadowSocksOption{} + ssOption := &outbound.ShadowSocksOption{} err = decoder.Decode(mapping, ssOption) if err != nil { break } - proxy, err = NewShadowSocks(*ssOption) + proxy, err = outbound.NewShadowSocks(*ssOption) case "ssr": - ssrOption := &ShadowSocksROption{} + ssrOption := &outbound.ShadowSocksROption{} err = decoder.Decode(mapping, ssrOption) if err != nil { break } - proxy, err = NewShadowSocksR(*ssrOption) + proxy, err = outbound.NewShadowSocksR(*ssrOption) case "socks5": - socksOption := &Socks5Option{} + socksOption := &outbound.Socks5Option{} err = decoder.Decode(mapping, socksOption) if err != nil { break } - proxy = NewSocks5(*socksOption) + proxy = outbound.NewSocks5(*socksOption) case "http": - httpOption := &HttpOption{} + httpOption := &outbound.HttpOption{} err = decoder.Decode(mapping, httpOption) if err != nil { break } - proxy = NewHttp(*httpOption) + proxy = outbound.NewHttp(*httpOption) case "vmess": - vmessOption := &VmessOption{ - HTTPOpts: HTTPOptions{ + vmessOption := &outbound.VmessOption{ + HTTPOpts: outbound.HTTPOptions{ Method: "GET", Path: []string{"/"}, }, @@ -58,21 +59,21 @@ func ParseProxy(mapping map[string]interface{}) (C.Proxy, error) { if err != nil { break } - proxy, err = NewVmess(*vmessOption) + proxy, err = outbound.NewVmess(*vmessOption) case "snell": - snellOption := &SnellOption{} + snellOption := &outbound.SnellOption{} err = decoder.Decode(mapping, snellOption) if err != nil { break } - proxy, err = NewSnell(*snellOption) + proxy, err = outbound.NewSnell(*snellOption) case "trojan": - trojanOption := &TrojanOption{} + trojanOption := &outbound.TrojanOption{} err = decoder.Decode(mapping, trojanOption) if err != nil { break } - proxy, err = NewTrojan(*trojanOption) + proxy, err = outbound.NewTrojan(*trojanOption) default: return nil, fmt.Errorf("unsupport proxy type: %s", proxyType) } diff --git a/adapters/provider/fetcher.go b/adapter/provider/fetcher.go similarity index 100% rename from adapters/provider/fetcher.go rename to adapter/provider/fetcher.go diff --git a/adapters/provider/healthcheck.go b/adapter/provider/healthcheck.go similarity index 100% rename from adapters/provider/healthcheck.go rename to adapter/provider/healthcheck.go diff --git a/adapters/provider/parser.go b/adapter/provider/parser.go similarity index 100% rename from adapters/provider/parser.go rename to adapter/provider/parser.go diff --git a/adapters/provider/provider.go b/adapter/provider/provider.go similarity index 98% rename from adapters/provider/provider.go rename to adapter/provider/provider.go index 756a89d12..f87fe2a12 100644 --- a/adapters/provider/provider.go +++ b/adapter/provider/provider.go @@ -7,7 +7,7 @@ import ( "runtime" "time" - "github.com/Dreamacro/clash/adapters/outbound" + "github.com/Dreamacro/clash/adapter" C "github.com/Dreamacro/clash/constant" "gopkg.in/yaml.v2" @@ -133,7 +133,7 @@ func proxiesParse(buf []byte) (interface{}, error) { proxies := []C.Proxy{} for idx, mapping := range schema.Proxies { - proxy, err := outbound.ParseProxy(mapping) + proxy, err := adapter.ParseProxy(mapping) if err != nil { return nil, fmt.Errorf("proxy %d error: %w", idx, err) } diff --git a/adapters/provider/vehicle.go b/adapter/provider/vehicle.go similarity index 100% rename from adapters/provider/vehicle.go rename to adapter/provider/vehicle.go diff --git a/config/config.go b/config/config.go index 903316492..a256d2820 100644 --- a/config/config.go +++ b/config/config.go @@ -8,16 +8,17 @@ import ( "os" "strings" - "github.com/Dreamacro/clash/adapters/outbound" - "github.com/Dreamacro/clash/adapters/outboundgroup" - "github.com/Dreamacro/clash/adapters/provider" + "github.com/Dreamacro/clash/adapter" + "github.com/Dreamacro/clash/adapter/outbound" + "github.com/Dreamacro/clash/adapter/outboundgroup" + "github.com/Dreamacro/clash/adapter/provider" "github.com/Dreamacro/clash/component/auth" "github.com/Dreamacro/clash/component/fakeip" "github.com/Dreamacro/clash/component/trie" C "github.com/Dreamacro/clash/constant" "github.com/Dreamacro/clash/dns" "github.com/Dreamacro/clash/log" - R "github.com/Dreamacro/clash/rules" + R "github.com/Dreamacro/clash/rule" T "github.com/Dreamacro/clash/tunnel" yaml "gopkg.in/yaml.v2" @@ -274,13 +275,13 @@ func parseProxies(cfg *RawConfig) (proxies map[string]C.Proxy, providersMap map[ groupsConfig := cfg.ProxyGroup providersConfig := cfg.ProxyProvider - proxies["DIRECT"] = outbound.NewProxy(outbound.NewDirect()) - proxies["REJECT"] = outbound.NewProxy(outbound.NewReject()) + proxies["DIRECT"] = adapter.NewProxy(outbound.NewDirect()) + proxies["REJECT"] = adapter.NewProxy(outbound.NewReject()) proxyList = append(proxyList, "DIRECT", "REJECT") // parse proxy for idx, mapping := range proxiesConfig { - proxy, err := outbound.ParseProxy(mapping) + proxy, err := adapter.ParseProxy(mapping) if err != nil { return nil, nil, fmt.Errorf("proxy %d: %w", idx, err) } @@ -339,7 +340,7 @@ func parseProxies(cfg *RawConfig) (proxies map[string]C.Proxy, providersMap map[ return nil, nil, fmt.Errorf("proxy group %s: the duplicate name", groupName) } - proxies[groupName] = outbound.NewProxy(group) + proxies[groupName] = adapter.NewProxy(group) } // initial compatible provider @@ -368,7 +369,7 @@ func parseProxies(cfg *RawConfig) (proxies map[string]C.Proxy, providersMap map[ }, []provider.ProxyProvider{pd}, ) - proxies["GLOBAL"] = outbound.NewProxy(global) + proxies["GLOBAL"] = adapter.NewProxy(global) return proxies, providersMap, nil } diff --git a/config/utils.go b/config/utils.go index b3d198f7f..387591d0b 100644 --- a/config/utils.go +++ b/config/utils.go @@ -4,7 +4,7 @@ import ( "fmt" "strings" - "github.com/Dreamacro/clash/adapters/outboundgroup" + "github.com/Dreamacro/clash/adapter/outboundgroup" "github.com/Dreamacro/clash/common/structure" ) diff --git a/constant/adapters.go b/constant/adapters.go index 333243d8a..733d86b91 100644 --- a/constant/adapters.go +++ b/constant/adapters.go @@ -27,6 +27,10 @@ const ( LoadBalance ) +const ( + DefaultTCPTimeout = 5 * time.Second +) + type Connection interface { Chains() Chain AppendToChains(adapter ProxyAdapter) diff --git a/hub/executor/executor.go b/hub/executor/executor.go index caf75aff9..5d803106a 100644 --- a/hub/executor/executor.go +++ b/hub/executor/executor.go @@ -6,9 +6,9 @@ import ( "os" "sync" - "github.com/Dreamacro/clash/adapters/outbound" - "github.com/Dreamacro/clash/adapters/outboundgroup" - "github.com/Dreamacro/clash/adapters/provider" + "github.com/Dreamacro/clash/adapter" + "github.com/Dreamacro/clash/adapter/outboundgroup" + "github.com/Dreamacro/clash/adapter/provider" "github.com/Dreamacro/clash/component/auth" "github.com/Dreamacro/clash/component/dialer" "github.com/Dreamacro/clash/component/profile" @@ -232,7 +232,7 @@ func patchSelectGroup(proxies map[string]C.Proxy) { } for name, proxy := range proxies { - outbound, ok := proxy.(*outbound.Proxy) + outbound, ok := proxy.(*adapter.Proxy) if !ok { continue } diff --git a/hub/route/provider.go b/hub/route/provider.go index 902f13aff..f373d5114 100644 --- a/hub/route/provider.go +++ b/hub/route/provider.go @@ -4,7 +4,7 @@ import ( "context" "net/http" - "github.com/Dreamacro/clash/adapters/provider" + "github.com/Dreamacro/clash/adapter/provider" "github.com/Dreamacro/clash/tunnel" "github.com/go-chi/chi/v5" diff --git a/hub/route/proxies.go b/hub/route/proxies.go index e541223dd..bba9e2a80 100644 --- a/hub/route/proxies.go +++ b/hub/route/proxies.go @@ -7,8 +7,8 @@ import ( "strconv" "time" - "github.com/Dreamacro/clash/adapters/outbound" - "github.com/Dreamacro/clash/adapters/outboundgroup" + "github.com/Dreamacro/clash/adapter" + "github.com/Dreamacro/clash/adapter/outboundgroup" "github.com/Dreamacro/clash/component/profile/cachefile" C "github.com/Dreamacro/clash/constant" "github.com/Dreamacro/clash/tunnel" @@ -78,7 +78,7 @@ func updateProxy(w http.ResponseWriter, r *http.Request) { return } - proxy := r.Context().Value(CtxKeyProxy).(*outbound.Proxy) + proxy := r.Context().Value(CtxKeyProxy).(*adapter.Proxy) selector, ok := proxy.ProxyAdapter.(*outboundgroup.Selector) if !ok { render.Status(r, http.StatusBadRequest) diff --git a/proxy/http/server.go b/proxy/http/server.go index 75f4fc368..69117dbb8 100644 --- a/proxy/http/server.go +++ b/proxy/http/server.go @@ -8,7 +8,7 @@ import ( "strings" "time" - adapters "github.com/Dreamacro/clash/adapters/inbound" + "github.com/Dreamacro/clash/adapter/inbound" "github.com/Dreamacro/clash/common/cache" "github.com/Dreamacro/clash/component/auth" "github.com/Dreamacro/clash/log" @@ -106,9 +106,9 @@ keepAlive: conn.Close() return } - tunnel.Add(adapters.NewHTTPS(request, conn)) + tunnel.Add(inbound.NewHTTPS(request, conn)) return } - tunnel.Add(adapters.NewHTTP(request, conn)) + tunnel.Add(inbound.NewHTTP(request, conn)) } diff --git a/proxy/redir/tcp.go b/proxy/redir/tcp.go index e53d000d6..ef6718ec9 100644 --- a/proxy/redir/tcp.go +++ b/proxy/redir/tcp.go @@ -3,7 +3,7 @@ package redir import ( "net" - "github.com/Dreamacro/clash/adapters/inbound" + "github.com/Dreamacro/clash/adapter/inbound" C "github.com/Dreamacro/clash/constant" "github.com/Dreamacro/clash/log" "github.com/Dreamacro/clash/tunnel" diff --git a/proxy/redir/tproxy.go b/proxy/redir/tproxy.go index 576c4d37f..44682362f 100644 --- a/proxy/redir/tproxy.go +++ b/proxy/redir/tproxy.go @@ -3,7 +3,7 @@ package redir import ( "net" - "github.com/Dreamacro/clash/adapters/inbound" + "github.com/Dreamacro/clash/adapter/inbound" C "github.com/Dreamacro/clash/constant" "github.com/Dreamacro/clash/log" "github.com/Dreamacro/clash/transport/socks5" diff --git a/proxy/redir/udp.go b/proxy/redir/udp.go index 57bd3ff35..e43af878b 100644 --- a/proxy/redir/udp.go +++ b/proxy/redir/udp.go @@ -3,7 +3,7 @@ package redir import ( "net" - adapters "github.com/Dreamacro/clash/adapters/inbound" + "github.com/Dreamacro/clash/adapter/inbound" "github.com/Dreamacro/clash/common/pool" C "github.com/Dreamacro/clash/constant" "github.com/Dreamacro/clash/transport/socks5" @@ -75,5 +75,5 @@ func handleRedirUDP(pc net.PacketConn, buf []byte, lAddr *net.UDPAddr, rAddr *ne lAddr: lAddr, buf: buf, } - tunnel.AddPacket(adapters.NewPacket(target, pkt, C.TPROXY)) + tunnel.AddPacket(inbound.NewPacket(target, pkt, C.TPROXY)) } diff --git a/proxy/socks/tcp.go b/proxy/socks/tcp.go index 116ea3f6b..a58d63d18 100644 --- a/proxy/socks/tcp.go +++ b/proxy/socks/tcp.go @@ -5,7 +5,7 @@ import ( "io/ioutil" "net" - adapters "github.com/Dreamacro/clash/adapters/inbound" + "github.com/Dreamacro/clash/adapter/inbound" C "github.com/Dreamacro/clash/constant" "github.com/Dreamacro/clash/log" authStore "github.com/Dreamacro/clash/proxy/auth" @@ -66,5 +66,5 @@ func HandleSocks(conn net.Conn) { io.Copy(ioutil.Discard, conn) return } - tunnel.Add(adapters.NewSocket(target, conn, C.SOCKS)) + tunnel.Add(inbound.NewSocket(target, conn, C.SOCKS)) } diff --git a/proxy/socks/udp.go b/proxy/socks/udp.go index a365353b8..b41e6f18e 100644 --- a/proxy/socks/udp.go +++ b/proxy/socks/udp.go @@ -3,7 +3,7 @@ package socks import ( "net" - adapters "github.com/Dreamacro/clash/adapters/inbound" + "github.com/Dreamacro/clash/adapter/inbound" "github.com/Dreamacro/clash/common/pool" "github.com/Dreamacro/clash/common/sockopt" C "github.com/Dreamacro/clash/constant" @@ -70,5 +70,5 @@ func handleSocksUDP(pc net.PacketConn, buf []byte, addr net.Addr) { payload: payload, bufRef: buf, } - tunnel.AddPacket(adapters.NewPacket(target, packet, C.SOCKS)) + tunnel.AddPacket(inbound.NewPacket(target, packet, C.SOCKS)) } diff --git a/rules/base.go b/rule/base.go similarity index 100% rename from rules/base.go rename to rule/base.go diff --git a/rules/domain.go b/rule/domain.go similarity index 100% rename from rules/domain.go rename to rule/domain.go diff --git a/rules/domain_keyword.go b/rule/domain_keyword.go similarity index 100% rename from rules/domain_keyword.go rename to rule/domain_keyword.go diff --git a/rules/domain_suffix.go b/rule/domain_suffix.go similarity index 100% rename from rules/domain_suffix.go rename to rule/domain_suffix.go diff --git a/rules/final.go b/rule/final.go similarity index 100% rename from rules/final.go rename to rule/final.go diff --git a/rules/geoip.go b/rule/geoip.go similarity index 100% rename from rules/geoip.go rename to rule/geoip.go diff --git a/rules/ipcidr.go b/rule/ipcidr.go similarity index 100% rename from rules/ipcidr.go rename to rule/ipcidr.go diff --git a/rules/parser.go b/rule/parser.go similarity index 100% rename from rules/parser.go rename to rule/parser.go diff --git a/rules/port.go b/rule/port.go similarity index 100% rename from rules/port.go rename to rule/port.go diff --git a/rules/process.go b/rule/process.go similarity index 100% rename from rules/process.go rename to rule/process.go diff --git a/test/snell_test.go b/test/snell_test.go index 0d9e059a0..bc8b47aa7 100644 --- a/test/snell_test.go +++ b/test/snell_test.go @@ -5,7 +5,7 @@ import ( "testing" "time" - "github.com/Dreamacro/clash/adapters/outbound" + "github.com/Dreamacro/clash/adapter/outbound" C "github.com/Dreamacro/clash/constant" "github.com/docker/docker/api/types/container" diff --git a/test/ss_test.go b/test/ss_test.go index 6876d3fb5..ea33445c5 100644 --- a/test/ss_test.go +++ b/test/ss_test.go @@ -4,7 +4,7 @@ import ( "testing" "time" - "github.com/Dreamacro/clash/adapters/outbound" + "github.com/Dreamacro/clash/adapter/outbound" "github.com/docker/docker/api/types/container" "github.com/stretchr/testify/assert" diff --git a/test/trojan_test.go b/test/trojan_test.go index c20f12792..236b5af1e 100644 --- a/test/trojan_test.go +++ b/test/trojan_test.go @@ -5,7 +5,7 @@ import ( "testing" "time" - "github.com/Dreamacro/clash/adapters/outbound" + "github.com/Dreamacro/clash/adapter/outbound" C "github.com/Dreamacro/clash/constant" "github.com/docker/docker/api/types/container" diff --git a/test/vmess_test.go b/test/vmess_test.go index cf539bf89..92cb300e2 100644 --- a/test/vmess_test.go +++ b/test/vmess_test.go @@ -5,7 +5,7 @@ import ( "testing" "time" - "github.com/Dreamacro/clash/adapters/outbound" + "github.com/Dreamacro/clash/adapter/outbound" C "github.com/Dreamacro/clash/constant" "github.com/docker/docker/api/types/container" diff --git a/tunnel/connection.go b/tunnel/connection.go index 24314fb6c..2cc5964c3 100644 --- a/tunnel/connection.go +++ b/tunnel/connection.go @@ -9,7 +9,7 @@ import ( "strings" "time" - "github.com/Dreamacro/clash/adapters/inbound" + "github.com/Dreamacro/clash/adapter/inbound" N "github.com/Dreamacro/clash/common/net" "github.com/Dreamacro/clash/common/pool" "github.com/Dreamacro/clash/component/resolver" diff --git a/tunnel/tunnel.go b/tunnel/tunnel.go index 77c24d889..18551ae87 100644 --- a/tunnel/tunnel.go +++ b/tunnel/tunnel.go @@ -7,8 +7,8 @@ import ( "sync" "time" - "github.com/Dreamacro/clash/adapters/inbound" - "github.com/Dreamacro/clash/adapters/provider" + "github.com/Dreamacro/clash/adapter/inbound" + "github.com/Dreamacro/clash/adapter/provider" "github.com/Dreamacro/clash/component/nat" "github.com/Dreamacro/clash/component/resolver" C "github.com/Dreamacro/clash/constant" From bcfc15e3980aa227a7dbdf21f4e299df76c57df2 Mon Sep 17 00:00:00 2001 From: Fndroid Date: Thu, 10 Jun 2021 15:08:33 +0800 Subject: [PATCH 07/96] chore: expose udp field to proxies API (#1441) --- adapter/adapter.go | 1 + 1 file changed, 1 insertion(+) diff --git a/adapter/adapter.go b/adapter/adapter.go index f3503f04c..787a45b13 100644 --- a/adapter/adapter.go +++ b/adapter/adapter.go @@ -82,6 +82,7 @@ func (p *Proxy) MarshalJSON() ([]byte, error) { json.Unmarshal(inner, &mapping) mapping["history"] = p.DelayHistory() mapping["name"] = p.Name() + mapping["udp"] = p.SupportUDP() return json.Marshal(mapping) } From 6091fcdfece557284ef519816111e86537d56775 Mon Sep 17 00:00:00 2001 From: Dreamacro <8615343+Dreamacro@users.noreply.github.com> Date: Sun, 13 Jun 2021 17:23:10 +0800 Subject: [PATCH 08/96] Style: code style --- hub/executor/executor.go | 17 ++--- hub/route/configs.go | 16 +++-- {proxy => listener}/auth/auth.go | 0 {proxy => listener}/http/server.go | 25 ++++---- {proxy => listener}/listener.go | 62 +++++++++++-------- {proxy => listener}/mixed/conn.go | 0 {proxy => listener}/mixed/mixed.go | 26 ++++---- {proxy => listener}/redir/tcp.go | 19 +++--- {proxy => listener}/redir/tcp_darwin.go | 0 {proxy => listener}/redir/tcp_freebsd.go | 0 {proxy => listener}/redir/tcp_linux.go | 0 {proxy => listener}/redir/tcp_linux_386.go | 0 {proxy => listener}/redir/tcp_linux_other.go | 0 {proxy => listener}/redir/tcp_other.go | 0 {proxy => listener}/socks/tcp.go | 21 +++---- {proxy => listener}/socks/udp.go | 23 +++---- {proxy => listener}/socks/utils.go | 0 .../utils.go => listener/tproxy/packet.go | 2 +- .../tproxy/setsockopt_linux.go | 2 +- .../tproxy/setsockopt_other.go | 2 +- {proxy/redir => listener/tproxy}/tproxy.go | 21 +++---- {proxy/redir => listener/tproxy}/udp.go | 22 ++++--- .../tproxy/udp_linux.go | 30 ++++++++- .../tproxy/udp_other.go | 6 +- proxy/redir/udp_linux.go | 36 ----------- proxy/redir/udp_other.go | 12 ---- tunnel/tunnel.go | 15 ++--- 27 files changed, 171 insertions(+), 186 deletions(-) rename {proxy => listener}/auth/auth.go (100%) rename {proxy => listener}/http/server.go (79%) rename {proxy => listener}/listener.go (71%) rename {proxy => listener}/mixed/conn.go (100%) rename {proxy => listener}/mixed/mixed.go (52%) rename {proxy => listener}/redir/tcp.go (56%) rename {proxy => listener}/redir/tcp_darwin.go (100%) rename {proxy => listener}/redir/tcp_freebsd.go (100%) rename {proxy => listener}/redir/tcp_linux.go (100%) rename {proxy => listener}/redir/tcp_linux_386.go (100%) rename {proxy => listener}/redir/tcp_linux_other.go (100%) rename {proxy => listener}/redir/tcp_other.go (100%) rename {proxy => listener}/socks/tcp.go (63%) rename {proxy => listener}/socks/udp.go (66%) rename {proxy => listener}/socks/utils.go (100%) rename proxy/redir/utils.go => listener/tproxy/packet.go (97%) rename proxy/redir/tproxy_linux.go => listener/tproxy/setsockopt_linux.go (98%) rename proxy/redir/tproxy_other.go => listener/tproxy/setsockopt_other.go (91%) rename {proxy/redir => listener/tproxy}/tproxy.go (62%) rename {proxy/redir => listener/tproxy}/udp.go (66%) rename proxy/redir/utils_linux.go => listener/tproxy/udp_linux.go (71%) rename proxy/redir/utils_other.go => listener/tproxy/udp_other.go (58%) delete mode 100644 proxy/redir/udp_linux.go delete mode 100644 proxy/redir/udp_other.go diff --git a/hub/executor/executor.go b/hub/executor/executor.go index 5d803106a..81920221d 100644 --- a/hub/executor/executor.go +++ b/hub/executor/executor.go @@ -18,9 +18,9 @@ import ( "github.com/Dreamacro/clash/config" C "github.com/Dreamacro/clash/constant" "github.com/Dreamacro/clash/dns" + P "github.com/Dreamacro/clash/listener" + authStore "github.com/Dreamacro/clash/listener/auth" "github.com/Dreamacro/clash/log" - P "github.com/Dreamacro/clash/proxy" - authStore "github.com/Dreamacro/clash/proxy/auth" "github.com/Dreamacro/clash/tunnel" ) @@ -187,23 +187,26 @@ func updateGeneral(general *config.General, force bool) { bindAddress := general.BindAddress P.SetBindAddress(bindAddress) - if err := P.ReCreateHTTP(general.Port); err != nil { + tcpIn := tunnel.TCPIn() + udpIn := tunnel.UDPIn() + + if err := P.ReCreateHTTP(general.Port, tcpIn); err != nil { log.Errorln("Start HTTP server error: %s", err.Error()) } - if err := P.ReCreateSocks(general.SocksPort); err != nil { + if err := P.ReCreateSocks(general.SocksPort, tcpIn, udpIn); err != nil { log.Errorln("Start SOCKS5 server error: %s", err.Error()) } - if err := P.ReCreateRedir(general.RedirPort); err != nil { + 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); err != nil { + 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); err != nil { + if err := P.ReCreateMixed(general.MixedPort, tcpIn, udpIn); err != nil { log.Errorln("Start Mixed(http and socks5) server error: %s", err.Error()) } } diff --git a/hub/route/configs.go b/hub/route/configs.go index 84dd10a6b..315180f77 100644 --- a/hub/route/configs.go +++ b/hub/route/configs.go @@ -7,8 +7,8 @@ import ( "github.com/Dreamacro/clash/component/resolver" "github.com/Dreamacro/clash/config" "github.com/Dreamacro/clash/hub/executor" + P "github.com/Dreamacro/clash/listener" "github.com/Dreamacro/clash/log" - P "github.com/Dreamacro/clash/proxy" "github.com/Dreamacro/clash/tunnel" "github.com/go-chi/chi/v5" @@ -66,11 +66,15 @@ func patchConfigs(w http.ResponseWriter, r *http.Request) { } ports := P.GetPorts() - P.ReCreateHTTP(pointerOrDefault(general.Port, ports.Port)) - P.ReCreateSocks(pointerOrDefault(general.SocksPort, ports.SocksPort)) - P.ReCreateRedir(pointerOrDefault(general.RedirPort, ports.RedirPort)) - P.ReCreateTProxy(pointerOrDefault(general.TProxyPort, ports.TProxyPort)) - P.ReCreateMixed(pointerOrDefault(general.MixedPort, ports.MixedPort)) + + tcpIn := tunnel.TCPIn() + udpIn := tunnel.UDPIn() + + P.ReCreateHTTP(pointerOrDefault(general.Port, ports.Port), tcpIn) + P.ReCreateSocks(pointerOrDefault(general.SocksPort, ports.SocksPort), tcpIn, udpIn) + P.ReCreateRedir(pointerOrDefault(general.RedirPort, ports.RedirPort), tcpIn, udpIn) + P.ReCreateTProxy(pointerOrDefault(general.TProxyPort, ports.TProxyPort), tcpIn, udpIn) + P.ReCreateMixed(pointerOrDefault(general.MixedPort, ports.MixedPort), tcpIn, udpIn) if general.Mode != nil { tunnel.SetMode(*general.Mode) diff --git a/proxy/auth/auth.go b/listener/auth/auth.go similarity index 100% rename from proxy/auth/auth.go rename to listener/auth/auth.go diff --git a/proxy/http/server.go b/listener/http/server.go similarity index 79% rename from proxy/http/server.go rename to listener/http/server.go index 69117dbb8..e52b84a96 100644 --- a/proxy/http/server.go +++ b/listener/http/server.go @@ -11,28 +11,25 @@ import ( "github.com/Dreamacro/clash/adapter/inbound" "github.com/Dreamacro/clash/common/cache" "github.com/Dreamacro/clash/component/auth" + C "github.com/Dreamacro/clash/constant" + authStore "github.com/Dreamacro/clash/listener/auth" "github.com/Dreamacro/clash/log" - authStore "github.com/Dreamacro/clash/proxy/auth" - "github.com/Dreamacro/clash/tunnel" ) -type HTTPListener struct { +type Listener struct { net.Listener address string closed bool cache *cache.Cache } -func NewHTTPProxy(addr string) (*HTTPListener, error) { +func New(addr string, in chan<- C.ConnContext) (*Listener, error) { l, err := net.Listen("tcp", addr) if err != nil { return nil, err } - hl := &HTTPListener{l, addr, false, cache.New(30 * time.Second)} - + hl := &Listener{l, addr, false, cache.New(30 * time.Second)} go func() { - log.Infoln("HTTP proxy listening at: %s", addr) - for { c, err := hl.Accept() if err != nil { @@ -41,19 +38,19 @@ func NewHTTPProxy(addr string) (*HTTPListener, error) { } continue } - go HandleConn(c, hl.cache) + go HandleConn(c, in, hl.cache) } }() return hl, nil } -func (l *HTTPListener) Close() { +func (l *Listener) Close() { l.closed = true l.Listener.Close() } -func (l *HTTPListener) Address() string { +func (l *Listener) Address() string { return l.address } @@ -70,7 +67,7 @@ func canActivate(loginStr string, authenticator auth.Authenticator, cache *cache return } -func HandleConn(conn net.Conn, cache *cache.Cache) { +func HandleConn(conn net.Conn, in chan<- C.ConnContext, cache *cache.Cache) { br := bufio.NewReader(conn) keepAlive: @@ -106,9 +103,9 @@ keepAlive: conn.Close() return } - tunnel.Add(inbound.NewHTTPS(request, conn)) + in <- inbound.NewHTTPS(request, conn) return } - tunnel.Add(inbound.NewHTTP(request, conn)) + in <- inbound.NewHTTP(request, conn) } diff --git a/proxy/listener.go b/listener/listener.go similarity index 71% rename from proxy/listener.go rename to listener/listener.go index ec9b69f9d..cf0390e7e 100644 --- a/proxy/listener.go +++ b/listener/listener.go @@ -6,26 +6,29 @@ import ( "strconv" "sync" + "github.com/Dreamacro/clash/adapter/inbound" + C "github.com/Dreamacro/clash/constant" + "github.com/Dreamacro/clash/listener/http" + "github.com/Dreamacro/clash/listener/mixed" + "github.com/Dreamacro/clash/listener/redir" + "github.com/Dreamacro/clash/listener/socks" + "github.com/Dreamacro/clash/listener/tproxy" "github.com/Dreamacro/clash/log" - "github.com/Dreamacro/clash/proxy/http" - "github.com/Dreamacro/clash/proxy/mixed" - "github.com/Dreamacro/clash/proxy/redir" - "github.com/Dreamacro/clash/proxy/socks" ) var ( allowLan = false bindAddress = "*" - socksListener *socks.SockListener - socksUDPListener *socks.SockUDPListener - httpListener *http.HTTPListener - redirListener *redir.RedirListener - redirUDPListener *redir.RedirUDPListener - tproxyListener *redir.TProxyListener - tproxyUDPListener *redir.RedirUDPListener - mixedListener *mixed.MixedListener - mixedUDPLister *socks.SockUDPListener + socksListener *socks.Listener + socksUDPListener *socks.UDPListener + httpListener *http.Listener + redirListener *redir.Listener + redirUDPListener *tproxy.UDPListener + tproxyListener *tproxy.Listener + tproxyUDPListener *tproxy.UDPListener + mixedListener *mixed.Listener + mixedUDPLister *socks.UDPListener // lock for recreate function socksMux sync.Mutex @@ -59,7 +62,7 @@ func SetBindAddress(host string) { bindAddress = host } -func ReCreateHTTP(port int) error { +func ReCreateHTTP(port int, tcpIn chan<- C.ConnContext) error { httpMux.Lock() defer httpMux.Unlock() @@ -78,15 +81,16 @@ func ReCreateHTTP(port int) error { } var err error - httpListener, err = http.NewHTTPProxy(addr) + httpListener, err = http.New(addr, tcpIn) if err != nil { return err } + log.Infoln("HTTP proxy listening at: %s", httpListener.Address()) return nil } -func ReCreateSocks(port int) error { +func ReCreateSocks(port int, tcpIn chan<- C.ConnContext, udpIn chan<- *inbound.PacketAdapter) error { socksMux.Lock() defer socksMux.Unlock() @@ -121,12 +125,12 @@ func ReCreateSocks(port int) error { return nil } - tcpListener, err := socks.NewSocksProxy(addr) + tcpListener, err := socks.New(addr, tcpIn) if err != nil { return err } - udpListener, err := socks.NewSocksUDPProxy(addr) + udpListener, err := socks.NewUDP(addr, udpIn) if err != nil { tcpListener.Close() return err @@ -135,10 +139,11 @@ func ReCreateSocks(port int) error { socksListener = tcpListener socksUDPListener = udpListener + log.Infoln("SOCKS5 proxy listening at: %s", socksListener.Address()) return nil } -func ReCreateRedir(port int) error { +func ReCreateRedir(port int, tcpIn chan<- C.ConnContext, udpIn chan<- *inbound.PacketAdapter) error { redirMux.Lock() defer redirMux.Unlock() @@ -165,20 +170,21 @@ func ReCreateRedir(port int) error { } var err error - redirListener, err = redir.NewRedirProxy(addr) + redirListener, err = redir.New(addr, tcpIn) if err != nil { return err } - redirUDPListener, err = redir.NewRedirUDPProxy(addr) + redirUDPListener, err = tproxy.NewUDP(addr, udpIn) if err != nil { log.Warnln("Failed to start Redir UDP Listener: %s", err) } + log.Infoln("Redirect proxy listening at: %s", redirListener.Address()) return nil } -func ReCreateTProxy(port int) error { +func ReCreateTProxy(port int, tcpIn chan<- C.ConnContext, udpIn chan<- *inbound.PacketAdapter) error { tproxyMux.Lock() defer tproxyMux.Unlock() @@ -205,20 +211,21 @@ func ReCreateTProxy(port int) error { } var err error - tproxyListener, err = redir.NewTProxy(addr) + tproxyListener, err = tproxy.New(addr, tcpIn) if err != nil { return err } - tproxyUDPListener, err = redir.NewRedirUDPProxy(addr) + tproxyUDPListener, err = tproxy.NewUDP(addr, udpIn) if err != nil { log.Warnln("Failed to start TProxy UDP Listener: %s", err) } + log.Infoln("TProxy server listening at: %s", tproxyListener.Address()) return nil } -func ReCreateMixed(port int) error { +func ReCreateMixed(port int, tcpIn chan<- C.ConnContext, udpIn chan<- *inbound.PacketAdapter) error { mixedMux.Lock() defer mixedMux.Unlock() @@ -253,17 +260,18 @@ func ReCreateMixed(port int) error { } var err error - mixedListener, err = mixed.NewMixedProxy(addr) + mixedListener, err = mixed.New(addr, tcpIn) if err != nil { return err } - mixedUDPLister, err = socks.NewSocksUDPProxy(addr) + mixedUDPLister, err = socks.NewUDP(addr, udpIn) if err != nil { mixedListener.Close() return err } + log.Infoln("Mixed(http+socks5) proxy listening at: %s", mixedListener.Address()) return nil } diff --git a/proxy/mixed/conn.go b/listener/mixed/conn.go similarity index 100% rename from proxy/mixed/conn.go rename to listener/mixed/conn.go diff --git a/proxy/mixed/mixed.go b/listener/mixed/mixed.go similarity index 52% rename from proxy/mixed/mixed.go rename to listener/mixed/mixed.go index b89748eea..b930d0682 100644 --- a/proxy/mixed/mixed.go +++ b/listener/mixed/mixed.go @@ -5,29 +5,27 @@ import ( "time" "github.com/Dreamacro/clash/common/cache" - "github.com/Dreamacro/clash/log" - "github.com/Dreamacro/clash/proxy/http" - "github.com/Dreamacro/clash/proxy/socks" + C "github.com/Dreamacro/clash/constant" + "github.com/Dreamacro/clash/listener/http" + "github.com/Dreamacro/clash/listener/socks" "github.com/Dreamacro/clash/transport/socks5" ) -type MixedListener struct { +type Listener struct { net.Listener address string closed bool cache *cache.Cache } -func NewMixedProxy(addr string) (*MixedListener, error) { +func New(addr string, in chan<- C.ConnContext) (*Listener, error) { l, err := net.Listen("tcp", addr) if err != nil { return nil, err } - ml := &MixedListener{l, addr, false, cache.New(30 * time.Second)} + ml := &Listener{l, addr, false, cache.New(30 * time.Second)} go func() { - log.Infoln("Mixed(http+socks5) proxy listening at: %s", addr) - for { c, err := ml.Accept() if err != nil { @@ -36,23 +34,23 @@ func NewMixedProxy(addr string) (*MixedListener, error) { } continue } - go handleConn(c, ml.cache) + go handleConn(c, in, ml.cache) } }() return ml, nil } -func (l *MixedListener) Close() { +func (l *Listener) Close() { l.closed = true l.Listener.Close() } -func (l *MixedListener) Address() string { +func (l *Listener) Address() string { return l.address } -func handleConn(conn net.Conn, cache *cache.Cache) { +func handleConn(conn net.Conn, in chan<- C.ConnContext, cache *cache.Cache) { bufConn := NewBufferedConn(conn) head, err := bufConn.Peek(1) if err != nil { @@ -60,9 +58,9 @@ func handleConn(conn net.Conn, cache *cache.Cache) { } if head[0] == socks5.Version { - socks.HandleSocks(bufConn) + socks.HandleSocks(bufConn, in) return } - http.HandleConn(bufConn, cache) + http.HandleConn(bufConn, in, cache) } diff --git a/proxy/redir/tcp.go b/listener/redir/tcp.go similarity index 56% rename from proxy/redir/tcp.go rename to listener/redir/tcp.go index ef6718ec9..a54bfff87 100644 --- a/proxy/redir/tcp.go +++ b/listener/redir/tcp.go @@ -5,25 +5,22 @@ import ( "github.com/Dreamacro/clash/adapter/inbound" C "github.com/Dreamacro/clash/constant" - "github.com/Dreamacro/clash/log" - "github.com/Dreamacro/clash/tunnel" ) -type RedirListener struct { +type Listener struct { net.Listener address string closed bool } -func NewRedirProxy(addr string) (*RedirListener, error) { +func New(addr string, in chan<- C.ConnContext) (*Listener, error) { l, err := net.Listen("tcp", addr) if err != nil { return nil, err } - rl := &RedirListener{l, addr, false} + rl := &Listener{l, addr, false} go func() { - log.Infoln("Redir proxy listening at: %s", addr) for { c, err := l.Accept() if err != nil { @@ -32,28 +29,28 @@ func NewRedirProxy(addr string) (*RedirListener, error) { } continue } - go handleRedir(c) + go handleRedir(c, in) } }() return rl, nil } -func (l *RedirListener) Close() { +func (l *Listener) Close() { l.closed = true l.Listener.Close() } -func (l *RedirListener) Address() string { +func (l *Listener) Address() string { return l.address } -func handleRedir(conn net.Conn) { +func handleRedir(conn net.Conn, in chan<- C.ConnContext) { target, err := parserPacket(conn) if err != nil { conn.Close() return } conn.(*net.TCPConn).SetKeepAlive(true) - tunnel.Add(inbound.NewSocket(target, conn, C.REDIR)) + in <- inbound.NewSocket(target, conn, C.REDIR) } diff --git a/proxy/redir/tcp_darwin.go b/listener/redir/tcp_darwin.go similarity index 100% rename from proxy/redir/tcp_darwin.go rename to listener/redir/tcp_darwin.go diff --git a/proxy/redir/tcp_freebsd.go b/listener/redir/tcp_freebsd.go similarity index 100% rename from proxy/redir/tcp_freebsd.go rename to listener/redir/tcp_freebsd.go diff --git a/proxy/redir/tcp_linux.go b/listener/redir/tcp_linux.go similarity index 100% rename from proxy/redir/tcp_linux.go rename to listener/redir/tcp_linux.go diff --git a/proxy/redir/tcp_linux_386.go b/listener/redir/tcp_linux_386.go similarity index 100% rename from proxy/redir/tcp_linux_386.go rename to listener/redir/tcp_linux_386.go diff --git a/proxy/redir/tcp_linux_other.go b/listener/redir/tcp_linux_other.go similarity index 100% rename from proxy/redir/tcp_linux_other.go rename to listener/redir/tcp_linux_other.go diff --git a/proxy/redir/tcp_other.go b/listener/redir/tcp_other.go similarity index 100% rename from proxy/redir/tcp_other.go rename to listener/redir/tcp_other.go diff --git a/proxy/socks/tcp.go b/listener/socks/tcp.go similarity index 63% rename from proxy/socks/tcp.go rename to listener/socks/tcp.go index a58d63d18..eca36f0fb 100644 --- a/proxy/socks/tcp.go +++ b/listener/socks/tcp.go @@ -7,27 +7,24 @@ import ( "github.com/Dreamacro/clash/adapter/inbound" C "github.com/Dreamacro/clash/constant" - "github.com/Dreamacro/clash/log" - authStore "github.com/Dreamacro/clash/proxy/auth" + authStore "github.com/Dreamacro/clash/listener/auth" "github.com/Dreamacro/clash/transport/socks5" - "github.com/Dreamacro/clash/tunnel" ) -type SockListener struct { +type Listener struct { net.Listener address string closed bool } -func NewSocksProxy(addr string) (*SockListener, error) { +func New(addr string, in chan<- C.ConnContext) (*Listener, error) { l, err := net.Listen("tcp", addr) if err != nil { return nil, err } - sl := &SockListener{l, addr, false} + sl := &Listener{l, addr, false} go func() { - log.Infoln("SOCKS proxy listening at: %s", addr) for { c, err := l.Accept() if err != nil { @@ -36,23 +33,23 @@ func NewSocksProxy(addr string) (*SockListener, error) { } continue } - go HandleSocks(c) + go HandleSocks(c, in) } }() return sl, nil } -func (l *SockListener) Close() { +func (l *Listener) Close() { l.closed = true l.Listener.Close() } -func (l *SockListener) Address() string { +func (l *Listener) Address() string { return l.address } -func HandleSocks(conn net.Conn) { +func HandleSocks(conn net.Conn, in chan<- C.ConnContext) { target, command, err := socks5.ServerHandshake(conn, authStore.Authenticator()) if err != nil { conn.Close() @@ -66,5 +63,5 @@ func HandleSocks(conn net.Conn) { io.Copy(ioutil.Discard, conn) return } - tunnel.Add(inbound.NewSocket(target, conn, C.SOCKS)) + in <- inbound.NewSocket(target, conn, C.SOCKS) } diff --git a/proxy/socks/udp.go b/listener/socks/udp.go similarity index 66% rename from proxy/socks/udp.go rename to listener/socks/udp.go index b41e6f18e..7ddeed202 100644 --- a/proxy/socks/udp.go +++ b/listener/socks/udp.go @@ -9,27 +9,25 @@ import ( C "github.com/Dreamacro/clash/constant" "github.com/Dreamacro/clash/log" "github.com/Dreamacro/clash/transport/socks5" - "github.com/Dreamacro/clash/tunnel" ) -type SockUDPListener struct { +type UDPListener struct { net.PacketConn address string closed bool } -func NewSocksUDPProxy(addr string) (*SockUDPListener, error) { +func NewUDP(addr string, in chan<- *inbound.PacketAdapter) (*UDPListener, error) { l, err := net.ListenPacket("udp", addr) if err != nil { return nil, err } - err = sockopt.UDPReuseaddr(l.(*net.UDPConn)) - if err != nil { + if err := sockopt.UDPReuseaddr(l.(*net.UDPConn)); err != nil { log.Warnln("Failed to Reuse UDP Address: %s", err) } - sl := &SockUDPListener{l, addr, false} + sl := &UDPListener{l, addr, false} go func() { for { buf := pool.Get(pool.RelayBufferSize) @@ -41,23 +39,23 @@ func NewSocksUDPProxy(addr string) (*SockUDPListener, error) { } continue } - handleSocksUDP(l, buf[:n], remoteAddr) + handleSocksUDP(l, in, buf[:n], remoteAddr) } }() return sl, nil } -func (l *SockUDPListener) Close() error { +func (l *UDPListener) Close() error { l.closed = true return l.PacketConn.Close() } -func (l *SockUDPListener) Address() string { +func (l *UDPListener) Address() string { return l.address } -func handleSocksUDP(pc net.PacketConn, buf []byte, addr net.Addr) { +func handleSocksUDP(pc net.PacketConn, in chan<- *inbound.PacketAdapter, buf []byte, addr net.Addr) { target, payload, err := socks5.DecodeUDPPacket(buf) if err != nil { // Unresolved UDP packet, return buffer to the pool @@ -70,5 +68,8 @@ func handleSocksUDP(pc net.PacketConn, buf []byte, addr net.Addr) { payload: payload, bufRef: buf, } - tunnel.AddPacket(inbound.NewPacket(target, packet, C.SOCKS)) + select { + case in <- inbound.NewPacket(target, packet, C.TPROXY): + default: + } } diff --git a/proxy/socks/utils.go b/listener/socks/utils.go similarity index 100% rename from proxy/socks/utils.go rename to listener/socks/utils.go diff --git a/proxy/redir/utils.go b/listener/tproxy/packet.go similarity index 97% rename from proxy/redir/utils.go rename to listener/tproxy/packet.go index 58e30b0ce..8aa3e9bf4 100644 --- a/proxy/redir/utils.go +++ b/listener/tproxy/packet.go @@ -1,4 +1,4 @@ -package redir +package tproxy import ( "net" diff --git a/proxy/redir/tproxy_linux.go b/listener/tproxy/setsockopt_linux.go similarity index 98% rename from proxy/redir/tproxy_linux.go rename to listener/tproxy/setsockopt_linux.go index 22f8b46b2..a70223f7f 100644 --- a/proxy/redir/tproxy_linux.go +++ b/listener/tproxy/setsockopt_linux.go @@ -1,6 +1,6 @@ // +build linux -package redir +package tproxy import ( "net" diff --git a/proxy/redir/tproxy_other.go b/listener/tproxy/setsockopt_other.go similarity index 91% rename from proxy/redir/tproxy_other.go rename to listener/tproxy/setsockopt_other.go index c20ea7d72..059477284 100644 --- a/proxy/redir/tproxy_other.go +++ b/listener/tproxy/setsockopt_other.go @@ -1,6 +1,6 @@ // +build !linux -package redir +package tproxy import ( "errors" diff --git a/proxy/redir/tproxy.go b/listener/tproxy/tproxy.go similarity index 62% rename from proxy/redir/tproxy.go rename to listener/tproxy/tproxy.go index 44682362f..a787b3595 100644 --- a/proxy/redir/tproxy.go +++ b/listener/tproxy/tproxy.go @@ -1,22 +1,20 @@ -package redir +package tproxy import ( "net" "github.com/Dreamacro/clash/adapter/inbound" C "github.com/Dreamacro/clash/constant" - "github.com/Dreamacro/clash/log" "github.com/Dreamacro/clash/transport/socks5" - "github.com/Dreamacro/clash/tunnel" ) -type TProxyListener struct { +type Listener struct { net.Listener address string closed bool } -func NewTProxy(addr string) (*TProxyListener, error) { +func New(addr string, in chan<- C.ConnContext) (*Listener, error) { l, err := net.Listen("tcp", addr) if err != nil { return nil, err @@ -33,13 +31,12 @@ func NewTProxy(addr string) (*TProxyListener, error) { return nil, err } - rl := &TProxyListener{ + rl := &Listener{ Listener: l, address: addr, } go func() { - log.Infoln("TProxy server listening at: %s", addr) for { c, err := l.Accept() if err != nil { @@ -48,24 +45,24 @@ func NewTProxy(addr string) (*TProxyListener, error) { } continue } - go rl.handleTProxy(c) + go rl.handleTProxy(c, in) } }() return rl, nil } -func (l *TProxyListener) Close() { +func (l *Listener) Close() { l.closed = true l.Listener.Close() } -func (l *TProxyListener) Address() string { +func (l *Listener) Address() string { return l.address } -func (l *TProxyListener) handleTProxy(conn net.Conn) { +func (l *Listener) handleTProxy(conn net.Conn, in chan<- C.ConnContext) { target := socks5.ParseAddrToSocksAddr(conn.LocalAddr()) conn.(*net.TCPConn).SetKeepAlive(true) - tunnel.Add(inbound.NewSocket(target, conn, C.TPROXY)) + in <- inbound.NewSocket(target, conn, C.TPROXY) } diff --git a/proxy/redir/udp.go b/listener/tproxy/udp.go similarity index 66% rename from proxy/redir/udp.go rename to listener/tproxy/udp.go index e43af878b..881250164 100644 --- a/proxy/redir/udp.go +++ b/listener/tproxy/udp.go @@ -1,4 +1,4 @@ -package redir +package tproxy import ( "net" @@ -7,22 +7,21 @@ import ( "github.com/Dreamacro/clash/common/pool" C "github.com/Dreamacro/clash/constant" "github.com/Dreamacro/clash/transport/socks5" - "github.com/Dreamacro/clash/tunnel" ) -type RedirUDPListener struct { +type UDPListener struct { net.PacketConn address string closed bool } -func NewRedirUDPProxy(addr string) (*RedirUDPListener, error) { +func NewUDP(addr string, in chan<- *inbound.PacketAdapter) (*UDPListener, error) { l, err := net.ListenPacket("udp", addr) if err != nil { return nil, err } - rl := &RedirUDPListener{l, addr, false} + rl := &UDPListener{l, addr, false} c := l.(*net.UDPConn) @@ -53,27 +52,30 @@ func NewRedirUDPProxy(addr string) (*RedirUDPListener, error) { if err != nil { continue } - handleRedirUDP(l, buf[:n], lAddr, rAddr) + handlePacketConn(l, in, buf[:n], lAddr, rAddr) } }() return rl, nil } -func (l *RedirUDPListener) Close() error { +func (l *UDPListener) Close() error { l.closed = true return l.PacketConn.Close() } -func (l *RedirUDPListener) Address() string { +func (l *UDPListener) Address() string { return l.address } -func handleRedirUDP(pc net.PacketConn, buf []byte, lAddr *net.UDPAddr, rAddr *net.UDPAddr) { +func handlePacketConn(pc net.PacketConn, in chan<- *inbound.PacketAdapter, buf []byte, lAddr *net.UDPAddr, rAddr *net.UDPAddr) { target := socks5.ParseAddrToSocksAddr(rAddr) pkt := &packet{ lAddr: lAddr, buf: buf, } - tunnel.AddPacket(inbound.NewPacket(target, pkt, C.TPROXY)) + select { + case in <- inbound.NewPacket(target, pkt, C.TPROXY): + default: + } } diff --git a/proxy/redir/utils_linux.go b/listener/tproxy/udp_linux.go similarity index 71% rename from proxy/redir/utils_linux.go rename to listener/tproxy/udp_linux.go index 888601a48..40c177e7e 100644 --- a/proxy/redir/utils_linux.go +++ b/listener/tproxy/udp_linux.go @@ -1,8 +1,10 @@ // +build linux -package redir +package tproxy import ( + "encoding/binary" + "errors" "fmt" "net" "os" @@ -10,6 +12,11 @@ import ( "syscall" ) +const ( + IPV6_TRANSPARENT = 0x4b + IPV6_RECVORIGDSTADDR = 0x4a +) + // dialUDP acts like net.DialUDP for transparent proxy. // It binds to a non-local address(`lAddr`). func dialUDP(network string, lAddr *net.UDPAddr, rAddr *net.UDPAddr) (*net.UDPConn, error) { @@ -94,3 +101,24 @@ func udpAddrFamily(net string, lAddr, rAddr *net.UDPAddr) int { } return syscall.AF_INET6 } + +func getOrigDst(oob []byte, oobn int) (*net.UDPAddr, error) { + msgs, err := syscall.ParseSocketControlMessage(oob[:oobn]) + if err != nil { + return nil, err + } + + for _, msg := range msgs { + if msg.Header.Level == syscall.SOL_IP && msg.Header.Type == syscall.IP_RECVORIGDSTADDR { + ip := net.IP(msg.Data[4:8]) + port := binary.BigEndian.Uint16(msg.Data[2:4]) + return &net.UDPAddr{IP: ip, Port: int(port)}, nil + } else if msg.Header.Level == syscall.SOL_IPV6 && msg.Header.Type == IPV6_RECVORIGDSTADDR { + ip := net.IP(msg.Data[8:24]) + port := binary.BigEndian.Uint16(msg.Data[2:4]) + return &net.UDPAddr{IP: ip, Port: int(port)}, nil + } + } + + return nil, errors.New("cannot find origDst") +} diff --git a/proxy/redir/utils_other.go b/listener/tproxy/udp_other.go similarity index 58% rename from proxy/redir/utils_other.go rename to listener/tproxy/udp_other.go index faec71e27..a4531b5d0 100644 --- a/proxy/redir/utils_other.go +++ b/listener/tproxy/udp_other.go @@ -1,12 +1,16 @@ // +build !linux -package redir +package tproxy import ( "errors" "net" ) +func getOrigDst(oob []byte, oobn int) (*net.UDPAddr, error) { + return nil, errors.New("UDP redir not supported on current platform") +} + func dialUDP(network string, lAddr *net.UDPAddr, rAddr *net.UDPAddr) (*net.UDPConn, error) { return nil, errors.New("UDP redir not supported on current platform") } diff --git a/proxy/redir/udp_linux.go b/proxy/redir/udp_linux.go deleted file mode 100644 index e5a53e4da..000000000 --- a/proxy/redir/udp_linux.go +++ /dev/null @@ -1,36 +0,0 @@ -// +build linux - -package redir - -import ( - "encoding/binary" - "errors" - "net" - "syscall" -) - -const ( - IPV6_TRANSPARENT = 0x4b - IPV6_RECVORIGDSTADDR = 0x4a -) - -func getOrigDst(oob []byte, oobn int) (*net.UDPAddr, error) { - msgs, err := syscall.ParseSocketControlMessage(oob[:oobn]) - if err != nil { - return nil, err - } - - for _, msg := range msgs { - if msg.Header.Level == syscall.SOL_IP && msg.Header.Type == syscall.IP_RECVORIGDSTADDR { - ip := net.IP(msg.Data[4:8]) - port := binary.BigEndian.Uint16(msg.Data[2:4]) - return &net.UDPAddr{IP: ip, Port: int(port)}, nil - } else if msg.Header.Level == syscall.SOL_IPV6 && msg.Header.Type == IPV6_RECVORIGDSTADDR { - ip := net.IP(msg.Data[8:24]) - port := binary.BigEndian.Uint16(msg.Data[2:4]) - return &net.UDPAddr{IP: ip, Port: int(port)}, nil - } - } - - return nil, errors.New("cannot find origDst") -} diff --git a/proxy/redir/udp_other.go b/proxy/redir/udp_other.go deleted file mode 100644 index e50ec5b97..000000000 --- a/proxy/redir/udp_other.go +++ /dev/null @@ -1,12 +0,0 @@ -// +build !linux - -package redir - -import ( - "errors" - "net" -) - -func getOrigDst(oob []byte, oobn int) (*net.UDPAddr, error) { - return nil, errors.New("UDP redir not supported on current platform") -} diff --git a/tunnel/tunnel.go b/tunnel/tunnel.go index 18551ae87..a9ffb61fc 100644 --- a/tunnel/tunnel.go +++ b/tunnel/tunnel.go @@ -37,17 +37,14 @@ func init() { go process() } -// Add request to queue -func Add(ctx C.ConnContext) { - tcpQueue <- ctx +// TCPIn return fan-in queue +func TCPIn() chan<- C.ConnContext { + return tcpQueue } -// AddPacket add udp Packet to queue -func AddPacket(packet *inbound.PacketAdapter) { - select { - case udpQueue <- packet: - default: - } +// UDPIn return fan-in udp queue +func UDPIn() chan<- *inbound.PacketAdapter { + return udpQueue } // Rules return all rules From f231a63e9322198deb8e4e65afd3572344f62d31 Mon Sep 17 00:00:00 2001 From: Dreamacro <8615343+Dreamacro@users.noreply.github.com> Date: Sun, 13 Jun 2021 23:05:22 +0800 Subject: [PATCH 09/96] Chore: Listener should not expose original net.Listener --- listener/http/server.go | 12 ++++++------ listener/mixed/mixed.go | 12 ++++++------ listener/redir/tcp.go | 8 ++++---- listener/socks/tcp.go | 8 ++++---- listener/socks/udp.go | 8 ++++---- listener/tproxy/tproxy.go | 10 +++++----- listener/tproxy/udp.go | 8 ++++---- 7 files changed, 33 insertions(+), 33 deletions(-) diff --git a/listener/http/server.go b/listener/http/server.go index e52b84a96..a77e01daa 100644 --- a/listener/http/server.go +++ b/listener/http/server.go @@ -17,10 +17,10 @@ import ( ) type Listener struct { - net.Listener - address string - closed bool - cache *cache.Cache + listener net.Listener + address string + closed bool + cache *cache.Cache } func New(addr string, in chan<- C.ConnContext) (*Listener, error) { @@ -31,7 +31,7 @@ func New(addr string, in chan<- C.ConnContext) (*Listener, error) { hl := &Listener{l, addr, false, cache.New(30 * time.Second)} go func() { for { - c, err := hl.Accept() + c, err := hl.listener.Accept() if err != nil { if hl.closed { break @@ -47,7 +47,7 @@ func New(addr string, in chan<- C.ConnContext) (*Listener, error) { func (l *Listener) Close() { l.closed = true - l.Listener.Close() + l.listener.Close() } func (l *Listener) Address() string { diff --git a/listener/mixed/mixed.go b/listener/mixed/mixed.go index b930d0682..3c4b49a84 100644 --- a/listener/mixed/mixed.go +++ b/listener/mixed/mixed.go @@ -12,10 +12,10 @@ import ( ) type Listener struct { - net.Listener - address string - closed bool - cache *cache.Cache + listener net.Listener + address string + closed bool + cache *cache.Cache } func New(addr string, in chan<- C.ConnContext) (*Listener, error) { @@ -27,7 +27,7 @@ func New(addr string, in chan<- C.ConnContext) (*Listener, error) { ml := &Listener{l, addr, false, cache.New(30 * time.Second)} go func() { for { - c, err := ml.Accept() + c, err := ml.listener.Accept() if err != nil { if ml.closed { break @@ -43,7 +43,7 @@ func New(addr string, in chan<- C.ConnContext) (*Listener, error) { func (l *Listener) Close() { l.closed = true - l.Listener.Close() + l.listener.Close() } func (l *Listener) Address() string { diff --git a/listener/redir/tcp.go b/listener/redir/tcp.go index a54bfff87..372688409 100644 --- a/listener/redir/tcp.go +++ b/listener/redir/tcp.go @@ -8,9 +8,9 @@ import ( ) type Listener struct { - net.Listener - address string - closed bool + listener net.Listener + address string + closed bool } func New(addr string, in chan<- C.ConnContext) (*Listener, error) { @@ -38,7 +38,7 @@ func New(addr string, in chan<- C.ConnContext) (*Listener, error) { func (l *Listener) Close() { l.closed = true - l.Listener.Close() + l.listener.Close() } func (l *Listener) Address() string { diff --git a/listener/socks/tcp.go b/listener/socks/tcp.go index eca36f0fb..8e12ac71d 100644 --- a/listener/socks/tcp.go +++ b/listener/socks/tcp.go @@ -12,9 +12,9 @@ import ( ) type Listener struct { - net.Listener - address string - closed bool + listener net.Listener + address string + closed bool } func New(addr string, in chan<- C.ConnContext) (*Listener, error) { @@ -42,7 +42,7 @@ func New(addr string, in chan<- C.ConnContext) (*Listener, error) { func (l *Listener) Close() { l.closed = true - l.Listener.Close() + l.listener.Close() } func (l *Listener) Address() string { diff --git a/listener/socks/udp.go b/listener/socks/udp.go index 7ddeed202..b98ae897a 100644 --- a/listener/socks/udp.go +++ b/listener/socks/udp.go @@ -12,9 +12,9 @@ import ( ) type UDPListener struct { - net.PacketConn - address string - closed bool + packetConn net.PacketConn + address string + closed bool } func NewUDP(addr string, in chan<- *inbound.PacketAdapter) (*UDPListener, error) { @@ -48,7 +48,7 @@ func NewUDP(addr string, in chan<- *inbound.PacketAdapter) (*UDPListener, error) func (l *UDPListener) Close() error { l.closed = true - return l.PacketConn.Close() + return l.packetConn.Close() } func (l *UDPListener) Address() string { diff --git a/listener/tproxy/tproxy.go b/listener/tproxy/tproxy.go index a787b3595..142336fe8 100644 --- a/listener/tproxy/tproxy.go +++ b/listener/tproxy/tproxy.go @@ -9,9 +9,9 @@ import ( ) type Listener struct { - net.Listener - address string - closed bool + listener net.Listener + address string + closed bool } func New(addr string, in chan<- C.ConnContext) (*Listener, error) { @@ -32,7 +32,7 @@ func New(addr string, in chan<- C.ConnContext) (*Listener, error) { } rl := &Listener{ - Listener: l, + listener: l, address: addr, } @@ -54,7 +54,7 @@ func New(addr string, in chan<- C.ConnContext) (*Listener, error) { func (l *Listener) Close() { l.closed = true - l.Listener.Close() + l.listener.Close() } func (l *Listener) Address() string { diff --git a/listener/tproxy/udp.go b/listener/tproxy/udp.go index 881250164..20c2e0836 100644 --- a/listener/tproxy/udp.go +++ b/listener/tproxy/udp.go @@ -10,9 +10,9 @@ import ( ) type UDPListener struct { - net.PacketConn - address string - closed bool + packetConn net.PacketConn + address string + closed bool } func NewUDP(addr string, in chan<- *inbound.PacketAdapter) (*UDPListener, error) { @@ -61,7 +61,7 @@ func NewUDP(addr string, in chan<- *inbound.PacketAdapter) (*UDPListener, error) func (l *UDPListener) Close() error { l.closed = true - return l.PacketConn.Close() + return l.packetConn.Close() } func (l *UDPListener) Address() string { From 70d53fd45aa33e0dfbbf4c885f80181896624151 Mon Sep 17 00:00:00 2001 From: Dreamacro <8615343+Dreamacro@users.noreply.github.com> Date: Sun, 13 Jun 2021 23:11:49 +0800 Subject: [PATCH 10/96] Chore: update development wiki to README.md --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index f2dbf7228..b948b49d0 100644 --- a/README.md +++ b/README.md @@ -40,6 +40,9 @@ Documentations are now moved to [GitHub Wiki](https://github.com/Dreamacro/clash ## Premium Release [Release](https://github.com/Dreamacro/clash/releases/tag/premium) +## Development +If you want to build an application that uses clash as a library, check out the the [GitHub Wiki](https://github.com/Dreamacro/clash/wiki/use-clash-as-a-library) + ## Credits * [riobard/go-shadowsocks2](https://github.com/riobard/go-shadowsocks2) From b6ff08074c858bb78d6fd670b9ce137c41dd25e9 Mon Sep 17 00:00:00 2001 From: Kr328 Date: Tue, 15 Jun 2021 17:13:40 +0800 Subject: [PATCH 11/96] Refactor: plain http proxy (#1443) --- adapter/inbound/http.go | 52 +------ .../mixed/conn.go => common/net/bufconn.go | 2 +- context/http.go | 47 ------- listener/http/client.go | 39 ++++++ listener/http/hack.go | 10 ++ listener/http/proxy.go | 132 ++++++++++++++++++ listener/http/server.go | 84 +++-------- listener/http/utils.go | 74 ++++++++++ listener/mixed/mixed.go | 3 +- tunnel/connection.go | 104 -------------- tunnel/tunnel.go | 7 +- 11 files changed, 281 insertions(+), 273 deletions(-) rename listener/mixed/conn.go => common/net/bufconn.go (98%) delete mode 100644 context/http.go create mode 100644 listener/http/client.go create mode 100644 listener/http/hack.go create mode 100644 listener/http/proxy.go create mode 100644 listener/http/utils.go diff --git a/adapter/inbound/http.go b/adapter/inbound/http.go index b01c62bfb..94b9fc21f 100644 --- a/adapter/inbound/http.go +++ b/adapter/inbound/http.go @@ -2,60 +2,20 @@ package inbound import ( "net" - "net/http" - "strings" C "github.com/Dreamacro/clash/constant" "github.com/Dreamacro/clash/context" + "github.com/Dreamacro/clash/transport/socks5" ) // NewHTTP receive normal http request and return HTTPContext -func NewHTTP(request *http.Request, conn net.Conn) *context.HTTPContext { - metadata := parseHTTPAddr(request) +func NewHTTP(target string, source net.Addr, conn net.Conn) *context.ConnContext { + metadata := parseSocksAddr(socks5.ParseAddr(target)) + metadata.NetWork = C.TCP metadata.Type = C.HTTP - if ip, port, err := parseAddr(conn.RemoteAddr().String()); err == nil { + if ip, port, err := parseAddr(source.String()); err == nil { metadata.SrcIP = ip metadata.SrcPort = port } - return context.NewHTTPContext(conn, request, metadata) -} - -// RemoveHopByHopHeaders remove hop-by-hop header -func RemoveHopByHopHeaders(header http.Header) { - // Strip hop-by-hop header based on RFC: - // http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.5.1 - // https://www.mnot.net/blog/2011/07/11/what_proxies_must_do - - header.Del("Proxy-Connection") - header.Del("Proxy-Authenticate") - header.Del("Proxy-Authorization") - header.Del("TE") - header.Del("Trailers") - header.Del("Transfer-Encoding") - header.Del("Upgrade") - - connections := header.Get("Connection") - header.Del("Connection") - if len(connections) == 0 { - return - } - for _, h := range strings.Split(connections, ",") { - header.Del(strings.TrimSpace(h)) - } -} - -// RemoveExtraHTTPHostPort remove extra host port (example.com:80 --> example.com) -// It resolves the behavior of some HTTP servers that do not handle host:80 (e.g. baidu.com) -func RemoveExtraHTTPHostPort(req *http.Request) { - host := req.Host - if host == "" { - host = req.URL.Host - } - - if pHost, port, err := net.SplitHostPort(host); err == nil && port == "80" { - host = pHost - } - - req.Host = host - req.URL.Host = host + return context.NewConnContext(conn, metadata) } diff --git a/listener/mixed/conn.go b/common/net/bufconn.go similarity index 98% rename from listener/mixed/conn.go rename to common/net/bufconn.go index f009a0060..cb7433d2e 100644 --- a/listener/mixed/conn.go +++ b/common/net/bufconn.go @@ -1,4 +1,4 @@ -package mixed +package net import ( "bufio" diff --git a/context/http.go b/context/http.go deleted file mode 100644 index 292f7d970..000000000 --- a/context/http.go +++ /dev/null @@ -1,47 +0,0 @@ -package context - -import ( - "net" - "net/http" - - C "github.com/Dreamacro/clash/constant" - - "github.com/gofrs/uuid" -) - -type HTTPContext struct { - id uuid.UUID - metadata *C.Metadata - conn net.Conn - req *http.Request -} - -func NewHTTPContext(conn net.Conn, req *http.Request, metadata *C.Metadata) *HTTPContext { - id, _ := uuid.NewV4() - return &HTTPContext{ - id: id, - metadata: metadata, - conn: conn, - req: req, - } -} - -// ID implement C.ConnContext ID -func (hc *HTTPContext) ID() uuid.UUID { - return hc.id -} - -// Metadata implement C.ConnContext Metadata -func (hc *HTTPContext) Metadata() *C.Metadata { - return hc.metadata -} - -// Conn implement C.ConnContext Conn -func (hc *HTTPContext) Conn() net.Conn { - return hc.conn -} - -// Request return the http request struct -func (hc *HTTPContext) Request() *http.Request { - return hc.req -} diff --git a/listener/http/client.go b/listener/http/client.go new file mode 100644 index 000000000..3b5fd3842 --- /dev/null +++ b/listener/http/client.go @@ -0,0 +1,39 @@ +package http + +import ( + "context" + "errors" + "net" + "net/http" + "time" + + "github.com/Dreamacro/clash/adapter/inbound" + C "github.com/Dreamacro/clash/constant" +) + +func newClient(source net.Addr, in chan<- C.ConnContext) *http.Client { + return &http.Client{ + Transport: &http.Transport{ + // from http.DefaultTransport + MaxIdleConns: 100, + IdleConnTimeout: 90 * time.Second, + TLSHandshakeTimeout: 10 * time.Second, + ResponseHeaderTimeout: 10 * time.Second, + ExpectContinueTimeout: 1 * time.Second, + DialContext: func(context context.Context, network, address string) (net.Conn, error) { + if network != "tcp" && network != "tcp4" && network != "tcp6" { + return nil, errors.New("unsupported network " + network) + } + + left, right := net.Pipe() + + in <- inbound.NewHTTP(address, source, right) + + return left, nil + }, + }, + CheckRedirect: func(req *http.Request, via []*http.Request) error { + return http.ErrUseLastResponse + }, + } +} diff --git a/listener/http/hack.go b/listener/http/hack.go new file mode 100644 index 000000000..14a725383 --- /dev/null +++ b/listener/http/hack.go @@ -0,0 +1,10 @@ +package http + +import ( + "bufio" + "net/http" + _ "unsafe" +) + +//go:linkname ReadRequest net/http.readRequest +func ReadRequest(b *bufio.Reader, deleteHostHeader bool) (req *http.Request, err error) diff --git a/listener/http/proxy.go b/listener/http/proxy.go new file mode 100644 index 000000000..12508ba3d --- /dev/null +++ b/listener/http/proxy.go @@ -0,0 +1,132 @@ +package http + +import ( + "net" + "net/http" + "strings" + "time" + + "github.com/Dreamacro/clash/adapter/inbound" + "github.com/Dreamacro/clash/common/cache" + N "github.com/Dreamacro/clash/common/net" + C "github.com/Dreamacro/clash/constant" + authStore "github.com/Dreamacro/clash/listener/auth" + "github.com/Dreamacro/clash/log" +) + +func HandleConn(c net.Conn, in chan<- C.ConnContext, cache *cache.Cache) { + client := newClient(c.RemoteAddr(), in) + defer client.CloseIdleConnections() + + conn := N.NewBufferedConn(c) + + keepAlive := true + trusted := cache == nil // disable authenticate if cache is nil + + for keepAlive { + request, err := ReadRequest(conn.Reader(), false) + if err != nil { + break + } + + request.RemoteAddr = conn.RemoteAddr().String() + + keepAlive = strings.TrimSpace(strings.ToLower(request.Header.Get("Proxy-Connection"))) == "keep-alive" + + var resp *http.Response + + if !trusted { + resp = authenticate(request, cache) + + trusted = resp == nil + } + + if trusted { + if request.Method == http.MethodConnect { + resp = responseWith(200) + resp.Status = "Connection established" + + if resp.Write(conn) != nil { + break // close connection + } + + in <- inbound.NewHTTPS(request, conn) + + return // hijack connection + } + + host := request.Header.Get("Host") + if host != "" { + request.Host = host + } + + request.RequestURI = "" + + RemoveHopByHopHeaders(request.Header) + RemoveExtraHTTPHostPort(request) + + if request.URL.Scheme == "" || request.URL.Host == "" { + resp = responseWith(http.StatusBadRequest) + } else { + resp, err = client.Do(request) + if err != nil { + resp = responseWith(http.StatusBadGateway) + } + } + } + + RemoveHopByHopHeaders(resp.Header) + + if keepAlive { + resp.Header.Set("Proxy-Connection", "keep-alive") + resp.Header.Set("Connection", "keep-alive") + resp.Header.Set("Keep-Alive", "timeout=4") + } + + resp.Close = !keepAlive + + err = resp.Write(conn) + if err != nil { + break // close connection + } + } + + conn.Close() +} + +func authenticate(request *http.Request, cache *cache.Cache) *http.Response { + authenticator := authStore.Authenticator() + if authenticator != nil { + credential := ParseBasicProxyAuthorization(request) + if credential == "" { + resp := responseWith(http.StatusProxyAuthRequired) + resp.Header.Set("Proxy-Authenticate", "Basic") + return resp + } + + var authed interface{} + if authed = cache.Get(credential); authed == nil { + user, pass, err := DecodeBasicProxyAuthorization(credential) + authed = err == nil && authenticator.Verify(user, pass) + cache.Put(credential, authed, time.Minute) + } + if !authed.(bool) { + log.Infoln("Auth failed from %s", request.RemoteAddr) + + return responseWith(http.StatusForbidden) + } + } + + return nil +} + +func responseWith(statusCode int) *http.Response { + return &http.Response{ + StatusCode: statusCode, + Status: http.StatusText(statusCode), + Proto: "HTTP/1.1", + ProtoMajor: 1, + ProtoMinor: 1, + Header: http.Header{}, + } +} diff --git a/listener/http/server.go b/listener/http/server.go index a77e01daa..ed8383710 100644 --- a/listener/http/server.go +++ b/listener/http/server.go @@ -1,44 +1,48 @@ package http import ( - "bufio" - "encoding/base64" "net" - "net/http" - "strings" "time" - "github.com/Dreamacro/clash/adapter/inbound" "github.com/Dreamacro/clash/common/cache" - "github.com/Dreamacro/clash/component/auth" C "github.com/Dreamacro/clash/constant" - authStore "github.com/Dreamacro/clash/listener/auth" - "github.com/Dreamacro/clash/log" ) type Listener struct { listener net.Listener address string closed bool - cache *cache.Cache } func New(addr string, in chan<- C.ConnContext) (*Listener, error) { + return NewWithAuthenticate(addr, in, true) +} + +func NewWithAuthenticate(addr string, in chan<- C.ConnContext, authenticate bool) (*Listener, error) { l, err := net.Listen("tcp", addr) if err != nil { return nil, err } - hl := &Listener{l, addr, false, cache.New(30 * time.Second)} + + var c *cache.Cache + if authenticate { + c = cache.New(time.Second * 30) + } + + hl := &Listener{ + listener: l, + address: addr, + } go func() { for { - c, err := hl.listener.Accept() + conn, err := hl.listener.Accept() if err != nil { if hl.closed { break } continue } - go HandleConn(c, in, hl.cache) + go HandleConn(conn, in, c) } }() @@ -53,59 +57,3 @@ func (l *Listener) Close() { func (l *Listener) Address() string { return l.address } - -func canActivate(loginStr string, authenticator auth.Authenticator, cache *cache.Cache) (ret bool) { - if result := cache.Get(loginStr); result != nil { - ret = result.(bool) - return - } - loginData, err := base64.StdEncoding.DecodeString(loginStr) - login := strings.Split(string(loginData), ":") - ret = err == nil && len(login) == 2 && authenticator.Verify(login[0], login[1]) - - cache.Put(loginStr, ret, time.Minute) - return -} - -func HandleConn(conn net.Conn, in chan<- C.ConnContext, cache *cache.Cache) { - br := bufio.NewReader(conn) - -keepAlive: - request, err := http.ReadRequest(br) - if err != nil || request.URL.Host == "" { - conn.Close() - return - } - - keepAlive := strings.TrimSpace(strings.ToLower(request.Header.Get("Proxy-Connection"))) == "keep-alive" - authenticator := authStore.Authenticator() - if authenticator != nil { - if authStrings := strings.Split(request.Header.Get("Proxy-Authorization"), " "); len(authStrings) != 2 { - conn.Write([]byte("HTTP/1.1 407 Proxy Authentication Required\r\nProxy-Authenticate: Basic\r\n\r\n")) - if keepAlive { - goto keepAlive - } - return - } else if !canActivate(authStrings[1], authenticator, cache) { - conn.Write([]byte("HTTP/1.1 403 Forbidden\r\n\r\n")) - log.Infoln("Auth failed from %s", conn.RemoteAddr().String()) - if keepAlive { - goto keepAlive - } - conn.Close() - return - } - } - - if request.Method == http.MethodConnect { - _, err := conn.Write([]byte("HTTP/1.1 200 Connection established\r\n\r\n")) - if err != nil { - conn.Close() - return - } - in <- inbound.NewHTTPS(request, conn) - return - } - - in <- inbound.NewHTTP(request, conn) -} diff --git a/listener/http/utils.go b/listener/http/utils.go new file mode 100644 index 000000000..f3d7840c6 --- /dev/null +++ b/listener/http/utils.go @@ -0,0 +1,74 @@ +package http + +import ( + "encoding/base64" + "errors" + "net" + "net/http" + "strings" +) + +// RemoveHopByHopHeaders remove hop-by-hop header +func RemoveHopByHopHeaders(header http.Header) { + // Strip hop-by-hop header based on RFC: + // http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.5.1 + // https://www.mnot.net/blog/2011/07/11/what_proxies_must_do + + header.Del("Proxy-Connection") + header.Del("Proxy-Authenticate") + header.Del("Proxy-Authorization") + header.Del("TE") + header.Del("Trailers") + header.Del("Transfer-Encoding") + header.Del("Upgrade") + + connections := header.Get("Connection") + header.Del("Connection") + if len(connections) == 0 { + return + } + for _, h := range strings.Split(connections, ",") { + header.Del(strings.TrimSpace(h)) + } +} + +// RemoveExtraHTTPHostPort remove extra host port (example.com:80 --> example.com) +// It resolves the behavior of some HTTP servers that do not handle host:80 (e.g. baidu.com) +func RemoveExtraHTTPHostPort(req *http.Request) { + host := req.Host + if host == "" { + host = req.URL.Host + } + + if pHost, port, err := net.SplitHostPort(host); err == nil && port == "80" { + host = pHost + } + + req.Host = host + req.URL.Host = host +} + +// ParseBasicProxyAuthorization parse header Proxy-Authorization and return base64-encoded credential +func ParseBasicProxyAuthorization(request *http.Request) string { + value := request.Header.Get("Proxy-Authorization") + if !strings.HasPrefix(value, "Basic ") { + return "" + } + + return value[6:] // value[len("Basic "):] +} + +// DecodeBasicProxyAuthorization decode base64-encoded credential +func DecodeBasicProxyAuthorization(credential string) (string, string, error) { + plain, err := base64.StdEncoding.DecodeString(credential) + if err != nil { + return "", "", err + } + + login := strings.Split(string(plain), ":") + if len(login) != 2 { + return "", "", errors.New("invalid login") + } + + return login[0], login[1], nil +} diff --git a/listener/mixed/mixed.go b/listener/mixed/mixed.go index 3c4b49a84..07ad03b62 100644 --- a/listener/mixed/mixed.go +++ b/listener/mixed/mixed.go @@ -5,6 +5,7 @@ import ( "time" "github.com/Dreamacro/clash/common/cache" + N "github.com/Dreamacro/clash/common/net" C "github.com/Dreamacro/clash/constant" "github.com/Dreamacro/clash/listener/http" "github.com/Dreamacro/clash/listener/socks" @@ -51,7 +52,7 @@ func (l *Listener) Address() string { } func handleConn(conn net.Conn, in chan<- C.ConnContext, cache *cache.Cache) { - bufConn := NewBufferedConn(conn) + bufConn := N.NewBufferedConn(conn) head, err := bufConn.Peek(1) if err != nil { return diff --git a/tunnel/connection.go b/tunnel/connection.go index 2cc5964c3..8c3b4cb61 100644 --- a/tunnel/connection.go +++ b/tunnel/connection.go @@ -1,93 +1,17 @@ package tunnel import ( - "bufio" "errors" "io" "net" - "net/http" - "strings" "time" - "github.com/Dreamacro/clash/adapter/inbound" N "github.com/Dreamacro/clash/common/net" "github.com/Dreamacro/clash/common/pool" "github.com/Dreamacro/clash/component/resolver" C "github.com/Dreamacro/clash/constant" - "github.com/Dreamacro/clash/context" ) -func handleHTTP(ctx *context.HTTPContext, outbound net.Conn) { - req := ctx.Request() - conn := ctx.Conn() - - // make outbound close after inbound error or close - conn = &connLinker{conn, outbound} - - inboundReader := bufio.NewReader(conn) - outboundReader := bufio.NewReader(outbound) - - inbound.RemoveExtraHTTPHostPort(req) - host := req.Host - for { - keepAlive := strings.TrimSpace(strings.ToLower(req.Header.Get("Proxy-Connection"))) == "keep-alive" - - req.RequestURI = "" - inbound.RemoveHopByHopHeaders(req.Header) - err := req.Write(outbound) - if err != nil { - break - } - - handleResponse: - // resp will be closed after we call resp.Write() - // see https://golang.org/pkg/net/http/#Response.Write - resp, err := http.ReadResponse(outboundReader, req) - if err != nil { - break - } - inbound.RemoveHopByHopHeaders(resp.Header) - - if resp.StatusCode == http.StatusContinue { - err = resp.Write(conn) - if err != nil { - break - } - goto handleResponse - } - - // close conn when header `Connection` is `close` - if resp.Header.Get("Connection") == "close" { - keepAlive = false - } - - if keepAlive { - resp.Header.Set("Proxy-Connection", "keep-alive") - resp.Header.Set("Connection", "keep-alive") - resp.Header.Set("Keep-Alive", "timeout=4") - resp.Close = false - } else { - resp.Close = true - } - err = resp.Write(conn) - if err != nil || resp.Close { - break - } - - req, err = http.ReadRequest(inboundReader) - if err != nil { - break - } - - inbound.RemoveExtraHTTPHostPort(req) - // Sometimes firefox just open a socket to process multiple domains in HTTP - // The temporary solution is close connection when encountering different HOST - if req.Host != host { - break - } - } -} - func handleUDPToRemote(packet C.UDPPacket, pc C.PacketConn, metadata *C.Metadata) error { defer packet.Drop() @@ -162,31 +86,3 @@ func relay(leftConn, rightConn net.Conn) { rightConn.SetReadDeadline(time.Now()) <-ch } - -// connLinker make the two net.Conn correlated, for temporary resolution of leaks. -// There is no better way to do this for now. -type connLinker struct { - net.Conn - linker net.Conn -} - -func (conn *connLinker) Read(b []byte) (n int, err error) { - n, err = conn.Conn.Read(b) - if err != nil { - conn.linker.Close() - } - return n, err -} - -func (conn *connLinker) Write(b []byte) (n int, err error) { - n, err = conn.Conn.Write(b) - if err != nil { - conn.linker.Close() - } - return n, err -} - -func (conn *connLinker) Close() error { - conn.linker.Close() - return conn.Conn.Close() -} diff --git a/tunnel/tunnel.go b/tunnel/tunnel.go index a9ffb61fc..a40b697df 100644 --- a/tunnel/tunnel.go +++ b/tunnel/tunnel.go @@ -289,12 +289,7 @@ func handleTCPConn(ctx C.ConnContext) { log.Infoln("[TCP] %s --> %v doesn't match any rule using DIRECT", metadata.SourceAddress(), metadata.String()) } - switch c := ctx.(type) { - case *context.HTTPContext: - handleHTTP(c, remoteConn) - default: - handleSocket(ctx, remoteConn) - } + handleSocket(ctx, remoteConn) } func shouldResolveIP(rule C.Rule, metadata *C.Metadata) bool { From c35cb24bdacf66cd65af508f48323a647882ef08 Mon Sep 17 00:00:00 2001 From: Dreamacro <8615343+Dreamacro@users.noreply.github.com> Date: Tue, 15 Jun 2021 21:03:47 +0800 Subject: [PATCH 12/96] Chore: use unix.ByteSliceToString transform cstring --- component/process/process_darwin.go | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/component/process/process_darwin.go b/component/process/process_darwin.go index 5157b2099..7e4baf74c 100644 --- a/component/process/process_darwin.go +++ b/component/process/process_darwin.go @@ -1,12 +1,13 @@ package process import ( - "bytes" "encoding/binary" "net" "path/filepath" "syscall" "unsafe" + + "golang.org/x/sys/unix" ) const ( @@ -94,12 +95,8 @@ func getExecPathFromPID(pid uint32) (string, error) { if errno != 0 { return "", errno } - firstZero := bytes.IndexByte(buf, 0) - if firstZero <= 0 { - return "", nil - } - return filepath.Base(string(buf[:firstZero])), nil + return filepath.Base(unix.ByteSliceToString(buf)), nil } func readNativeUint32(b []byte) uint32 { From 244cb370a438cdf663370bc6bfb0ad784a219b4b Mon Sep 17 00:00:00 2001 From: ayanamist Date: Mon, 21 Jun 2021 17:33:34 +0800 Subject: [PATCH 13/96] Change: config reload API use default path when both path and payload don't exist (#1447) --- hub/route/configs.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/hub/route/configs.go b/hub/route/configs.go index 315180f77..48cb95eda 100644 --- a/hub/route/configs.go +++ b/hub/route/configs.go @@ -6,6 +6,7 @@ import ( "github.com/Dreamacro/clash/component/resolver" "github.com/Dreamacro/clash/config" + "github.com/Dreamacro/clash/constant" "github.com/Dreamacro/clash/hub/executor" P "github.com/Dreamacro/clash/listener" "github.com/Dreamacro/clash/log" @@ -116,6 +117,9 @@ func updateConfigs(w http.ResponseWriter, r *http.Request) { return } } else { + if req.Path == "" { + req.Path = constant.Path.Config() + } if !filepath.IsAbs(req.Path) { render.Status(r, http.StatusBadRequest) render.JSON(w, r, newError("path is not a absolute path")) From 3ca5d17c40d3cc682e71f295f0761445cf7a4793 Mon Sep 17 00:00:00 2001 From: Indust Date: Thu, 24 Jun 2021 13:38:44 +0800 Subject: [PATCH 14/96] Fix: enable DNS server message compression (#1451) --- dns/server.go | 1 + 1 file changed, 1 insertion(+) diff --git a/dns/server.go b/dns/server.go index 84ff0bac4..7abdd4d0f 100644 --- a/dns/server.go +++ b/dns/server.go @@ -30,6 +30,7 @@ func (s *Server) ServeDNS(w D.ResponseWriter, r *D.Msg) { D.HandleFailed(w, r) return } + msg.Compress = true w.WriteMsg(msg) } From 995aa7a8fc641fa00b44ad290ac59c3e4c2a565f Mon Sep 17 00:00:00 2001 From: Dreamacro <8615343+Dreamacro@users.noreply.github.com> Date: Sat, 3 Jul 2021 20:34:44 +0800 Subject: [PATCH 15/96] Fix: remove ClientSessionCache and add NextProtos for vmess to fix #1468 --- adapter/outbound/http.go | 1 - adapter/outbound/shadowsocks.go | 1 - adapter/outbound/socks5.go | 1 - adapter/outbound/trojan.go | 10 ++++------ adapter/outbound/util.go | 14 -------------- adapter/outbound/vmess.go | 4 ---- dns/doh.go | 2 -- dns/resolver.go | 5 ----- dns/util.go | 1 - transport/trojan/trojan.go | 10 ++++------ transport/v2ray-plugin/websocket.go | 3 --- transport/vmess/tls.go | 2 -- transport/vmess/websocket.go | 3 +-- 13 files changed, 9 insertions(+), 48 deletions(-) diff --git a/adapter/outbound/http.go b/adapter/outbound/http.go index 43ca12042..b4dffdf78 100644 --- a/adapter/outbound/http.go +++ b/adapter/outbound/http.go @@ -125,7 +125,6 @@ func NewHttp(option HttpOption) *Http { } tlsConfig = &tls.Config{ InsecureSkipVerify: option.SkipCertVerify, - ClientSessionCache: getClientSessionCache(), ServerName: sni, } } diff --git a/adapter/outbound/shadowsocks.go b/adapter/outbound/shadowsocks.go index 0fb3ab9a8..39d1e36d0 100644 --- a/adapter/outbound/shadowsocks.go +++ b/adapter/outbound/shadowsocks.go @@ -149,7 +149,6 @@ func NewShadowSocks(option ShadowSocksOption) (*ShadowSocks, error) { if opts.TLS { v2rayOption.TLS = true v2rayOption.SkipCertVerify = opts.SkipCertVerify - v2rayOption.SessionCache = getClientSessionCache() } } diff --git a/adapter/outbound/socks5.go b/adapter/outbound/socks5.go index 26c7c06ad..8106e0e2e 100644 --- a/adapter/outbound/socks5.go +++ b/adapter/outbound/socks5.go @@ -145,7 +145,6 @@ func NewSocks5(option Socks5Option) *Socks5 { if option.TLS { tlsConfig = &tls.Config{ InsecureSkipVerify: option.SkipCertVerify, - ClientSessionCache: getClientSessionCache(), ServerName: option.Server, } } diff --git a/adapter/outbound/trojan.go b/adapter/outbound/trojan.go index 5d8527353..afed410fb 100644 --- a/adapter/outbound/trojan.go +++ b/adapter/outbound/trojan.go @@ -127,11 +127,10 @@ func NewTrojan(option TrojanOption) (*Trojan, error) { addr := net.JoinHostPort(option.Server, strconv.Itoa(option.Port)) tOption := &trojan.Option{ - Password: option.Password, - ALPN: option.ALPN, - ServerName: option.Server, - SkipCertVerify: option.SkipCertVerify, - ClientSessionCache: getClientSessionCache(), + Password: option.Password, + ALPN: option.ALPN, + ServerName: option.Server, + SkipCertVerify: option.SkipCertVerify, } if option.SNI != "" { @@ -163,7 +162,6 @@ func NewTrojan(option TrojanOption) (*Trojan, error) { MinVersion: tls.VersionTLS12, InsecureSkipVerify: tOption.SkipCertVerify, ServerName: tOption.ServerName, - ClientSessionCache: getClientSessionCache(), } t.transport = gun.NewHTTP2Client(dialFn, tlsConfig) diff --git a/adapter/outbound/util.go b/adapter/outbound/util.go index 4b81eb5d6..0e1d4c8e5 100644 --- a/adapter/outbound/util.go +++ b/adapter/outbound/util.go @@ -2,10 +2,8 @@ package outbound import ( "bytes" - "crypto/tls" "net" "strconv" - "sync" "time" "github.com/Dreamacro/clash/component/resolver" @@ -13,11 +11,6 @@ import ( "github.com/Dreamacro/clash/transport/socks5" ) -var ( - globalClientSessionCache tls.ClientSessionCache - once sync.Once -) - func tcpKeepAlive(c net.Conn) { if tcp, ok := c.(*net.TCPConn); ok { tcp.SetKeepAlive(true) @@ -25,13 +18,6 @@ func tcpKeepAlive(c net.Conn) { } } -func getClientSessionCache() tls.ClientSessionCache { - once.Do(func() { - globalClientSessionCache = tls.NewLRUClientSessionCache(128) - }) - return globalClientSessionCache -} - func serializesSocksAddr(metadata *C.Metadata) []byte { var buf [][]byte aType := uint8(metadata.AddrType) diff --git a/adapter/outbound/vmess.go b/adapter/outbound/vmess.go index 672f767ba..5ee4abbc3 100644 --- a/adapter/outbound/vmess.go +++ b/adapter/outbound/vmess.go @@ -86,7 +86,6 @@ func (v *Vmess) StreamConn(c net.Conn, metadata *C.Metadata) (net.Conn, error) { if v.option.TLS { wsOpts.TLS = true - wsOpts.SessionCache = getClientSessionCache() wsOpts.SkipCertVerify = v.option.SkipCertVerify wsOpts.ServerName = v.option.ServerName } @@ -98,7 +97,6 @@ func (v *Vmess) StreamConn(c net.Conn, metadata *C.Metadata) (net.Conn, error) { tlsOpts := &vmess.TLSConfig{ Host: host, SkipCertVerify: v.option.SkipCertVerify, - SessionCache: getClientSessionCache(), } if v.option.ServerName != "" { @@ -125,7 +123,6 @@ func (v *Vmess) StreamConn(c net.Conn, metadata *C.Metadata) (net.Conn, error) { tlsOpts := vmess.TLSConfig{ Host: host, SkipCertVerify: v.option.SkipCertVerify, - SessionCache: getClientSessionCache(), NextProtos: []string{"h2"}, } @@ -153,7 +150,6 @@ func (v *Vmess) StreamConn(c net.Conn, metadata *C.Metadata) (net.Conn, error) { tlsOpts := &vmess.TLSConfig{ Host: host, SkipCertVerify: v.option.SkipCertVerify, - SessionCache: getClientSessionCache(), } if v.option.ServerName != "" { diff --git a/dns/doh.go b/dns/doh.go index 247e0704d..34375017d 100644 --- a/dns/doh.go +++ b/dns/doh.go @@ -3,7 +3,6 @@ package dns import ( "bytes" "context" - "crypto/tls" "io/ioutil" "net" "net/http" @@ -76,7 +75,6 @@ func newDoHClient(url string, r *Resolver) *dohClient { return &dohClient{ url: url, transport: &http.Transport{ - TLSClientConfig: &tls.Config{ClientSessionCache: globalSessionCache}, ForceAttemptHTTP2: true, DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) { host, port, err := net.SplitHostPort(addr) diff --git a/dns/resolver.go b/dns/resolver.go index f57fec525..1ca0293ea 100644 --- a/dns/resolver.go +++ b/dns/resolver.go @@ -2,7 +2,6 @@ package dns import ( "context" - "crypto/tls" "errors" "fmt" "math/rand" @@ -20,10 +19,6 @@ import ( "golang.org/x/sync/singleflight" ) -var ( - globalSessionCache = tls.NewLRUClientSessionCache(64) -) - type dnsClient interface { Exchange(m *D.Msg) (msg *D.Msg, err error) ExchangeContext(ctx context.Context, m *D.Msg) (msg *D.Msg, err error) diff --git a/dns/util.go b/dns/util.go index c2bb11d86..e56aaeb5a 100644 --- a/dns/util.go +++ b/dns/util.go @@ -127,7 +127,6 @@ func transform(servers []NameServer, resolver *Resolver) []dnsClient { Client: &D.Client{ Net: s.Net, TLSConfig: &tls.Config{ - ClientSessionCache: globalSessionCache, // alpn identifier, see https://tools.ietf.org/html/draft-hoffman-dprive-dns-tls-alpn-00#page-6 NextProtos: []string{"dns"}, ServerName: host, diff --git a/transport/trojan/trojan.go b/transport/trojan/trojan.go index 88cc95fb1..d62e3f80d 100644 --- a/transport/trojan/trojan.go +++ b/transport/trojan/trojan.go @@ -34,11 +34,10 @@ var ( ) type Option struct { - Password string - ALPN []string - ServerName string - SkipCertVerify bool - ClientSessionCache tls.ClientSessionCache + Password string + ALPN []string + ServerName string + SkipCertVerify bool } type Trojan struct { @@ -57,7 +56,6 @@ func (t *Trojan) StreamConn(conn net.Conn) (net.Conn, error) { MinVersion: tls.VersionTLS12, InsecureSkipVerify: t.option.SkipCertVerify, ServerName: t.option.ServerName, - ClientSessionCache: t.option.ClientSessionCache, } tlsConn := tls.Client(conn, tlsConfig) diff --git a/transport/v2ray-plugin/websocket.go b/transport/v2ray-plugin/websocket.go index 9feaf2c2f..317c172fc 100644 --- a/transport/v2ray-plugin/websocket.go +++ b/transport/v2ray-plugin/websocket.go @@ -1,7 +1,6 @@ package obfs import ( - "crypto/tls" "net" "net/http" @@ -16,7 +15,6 @@ type Option struct { Headers map[string]string TLS bool SkipCertVerify bool - SessionCache tls.ClientSessionCache Mux bool } @@ -34,7 +32,6 @@ func NewV2rayObfs(conn net.Conn, option *Option) (net.Conn, error) { TLS: option.TLS, Headers: header, SkipCertVerify: option.SkipCertVerify, - SessionCache: option.SessionCache, } var err error diff --git a/transport/vmess/tls.go b/transport/vmess/tls.go index b003a7533..234c31477 100644 --- a/transport/vmess/tls.go +++ b/transport/vmess/tls.go @@ -8,7 +8,6 @@ import ( type TLSConfig struct { Host string SkipCertVerify bool - SessionCache tls.ClientSessionCache NextProtos []string } @@ -16,7 +15,6 @@ func StreamTLSConn(conn net.Conn, cfg *TLSConfig) (net.Conn, error) { tlsConfig := &tls.Config{ ServerName: cfg.Host, InsecureSkipVerify: cfg.SkipCertVerify, - ClientSessionCache: cfg.SessionCache, NextProtos: cfg.NextProtos, } diff --git a/transport/vmess/websocket.go b/transport/vmess/websocket.go index 980add13e..6ed353e76 100644 --- a/transport/vmess/websocket.go +++ b/transport/vmess/websocket.go @@ -32,7 +32,6 @@ type WebsocketConfig struct { TLS bool SkipCertVerify bool ServerName string - SessionCache tls.ClientSessionCache } // Read implements net.Conn.Read() @@ -130,7 +129,7 @@ func StreamWebsocketConn(conn net.Conn, c *WebsocketConfig) (net.Conn, error) { dialer.TLSClientConfig = &tls.Config{ ServerName: c.Host, InsecureSkipVerify: c.SkipCertVerify, - ClientSessionCache: c.SessionCache, + NextProtos: []string{"http/1.1"}, } if c.ServerName != "" { From dff1e8f1ce0c6ed9d8a070c513a6b3478f701e2b Mon Sep 17 00:00:00 2001 From: Dreamacro <8615343+Dreamacro@users.noreply.github.com> Date: Sat, 3 Jul 2021 21:01:41 +0800 Subject: [PATCH 16/96] Chore: update dependencies --- go.mod | 10 +++++----- go.sum | 21 +++++++++++---------- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/go.mod b/go.mod index 17056c628..28e4d44ba 100644 --- a/go.mod +++ b/go.mod @@ -9,14 +9,14 @@ require ( github.com/go-chi/render v1.0.1 github.com/gofrs/uuid v4.0.0+incompatible github.com/gorilla/websocket v1.4.2 - github.com/miekg/dns v1.1.42 + github.com/miekg/dns v1.1.43 github.com/oschwald/geoip2-golang v1.5.0 github.com/sirupsen/logrus v1.8.1 github.com/stretchr/testify v1.7.0 - go.uber.org/atomic v1.7.0 - golang.org/x/crypto v0.0.0-20210506145944-38f3c27a63bf - golang.org/x/net v0.0.0-20210508051633-16afe75a6701 + go.uber.org/atomic v1.8.0 + golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e + golang.org/x/net v0.0.0-20210614182718-04defd469f4e golang.org/x/sync v0.0.0-20210220032951-036812b2e83c - golang.org/x/sys v0.0.0-20210507161434-a76c4d0a0096 + golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c gopkg.in/yaml.v2 v2.4.0 ) diff --git a/go.sum b/go.sum index 58dcc672b..fa37dc3be 100644 --- a/go.sum +++ b/go.sum @@ -13,8 +13,8 @@ github.com/gofrs/uuid v4.0.0+incompatible h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPh github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/miekg/dns v1.1.42 h1:gWGe42RGaIqXQZ+r3WUGEKBEtvPHY2SXo4dqixDNxuY= -github.com/miekg/dns v1.1.42/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4= +github.com/miekg/dns v1.1.43 h1:JKfpVSCB84vrAmHzyrsxB5NAr5kLoMXZArPSw7Qlgyg= +github.com/miekg/dns v1.1.43/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4= github.com/oschwald/geoip2-golang v1.5.0 h1:igg2yQIrrcRccB1ytFXqBfOHCjXWIoMv85lVJ1ONZzw= github.com/oschwald/geoip2-golang v1.5.0/go.mod h1:xdvYt5xQzB8ORWFqPnqMwZpCpgNagttWdoZLlJQzg7s= github.com/oschwald/maxminddb-golang v1.8.0 h1:Uh/DSnGoxsyp/KYbY1AuP0tYEwfs0sCph9p/UMXK/Hk= @@ -29,14 +29,14 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= -go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/atomic v1.8.0 h1:CUhrE4N1rqSE6FM9ecihEjRkLQu8cDfgDyoOs83mEY4= +go.uber.org/atomic v1.8.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= golang.org/x/crypto v0.0.0-20210317152858-513c2a44f670/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= -golang.org/x/crypto v0.0.0-20210506145944-38f3c27a63bf h1:B2n+Zi5QeYRDAEodEu72OS36gmTWjgpXr2+cWcBW90o= -golang.org/x/crypto v0.0.0-20210506145944-38f3c27a63bf/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= +golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e h1:gsTQYXdTw2Gq7RBsWvlQ91b+aEQ6bXFUngBGuR8sPpI= +golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210508051633-16afe75a6701 h1:lQVgcB3+FoAXOb20Dp6zTzAIrpj1k/yOOBN7s+Zv1rA= -golang.org/x/net v0.0.0-20210508051633-16afe75a6701/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210614182718-04defd469f4e h1:XpT3nA5TvE525Ne3hInMh6+GETgn27Zfm9dxsThnX2Q= +golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -44,8 +44,9 @@ golang.org/x/sys v0.0.0-20191224085550-c709ea063b76/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210507161434-a76c4d0a0096 h1:5PbJGn5Sp3GEUjJ61aYbUP6RIo3Z3r2E4Tv9y2z8UHo= -golang.org/x/sys v0.0.0-20210507161434-a76c4d0a0096/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 h1:F1jZWGFhYfh0Ci55sIpILtKKK8p3i2/krTr0H1rg74I= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= From d755383e394e8754cebd6f7cb2dbf205b9a3c686 Mon Sep 17 00:00:00 2001 From: Dreamacro <8615343+Dreamacro@users.noreply.github.com> Date: Sun, 4 Jul 2021 20:32:59 +0800 Subject: [PATCH 17/96] Chore: move provider interface to constant --- adapter/outboundgroup/common.go | 2 +- adapter/outboundgroup/fallback.go | 2 +- adapter/outboundgroup/loadbalance.go | 2 +- adapter/outboundgroup/parser.go | 11 +-- adapter/outboundgroup/relay.go | 2 +- adapter/outboundgroup/selector.go | 2 +- adapter/outboundgroup/urltest.go | 2 +- adapter/provider/fetcher.go | 11 +-- adapter/provider/parser.go | 5 +- adapter/provider/provider.go | 54 ++------------ adapter/provider/vehicle.go | 38 ++-------- config/config.go | 11 +-- constant/provider/interface.go | 105 +++++++++++++++++++++++++++ hub/executor/executor.go | 2 +- hub/route/provider.go | 2 +- tunnel/tunnel.go | 2 +- 16 files changed, 148 insertions(+), 105 deletions(-) create mode 100644 constant/provider/interface.go diff --git a/adapter/outboundgroup/common.go b/adapter/outboundgroup/common.go index 31b8cb6bb..758c7801a 100644 --- a/adapter/outboundgroup/common.go +++ b/adapter/outboundgroup/common.go @@ -3,8 +3,8 @@ package outboundgroup import ( "time" - "github.com/Dreamacro/clash/adapter/provider" C "github.com/Dreamacro/clash/constant" + "github.com/Dreamacro/clash/constant/provider" ) const ( diff --git a/adapter/outboundgroup/fallback.go b/adapter/outboundgroup/fallback.go index 8b38f09ca..da01d4de1 100644 --- a/adapter/outboundgroup/fallback.go +++ b/adapter/outboundgroup/fallback.go @@ -5,9 +5,9 @@ import ( "encoding/json" "github.com/Dreamacro/clash/adapter/outbound" - "github.com/Dreamacro/clash/adapter/provider" "github.com/Dreamacro/clash/common/singledo" C "github.com/Dreamacro/clash/constant" + "github.com/Dreamacro/clash/constant/provider" ) type Fallback struct { diff --git a/adapter/outboundgroup/loadbalance.go b/adapter/outboundgroup/loadbalance.go index 7856a07d6..e529b53be 100644 --- a/adapter/outboundgroup/loadbalance.go +++ b/adapter/outboundgroup/loadbalance.go @@ -8,10 +8,10 @@ import ( "net" "github.com/Dreamacro/clash/adapter/outbound" - "github.com/Dreamacro/clash/adapter/provider" "github.com/Dreamacro/clash/common/murmur3" "github.com/Dreamacro/clash/common/singledo" C "github.com/Dreamacro/clash/constant" + "github.com/Dreamacro/clash/constant/provider" "golang.org/x/net/publicsuffix" ) diff --git a/adapter/outboundgroup/parser.go b/adapter/outboundgroup/parser.go index d11040a5f..cf97579f9 100644 --- a/adapter/outboundgroup/parser.go +++ b/adapter/outboundgroup/parser.go @@ -7,6 +7,7 @@ import ( "github.com/Dreamacro/clash/adapter/provider" "github.com/Dreamacro/clash/common/structure" C "github.com/Dreamacro/clash/constant" + types "github.com/Dreamacro/clash/constant/provider" ) var ( @@ -28,7 +29,7 @@ type GroupCommonOption struct { DisableUDP bool `group:"disable-udp,omitempty"` } -func ParseProxyGroup(config map[string]interface{}, proxyMap map[string]C.Proxy, providersMap map[string]provider.ProxyProvider) (C.ProxyAdapter, error) { +func ParseProxyGroup(config map[string]interface{}, proxyMap map[string]C.Proxy, providersMap map[string]types.ProxyProvider) (C.ProxyAdapter, error) { decoder := structure.NewDecoder(structure.Option{TagName: "group", WeaklyTypedInput: true}) groupOption := &GroupCommonOption{ @@ -44,7 +45,7 @@ func ParseProxyGroup(config map[string]interface{}, proxyMap map[string]C.Proxy, groupName := groupOption.Name - providers := []provider.ProxyProvider{} + providers := []types.ProxyProvider{} if len(groupOption.Proxies) == 0 && len(groupOption.Use) == 0 { return nil, errMissProxy @@ -138,15 +139,15 @@ func getProxies(mapping map[string]C.Proxy, list []string) ([]C.Proxy, error) { return ps, nil } -func getProviders(mapping map[string]provider.ProxyProvider, list []string) ([]provider.ProxyProvider, error) { - var ps []provider.ProxyProvider +func getProviders(mapping map[string]types.ProxyProvider, list []string) ([]types.ProxyProvider, error) { + var ps []types.ProxyProvider for _, name := range list { p, ok := mapping[name] if !ok { return nil, fmt.Errorf("'%s' not found", name) } - if p.VehicleType() == provider.Compatible { + if p.VehicleType() == types.Compatible { return nil, fmt.Errorf("proxy group %s can't contains in `use`", name) } ps = append(ps, p) diff --git a/adapter/outboundgroup/relay.go b/adapter/outboundgroup/relay.go index e4a897b8a..8d8128bac 100644 --- a/adapter/outboundgroup/relay.go +++ b/adapter/outboundgroup/relay.go @@ -7,10 +7,10 @@ import ( "fmt" "github.com/Dreamacro/clash/adapter/outbound" - "github.com/Dreamacro/clash/adapter/provider" "github.com/Dreamacro/clash/common/singledo" "github.com/Dreamacro/clash/component/dialer" C "github.com/Dreamacro/clash/constant" + "github.com/Dreamacro/clash/constant/provider" ) type Relay struct { diff --git a/adapter/outboundgroup/selector.go b/adapter/outboundgroup/selector.go index c28b6f8cf..124539278 100644 --- a/adapter/outboundgroup/selector.go +++ b/adapter/outboundgroup/selector.go @@ -6,9 +6,9 @@ import ( "errors" "github.com/Dreamacro/clash/adapter/outbound" - "github.com/Dreamacro/clash/adapter/provider" "github.com/Dreamacro/clash/common/singledo" C "github.com/Dreamacro/clash/constant" + "github.com/Dreamacro/clash/constant/provider" ) type Selector struct { diff --git a/adapter/outboundgroup/urltest.go b/adapter/outboundgroup/urltest.go index 0f59d4be5..2a11cd23b 100644 --- a/adapter/outboundgroup/urltest.go +++ b/adapter/outboundgroup/urltest.go @@ -6,9 +6,9 @@ import ( "time" "github.com/Dreamacro/clash/adapter/outbound" - "github.com/Dreamacro/clash/adapter/provider" "github.com/Dreamacro/clash/common/singledo" C "github.com/Dreamacro/clash/constant" + "github.com/Dreamacro/clash/constant/provider" ) type urlTestOption func(*URLTest) diff --git a/adapter/provider/fetcher.go b/adapter/provider/fetcher.go index 5ef3f25ca..777e3aa54 100644 --- a/adapter/provider/fetcher.go +++ b/adapter/provider/fetcher.go @@ -8,6 +8,7 @@ import ( "path/filepath" "time" + types "github.com/Dreamacro/clash/constant/provider" "github.com/Dreamacro/clash/log" ) @@ -20,7 +21,7 @@ type parser = func([]byte) (interface{}, error) type fetcher struct { name string - vehicle Vehicle + vehicle types.Vehicle updatedAt *time.Time ticker *time.Ticker done chan struct{} @@ -33,7 +34,7 @@ func (f *fetcher) Name() string { return f.name } -func (f *fetcher) VehicleType() VehicleType { +func (f *fetcher) VehicleType() types.VehicleType { return f.vehicle.Type() } @@ -76,7 +77,7 @@ func (f *fetcher) Initial() (interface{}, error) { isLocal = false } - if f.vehicle.Type() != File && !isLocal { + if f.vehicle.Type() != types.File && !isLocal { if err := safeWrite(f.vehicle.Path(), buf); err != nil { return nil, err } @@ -110,7 +111,7 @@ func (f *fetcher) Update() (interface{}, bool, error) { return nil, false, err } - if f.vehicle.Type() != File { + if f.vehicle.Type() != types.File { if err := safeWrite(f.vehicle.Path(), buf); err != nil { return nil, false, err } @@ -167,7 +168,7 @@ func safeWrite(path string, buf []byte) error { return ioutil.WriteFile(path, buf, fileMode) } -func newFetcher(name string, interval time.Duration, vehicle Vehicle, parser parser, onUpdate func(interface{})) *fetcher { +func newFetcher(name string, interval time.Duration, vehicle types.Vehicle, parser parser, onUpdate func(interface{})) *fetcher { var ticker *time.Ticker if interval != 0 { ticker = time.NewTicker(interval) diff --git a/adapter/provider/parser.go b/adapter/provider/parser.go index aa5d7ae29..f326d4ccb 100644 --- a/adapter/provider/parser.go +++ b/adapter/provider/parser.go @@ -7,6 +7,7 @@ import ( "github.com/Dreamacro/clash/common/structure" C "github.com/Dreamacro/clash/constant" + types "github.com/Dreamacro/clash/constant/provider" ) var ( @@ -28,7 +29,7 @@ type proxyProviderSchema struct { HealthCheck healthCheckSchema `provider:"health-check,omitempty"` } -func ParseProxyProvider(name string, mapping map[string]interface{}) (ProxyProvider, error) { +func ParseProxyProvider(name string, mapping map[string]interface{}) (types.ProxyProvider, error) { decoder := structure.NewDecoder(structure.Option{TagName: "provider", WeaklyTypedInput: true}) schema := &proxyProviderSchema{ @@ -48,7 +49,7 @@ func ParseProxyProvider(name string, mapping map[string]interface{}) (ProxyProvi path := C.Path.Resolve(schema.Path) - var vehicle Vehicle + var vehicle types.Vehicle switch schema.Type { case "file": vehicle = NewFileVehicle(path) diff --git a/adapter/provider/provider.go b/adapter/provider/provider.go index f87fe2a12..b6e1ac754 100644 --- a/adapter/provider/provider.go +++ b/adapter/provider/provider.go @@ -9,6 +9,7 @@ import ( "github.com/Dreamacro/clash/adapter" C "github.com/Dreamacro/clash/constant" + types "github.com/Dreamacro/clash/constant/provider" "gopkg.in/yaml.v2" ) @@ -17,45 +18,6 @@ const ( ReservedName = "default" ) -// Provider Type -const ( - Proxy ProviderType = iota - Rule -) - -// ProviderType defined -type ProviderType int - -func (pt ProviderType) String() string { - switch pt { - case Proxy: - return "Proxy" - case Rule: - return "Rule" - default: - return "Unknown" - } -} - -// Provider interface -type Provider interface { - Name() string - VehicleType() VehicleType - Type() ProviderType - Initial() error - Update() error -} - -// ProxyProvider interface -type ProxyProvider interface { - Provider - Proxies() []C.Proxy - // ProxiesWithTouch is used to inform the provider that the proxy is actually being used while getting the list of proxies. - // Commonly used in Dial and DialUDP - ProxiesWithTouch() []C.Proxy - HealthCheck() -} - type ProxySchema struct { Proxies []map[string]interface{} `yaml:"proxies"` } @@ -107,8 +69,8 @@ func (pp *proxySetProvider) Initial() error { return nil } -func (pp *proxySetProvider) Type() ProviderType { - return Proxy +func (pp *proxySetProvider) Type() types.ProviderType { + return types.Proxy } func (pp *proxySetProvider) Proxies() []C.Proxy { @@ -160,7 +122,7 @@ func stopProxyProvider(pd *ProxySetProvider) { pd.fetcher.Destroy() } -func NewProxySetProvider(name string, interval time.Duration, vehicle Vehicle, hc *HealthCheck) *ProxySetProvider { +func NewProxySetProvider(name string, interval time.Duration, vehicle types.Vehicle, hc *HealthCheck) *ProxySetProvider { if hc.auto() { go hc.process() } @@ -219,12 +181,12 @@ func (cp *compatibleProvider) Initial() error { return nil } -func (cp *compatibleProvider) VehicleType() VehicleType { - return Compatible +func (cp *compatibleProvider) VehicleType() types.VehicleType { + return types.Compatible } -func (cp *compatibleProvider) Type() ProviderType { - return Proxy +func (cp *compatibleProvider) Type() types.ProviderType { + return types.Proxy } func (cp *compatibleProvider) Proxies() []C.Proxy { diff --git a/adapter/provider/vehicle.go b/adapter/provider/vehicle.go index 13d898fc8..ea6a835a2 100644 --- a/adapter/provider/vehicle.go +++ b/adapter/provider/vehicle.go @@ -8,43 +8,15 @@ import ( "time" "github.com/Dreamacro/clash/component/dialer" + types "github.com/Dreamacro/clash/constant/provider" ) -// Vehicle Type -const ( - File VehicleType = iota - HTTP - Compatible -) - -// VehicleType defined -type VehicleType int - -func (v VehicleType) String() string { - switch v { - case File: - return "File" - case HTTP: - return "HTTP" - case Compatible: - return "Compatible" - default: - return "Unknown" - } -} - -type Vehicle interface { - Read() ([]byte, error) - Path() string - Type() VehicleType -} - type FileVehicle struct { path string } -func (f *FileVehicle) Type() VehicleType { - return File +func (f *FileVehicle) Type() types.VehicleType { + return types.File } func (f *FileVehicle) Path() string { @@ -64,8 +36,8 @@ type HTTPVehicle struct { path string } -func (h *HTTPVehicle) Type() VehicleType { - return HTTP +func (h *HTTPVehicle) Type() types.VehicleType { + return types.HTTP } func (h *HTTPVehicle) Path() string { diff --git a/config/config.go b/config/config.go index a256d2820..a9628192b 100644 --- a/config/config.go +++ b/config/config.go @@ -16,6 +16,7 @@ import ( "github.com/Dreamacro/clash/component/fakeip" "github.com/Dreamacro/clash/component/trie" C "github.com/Dreamacro/clash/constant" + providerTypes "github.com/Dreamacro/clash/constant/provider" "github.com/Dreamacro/clash/dns" "github.com/Dreamacro/clash/log" R "github.com/Dreamacro/clash/rule" @@ -93,7 +94,7 @@ type Config struct { Rules []C.Rule Users []auth.AuthUser Proxies map[string]C.Proxy - Providers map[string]provider.ProxyProvider + Providers map[string]providerTypes.ProxyProvider } type RawDNS struct { @@ -267,9 +268,9 @@ func parseGeneral(cfg *RawConfig) (*General, error) { }, nil } -func parseProxies(cfg *RawConfig) (proxies map[string]C.Proxy, providersMap map[string]provider.ProxyProvider, err error) { +func parseProxies(cfg *RawConfig) (proxies map[string]C.Proxy, providersMap map[string]providerTypes.ProxyProvider, err error) { proxies = make(map[string]C.Proxy) - providersMap = make(map[string]provider.ProxyProvider) + providersMap = make(map[string]providerTypes.ProxyProvider) proxyList := []string{} proxiesConfig := cfg.Proxy groupsConfig := cfg.ProxyGroup @@ -345,7 +346,7 @@ func parseProxies(cfg *RawConfig) (proxies map[string]C.Proxy, providersMap map[ // initial compatible provider for _, pd := range providersMap { - if pd.VehicleType() != provider.Compatible { + if pd.VehicleType() != providerTypes.Compatible { continue } @@ -367,7 +368,7 @@ func parseProxies(cfg *RawConfig) (proxies map[string]C.Proxy, providersMap map[ &outboundgroup.GroupCommonOption{ Name: "GLOBAL", }, - []provider.ProxyProvider{pd}, + []providerTypes.ProxyProvider{pd}, ) proxies["GLOBAL"] = adapter.NewProxy(global) return proxies, providersMap, nil diff --git a/constant/provider/interface.go b/constant/provider/interface.go new file mode 100644 index 000000000..d3483cdcd --- /dev/null +++ b/constant/provider/interface.go @@ -0,0 +1,105 @@ +package provider + +import ( + "github.com/Dreamacro/clash/constant" +) + +// Vehicle Type +const ( + File VehicleType = iota + HTTP + Compatible +) + +// VehicleType defined +type VehicleType int + +func (v VehicleType) String() string { + switch v { + case File: + return "File" + case HTTP: + return "HTTP" + case Compatible: + return "Compatible" + default: + return "Unknown" + } +} + +type Vehicle interface { + Read() ([]byte, error) + Path() string + Type() VehicleType +} + +// Provider Type +const ( + Proxy ProviderType = iota + Rule +) + +// ProviderType defined +type ProviderType int + +func (pt ProviderType) String() string { + switch pt { + case Proxy: + return "Proxy" + case Rule: + return "Rule" + default: + return "Unknown" + } +} + +// Provider interface +type Provider interface { + Name() string + VehicleType() VehicleType + Type() ProviderType + Initial() error + Update() error +} + +// ProxyProvider interface +type ProxyProvider interface { + Provider + Proxies() []constant.Proxy + // ProxiesWithTouch is used to inform the provider that the proxy is actually being used while getting the list of proxies. + // Commonly used in Dial and DialUDP + ProxiesWithTouch() []constant.Proxy + HealthCheck() +} + +// Rule Type +const ( + Domain RuleType = iota + IPCIDR + Classical +) + +// RuleType defined +type RuleType int + +func (rt RuleType) String() string { + switch rt { + case Domain: + return "Domain" + case IPCIDR: + return "IPCIDR" + case Classical: + return "Classical" + default: + return "Unknown" + } +} + +// RuleProvider interface +type RuleProvider interface { + Provider + Behavior() RuleType + Match(*constant.Metadata) bool + ShouldResolveIP() bool + AsRule(adaptor string) constant.Rule +} diff --git a/hub/executor/executor.go b/hub/executor/executor.go index 81920221d..321efe250 100644 --- a/hub/executor/executor.go +++ b/hub/executor/executor.go @@ -8,7 +8,6 @@ import ( "github.com/Dreamacro/clash/adapter" "github.com/Dreamacro/clash/adapter/outboundgroup" - "github.com/Dreamacro/clash/adapter/provider" "github.com/Dreamacro/clash/component/auth" "github.com/Dreamacro/clash/component/dialer" "github.com/Dreamacro/clash/component/profile" @@ -17,6 +16,7 @@ import ( "github.com/Dreamacro/clash/component/trie" "github.com/Dreamacro/clash/config" C "github.com/Dreamacro/clash/constant" + "github.com/Dreamacro/clash/constant/provider" "github.com/Dreamacro/clash/dns" P "github.com/Dreamacro/clash/listener" authStore "github.com/Dreamacro/clash/listener/auth" diff --git a/hub/route/provider.go b/hub/route/provider.go index f373d5114..0b599445a 100644 --- a/hub/route/provider.go +++ b/hub/route/provider.go @@ -4,7 +4,7 @@ import ( "context" "net/http" - "github.com/Dreamacro/clash/adapter/provider" + "github.com/Dreamacro/clash/constant/provider" "github.com/Dreamacro/clash/tunnel" "github.com/go-chi/chi/v5" diff --git a/tunnel/tunnel.go b/tunnel/tunnel.go index a40b697df..0ec36d3f1 100644 --- a/tunnel/tunnel.go +++ b/tunnel/tunnel.go @@ -8,10 +8,10 @@ import ( "time" "github.com/Dreamacro/clash/adapter/inbound" - "github.com/Dreamacro/clash/adapter/provider" "github.com/Dreamacro/clash/component/nat" "github.com/Dreamacro/clash/component/resolver" C "github.com/Dreamacro/clash/constant" + "github.com/Dreamacro/clash/constant/provider" "github.com/Dreamacro/clash/context" "github.com/Dreamacro/clash/log" "github.com/Dreamacro/clash/tunnel/statistic" From b4292d09721e3cc20745903e9dc3bece1a5a1221 Mon Sep 17 00:00:00 2001 From: Dreamacro <8615343+Dreamacro@users.noreply.github.com> Date: Tue, 6 Jul 2021 00:33:13 +0800 Subject: [PATCH 18/96] Fix: staticcheck error --- adapter/provider/provider.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/adapter/provider/provider.go b/adapter/provider/provider.go index b6e1ac754..32baaedd9 100644 --- a/adapter/provider/provider.go +++ b/adapter/provider/provider.go @@ -204,7 +204,7 @@ func stopCompatibleProvider(pd *CompatibleProvider) { func NewCompatibleProvider(name string, proxies []C.Proxy, hc *HealthCheck) (*CompatibleProvider, error) { if len(proxies) == 0 { - return nil, errors.New("Provider need one proxy at least") + return nil, errors.New("provider need one proxy at least") } if hc.auto() { From 250a9f4f847cad95f1960d280603d4bf07991d47 Mon Sep 17 00:00:00 2001 From: Dreamacro <8615343+Dreamacro@users.noreply.github.com> Date: Sat, 10 Jul 2021 17:01:40 +0800 Subject: [PATCH 19/96] Fix: reorder apply config to ensure update proxies and rules --- hub/executor/executor.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hub/executor/executor.go b/hub/executor/executor.go index 321efe250..4438a5761 100644 --- a/hub/executor/executor.go +++ b/hub/executor/executor.go @@ -70,13 +70,13 @@ func ApplyConfig(cfg *config.Config, force bool) { defer mux.Unlock() updateUsers(cfg.Users) - updateGeneral(cfg.General, force) updateProxies(cfg.Proxies, cfg.Providers) updateRules(cfg.Rules) - updateDNS(cfg.DNS) updateHosts(cfg.Hosts) - updateExperimental(cfg) updateProfile(cfg) + updateGeneral(cfg.General, force) + updateDNS(cfg.DNS) + updateExperimental(cfg) } func GetGeneral() *config.General { From 46f4f8444260bc0b93f1d83c88ba92ef39cb9a9c Mon Sep 17 00:00:00 2001 From: Dreamacro <8615343+Dreamacro@users.noreply.github.com> Date: Sun, 11 Jul 2021 19:42:54 +0800 Subject: [PATCH 20/96] Chore: use iife replace init in some cases --- common/pool/alloc.go | 6 +----- component/process/process_linux.go | 12 +++++------- constant/path.go | 16 +++++++--------- 3 files changed, 13 insertions(+), 21 deletions(-) diff --git a/common/pool/alloc.go b/common/pool/alloc.go index bf177da88..6ae53c1db 100644 --- a/common/pool/alloc.go +++ b/common/pool/alloc.go @@ -8,11 +8,7 @@ import ( "sync" ) -var defaultAllocator *Allocator - -func init() { - defaultAllocator = NewAllocator() -} +var defaultAllocator = NewAllocator() // Allocator for incoming frames, optimized to prevent overwriting after zeroing type Allocator struct { diff --git a/component/process/process_linux.go b/component/process/process_linux.go index 1f651cd48..fabe969c8 100644 --- a/component/process/process_linux.go +++ b/component/process/process_linux.go @@ -16,14 +16,14 @@ import ( ) // from https://github.com/vishvananda/netlink/blob/bca67dfc8220b44ef582c9da4e9172bf1c9ec973/nl/nl_linux.go#L52-L62 -func init() { +var nativeEndian = func() binary.ByteOrder { var x uint32 = 0x01020304 if *(*byte)(unsafe.Pointer(&x)) == 0x01 { - nativeEndian = binary.BigEndian - } else { - nativeEndian = binary.LittleEndian + return binary.BigEndian } -} + + return binary.LittleEndian +}() type SocketResolver func(network string, ip net.IP, srcPort int) (inode, uid int, err error) type ProcessNameResolver func(inode, uid int) (name string, err error) @@ -40,8 +40,6 @@ const ( pathProc = "/proc" ) -var nativeEndian binary.ByteOrder = binary.LittleEndian - func findProcessName(network string, ip net.IP, srcPort int) (string, error) { inode, uid, err := DefaultSocketResolver(network, ip, srcPort) if err != nil { diff --git a/constant/path.go b/constant/path.go index 021721ec4..ba0e8c23b 100644 --- a/constant/path.go +++ b/constant/path.go @@ -9,21 +9,19 @@ import ( const Name = "clash" // Path is used to get the configuration path -var Path *path - -type path struct { - homeDir string - configFile string -} - -func init() { +var Path = func() *path { homeDir, err := os.UserHomeDir() if err != nil { homeDir, _ = os.Getwd() } homeDir = P.Join(homeDir, ".config", Name) - Path = &path{homeDir: homeDir, configFile: "config.yaml"} + return &path{homeDir: homeDir, configFile: "config.yaml"} +}() + +type path struct { + homeDir string + configFile string } // SetHomeDir is used to set the configuration path From a461c2306ab97d7814b196d057e91ed9dce71284 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?x=E1=B4=8A=E1=B4=80s=E1=B4=8F=C9=B4=CA=9F=CA=8F=E1=B4=9C?= Date: Sun, 18 Jul 2021 16:09:09 +0800 Subject: [PATCH 21/96] Feature: SOCKS4/SOCKS4A Inbound Compatible Support (#1491) --- hub/executor/executor.go | 4 +- listener/listener.go | 4 +- listener/mixed/mixed.go | 13 ++- listener/socks/tcp.go | 36 ++++++- transport/socks4/socks4.go | 195 +++++++++++++++++++++++++++++++++++++ 5 files changed, 241 insertions(+), 11 deletions(-) create mode 100644 transport/socks4/socks4.go diff --git a/hub/executor/executor.go b/hub/executor/executor.go index 4438a5761..b3772211f 100644 --- a/hub/executor/executor.go +++ b/hub/executor/executor.go @@ -195,7 +195,7 @@ func updateGeneral(general *config.General, force bool) { } if err := P.ReCreateSocks(general.SocksPort, tcpIn, udpIn); err != nil { - log.Errorln("Start SOCKS5 server error: %s", err.Error()) + log.Errorln("Start SOCKS server error: %s", err.Error()) } if err := P.ReCreateRedir(general.RedirPort, tcpIn, udpIn); err != nil { @@ -207,7 +207,7 @@ func updateGeneral(general *config.General, force bool) { } if err := P.ReCreateMixed(general.MixedPort, tcpIn, udpIn); err != nil { - log.Errorln("Start Mixed(http and socks5) server error: %s", err.Error()) + log.Errorln("Start Mixed(http and socks) server error: %s", err.Error()) } } diff --git a/listener/listener.go b/listener/listener.go index cf0390e7e..5d0e8d7bf 100644 --- a/listener/listener.go +++ b/listener/listener.go @@ -139,7 +139,7 @@ func ReCreateSocks(port int, tcpIn chan<- C.ConnContext, udpIn chan<- *inbound.P socksListener = tcpListener socksUDPListener = udpListener - log.Infoln("SOCKS5 proxy listening at: %s", socksListener.Address()) + log.Infoln("SOCKS proxy listening at: %s", socksListener.Address()) return nil } @@ -271,7 +271,7 @@ func ReCreateMixed(port int, tcpIn chan<- C.ConnContext, udpIn chan<- *inbound.P return err } - log.Infoln("Mixed(http+socks5) proxy listening at: %s", mixedListener.Address()) + log.Infoln("Mixed(http+socks) proxy listening at: %s", mixedListener.Address()) return nil } diff --git a/listener/mixed/mixed.go b/listener/mixed/mixed.go index 07ad03b62..7d89e3c8d 100644 --- a/listener/mixed/mixed.go +++ b/listener/mixed/mixed.go @@ -9,6 +9,7 @@ import ( C "github.com/Dreamacro/clash/constant" "github.com/Dreamacro/clash/listener/http" "github.com/Dreamacro/clash/listener/socks" + "github.com/Dreamacro/clash/transport/socks4" "github.com/Dreamacro/clash/transport/socks5" ) @@ -58,10 +59,12 @@ func handleConn(conn net.Conn, in chan<- C.ConnContext, cache *cache.Cache) { return } - if head[0] == socks5.Version { - socks.HandleSocks(bufConn, in) - return + switch head[0] { + case socks4.Version: + socks.HandleSocks4(bufConn, in) + case socks5.Version: + socks.HandleSocks5(bufConn, in) + default: + http.HandleConn(bufConn, in, cache) } - - http.HandleConn(bufConn, in, cache) } diff --git a/listener/socks/tcp.go b/listener/socks/tcp.go index 8e12ac71d..60da0e264 100644 --- a/listener/socks/tcp.go +++ b/listener/socks/tcp.go @@ -6,8 +6,10 @@ import ( "net" "github.com/Dreamacro/clash/adapter/inbound" + N "github.com/Dreamacro/clash/common/net" C "github.com/Dreamacro/clash/constant" authStore "github.com/Dreamacro/clash/listener/auth" + "github.com/Dreamacro/clash/transport/socks4" "github.com/Dreamacro/clash/transport/socks5" ) @@ -33,7 +35,7 @@ func New(addr string, in chan<- C.ConnContext) (*Listener, error) { } continue } - go HandleSocks(c, in) + go handleSocks(c, in) } }() @@ -49,7 +51,37 @@ func (l *Listener) Address() string { return l.address } -func HandleSocks(conn net.Conn, in chan<- C.ConnContext) { +func handleSocks(conn net.Conn, in chan<- C.ConnContext) { + bufConn := N.NewBufferedConn(conn) + head, err := bufConn.Peek(1) + if err != nil { + conn.Close() + return + } + + switch head[0] { + case socks4.Version: + HandleSocks4(bufConn, in) + case socks5.Version: + HandleSocks5(bufConn, in) + default: + conn.Close() + } +} + +func HandleSocks4(conn net.Conn, in chan<- C.ConnContext) { + addr, _, err := socks4.ServerHandshake(conn, authStore.Authenticator()) + if err != nil { + conn.Close() + return + } + if c, ok := conn.(*net.TCPConn); ok { + c.SetKeepAlive(true) + } + in <- inbound.NewSocket(socks5.ParseAddr(addr), conn, C.SOCKS) +} + +func HandleSocks5(conn net.Conn, in chan<- C.ConnContext) { target, command, err := socks5.ServerHandshake(conn, authStore.Authenticator()) if err != nil { conn.Close() diff --git a/transport/socks4/socks4.go b/transport/socks4/socks4.go new file mode 100644 index 000000000..c6b2f2db5 --- /dev/null +++ b/transport/socks4/socks4.go @@ -0,0 +1,195 @@ +package socks4 + +import ( + "bytes" + "encoding/binary" + "errors" + "io" + "net" + "strconv" + + "github.com/Dreamacro/clash/component/auth" +) + +const Version = 0x04 + +type Command = uint8 + +const ( + CmdConnect Command = 0x01 + CmdBind Command = 0x02 +) + +type Code = uint8 + +const ( + RequestGranted Code = 90 + RequestRejected Code = 91 + RequestIdentdFailed Code = 92 + RequestIdentdMismatched Code = 93 +) + +var ( + errVersionMismatched = errors.New("version code mismatched") + errCommandNotSupported = errors.New("command not supported") + errIPv6NotSupported = errors.New("IPv6 not supported") + + ErrRequestRejected = errors.New("request rejected or failed") + ErrRequestIdentdFailed = errors.New("request rejected because SOCKS server cannot connect to identd on the client") + ErrRequestIdentdMismatched = errors.New("request rejected because the client program and identd report different user-ids") + ErrRequestUnknownCode = errors.New("request failed with unknown code") +) + +func ServerHandshake(rw io.ReadWriter, authenticator auth.Authenticator) (addr string, command Command, err error) { + var req [8]byte + if _, err = io.ReadFull(rw, req[:]); err != nil { + return + } + + if req[0] != Version { + err = errVersionMismatched + return + } + + if command = req[1]; command != CmdConnect { + err = errCommandNotSupported + return + } + + var ( + dstIP = req[4:8] // [4]byte + dstPort = req[2:4] // [2]byte + ) + + var ( + host string + port string + code uint8 + userID []byte + ) + if userID, err = readUntilNull(rw); err != nil { + return + } + + if isReservedIP(dstIP) { + var target []byte + if target, err = readUntilNull(rw); err != nil { + return + } + host = string(target) + } + + port = strconv.Itoa(int(binary.BigEndian.Uint16(dstPort))) + if host != "" { + addr = net.JoinHostPort(host, port) + } else { + addr = net.JoinHostPort(net.IP(dstIP).String(), port) + } + + // SOCKS4 only support USERID auth. + if authenticator == nil || authenticator.Verify(string(userID), "") { + code = RequestGranted + } else { + code = RequestIdentdMismatched + } + + var reply [8]byte + reply[0] = 0x00 // reply code + reply[1] = code // result code + copy(reply[4:8], dstIP) + copy(reply[2:4], dstPort) + + _, err = rw.Write(reply[:]) + return +} + +func ClientHandshake(rw io.ReadWriter, addr string, command Command, userID string) (err error) { + host, portStr, err := net.SplitHostPort(addr) + if err != nil { + return err + } + + port, err := strconv.ParseUint(portStr, 10, 16) + if err != nil { + return err + } + + ip := net.ParseIP(host) + if ip == nil /* HOST */ { + ip = net.IPv4(0, 0, 0, 1).To4() + } else if ip.To4() == nil /* IPv6 */ { + return errIPv6NotSupported + } + + dstIP := ip.To4() + + req := &bytes.Buffer{} + req.WriteByte(Version) + req.WriteByte(command) + binary.Write(req, binary.BigEndian, uint16(port)) + req.Write(dstIP) + req.WriteString(userID) + req.WriteByte(0) /* NULL */ + + if isReservedIP(dstIP) /* SOCKS4A */ { + req.WriteString(host) + req.WriteByte(0) /* NULL */ + } + + if _, err = rw.Write(req.Bytes()); err != nil { + return err + } + + var resp [8]byte + if _, err = io.ReadFull(rw, resp[:]); err != nil { + return err + } + + if resp[0] != 0x00 { + return errVersionMismatched + } + + switch resp[1] { + case RequestGranted: + return nil + case RequestRejected: + return ErrRequestRejected + case RequestIdentdFailed: + return ErrRequestIdentdFailed + case RequestIdentdMismatched: + return ErrRequestIdentdMismatched + default: + return ErrRequestUnknownCode + } +} + +// For version 4A, if the client cannot resolve the destination host's +// domain name to find its IP address, it should set the first three bytes +// of DSTIP to NULL and the last byte to a non-zero value. (This corresponds +// to IP address 0.0.0.x, with x nonzero. As decreed by IANA -- The +// Internet Assigned Numbers Authority -- such an address is inadmissible +// as a destination IP address and thus should never occur if the client +// can resolve the domain name.) +func isReservedIP(ip net.IP) bool { + subnet := net.IPNet{ + IP: net.IPv4zero, + Mask: net.IPv4Mask(0xff, 0xff, 0xff, 0x00), + } + + return !ip.IsUnspecified() && subnet.Contains(ip) +} + +func readUntilNull(r io.Reader) ([]byte, error) { + var buf = &bytes.Buffer{} + var data [1]byte + + for { + if _, err := r.Read(data[:]); err != nil { + return nil, err + } + if data[0] == 0 { + return buf.Bytes(), nil + } + buf.WriteByte(data[0]) + } +} From 91ed0118f628dd378fb3c74a23f3e46f838012ae Mon Sep 17 00:00:00 2001 From: Dreamacro <8615343+Dreamacro@users.noreply.github.com> Date: Sun, 18 Jul 2021 17:23:22 +0800 Subject: [PATCH 22/96] Test: add basic protocol benchmark --- test/clash_test.go | 35 + test/go.mod | 25 +- test/go.sum | 844 ++++++++++++++++++++- test/snell_test.go | 37 + test/ss_test.go | 35 + test/trojan_test.go | 40 + test/{util_test.go => util_darwin_test.go} | 0 test/util_other_test.go | 12 + test/vmess_test.go | 38 + 9 files changed, 1020 insertions(+), 46 deletions(-) rename test/{util_test.go => util_darwin_test.go} (100%) create mode 100644 test/util_other_test.go diff --git a/test/clash_test.go b/test/clash_test.go index e835b0fec..97f6648b1 100644 --- a/test/clash_test.go +++ b/test/clash_test.go @@ -619,6 +619,41 @@ func testSuit(t *testing.T, proxy C.ProxyAdapter) { assert.NoError(t, testPacketConnTimeout(t, pc)) } +func benchmarkProxy(b *testing.B, proxy C.ProxyAdapter) { + l, err := net.Listen("tcp", ":10001") + if err != nil { + assert.FailNow(b, err.Error()) + } + + go func() { + c, err := l.Accept() + if err != nil { + assert.FailNow(b, err.Error()) + } + + io.Copy(io.Discard, c) + c.Close() + }() + + chunk := make([]byte, 1024) + conn, err := proxy.DialContext(context.Background(), &C.Metadata{ + Host: localIP.String(), + DstPort: "10001", + AddrType: socks5.AtypDomainName, + }) + if err != nil { + assert.FailNow(b, err.Error()) + } + + b.SetBytes(1024) + b.ResetTimer() + for i := 0; i < b.N; i++ { + if _, err := conn.Write(chunk); err != nil { + assert.FailNow(b, err.Error()) + } + } +} + func TestClash_Basic(t *testing.T) { basic := ` mixed-port: 10000 diff --git a/test/go.mod b/test/go.mod index 1a5cb6763..88db62292 100644 --- a/test/go.mod +++ b/test/go.mod @@ -3,24 +3,17 @@ module clash-test go 1.16 require ( - github.com/Dreamacro/clash v1.6.1-0.20210516120541-06fdd3abe0ab - github.com/Microsoft/go-winio v0.4.16 // indirect - github.com/containerd/containerd v1.4.4 // indirect - github.com/docker/distribution v2.7.1+incompatible // indirect - github.com/docker/docker v20.10.6+incompatible + github.com/Dreamacro/clash v1.6.5 + github.com/Microsoft/go-winio v0.5.0 // indirect + github.com/containerd/containerd v1.5.3 // indirect + github.com/docker/docker v20.10.7+incompatible github.com/docker/go-connections v0.4.0 - github.com/docker/go-units v0.4.0 // indirect - github.com/gogo/protobuf v1.3.2 // indirect - github.com/google/go-cmp v0.5.5 // indirect github.com/gorilla/mux v1.8.0 // indirect - github.com/miekg/dns v1.1.42 - github.com/moby/term v0.0.0-20201216013528-df9cb8a40635 // indirect + github.com/miekg/dns v1.1.43 + github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 // indirect github.com/morikuni/aec v1.0.0 // indirect - github.com/opencontainers/go-digest v1.0.0 // indirect - github.com/opencontainers/image-spec v1.0.1 // indirect github.com/stretchr/testify v1.7.0 - golang.org/x/net v0.0.0-20210510120150-4163338589ed - golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba // indirect - google.golang.org/grpc v1.36.0 // indirect - gotest.tools/v3 v3.0.3 // indirect + golang.org/x/net v0.0.0-20210614182718-04defd469f4e + golang.org/x/time v0.0.0-20210611083556-38a9dc6acbc6 // indirect + google.golang.org/grpc v1.39.0 // indirect ) diff --git a/test/go.sum b/test/go.sum index 2a641fb70..0b460241b 100644 --- a/test/go.sum +++ b/test/go.sum @@ -1,164 +1,837 @@ +bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 h1:w+iIsaOQNcT7OZ575w+acHgRric5iCyQh+xv+KJ4HB8= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= +cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= +cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= +cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= +cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= +cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= +cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= +cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= +cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= +cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= +cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= +cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= +cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= +cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= +cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= +cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= +cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= +cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +github.com/Azure/azure-sdk-for-go v16.2.1+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= +github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= +github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= +github.com/Azure/go-autorest v10.8.1+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= +github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= +github.com/Azure/go-autorest/autorest v0.11.1/go.mod h1:JFgpikqFJ/MleTTxwepExTKnFUKKszPS8UavbQYUMuw= +github.com/Azure/go-autorest/autorest/adal v0.9.0/go.mod h1:/c022QCutn2P7uY+/oQWWNcK9YU+MH96NgK+jErpbcg= +github.com/Azure/go-autorest/autorest/adal v0.9.5/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A= +github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= +github.com/Azure/go-autorest/autorest/mocks v0.4.0/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= +github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= +github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= +github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/Dreamacro/clash v1.6.1-0.20210516120541-06fdd3abe0ab h1:hfjxpY+73Xo6k+JHMkLlaOR3Tw5hG/YZxmDFyV9Y6sY= -github.com/Dreamacro/clash v1.6.1-0.20210516120541-06fdd3abe0ab/go.mod h1:Pz9GwWR244jrMSInQ0KUL02jMCe5xIJ+pkgzuNIy2Iw= +github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/Dreamacro/clash v1.6.5 h1:bO8MJpfDOqZsgiK32x2xe9fjniujqVabQOWEYAg5Rac= +github.com/Dreamacro/clash v1.6.5/go.mod h1:AqwqYq0ibcW8j14Re3/uY0bido9PzAuME7Dj+7zst/o= github.com/Dreamacro/go-shadowsocks2 v0.1.7 h1:8CtbE1HoPPMfrQZGXmlluq6dO2lL31W6WRRE8fabc4Q= github.com/Dreamacro/go-shadowsocks2 v0.1.7/go.mod h1:8p5G4cAj5ZlXwUR+Ww63gfSikr8kvw8uw3TDwLAJpUc= -github.com/Microsoft/go-winio v0.4.16 h1:FtSW/jqD+l4ba5iPBj9CODVtgfYAD8w2wS923g/cFDk= +github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA= +github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= +github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw= +github.com/Microsoft/go-winio v0.4.16-0.20201130162521-d1ffc52c7331/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= +github.com/Microsoft/go-winio v0.4.17-0.20210211115548-6eac466e5fa3/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= +github.com/Microsoft/go-winio v0.4.17-0.20210324224401-5516f17a5958/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= +github.com/Microsoft/go-winio v0.4.17/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= +github.com/Microsoft/go-winio v0.5.0 h1:Elr9Wn+sGKPlkaBvwu4mTrxtmOp3F3yV9qhaHbXGjwU= +github.com/Microsoft/go-winio v0.5.0/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= +github.com/Microsoft/hcsshim v0.8.6/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg= +github.com/Microsoft/hcsshim v0.8.7-0.20190325164909-8abdbb8205e4/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg= +github.com/Microsoft/hcsshim v0.8.7/go.mod h1:OHd7sQqRFrYd3RmSgbgji+ctCwkbq2wbEYNSzOYtcBQ= +github.com/Microsoft/hcsshim v0.8.9/go.mod h1:5692vkUqntj1idxauYlpoINNKeqCiG6Sg38RRsjT5y8= +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.16/go.mod h1:o5/SZqmR7x9JNKsW3pu+nqHm0MF8vbA+VxGOoXdC600= +github.com/Microsoft/hcsshim v0.8.18/go.mod h1:+w2gRZ5ReXQhFOrvSQeNfhrYB/dg3oDwTOcER2fw4I4= +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/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= +github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= +github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ= +github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:CgnQgUtFrFz9mxFNtED3jI5tLDjKlOM+oUF/sTk6ps0= +github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= +github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= +github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= +github.com/aws/aws-sdk-go v1.15.11/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0= +github.com/beorn7/perks v0.0.0-20160804104726-4c0e84591b9a/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA= +github.com/blang/semver v3.1.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= +github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= +github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= +github.com/bshuster-repo/logrus-logstash-hook v0.4.1/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk= +github.com/buger/jsonparser v0.0.0-20180808090653-f4dd9f5a6b44/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= +github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8= +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/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/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/checkpoint-restore/go-criu/v4 v4.1.0/go.mod h1:xUQBLp4RLc5zJtWY++yjOoMoB5lihDt7fai+75m+rGw= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/cilium/ebpf v0.0.0-20200110133405-4032b1d8aae3/go.mod h1:MA5e5Lr8slmEg9bt0VpxxWqJlO4iwu3FBdHUzV7wQVg= +github.com/cilium/ebpf v0.0.0-20200702112145-1c8d4c9ef775/go.mod h1:7cR51M8ViRLIdUjrmSXlK9pkrsDlLHbO8jiB8X8JnOc= +github.com/cilium/ebpf v0.2.0/go.mod h1:To2CFviqOWL/M0gIMsvSMlqe7em/l1ALkX1PyjrX2Qs= +github.com/cilium/ebpf v0.4.0/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/containerd/containerd v1.4.4 h1:rtRG4N6Ct7GNssATwgpvMGfnjnwfjnu/Zs9W3Ikzq+M= -github.com/containerd/containerd v1.4.4/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= +github.com/containerd/aufs v0.0.0-20200908144142-dab0cbea06f4/go.mod h1:nukgQABAEopAHvB6j7cnP5zJ+/3aVcE7hCYqvIwAHyE= +github.com/containerd/aufs v0.0.0-20201003224125-76a6863f2989/go.mod h1:AkGGQs9NM2vtYHaUen+NljV0/baGCAPELGm2q9ZXpWU= +github.com/containerd/aufs v0.0.0-20210316121734-20793ff83c97/go.mod h1:kL5kd6KM5TzQjR79jljyi4olc1Vrx6XBlcyj3gNv2PU= +github.com/containerd/aufs v1.0.0/go.mod h1:kL5kd6KM5TzQjR79jljyi4olc1Vrx6XBlcyj3gNv2PU= +github.com/containerd/btrfs v0.0.0-20201111183144-404b9149801e/go.mod h1:jg2QkJcsabfHugurUvvPhS3E08Oxiuh5W/g1ybB4e0E= +github.com/containerd/btrfs v0.0.0-20210316141732-918d888fb676/go.mod h1:zMcX3qkXTAi9GI50+0HOeuV8LU2ryCE/V2vG/ZBiTss= +github.com/containerd/btrfs v1.0.0/go.mod h1:zMcX3qkXTAi9GI50+0HOeuV8LU2ryCE/V2vG/ZBiTss= +github.com/containerd/cgroups v0.0.0-20190717030353-c4b9ac5c7601/go.mod h1:X9rLEHIqSf/wfK8NsPqxJmeZgW4pcfzdXITDrUSJ6uI= +github.com/containerd/cgroups v0.0.0-20190919134610-bf292b21730f/go.mod h1:OApqhQ4XNSNC13gXIwDjhOQxjWa/NxkwZXJ1EvqT0ko= +github.com/containerd/cgroups v0.0.0-20200531161412-0dbf7f05ba59/go.mod h1:pA0z1pT8KYB3TCXK/ocprsh7MAkoW8bZVzPdih9snmM= +github.com/containerd/cgroups v0.0.0-20200710171044-318312a37340/go.mod h1:s5q4SojHctfxANBDvMeIaIovkq29IP48TKAxnhYRxvo= +github.com/containerd/cgroups v0.0.0-20200824123100-0b889c03f102/go.mod h1:s5q4SojHctfxANBDvMeIaIovkq29IP48TKAxnhYRxvo= +github.com/containerd/cgroups v0.0.0-20210114181951-8a68de567b68/go.mod h1:ZJeTFisyysqgcCdecO57Dj79RfL0LNeGiFUqLYQRYLE= +github.com/containerd/cgroups v1.0.1/go.mod h1:0SJrPIenamHDcZhEcJMNBB85rHcUsw4f25ZfBiPYRkU= +github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw= +github.com/containerd/console v0.0.0-20181022165439-0650fd9eeb50/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw= +github.com/containerd/console v0.0.0-20191206165004-02ecf6a7291e/go.mod h1:8Pf4gM6VEbTNRIT26AyyU7hxdQU3MvAvxVI0sc00XBE= +github.com/containerd/console v1.0.1/go.mod h1:XUsP6YE/mKtz6bxc+I8UiKKTP04qjQL4qcS3XoQ5xkw= +github.com/containerd/console v1.0.2/go.mod h1:ytZPjGgY2oeTkAONYafi2kSj0aYggsf8acV1PGKCbzQ= +github.com/containerd/containerd v1.2.10/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.3.0-beta.2.0.20190828155532-0293cbd26c69/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.3.0/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.3.1-0.20191213020239-082f7e3aed57/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.3.2/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.3/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.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-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.3 h1:mfKOepNDIJ3EiBTEyHFpEqB6YSOSkGcjPDIu7cD+YzY= +github.com/containerd/containerd v1.5.3/go.mod h1:sx18RgvW6ABJ4iYUw7Q5x7bgFOAB9B6G7+yO0XBc4zw= +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-20191127005431-f65d91d395eb/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= +github.com/containerd/continuity v0.0.0-20200710164510-efbc4488d8fe/go.mod h1:cECdGN1O8G9bgKTlLhuPJimka6Xb/Gg7vYzCTNVxhvo= +github.com/containerd/continuity v0.0.0-20201208142359-180525291bb7/go.mod h1:kR3BEg7bDFaEddKm54WSmrol1fKWDU1nKYkgrcgZT7Y= +github.com/containerd/continuity v0.0.0-20210208174643-50096c924a4e/go.mod h1:EXlVlkqNba9rJe3j7w3Xa924itAMLgZH4UD/Q4PExuQ= +github.com/containerd/continuity v0.1.0/go.mod h1:ICJu0PwR54nI0yPEnJ6jcS+J7CZAUXrLh8lPo2knzsM= +github.com/containerd/fifo v0.0.0-20180307165137-3d5202aec260/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI= +github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI= +github.com/containerd/fifo v0.0.0-20200410184934-f15a3290365b/go.mod h1:jPQ2IAeZRCYxpS/Cm1495vGFww6ecHmMk1YJH2Q5ln0= +github.com/containerd/fifo v0.0.0-20201026212402-0724c46b320c/go.mod h1:jPQ2IAeZRCYxpS/Cm1495vGFww6ecHmMk1YJH2Q5ln0= +github.com/containerd/fifo v0.0.0-20210316144830-115abcc95a1d/go.mod h1:ocF/ME1SX5b1AOlWi9r677YJmCPSwwWnQ9O123vzpE4= +github.com/containerd/fifo v1.0.0/go.mod h1:ocF/ME1SX5b1AOlWi9r677YJmCPSwwWnQ9O123vzpE4= +github.com/containerd/go-cni v1.0.1/go.mod h1:+vUpYxKvAF72G9i1WoDOiPGRtQpqsNW/ZHtSlv++smU= +github.com/containerd/go-cni v1.0.2/go.mod h1:nrNABBHzu0ZwCug9Ije8hL2xBCYh/pjfMb1aZGrrohk= +github.com/containerd/go-runc v0.0.0-20180907222934-5a6d9f37cfa3/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0= +github.com/containerd/go-runc v0.0.0-20190911050354-e029b79d8cda/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0= +github.com/containerd/go-runc v0.0.0-20200220073739-7016d3ce2328/go.mod h1:PpyHrqVs8FTi9vpyHwPwiNEGaACDxT/N/pLcvMSRA9g= +github.com/containerd/go-runc v0.0.0-20201020171139-16b287bc67d0/go.mod h1:cNU0ZbCgCQVZK4lgG3P+9tn9/PaJNmoDXPpoJhDR+Ok= +github.com/containerd/go-runc v1.0.0/go.mod h1:cNU0ZbCgCQVZK4lgG3P+9tn9/PaJNmoDXPpoJhDR+Ok= +github.com/containerd/imgcrypt v1.0.1/go.mod h1:mdd8cEPW7TPgNG4FpuP3sGBiQ7Yi/zak9TYCG3juvb0= +github.com/containerd/imgcrypt v1.0.4-0.20210301171431-0ae5c75f59ba/go.mod h1:6TNsg0ctmizkrOgXRNQjAPFWpMYRWuiB6dSF4Pfa5SA= +github.com/containerd/imgcrypt v1.1.1-0.20210312161619-7ed62a527887/go.mod h1:5AZJNI6sLHJljKuI9IHnw1pWqo/F0nGDOuR9zgTs7ow= +github.com/containerd/imgcrypt v1.1.1/go.mod h1:xpLnwiQmEUJPvQoAapeb2SNCxz7Xr6PJrXQb0Dpc4ms= +github.com/containerd/nri v0.0.0-20201007170849-eb1350a75164/go.mod h1:+2wGSDGFYfE5+So4M5syatU0N0f0LbWpuqyMi4/BE8c= +github.com/containerd/nri v0.0.0-20210316161719-dbaa18c31c14/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY= +github.com/containerd/nri v0.1.0/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY= +github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o= +github.com/containerd/ttrpc v0.0.0-20190828172938-92c8520ef9f8/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o= +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.2/go.mod h1:UAxOpgT9ziI0gJrmKvgcZivgxOp8iFPSk8httJEt98Y= +github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd/go.mod h1:Cm3kwCdlkCfMSHURc+r6fwoGH6/F1hH3S4sg0rLFWPc= +github.com/containerd/typeurl v0.0.0-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.2/go.mod h1:9trJWW2sRlGub4wZJRTW83VtbOLS6hwcDZXTn6oPz9s= +github.com/containerd/zfs v0.0.0-20200918131355-0a33824f23a2/go.mod h1:8IgZOBdv8fAgXddBT4dBXJPtxyRsejFIpXoklgxgEjw= +github.com/containerd/zfs v0.0.0-20210301145711-11e8f1707f62/go.mod h1:A9zfAbMlQwE+/is6hi0Xw8ktpL+6glmqZYtevJgaB8Y= +github.com/containerd/zfs v0.0.0-20210315114300-dde8f0fda960/go.mod h1:m+m51S1DvAP6r3FcmYCp54bQ34pyOwTieQDNRIRHsFY= +github.com/containerd/zfs v0.0.0-20210324211415-d5c4544f0433/go.mod h1:m+m51S1DvAP6r3FcmYCp54bQ34pyOwTieQDNRIRHsFY= +github.com/containerd/zfs v1.0.0/go.mod h1:m+m51S1DvAP6r3FcmYCp54bQ34pyOwTieQDNRIRHsFY= +github.com/containernetworking/cni v0.7.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= +github.com/containernetworking/cni v0.8.0/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= +github.com/containernetworking/cni v0.8.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= +github.com/containernetworking/plugins v0.8.6/go.mod h1:qnw5mN19D8fIwkqW7oHHYDHVlzhJpcY6TQxn/fUyDDM= +github.com/containernetworking/plugins v0.9.1/go.mod h1:xP/idU2ldlzN6m4p5LmGiwRDjeJr6FLK6vuiUwoH7P8= +github.com/containers/ocicrypt v1.0.1/go.mod h1:MeJDzk1RJHv89LjsH0Sp5KTY3ZYkjXO/C+bKAeWFIrc= +github.com/containers/ocicrypt v1.1.0/go.mod h1:b8AOe0YR67uU8OqfVNcznfFpAzu3rdgUV4GP9qXPfu4= +github.com/containers/ocicrypt v1.1.1/go.mod h1:Dm55fwWm1YZAjYRaJ94z2mfZikIyIN4B0oB3dj3jFxY= +github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= +github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/go-iptables v0.4.5/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU= +github.com/coreos/go-iptables v0.5.0/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU= +github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= +github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-systemd v0.0.0-20161114122254-48702e0da86b/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd/v22 v22.0.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= +github.com/coreos/go-systemd/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= +github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4= +github.com/d2g/dhcp4 v0.0.0-20170904100407-a1d1b6c41b1c/go.mod h1:Ct2BUK8SB0YC1SMSibvLzxjeJLnrYEVLULFNiHY9YfQ= +github.com/d2g/dhcp4client v1.0.0/go.mod h1:j0hNfjhrt2SxUOw55nL0ATM/z4Yt3t2Kd1mW34z5W5s= +github.com/d2g/dhcp4server v0.0.0-20181031114812-7d4a0a7f59a5/go.mod h1:Eo87+Kg/IX2hfWJfwxMzLyuSZyxSoAug2nGa1G2QAi8= +github.com/d2g/hardwareaddr v0.0.0-20190221164911-e7d9fbe030e4/go.mod h1:bMl4RjIciD2oAxI7DmWRx6gbeqrkoLqv3MV0vzNad+I= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/denverdino/aliyungo v0.0.0-20190125010748-a747050bb1ba/go.mod h1:dV8lFg6daOBZbT6/BDGIz6Y3WFGn8juu6G+CQ6LHtl0= +github.com/dgrijalva/jwt-go v0.0.0-20170104182250-a601269ab70c/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= +github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= +github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= +github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E= +github.com/docker/distribution v0.0.0-20190905152932-14b96e55d84c/go.mod h1:0+TTO4EOBfRPhZXAeF1Vu+W3hHZ8eLp8PgKVZlcvtFY= +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/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/docker v20.10.6+incompatible h1:oXI3Vas8TI8Eu/EjH4srKHJBVqraSzJybhxY7Om9faQ= -github.com/docker/docker v20.10.6+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v20.10.7+incompatible h1:Z6O9Nhsjv+ayUEeI1IojKbYcsGdgYSNqxe1s2MYzUhQ= +github.com/docker/docker v20.10.7+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/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-20190806004212-e31b211e4f1c/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= +github.com/docker/go-metrics v0.0.0-20180209012529-399ea8c73916/go.mod h1:/u0gXw0Gay3ceNrsHubL3BtdOL2fHf93USgMTe0W5dI= +github.com/docker/go-metrics v0.0.1/go.mod h1:cG1hvH2utMXtqgqqYE9plW6lDxS3/5ayHzueweSI3Vw= github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw= github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE= +github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= +github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= +github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= +github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= +github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= +github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa/go.mod h1:KnogPXtdwXqoenmZCw6S+25EAm2MkxbG0deNDu4cbSA= +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 v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-chi/chi/v5 v5.0.3/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= 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-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-ini/ini v1.25.4/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= +github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= +github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= +github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= +github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg= +github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= +github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc= +github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= +github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo= +github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= +github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/godbus/dbus v0.0.0-20151105175453-c7fdd8b5cd55/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw= +github.com/godbus/dbus v0.0.0-20180201030542-885f9cc04c9c/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw= +github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= +github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gofrs/uuid v4.0.0+incompatible h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPhW6m+TnJw= github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/gogo/googleapis v1.2.0/go.mod h1:Njal3psf3qN6dwBtQfUmBZh2ybovJ0tlu3o/AC7HYjU= +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.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.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= +github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= -github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.4 h1:L8R9j+yAqZuZjsqh/z+F1NCffTKKLShY6zXTItVIZ8M= +github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= +github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ= +github.com/gorilla/mux v1.7.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= +github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= +github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-multierror v0.0.0-20161216184304-ed905158d874/go.mod h1:JMRHfdO9jKNzS/+BTlxCjKNQHg/jZAft8U7LloJvN7I= +github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/imdario/mergo v0.3.10/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= +github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/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-20160803190731-bd40a432e4c7/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= +github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= +github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/compress v1.11.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= +github.com/klauspost/compress v1.11.13/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/miekg/dns v1.1.42 h1:gWGe42RGaIqXQZ+r3WUGEKBEtvPHY2SXo4dqixDNxuY= -github.com/miekg/dns v1.1.42/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4= -github.com/moby/term v0.0.0-20201216013528-df9cb8a40635 h1:rzf0wL0CHVc8CEsgyygG0Mn9CNCCPZqOPaz8RiiHYQk= -github.com/moby/term v0.0.0-20201216013528-df9cb8a40635/go.mod h1:FBS0z0QWA44HXygs7VXDUOGoN/1TV3RuWkLO04am3wc= +github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs= +github.com/marstr/guid v1.1.0/go.mod h1:74gB1z2wpxxInTG6yaqA7KrtM0NZ+RbrcqDvYHefzho= +github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/mattn/go-shellwords v1.0.3/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o= +github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +github.com/miekg/dns v1.1.43 h1:JKfpVSCB84vrAmHzyrsxB5NAr5kLoMXZArPSw7Qlgyg= +github.com/miekg/dns v1.1.43/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4= +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/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A= +github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc= +github.com/moby/sys/mountinfo v0.4.0/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= +github.com/moby/sys/mountinfo v0.4.1/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= +github.com/moby/sys/symlink v0.1.0/go.mod h1:GGDODQmbFOjFsXvfLVn3+ZRxkch54RkSiGqsZeMYowQ= +github.com/moby/term v0.0.0-20200312100748-672ec06f55cd/go.mod h1:DdlQx2hp0Ss5/fLikoLlEeIYiATotOjgB//nb973jeo= +github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 h1:dcztxKSvZ4Id8iPpHERQBbIJfabdt4wUm5qy3wOL2Zc= +github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6/go.mod h1:E2VnQOmVuvZB6UYnnDB0qG5Nq/1tD9acaOpo6xmt0Kw= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= +github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ= +github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= +github.com/ncw/swift v1.0.47/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/ZM= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= +github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= +github.com/onsi/ginkgo v0.0.0-20151202141238-7f8ab55aaf3b/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/gomega v0.0.0-20151007035656-2152b45fa28a/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= +github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= +github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc= +github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= +github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= +github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= +github.com/opencontainers/go-digest v1.0.0-rc1.0.20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= 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/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/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 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-rc93/go.mod h1:3NOsor4w32B2tC0Zbl8Knk4Wg84SM2ImC1fxBuqJ/H0= +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.2-0.20190207185410-29686dbc5559/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/runtime-spec v1.0.3-0.20200929063507-e6143ca7d51d/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/runtime-tools v0.0.0-20181011054405-1d69bd0f9c39/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs= +github.com/opencontainers/selinux v1.6.0/go.mod h1:VVGKuOLlE7v4PJyT6h7mNWvq1rzqiriPsEqVhc+svHE= +github.com/opencontainers/selinux v1.8.0/go.mod h1:RScLhm78qiWa2gbVCcGkC7tCGdgk3ogry1nUQF8Evvo= github.com/oschwald/geoip2-golang v1.5.0 h1:igg2yQIrrcRccB1ytFXqBfOHCjXWIoMv85lVJ1ONZzw= github.com/oschwald/geoip2-golang v1.5.0/go.mod h1:xdvYt5xQzB8ORWFqPnqMwZpCpgNagttWdoZLlJQzg7s= github.com/oschwald/maxminddb-golang v1.8.0 h1:Uh/DSnGoxsyp/KYbY1AuP0tYEwfs0sCph9p/UMXK/Hk= github.com/oschwald/maxminddb-golang v1.8.0/go.mod h1:RXZtst0N6+FY/3qCNmZMBApR19cdQj43/NM9VkrNAis= +github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc= +github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1-0.20171018195549-f15c970de5b7/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= +github.com/prometheus/client_golang v0.0.0-20180209125602-c332b6f63c06/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= +github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g= +github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= +github.com/prometheus/client_model v0.0.0-20171117100541-99fa1f4be8e5/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/common v0.0.0-20180110214958-89604d197083/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= +github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= +github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.0-20190522114515-bc1a522cf7b1/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= +github.com/prometheus/procfs v0.0.5/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= +github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= +github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= +github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/safchain/ethtool v0.0.0-20190326074333-42ed695e3de8/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4= +github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= +github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/sirupsen/logrus v1.0.4-0.20170822132746-89742aefa4b2/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= +github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= +github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= +github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cobra v0.0.2-0.20171109065643-2da4a54c5cee/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= +github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= +github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= +github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.1-0.20171106142849-4c012f6dcd95/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= +github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980/go.mod h1:AO3tvPzVZ/ayst6UlUKUv6rcPQInYe3IknH3jYhAKu8= +github.com/stretchr/objx v0.0.0-20180129172003-8a3f7159479f/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= +github.com/stretchr/testify v0.0.0-20180303142811-b89eecf5ca5d/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= +github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= +github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= +github.com/tchap/go-patricia v2.2.6+incompatible/go.mod h1:bmLyhP68RS6kStMGxByiQ23RP/odRBOTVjwp2cDyi6I= +github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= +github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= +github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= +github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/vishvananda/netlink v0.0.0-20181108222139-023a6dafdcdf/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk= +github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= +github.com/vishvananda/netlink v1.1.1-0.20201029203352-d40f9887b852/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho= +github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc/go.mod h1:ZjcWmFBXmLKZu9Nxj3WKYEafiSqer2rnvPr0en9UNpI= +github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= +github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= +github.com/willf/bitset v1.1.11-0.20200630133818-d5bec3311243/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4= +github.com/willf/bitset v1.1.11/go.mod h1:83CECat5yLh5zVOf4P1ErAgKA5UDvKtgyUABdr3+MjI= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema 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/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= -go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs= +github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA= +github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg= +go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= +go.etcd.io/etcd v0.5.0-alpha.5.0.20200910180754-dd1b699fc489/go.mod h1:yVHk9ub3CSBatqGNg7GRmsnfLWtoW60w4eDYfh7vHDg= +go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk= +go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= +go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= +go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= +go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.8.0 h1:CUhrE4N1rqSE6FM9ecihEjRkLQu8cDfgDyoOs83mEY4= +go.uber.org/atomic v1.8.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +golang.org/x/crypto v0.0.0-20171113213409-9f005a07e0d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181009213950-7c1a557ab941/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-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-20210506145944-38f3c27a63bf h1:B2n+Zi5QeYRDAEodEu72OS36gmTWjgpXr2+cWcBW90o= -golang.org/x/crypto v0.0.0-20210506145944-38f3c27a63bf/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= +golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= +golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e h1:gsTQYXdTw2Gq7RBsWvlQ91b+aEQ6bXFUngBGuR8sPpI= +golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= +golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= +golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= +golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= +golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= +golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190619014844-b5b0513f8c1b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210508051633-16afe75a6701/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210510120150-4163338589ed h1:p9UgmWI9wKpfYmgaV/IZKGdXc5qEK45tDwwwDyjS26I= -golang.org/x/net v0.0.0-20210510120150-4163338589ed/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210614182718-04defd469f4e h1:XpT3nA5TvE525Ne3hInMh6+GETgn27Zfm9dxsThnX2Q= +golang.org/x/net v0.0.0-20210614182718-04defd469f4e/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-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190514135907-3a4b5fb9f71f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190522044717-8097e1b27ff5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190602015325-4c4f7f33c9ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190812073006-9eafafc0a87e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191210023423-ac6580df4449/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191224085550-c709ea063b76/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200831180312-196b9ba8737a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200120151820-655fe14d7479/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200817155316-9781c653f443/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200916030750-2334cc1a136f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200922070232-aee5d888a860/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201112073958-5cba982894dd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201117170446-d9b008d0a637/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-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-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-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210507161434-a76c4d0a0096 h1:5PbJGn5Sp3GEUjJ61aYbUP6RIo3Z3r2E4Tv9y2z8UHo= -golang.org/x/sys v0.0.0-20210507161434-a76c4d0a0096/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c h1:F1jZWGFhYfh0Ci55sIpILtKKK8p3i2/krTr0H1rg74I= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba h1:O8mE0/t419eoIwhTFpKVkHiTs/Igowgfkj25AcZrtiE= -golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/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-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-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20210611083556-38a9dc6acbc6 h1:Vv0JUPWTyeqUq42B2WJ1FeIDjjvGKoA2Ss+Ts0lAVbs= +golang.org/x/time v0.0.0-20210611083556-38a9dc6acbc6/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-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -166,18 +839,65 @@ golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/api v0.0.0-20160322025152-9bf6e6e569ff/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= +google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= +google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= +google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/cloud v0.0.0-20151119220103-975617b05ea8/go.mod h1:0H1ncTHf11KCFhTc/+EFRbzSCOZx+VUbRMk55Yv5MYk= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190522204451-c2c4e71fbf69/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= +google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 h1:+kGHl1aib/qcwaRi1CbqBZ1rk19r85MNUf8HaBghugY= +google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= +google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200117163144-32f20d992d24/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= +google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a h1:pOwg4OoaRYScjmR4LlLgdtnyoHYTSAVhhqe5uPdpII8= +google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.36.0 h1:o1bcQ6imQMIOpdrO3SWf2z5RV72WbDwdXuK0MDlc8As= +google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= +google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.39.0 h1:Klz8I9kdtkIN6EpHHUOMLCYhTn/2WAe5a0s1hcBkdTI= +google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -186,17 +906,81 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= +gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20141024133853-64131543e789/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo= +gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= +gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= +gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= +gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= +gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= +gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= +gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= gotest.tools/v3 v3.0.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0= gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +k8s.io/api v0.20.1/go.mod h1:KqwcCVogGxQY3nBlRpwt+wpAMF/KjaCc7RpywacvqUo= +k8s.io/api v0.20.4/go.mod h1:++lNL1AJMkDymriNniQsWRkMDzRaX2Y/POTUi8yvqYQ= +k8s.io/api v0.20.6/go.mod h1:X9e8Qag6JV/bL5G6bU8sdVRltWKmdHsFUGS3eVndqE8= +k8s.io/apimachinery v0.20.1/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU= +k8s.io/apimachinery v0.20.4/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU= +k8s.io/apimachinery v0.20.6/go.mod h1:ejZXtW1Ra6V1O5H8xPBGz+T3+4gfkTCeExAHKU57MAc= +k8s.io/apiserver v0.20.1/go.mod h1:ro5QHeQkgMS7ZGpvf4tSMx6bBOgPfE+f52KwvXfScaU= +k8s.io/apiserver v0.20.4/go.mod h1:Mc80thBKOyy7tbvFtB4kJv1kbdD0eIH8k8vianJcbFM= +k8s.io/apiserver v0.20.6/go.mod h1:QIJXNt6i6JB+0YQRNcS0hdRHJlMhflFmsBDeSgT1r8Q= +k8s.io/client-go v0.20.1/go.mod h1:/zcHdt1TeWSd5HoUe6elJmHSQ6uLLgp4bIJHVEuy+/Y= +k8s.io/client-go v0.20.4/go.mod h1:LiMv25ND1gLUdBeYxBIwKpkSC5IsozMMmOOeSJboP+k= +k8s.io/client-go v0.20.6/go.mod h1:nNQMnOvEUEsOzRRFIIkdmYOjAZrC8bgq0ExboWSU1I0= +k8s.io/component-base v0.20.1/go.mod h1:guxkoJnNoh8LNrbtiQOlyp2Y2XFCZQmrcg2n/DeYNLk= +k8s.io/component-base v0.20.4/go.mod h1:t4p9EdiagbVCJKrQ1RsA5/V4rFQNDfRlevJajlGwgjI= +k8s.io/component-base v0.20.6/go.mod h1:6f1MPBAeI+mvuts3sIdtpjljHWBQ2cIy38oBIWMYnrM= +k8s.io/cri-api v0.17.3/go.mod h1:X1sbHmuXhwaHs9xxYffLqJogVsnI+f6cPRcgPel7ywM= +k8s.io/cri-api v0.20.1/go.mod h1:2JRbKt+BFLTjtrILYVqQK5jqhI+XNdF6UiGMgczeBCI= +k8s.io/cri-api v0.20.4/go.mod h1:2JRbKt+BFLTjtrILYVqQK5jqhI+XNdF6UiGMgczeBCI= +k8s.io/cri-api v0.20.6/go.mod h1:ew44AjNXwyn1s0U4xCKGodU7J1HzBeZ1MpGrpa5r8Yc= +k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= +k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= +k8s.io/klog/v2 v2.4.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= +k8s.io/kube-openapi v0.0.0-20201113171705-d219536bb9fd/go.mod h1:WOJ3KddDSol4tAGcJo0Tvi+dK12EcqSLqcWsryKMpfM= +k8s.io/kubernetes v1.13.0/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk= +k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= +rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= +sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.14/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg= +sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.15/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg= +sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= +sigs.k8s.io/structured-merge-diff/v4 v4.0.3/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= +sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= +sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= diff --git a/test/snell_test.go b/test/snell_test.go index bc8b47aa7..f9cd610c0 100644 --- a/test/snell_test.go +++ b/test/snell_test.go @@ -119,3 +119,40 @@ func TestClash_Snell(t *testing.T) { time.Sleep(waitTime) testSuit(t, proxy) } + +func Benchmark_Snell(b *testing.B) { + 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-http.conf"))}, + } + + id, err := startContainer(cfg, hostCfg, "snell-http") + if err != nil { + assert.FailNow(b, err.Error()) + } + + b.Cleanup(func() { + cleanContainer(id) + }) + + proxy, err := outbound.NewSnell(outbound.SnellOption{ + Name: "snell", + Server: localIP.String(), + Port: 10002, + Psk: "password", + ObfsOpts: map[string]interface{}{ + "mode": "http", + }, + }) + if err != nil { + assert.FailNow(b, err.Error()) + } + + time.Sleep(waitTime) + benchmarkProxy(b, proxy) +} diff --git a/test/ss_test.go b/test/ss_test.go index ea33445c5..caac90337 100644 --- a/test/ss_test.go +++ b/test/ss_test.go @@ -170,3 +170,38 @@ func TestClash_ShadowsocksV2RayPlugin(t *testing.T) { time.Sleep(waitTime) testSuit(t, proxy) } + +func Benchmark_Shadowsocks(b *testing.B) { + cfg := &container.Config{ + Image: ImageShadowsocks, + Env: []string{"SS_MODULE=ss-server", "SS_CONFIG=-s 0.0.0.0 -u -v -p 10002 -m chacha20-ietf-poly1305 -k FzcLbKs2dY9mhL"}, + ExposedPorts: defaultExposedPorts, + } + hostCfg := &container.HostConfig{ + PortBindings: defaultPortBindings, + } + + id, err := startContainer(cfg, hostCfg, "ss") + if err != nil { + assert.FailNow(b, err.Error()) + } + + b.Cleanup(func() { + cleanContainer(id) + }) + + proxy, err := outbound.NewShadowSocks(outbound.ShadowSocksOption{ + Name: "ss", + Server: localIP.String(), + Port: 10002, + Password: "FzcLbKs2dY9mhL", + Cipher: "chacha20-ietf-poly1305", + UDP: true, + }) + if err != nil { + assert.FailNow(b, err.Error()) + } + + time.Sleep(waitTime) + benchmarkProxy(b, proxy) +} diff --git a/test/trojan_test.go b/test/trojan_test.go index 236b5af1e..a57dab99f 100644 --- a/test/trojan_test.go +++ b/test/trojan_test.go @@ -92,3 +92,43 @@ func TestClash_TrojanGrpc(t *testing.T) { time.Sleep(waitTime) testSuit(t, proxy) } + +func Benchmark_Trojan(b *testing.B) { + cfg := &container.Config{ + Image: ImageTrojan, + ExposedPorts: defaultExposedPorts, + } + hostCfg := &container.HostConfig{ + PortBindings: defaultPortBindings, + Binds: []string{ + fmt.Sprintf("%s:/config/config.json", C.Path.Resolve("trojan.json")), + fmt.Sprintf("%s:/path/to/certificate.crt", C.Path.Resolve("example.org.pem")), + fmt.Sprintf("%s:/path/to/private.key", C.Path.Resolve("example.org-key.pem")), + }, + } + + id, err := startContainer(cfg, hostCfg, "trojan") + if err != nil { + assert.FailNow(b, err.Error()) + } + + b.Cleanup(func() { + cleanContainer(id) + }) + + proxy, err := outbound.NewTrojan(outbound.TrojanOption{ + Name: "trojan", + Server: localIP.String(), + Port: 10002, + Password: "password", + SNI: "example.org", + SkipCertVerify: true, + UDP: true, + }) + if err != nil { + assert.FailNow(b, err.Error()) + } + + time.Sleep(waitTime) + benchmarkProxy(b, proxy) +} diff --git a/test/util_test.go b/test/util_darwin_test.go similarity index 100% rename from test/util_test.go rename to test/util_darwin_test.go diff --git a/test/util_other_test.go b/test/util_other_test.go new file mode 100644 index 000000000..e325bd8ba --- /dev/null +++ b/test/util_other_test.go @@ -0,0 +1,12 @@ +// +build !darwin + +package main + +import ( + "errors" + "net" +) + +func defaultRouteIP() (net.IP, error) { + return nil, errors.New("not supported") +} diff --git a/test/vmess_test.go b/test/vmess_test.go index 92cb300e2..bdc5ad9e0 100644 --- a/test/vmess_test.go +++ b/test/vmess_test.go @@ -345,3 +345,41 @@ func TestClash_VmessGrpc(t *testing.T) { time.Sleep(waitTime) testSuit(t, proxy) } + +func Benchmark_Vmess(b *testing.B) { + configPath := C.Path.Resolve("vmess.json") + + cfg := &container.Config{ + Image: ImageVmess, + ExposedPorts: defaultExposedPorts, + } + hostCfg := &container.HostConfig{ + PortBindings: defaultPortBindings, + Binds: []string{fmt.Sprintf("%s:/etc/v2ray/config.json", configPath)}, + } + + id, err := startContainer(cfg, hostCfg, "vmess") + if err != nil { + assert.FailNow(b, err.Error()) + } + + b.Cleanup(func() { + cleanContainer(id) + }) + + proxy, err := outbound.NewVmess(outbound.VmessOption{ + Name: "vmess", + Server: localIP.String(), + Port: 10002, + UUID: "b831381d-6324-4d53-ad4f-8cda48b30811", + Cipher: "auto", + AlterID: 32, + UDP: true, + }) + if err != nil { + assert.FailNow(b, err.Error()) + } + + time.Sleep(waitTime) + benchmarkProxy(b, proxy) +} From 44872300e94698428e7e4bacf8255b09042cb40a Mon Sep 17 00:00:00 2001 From: Dreamacro <8615343+Dreamacro@users.noreply.github.com> Date: Sun, 18 Jul 2021 17:37:23 +0800 Subject: [PATCH 23/96] Test: ss use aes-256-gcm and vmess-aead for benchmark --- test/ss_test.go | 4 ++-- test/vmess_test.go | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/test/ss_test.go b/test/ss_test.go index caac90337..7cba7efd9 100644 --- a/test/ss_test.go +++ b/test/ss_test.go @@ -174,7 +174,7 @@ func TestClash_ShadowsocksV2RayPlugin(t *testing.T) { func Benchmark_Shadowsocks(b *testing.B) { cfg := &container.Config{ Image: ImageShadowsocks, - Env: []string{"SS_MODULE=ss-server", "SS_CONFIG=-s 0.0.0.0 -u -v -p 10002 -m chacha20-ietf-poly1305 -k FzcLbKs2dY9mhL"}, + Env: []string{"SS_MODULE=ss-server", "SS_CONFIG=-s 0.0.0.0 -u -v -p 10002 -m aes-256-gcm -k FzcLbKs2dY9mhL"}, ExposedPorts: defaultExposedPorts, } hostCfg := &container.HostConfig{ @@ -195,7 +195,7 @@ func Benchmark_Shadowsocks(b *testing.B) { Server: localIP.String(), Port: 10002, Password: "FzcLbKs2dY9mhL", - Cipher: "chacha20-ietf-poly1305", + Cipher: "aes-256-gcm", UDP: true, }) if err != nil { diff --git a/test/vmess_test.go b/test/vmess_test.go index bdc5ad9e0..de3b2ba6a 100644 --- a/test/vmess_test.go +++ b/test/vmess_test.go @@ -347,7 +347,7 @@ func TestClash_VmessGrpc(t *testing.T) { } func Benchmark_Vmess(b *testing.B) { - configPath := C.Path.Resolve("vmess.json") + configPath := C.Path.Resolve("vmess-aead.json") cfg := &container.Config{ Image: ImageVmess, @@ -358,7 +358,7 @@ func Benchmark_Vmess(b *testing.B) { Binds: []string{fmt.Sprintf("%s:/etc/v2ray/config.json", configPath)}, } - id, err := startContainer(cfg, hostCfg, "vmess") + id, err := startContainer(cfg, hostCfg, "vmess-aead") if err != nil { assert.FailNow(b, err.Error()) } @@ -373,7 +373,7 @@ func Benchmark_Vmess(b *testing.B) { Port: 10002, UUID: "b831381d-6324-4d53-ad4f-8cda48b30811", Cipher: "auto", - AlterID: 32, + AlterID: 0, UDP: true, }) if err != nil { From c2f3111922fcc5de65273d4fbe2493de6000cb17 Mon Sep 17 00:00:00 2001 From: Dreamacro <8615343+Dreamacro@users.noreply.github.com> Date: Sun, 18 Jul 2021 19:26:51 +0800 Subject: [PATCH 24/96] Test: add direct benchmark --- test/clash_test.go | 8 +++++++- test/docker_test.go | 4 ++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/test/clash_test.go b/test/clash_test.go index 97f6648b1..7d373bbd5 100644 --- a/test/clash_test.go +++ b/test/clash_test.go @@ -15,6 +15,7 @@ import ( "testing" "time" + "github.com/Dreamacro/clash/adapter/outbound" C "github.com/Dreamacro/clash/constant" "github.com/Dreamacro/clash/hub/executor" "github.com/Dreamacro/clash/transport/socks5" @@ -70,7 +71,7 @@ func init() { } } - c, err := client.NewClientWithOpts(client.FromEnv) + c, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation()) if err != nil { panic(err) } @@ -668,3 +669,8 @@ log-level: silent time.Sleep(waitTime) testPingPongWithSocksPort(t, 10000) } + +func Benchmark_Direct(b *testing.B) { + proxy := outbound.NewDirect() + benchmarkProxy(b, proxy) +} diff --git a/test/docker_test.go b/test/docker_test.go index ce4c2de47..12c427b18 100644 --- a/test/docker_test.go +++ b/test/docker_test.go @@ -11,7 +11,7 @@ import ( var isDarwin = false func startContainer(cfg *container.Config, hostCfg *container.HostConfig, name string) (string, error) { - c, err := client.NewClientWithOpts(client.FromEnv) + c, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation()) if err != nil { return "", err } @@ -34,7 +34,7 @@ func startContainer(cfg *container.Config, hostCfg *container.HostConfig, name s } func cleanContainer(id string) error { - c, err := client.NewClientWithOpts(client.FromEnv) + c, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation()) if err != nil { return err } From 247dd84970f00f2e1f43fac3b73cb710ff4f5a5d Mon Sep 17 00:00:00 2001 From: ayanamist Date: Mon, 19 Jul 2021 14:07:51 +0800 Subject: [PATCH 25/96] Chore: logging real listen port (#1492) --- hub/route/server.go | 12 +++++++++--- listener/http/server.go | 4 +--- listener/mixed/mixed.go | 8 +++++--- listener/redir/tcp.go | 7 ++++--- listener/socks/tcp.go | 7 ++++--- listener/socks/udp.go | 7 ++++--- listener/tproxy/tproxy.go | 4 +--- listener/tproxy/udp.go | 7 ++++--- 8 files changed, 32 insertions(+), 24 deletions(-) diff --git a/hub/route/server.go b/hub/route/server.go index 98dc3588d..e01696bed 100644 --- a/hub/route/server.go +++ b/hub/route/server.go @@ -3,6 +3,7 @@ package route import ( "bytes" "encoding/json" + "net" "net/http" "strings" "time" @@ -81,10 +82,15 @@ func Start(addr string, secret string) { }) } - log.Infoln("RESTful API listening at: %s", addr) - err := http.ListenAndServe(addr, r) + l, err := net.Listen("tcp", addr) if err != nil { - log.Errorln("External controller error: %s", err.Error()) + log.Errorln("External controller listen error: %s", err) + return + } + serverAddr = l.Addr().String() + log.Infoln("RESTful API listening at: %s", serverAddr) + if err = http.Serve(l, r); err != nil { + log.Errorln("External controller serve error: %s", err) } } diff --git a/listener/http/server.go b/listener/http/server.go index ed8383710..6c5a7f6a4 100644 --- a/listener/http/server.go +++ b/listener/http/server.go @@ -10,7 +10,6 @@ import ( type Listener struct { listener net.Listener - address string closed bool } @@ -31,7 +30,6 @@ func NewWithAuthenticate(addr string, in chan<- C.ConnContext, authenticate bool hl := &Listener{ listener: l, - address: addr, } go func() { for { @@ -55,5 +53,5 @@ func (l *Listener) Close() { } func (l *Listener) Address() string { - return l.address + return l.listener.Addr().String() } diff --git a/listener/mixed/mixed.go b/listener/mixed/mixed.go index 7d89e3c8d..97be69f0b 100644 --- a/listener/mixed/mixed.go +++ b/listener/mixed/mixed.go @@ -15,7 +15,6 @@ import ( type Listener struct { listener net.Listener - address string closed bool cache *cache.Cache } @@ -26,7 +25,10 @@ func New(addr string, in chan<- C.ConnContext) (*Listener, error) { return nil, err } - ml := &Listener{l, addr, false, cache.New(30 * time.Second)} + ml := &Listener{ + listener: l, + cache: cache.New(30 * time.Second), + } go func() { for { c, err := ml.listener.Accept() @@ -49,7 +51,7 @@ func (l *Listener) Close() { } func (l *Listener) Address() string { - return l.address + return l.listener.Addr().String() } func handleConn(conn net.Conn, in chan<- C.ConnContext, cache *cache.Cache) { diff --git a/listener/redir/tcp.go b/listener/redir/tcp.go index 372688409..f7160eb01 100644 --- a/listener/redir/tcp.go +++ b/listener/redir/tcp.go @@ -9,7 +9,6 @@ import ( type Listener struct { listener net.Listener - address string closed bool } @@ -18,7 +17,9 @@ func New(addr string, in chan<- C.ConnContext) (*Listener, error) { if err != nil { return nil, err } - rl := &Listener{l, addr, false} + rl := &Listener{ + listener: l, + } go func() { for { @@ -42,7 +43,7 @@ func (l *Listener) Close() { } func (l *Listener) Address() string { - return l.address + return l.listener.Addr().String() } func handleRedir(conn net.Conn, in chan<- C.ConnContext) { diff --git a/listener/socks/tcp.go b/listener/socks/tcp.go index 60da0e264..587af2213 100644 --- a/listener/socks/tcp.go +++ b/listener/socks/tcp.go @@ -15,7 +15,6 @@ import ( type Listener struct { listener net.Listener - address string closed bool } @@ -25,7 +24,9 @@ func New(addr string, in chan<- C.ConnContext) (*Listener, error) { return nil, err } - sl := &Listener{l, addr, false} + sl := &Listener{ + listener: l, + } go func() { for { c, err := l.Accept() @@ -48,7 +49,7 @@ func (l *Listener) Close() { } func (l *Listener) Address() string { - return l.address + return l.listener.Addr().String() } func handleSocks(conn net.Conn, in chan<- C.ConnContext) { diff --git a/listener/socks/udp.go b/listener/socks/udp.go index b98ae897a..5de0a0bf3 100644 --- a/listener/socks/udp.go +++ b/listener/socks/udp.go @@ -13,7 +13,6 @@ import ( type UDPListener struct { packetConn net.PacketConn - address string closed bool } @@ -27,7 +26,9 @@ func NewUDP(addr string, in chan<- *inbound.PacketAdapter) (*UDPListener, error) log.Warnln("Failed to Reuse UDP Address: %s", err) } - sl := &UDPListener{l, addr, false} + sl := &UDPListener{ + packetConn: l, + } go func() { for { buf := pool.Get(pool.RelayBufferSize) @@ -52,7 +53,7 @@ func (l *UDPListener) Close() error { } func (l *UDPListener) Address() string { - return l.address + return l.packetConn.LocalAddr().String() } func handleSocksUDP(pc net.PacketConn, in chan<- *inbound.PacketAdapter, buf []byte, addr net.Addr) { diff --git a/listener/tproxy/tproxy.go b/listener/tproxy/tproxy.go index 142336fe8..87f2d7d67 100644 --- a/listener/tproxy/tproxy.go +++ b/listener/tproxy/tproxy.go @@ -10,7 +10,6 @@ import ( type Listener struct { listener net.Listener - address string closed bool } @@ -33,7 +32,6 @@ func New(addr string, in chan<- C.ConnContext) (*Listener, error) { rl := &Listener{ listener: l, - address: addr, } go func() { @@ -58,7 +56,7 @@ func (l *Listener) Close() { } func (l *Listener) Address() string { - return l.address + return l.listener.Addr().String() } func (l *Listener) handleTProxy(conn net.Conn, in chan<- C.ConnContext) { diff --git a/listener/tproxy/udp.go b/listener/tproxy/udp.go index 20c2e0836..6f9de6f54 100644 --- a/listener/tproxy/udp.go +++ b/listener/tproxy/udp.go @@ -11,7 +11,6 @@ import ( type UDPListener struct { packetConn net.PacketConn - address string closed bool } @@ -21,7 +20,9 @@ func NewUDP(addr string, in chan<- *inbound.PacketAdapter) (*UDPListener, error) return nil, err } - rl := &UDPListener{l, addr, false} + rl := &UDPListener{ + packetConn: l, + } c := l.(*net.UDPConn) @@ -65,7 +66,7 @@ func (l *UDPListener) Close() error { } func (l *UDPListener) Address() string { - return l.address + return l.packetConn.LocalAddr().String() } func handlePacketConn(pc net.PacketConn, in chan<- *inbound.PacketAdapter, buf []byte, lAddr *net.UDPAddr, rAddr *net.UDPAddr) { From 53e17a916bb08a042b610b256bf640327895bfa9 Mon Sep 17 00:00:00 2001 From: ayanamist Date: Mon, 19 Jul 2021 15:31:38 +0800 Subject: [PATCH 26/96] Chore: logging remote port on request (#1494) --- adapter/outbound/direct.go | 4 +--- tunnel/tunnel.go | 24 ++++++++++++------------ 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/adapter/outbound/direct.go b/adapter/outbound/direct.go index 5b4a710fd..83ea22eb8 100644 --- a/adapter/outbound/direct.go +++ b/adapter/outbound/direct.go @@ -14,9 +14,7 @@ type Direct struct { // DialContext implements C.ProxyAdapter func (d *Direct) DialContext(ctx context.Context, metadata *C.Metadata) (C.Conn, error) { - address := net.JoinHostPort(metadata.String(), metadata.DstPort) - - c, err := dialer.DialContext(ctx, "tcp", address) + c, err := dialer.DialContext(ctx, "tcp", metadata.RemoteAddress()) if err != nil { return nil, err } diff --git a/tunnel/tunnel.go b/tunnel/tunnel.go index 0ec36d3f1..2a35f0960 100644 --- a/tunnel/tunnel.go +++ b/tunnel/tunnel.go @@ -219,9 +219,9 @@ func handleUDPConn(packet *inbound.PacketAdapter) { rawPc, err := proxy.DialUDP(metadata) if err != nil { if rule == nil { - log.Warnln("[UDP] dial %s to %s error: %s", proxy.Name(), metadata.String(), err.Error()) + log.Warnln("[UDP] dial %s to %s error: %s", proxy.Name(), metadata.RemoteAddress(), err.Error()) } else { - log.Warnln("[UDP] dial %s (match %s/%s) to %s error: %s", proxy.Name(), rule.RuleType().String(), rule.Payload(), metadata.String(), err.Error()) + log.Warnln("[UDP] dial %s (match %s/%s) to %s error: %s", proxy.Name(), rule.RuleType().String(), rule.Payload(), metadata.RemoteAddress(), err.Error()) } return } @@ -230,13 +230,13 @@ func handleUDPConn(packet *inbound.PacketAdapter) { switch true { case rule != nil: - log.Infoln("[UDP] %s --> %v match %s(%s) using %s", metadata.SourceAddress(), metadata.String(), rule.RuleType().String(), rule.Payload(), rawPc.Chains().String()) + log.Infoln("[UDP] %s --> %s match %s(%s) using %s", metadata.SourceAddress(), metadata.RemoteAddress(), rule.RuleType().String(), rule.Payload(), rawPc.Chains().String()) case mode == Global: - log.Infoln("[UDP] %s --> %v using GLOBAL", metadata.SourceAddress(), metadata.String()) + log.Infoln("[UDP] %s --> %s using GLOBAL", metadata.SourceAddress(), metadata.RemoteAddress()) case mode == Direct: - log.Infoln("[UDP] %s --> %v using DIRECT", metadata.SourceAddress(), metadata.String()) + log.Infoln("[UDP] %s --> %s using DIRECT", metadata.SourceAddress(), metadata.RemoteAddress()) default: - log.Infoln("[UDP] %s --> %v doesn't match any rule using DIRECT", metadata.SourceAddress(), metadata.String()) + log.Infoln("[UDP] %s --> %s doesn't match any rule using DIRECT", metadata.SourceAddress(), metadata.RemoteAddress()) } go handleUDPToLocal(packet.UDPPacket, pc, key, fAddr) @@ -269,9 +269,9 @@ func handleTCPConn(ctx C.ConnContext) { remoteConn, err := proxy.Dial(metadata) if err != nil { if rule == nil { - log.Warnln("[TCP] dial %s to %s error: %s", proxy.Name(), metadata.String(), err.Error()) + log.Warnln("[TCP] dial %s to %s error: %s", proxy.Name(), metadata.RemoteAddress(), err.Error()) } else { - log.Warnln("[TCP] dial %s (match %s/%s) to %s error: %s", proxy.Name(), rule.RuleType().String(), rule.Payload(), metadata.String(), err.Error()) + log.Warnln("[TCP] dial %s (match %s/%s) to %s error: %s", proxy.Name(), rule.RuleType().String(), rule.Payload(), metadata.RemoteAddress(), err.Error()) } return } @@ -280,13 +280,13 @@ func handleTCPConn(ctx C.ConnContext) { switch true { case rule != nil: - log.Infoln("[TCP] %s --> %v match %s(%s) using %s", metadata.SourceAddress(), metadata.String(), rule.RuleType().String(), rule.Payload(), remoteConn.Chains().String()) + log.Infoln("[TCP] %s --> %s match %s(%s) using %s", metadata.SourceAddress(), metadata.RemoteAddress(), rule.RuleType().String(), rule.Payload(), remoteConn.Chains().String()) case mode == Global: - log.Infoln("[TCP] %s --> %v using GLOBAL", metadata.SourceAddress(), metadata.String()) + log.Infoln("[TCP] %s --> %s using GLOBAL", metadata.SourceAddress(), metadata.RemoteAddress()) case mode == Direct: - log.Infoln("[TCP] %s --> %v using DIRECT", metadata.SourceAddress(), metadata.String()) + log.Infoln("[TCP] %s --> %s using DIRECT", metadata.SourceAddress(), metadata.RemoteAddress()) default: - log.Infoln("[TCP] %s --> %v doesn't match any rule using DIRECT", metadata.SourceAddress(), metadata.String()) + log.Infoln("[TCP] %s --> %s doesn't match any rule using DIRECT", metadata.SourceAddress(), metadata.RemoteAddress()) } handleSocket(ctx, remoteConn) From 8d37220566c2c312658b903a7baff64ca0878d0a Mon Sep 17 00:00:00 2001 From: Dreamacro <8615343+Dreamacro@users.noreply.github.com> Date: Wed, 21 Jul 2021 17:01:02 +0800 Subject: [PATCH 27/96] Fix: limit concurrency number of provider health check --- adapter/adapter.go | 2 + adapter/provider/healthcheck.go | 19 +++--- common/batch/batch.go | 111 ++++++++++++++++++++++++++++++++ common/batch/batch_test.go | 82 +++++++++++++++++++++++ 4 files changed, 203 insertions(+), 11 deletions(-) create mode 100644 common/batch/batch.go create mode 100644 common/batch/batch_test.go diff --git a/adapter/adapter.go b/adapter/adapter.go index 787a45b13..526866a5c 100644 --- a/adapter/adapter.go +++ b/adapter/adapter.go @@ -136,6 +136,8 @@ func (p *Proxy) URLTest(ctx context.Context, url string) (t uint16, err error) { return http.ErrUseLastResponse }, } + defer client.CloseIdleConnections() + resp, err := client.Do(req) if err != nil { return diff --git a/adapter/provider/healthcheck.go b/adapter/provider/healthcheck.go index 98f934e42..636873d94 100644 --- a/adapter/provider/healthcheck.go +++ b/adapter/provider/healthcheck.go @@ -2,9 +2,9 @@ package provider import ( "context" - "sync" "time" + "github.com/Dreamacro/clash/common/batch" C "github.com/Dreamacro/clash/constant" "go.uber.org/atomic" @@ -60,19 +60,16 @@ func (hc *HealthCheck) touch() { func (hc *HealthCheck) check() { ctx, cancel := context.WithTimeout(context.Background(), defaultURLTestTimeout) - wg := &sync.WaitGroup{} + defer cancel() + b, ctx := batch.WithContext(ctx, batch.WithConcurrencyNum(10)) for _, proxy := range hc.proxies { - wg.Add(1) - - go func(p C.Proxy) { - p.URLTest(ctx, hc.url) - wg.Done() - }(proxy) + p := proxy + b.Go(p.Name(), func() (interface{}, error) { + return p.URLTest(ctx, hc.url) + }) } - - wg.Wait() - cancel() + b.Wait() } func (hc *HealthCheck) close() { diff --git a/common/batch/batch.go b/common/batch/batch.go new file mode 100644 index 000000000..7fbca4217 --- /dev/null +++ b/common/batch/batch.go @@ -0,0 +1,111 @@ +package batch + +import ( + "context" + "sync" +) + +type Option = func(b *Batch) + +type Result struct { + Value interface{} + Err error +} + +type Error struct { + Key string + Err error +} + +func WithConcurrencyNum(n int) Option { + return func(b *Batch) { + q := make(chan struct{}, n) + for i := 0; i < n; i++ { + q <- struct{}{} + } + b.queue = q + } +} + +// Batch similar to errgroup, but can control the maximum number of concurrent +type Batch struct { + result map[string]Result + queue chan struct{} + wg sync.WaitGroup + mux sync.Mutex + err *Error + once sync.Once + cancel func() +} + +func (b *Batch) Go(key string, fn func() (interface{}, error)) { + b.wg.Add(1) + go func() { + defer b.wg.Done() + if b.queue != nil { + <-b.queue + defer func() { + b.queue <- struct{}{} + }() + } + + value, err := fn() + if err != nil { + b.once.Do(func() { + b.err = &Error{key, err} + if b.cancel != nil { + b.cancel() + } + }) + } + + ret := Result{value, err} + b.mux.Lock() + defer b.mux.Unlock() + b.result[key] = ret + }() +} + +func (b *Batch) Wait() *Error { + b.wg.Wait() + if b.cancel != nil { + b.cancel() + } + return b.err +} + +func (b *Batch) WaitAndGetResult() (map[string]Result, *Error) { + err := b.Wait() + return b.Result(), err +} + +func (b *Batch) Result() map[string]Result { + b.mux.Lock() + defer b.mux.Unlock() + copy := map[string]Result{} + for k, v := range b.result { + copy[k] = v + } + return copy +} + +func New(opts ...Option) *Batch { + b := &Batch{ + result: map[string]Result{}, + } + + for _, o := range opts { + o(b) + } + + return b +} + +func WithContext(ctx context.Context, opts ...Option) (*Batch, context.Context) { + ctx, cancel := context.WithCancel(ctx) + + b := New(opts...) + b.cancel = cancel + + return b, ctx +} diff --git a/common/batch/batch_test.go b/common/batch/batch_test.go new file mode 100644 index 000000000..4fcdbe81c --- /dev/null +++ b/common/batch/batch_test.go @@ -0,0 +1,82 @@ +package batch + +import ( + "context" + "errors" + "strconv" + "testing" + "time" + + "github.com/stretchr/testify/assert" +) + +func TestBatch(t *testing.T) { + b := New() + + now := time.Now() + b.Go("foo", func() (interface{}, error) { + time.Sleep(time.Millisecond * 100) + return "foo", nil + }) + b.Go("bar", func() (interface{}, error) { + time.Sleep(time.Millisecond * 150) + return "bar", nil + }) + result, err := b.WaitAndGetResult() + + assert.Nil(t, err) + + duration := time.Since(now) + assert.Less(t, duration, time.Millisecond*200) + assert.Equal(t, 2, len(result)) + + for k, v := range result { + assert.NoError(t, v.Err) + assert.Equal(t, k, v.Value.(string)) + } +} + +func TestBatchWithConcurrencyNum(t *testing.T) { + b := New( + WithConcurrencyNum(3), + ) + + now := time.Now() + for i := 0; i < 7; i++ { + idx := i + b.Go(strconv.Itoa(idx), func() (interface{}, error) { + time.Sleep(time.Millisecond * 100) + return strconv.Itoa(idx), nil + }) + } + result, _ := b.WaitAndGetResult() + duration := time.Since(now) + assert.Greater(t, duration, time.Millisecond*260) + assert.Equal(t, 7, len(result)) + + for k, v := range result { + assert.NoError(t, v.Err) + assert.Equal(t, k, v.Value.(string)) + } +} + +func TestBatchContext(t *testing.T) { + b, ctx := WithContext(context.Background()) + + b.Go("error", func() (interface{}, error) { + time.Sleep(time.Millisecond * 100) + return nil, errors.New("test error") + }) + + b.Go("ctx", func() (interface{}, error) { + <-ctx.Done() + return nil, ctx.Err() + }) + + result, err := b.WaitAndGetResult() + + assert.NotNil(t, err) + assert.Equal(t, "error", err.Key) + + assert.Equal(t, ctx.Err(), result["ctx"].Err) +} From aa9f8a39a3a620f9a4ec0a241308414695735b31 Mon Sep 17 00:00:00 2001 From: Dreamacro <8615343+Dreamacro@users.noreply.github.com> Date: Wed, 21 Jul 2021 23:08:52 +0800 Subject: [PATCH 28/96] Fix: socks inbound packet typo --- listener/socks/udp.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/listener/socks/udp.go b/listener/socks/udp.go index 5de0a0bf3..ca75b2c8a 100644 --- a/listener/socks/udp.go +++ b/listener/socks/udp.go @@ -70,7 +70,7 @@ func handleSocksUDP(pc net.PacketConn, in chan<- *inbound.PacketAdapter, buf []b bufRef: buf, } select { - case in <- inbound.NewPacket(target, packet, C.TPROXY): + case in <- inbound.NewPacket(target, packet, C.SOCKS): default: } } From 507ba1606564cf061242be1d450c14277331c2be Mon Sep 17 00:00:00 2001 From: Dreamacro <8615343+Dreamacro@users.noreply.github.com> Date: Wed, 21 Jul 2021 23:53:31 +0800 Subject: [PATCH 29/96] Fix: incorrect use batch --- adapter/provider/healthcheck.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/adapter/provider/healthcheck.go b/adapter/provider/healthcheck.go index 636873d94..4d2711a51 100644 --- a/adapter/provider/healthcheck.go +++ b/adapter/provider/healthcheck.go @@ -59,14 +59,14 @@ func (hc *HealthCheck) touch() { } func (hc *HealthCheck) check() { - ctx, cancel := context.WithTimeout(context.Background(), defaultURLTestTimeout) - defer cancel() - - b, ctx := batch.WithContext(ctx, batch.WithConcurrencyNum(10)) + b := batch.New(batch.WithConcurrencyNum(10)) for _, proxy := range hc.proxies { p := proxy b.Go(p.Name(), func() (interface{}, error) { - return p.URLTest(ctx, hc.url) + ctx, cancel := context.WithTimeout(context.Background(), defaultURLTestTimeout) + defer cancel() + p.URLTest(ctx, hc.url) + return nil, nil }) } b.Wait() From b3a293ab078eb192001871be6fcb49e9749f20a7 Mon Sep 17 00:00:00 2001 From: Dreamacro <8615343+Dreamacro@users.noreply.github.com> Date: Thu, 22 Jul 2021 00:01:11 +0800 Subject: [PATCH 30/96] Chore: benchmark explanation --- test/README.md | 10 ++++++++++ test/clash_test.go | 5 +++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/test/README.md b/test/README.md index dec9999c2..823fc5446 100644 --- a/test/README.md +++ b/test/README.md @@ -47,3 +47,13 @@ Prerequisite ``` $ go test -p 1 -v ``` + +benchmark (Linux) + +> Cannot represent the throughput of the protocol on your machine +> but you can compare the corresponding throughput of the protocol on clash +> (change chunkSize to measure the maximum throughput of clash on your machine) + +``` +$ go test -benchmem -run=^$ -bench . +``` diff --git a/test/clash_test.go b/test/clash_test.go index 7d373bbd5..366cc260b 100644 --- a/test/clash_test.go +++ b/test/clash_test.go @@ -636,7 +636,8 @@ func benchmarkProxy(b *testing.B, proxy C.ProxyAdapter) { c.Close() }() - chunk := make([]byte, 1024) + chunkSize := int64(16 * 1024) + chunk := make([]byte, chunkSize) conn, err := proxy.DialContext(context.Background(), &C.Metadata{ Host: localIP.String(), DstPort: "10001", @@ -646,7 +647,7 @@ func benchmarkProxy(b *testing.B, proxy C.ProxyAdapter) { assert.FailNow(b, err.Error()) } - b.SetBytes(1024) + b.SetBytes(chunkSize) b.ResetTimer() for i := 0; i < b.N; i++ { if _, err := conn.Write(chunk); err != nil { From 4578b2c82635ac76df26a8ab0bbf0fba4c24a851 Mon Sep 17 00:00:00 2001 From: duama <30264485+duament@users.noreply.github.com> Date: Thu, 22 Jul 2021 18:06:03 +0800 Subject: [PATCH 31/96] Fix: remove Content-Length from CONNECT response (#1502) --- listener/http/proxy.go | 1 + 1 file changed, 1 insertion(+) diff --git a/listener/http/proxy.go b/listener/http/proxy.go index 12508ba3d..9ac95cb49 100644 --- a/listener/http/proxy.go +++ b/listener/http/proxy.go @@ -45,6 +45,7 @@ func HandleConn(c net.Conn, in chan<- C.ConnContext, cache *cache.Cache) { if request.Method == http.MethodConnect { resp = responseWith(200) resp.Status = "Connection established" + resp.ContentLength = -1 if resp.Write(conn) != nil { break // close connection From 09697b7679e0d934d51ef1ee55192e236c2c02f1 Mon Sep 17 00:00:00 2001 From: Dreamacro <8615343+Dreamacro@users.noreply.github.com> Date: Fri, 23 Jul 2021 00:30:23 +0800 Subject: [PATCH 32/96] Chore: adjust batch --- adapter/provider/healthcheck.go | 2 +- common/batch/batch.go | 12 +++--------- common/batch/batch_test.go | 7 ++++--- 3 files changed, 8 insertions(+), 13 deletions(-) diff --git a/adapter/provider/healthcheck.go b/adapter/provider/healthcheck.go index 4d2711a51..f41a4788d 100644 --- a/adapter/provider/healthcheck.go +++ b/adapter/provider/healthcheck.go @@ -59,7 +59,7 @@ func (hc *HealthCheck) touch() { } func (hc *HealthCheck) check() { - b := batch.New(batch.WithConcurrencyNum(10)) + b, _ := batch.New(context.Background(), batch.WithConcurrencyNum(10)) for _, proxy := range hc.proxies { p := proxy b.Go(p.Name(), func() (interface{}, error) { diff --git a/common/batch/batch.go b/common/batch/batch.go index 7fbca4217..ce20ed612 100644 --- a/common/batch/batch.go +++ b/common/batch/batch.go @@ -89,7 +89,9 @@ func (b *Batch) Result() map[string]Result { return copy } -func New(opts ...Option) *Batch { +func New(ctx context.Context, opts ...Option) (*Batch, context.Context) { + ctx, cancel := context.WithCancel(ctx) + b := &Batch{ result: map[string]Result{}, } @@ -98,14 +100,6 @@ func New(opts ...Option) *Batch { o(b) } - return b -} - -func WithContext(ctx context.Context, opts ...Option) (*Batch, context.Context) { - ctx, cancel := context.WithCancel(ctx) - - b := New(opts...) b.cancel = cancel - return b, ctx } diff --git a/common/batch/batch_test.go b/common/batch/batch_test.go index 4fcdbe81c..9465dbad9 100644 --- a/common/batch/batch_test.go +++ b/common/batch/batch_test.go @@ -11,7 +11,7 @@ import ( ) func TestBatch(t *testing.T) { - b := New() + b, _ := New(context.Background()) now := time.Now() b.Go("foo", func() (interface{}, error) { @@ -37,7 +37,8 @@ func TestBatch(t *testing.T) { } func TestBatchWithConcurrencyNum(t *testing.T) { - b := New( + b, _ := New( + context.Background(), WithConcurrencyNum(3), ) @@ -61,7 +62,7 @@ func TestBatchWithConcurrencyNum(t *testing.T) { } func TestBatchContext(t *testing.T) { - b, ctx := WithContext(context.Background()) + b, ctx := New(context.Background()) b.Go("error", func() (interface{}, error) { time.Sleep(time.Millisecond * 100) From 37059969740315cd342967fe1bb29b07592a75e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?x=E1=B4=8A=E1=B4=80s=E1=B4=8F=C9=B4=CA=9F=CA=8F=E1=B4=9C?= Date: Tue, 27 Jul 2021 13:58:29 +0800 Subject: [PATCH 33/96] Chore: split SOCKS version inbound metadata type (#1513) --- constant/metadata.go | 7 +++++-- listener/socks/tcp.go | 4 ++-- listener/socks/udp.go | 2 +- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/constant/metadata.go b/constant/metadata.go index 93ef406d2..9fff773b3 100644 --- a/constant/metadata.go +++ b/constant/metadata.go @@ -17,7 +17,8 @@ const ( HTTP Type = iota HTTPCONNECT - SOCKS + SOCKS4 + SOCKS5 REDIR TPROXY ) @@ -43,7 +44,9 @@ func (t Type) String() string { return "HTTP" case HTTPCONNECT: return "HTTP Connect" - case SOCKS: + case SOCKS4: + return "Socks4" + case SOCKS5: return "Socks5" case REDIR: return "Redir" diff --git a/listener/socks/tcp.go b/listener/socks/tcp.go index 587af2213..20e48f85c 100644 --- a/listener/socks/tcp.go +++ b/listener/socks/tcp.go @@ -79,7 +79,7 @@ func HandleSocks4(conn net.Conn, in chan<- C.ConnContext) { if c, ok := conn.(*net.TCPConn); ok { c.SetKeepAlive(true) } - in <- inbound.NewSocket(socks5.ParseAddr(addr), conn, C.SOCKS) + in <- inbound.NewSocket(socks5.ParseAddr(addr), conn, C.SOCKS4) } func HandleSocks5(conn net.Conn, in chan<- C.ConnContext) { @@ -96,5 +96,5 @@ func HandleSocks5(conn net.Conn, in chan<- C.ConnContext) { io.Copy(ioutil.Discard, conn) return } - in <- inbound.NewSocket(target, conn, C.SOCKS) + in <- inbound.NewSocket(target, conn, C.SOCKS5) } diff --git a/listener/socks/udp.go b/listener/socks/udp.go index ca75b2c8a..f822d76af 100644 --- a/listener/socks/udp.go +++ b/listener/socks/udp.go @@ -70,7 +70,7 @@ func handleSocksUDP(pc net.PacketConn, in chan<- *inbound.PacketAdapter, buf []b bufRef: buf, } select { - case in <- inbound.NewPacket(target, packet, C.SOCKS): + case in <- inbound.NewPacket(target, packet, C.SOCKS5): default: } } From 1bfebd0d037b7d7fc877351cba46cd8a8f4ad65b Mon Sep 17 00:00:00 2001 From: Dreamacro <8615343+Dreamacro@users.noreply.github.com> Date: Sun, 1 Aug 2021 00:35:37 +0800 Subject: [PATCH 34/96] Fix: listener patch diff --- constant/listener.go | 7 +++++++ listener/http/server.go | 27 ++++++++++++++++++--------- listener/listener.go | 36 ++++++++++++++++++------------------ listener/mixed/mixed.go | 29 +++++++++++++++++++---------- listener/redir/tcp.go | 27 ++++++++++++++++++--------- listener/socks/tcp.go | 27 ++++++++++++++++++--------- listener/socks/udp.go | 27 ++++++++++++++++++--------- listener/tproxy/tproxy.go | 39 ++++++++++++++++++++++++--------------- listener/tproxy/udp.go | 27 ++++++++++++++++++--------- 9 files changed, 158 insertions(+), 88 deletions(-) create mode 100644 constant/listener.go diff --git a/constant/listener.go b/constant/listener.go new file mode 100644 index 000000000..07782a9e0 --- /dev/null +++ b/constant/listener.go @@ -0,0 +1,7 @@ +package constant + +type Listener interface { + RawAddress() string + Address() string + Close() error +} diff --git a/listener/http/server.go b/listener/http/server.go index 6c5a7f6a4..bfdd9f1b6 100644 --- a/listener/http/server.go +++ b/listener/http/server.go @@ -10,9 +10,26 @@ import ( type Listener struct { listener net.Listener + addr string closed bool } +// RawAddress implements C.Listener +func (l *Listener) RawAddress() string { + return l.addr +} + +// Address implements C.Listener +func (l *Listener) Address() string { + return l.listener.Addr().String() +} + +// Close implements C.Listener +func (l *Listener) Close() error { + l.closed = true + return l.listener.Close() +} + func New(addr string, in chan<- C.ConnContext) (*Listener, error) { return NewWithAuthenticate(addr, in, true) } @@ -30,6 +47,7 @@ func NewWithAuthenticate(addr string, in chan<- C.ConnContext, authenticate bool hl := &Listener{ listener: l, + addr: addr, } go func() { for { @@ -46,12 +64,3 @@ func NewWithAuthenticate(addr string, in chan<- C.ConnContext, authenticate bool return hl, nil } - -func (l *Listener) Close() { - l.closed = true - l.listener.Close() -} - -func (l *Listener) Address() string { - return l.listener.Addr().String() -} diff --git a/listener/listener.go b/listener/listener.go index 5d0e8d7bf..f9fffdf45 100644 --- a/listener/listener.go +++ b/listener/listener.go @@ -20,15 +20,15 @@ var ( allowLan = false bindAddress = "*" - socksListener *socks.Listener - socksUDPListener *socks.UDPListener - httpListener *http.Listener - redirListener *redir.Listener - redirUDPListener *tproxy.UDPListener - tproxyListener *tproxy.Listener - tproxyUDPListener *tproxy.UDPListener - mixedListener *mixed.Listener - mixedUDPLister *socks.UDPListener + socksListener C.Listener + socksUDPListener C.Listener + httpListener C.Listener + redirListener C.Listener + redirUDPListener C.Listener + tproxyListener C.Listener + tproxyUDPListener C.Listener + mixedListener C.Listener + mixedUDPLister C.Listener // lock for recreate function socksMux sync.Mutex @@ -69,7 +69,7 @@ func ReCreateHTTP(port int, tcpIn chan<- C.ConnContext) error { addr := genAddr(bindAddress, port, allowLan) if httpListener != nil { - if httpListener.Address() == addr { + if httpListener.RawAddress() == addr { return nil } httpListener.Close() @@ -100,7 +100,7 @@ func ReCreateSocks(port int, tcpIn chan<- C.ConnContext, udpIn chan<- *inbound.P shouldUDPIgnore := false if socksListener != nil { - if socksListener.Address() != addr { + if socksListener.RawAddress() != addr { socksListener.Close() socksListener = nil } else { @@ -109,7 +109,7 @@ func ReCreateSocks(port int, tcpIn chan<- C.ConnContext, udpIn chan<- *inbound.P } if socksUDPListener != nil { - if socksUDPListener.Address() != addr { + if socksUDPListener.RawAddress() != addr { socksUDPListener.Close() socksUDPListener = nil } else { @@ -150,7 +150,7 @@ func ReCreateRedir(port int, tcpIn chan<- C.ConnContext, udpIn chan<- *inbound.P addr := genAddr(bindAddress, port, allowLan) if redirListener != nil { - if redirListener.Address() == addr { + if redirListener.RawAddress() == addr { return nil } redirListener.Close() @@ -158,7 +158,7 @@ func ReCreateRedir(port int, tcpIn chan<- C.ConnContext, udpIn chan<- *inbound.P } if redirUDPListener != nil { - if redirUDPListener.Address() == addr { + if redirUDPListener.RawAddress() == addr { return nil } redirUDPListener.Close() @@ -191,7 +191,7 @@ func ReCreateTProxy(port int, tcpIn chan<- C.ConnContext, udpIn chan<- *inbound. addr := genAddr(bindAddress, port, allowLan) if tproxyListener != nil { - if tproxyListener.Address() == addr { + if tproxyListener.RawAddress() == addr { return nil } tproxyListener.Close() @@ -199,7 +199,7 @@ func ReCreateTProxy(port int, tcpIn chan<- C.ConnContext, udpIn chan<- *inbound. } if tproxyUDPListener != nil { - if tproxyUDPListener.Address() == addr { + if tproxyUDPListener.RawAddress() == addr { return nil } tproxyUDPListener.Close() @@ -235,7 +235,7 @@ func ReCreateMixed(port int, tcpIn chan<- C.ConnContext, udpIn chan<- *inbound.P shouldUDPIgnore := false if mixedListener != nil { - if mixedListener.Address() != addr { + if mixedListener.RawAddress() != addr { mixedListener.Close() mixedListener = nil } else { @@ -243,7 +243,7 @@ func ReCreateMixed(port int, tcpIn chan<- C.ConnContext, udpIn chan<- *inbound.P } } if mixedUDPLister != nil { - if mixedUDPLister.Address() != addr { + if mixedUDPLister.RawAddress() != addr { mixedUDPLister.Close() mixedUDPLister = nil } else { diff --git a/listener/mixed/mixed.go b/listener/mixed/mixed.go index 97be69f0b..8fd4f990e 100644 --- a/listener/mixed/mixed.go +++ b/listener/mixed/mixed.go @@ -15,8 +15,25 @@ import ( type Listener struct { listener net.Listener - closed bool + addr string cache *cache.Cache + closed bool +} + +// RawAddress implements C.Listener +func (l *Listener) RawAddress() string { + return l.addr +} + +// Address implements C.Listener +func (l *Listener) Address() string { + return l.listener.Addr().String() +} + +// Close implements C.Listener +func (l *Listener) Close() error { + l.closed = true + return l.listener.Close() } func New(addr string, in chan<- C.ConnContext) (*Listener, error) { @@ -27,6 +44,7 @@ func New(addr string, in chan<- C.ConnContext) (*Listener, error) { ml := &Listener{ listener: l, + addr: addr, cache: cache.New(30 * time.Second), } go func() { @@ -45,15 +63,6 @@ func New(addr string, in chan<- C.ConnContext) (*Listener, error) { return ml, nil } -func (l *Listener) Close() { - l.closed = true - l.listener.Close() -} - -func (l *Listener) Address() string { - return l.listener.Addr().String() -} - func handleConn(conn net.Conn, in chan<- C.ConnContext, cache *cache.Cache) { bufConn := N.NewBufferedConn(conn) head, err := bufConn.Peek(1) diff --git a/listener/redir/tcp.go b/listener/redir/tcp.go index f7160eb01..15c98a8f3 100644 --- a/listener/redir/tcp.go +++ b/listener/redir/tcp.go @@ -9,9 +9,26 @@ import ( type Listener struct { listener net.Listener + addr string closed bool } +// RawAddress implements C.Listener +func (l *Listener) RawAddress() string { + return l.addr +} + +// Address implements C.Listener +func (l *Listener) Address() string { + return l.listener.Addr().String() +} + +// Close implements C.Listener +func (l *Listener) Close() error { + l.closed = true + return l.listener.Close() +} + func New(addr string, in chan<- C.ConnContext) (*Listener, error) { l, err := net.Listen("tcp", addr) if err != nil { @@ -19,6 +36,7 @@ func New(addr string, in chan<- C.ConnContext) (*Listener, error) { } rl := &Listener{ listener: l, + addr: addr, } go func() { @@ -37,15 +55,6 @@ func New(addr string, in chan<- C.ConnContext) (*Listener, error) { return rl, nil } -func (l *Listener) Close() { - l.closed = true - l.listener.Close() -} - -func (l *Listener) Address() string { - return l.listener.Addr().String() -} - func handleRedir(conn net.Conn, in chan<- C.ConnContext) { target, err := parserPacket(conn) if err != nil { diff --git a/listener/socks/tcp.go b/listener/socks/tcp.go index 20e48f85c..49d0a1e31 100644 --- a/listener/socks/tcp.go +++ b/listener/socks/tcp.go @@ -15,9 +15,26 @@ import ( type Listener struct { listener net.Listener + addr string closed bool } +// RawAddress implements C.Listener +func (l *Listener) RawAddress() string { + return l.addr +} + +// Address implements C.Listener +func (l *Listener) Address() string { + return l.listener.Addr().String() +} + +// Close implements C.Listener +func (l *Listener) Close() error { + l.closed = true + return l.listener.Close() +} + func New(addr string, in chan<- C.ConnContext) (*Listener, error) { l, err := net.Listen("tcp", addr) if err != nil { @@ -26,6 +43,7 @@ func New(addr string, in chan<- C.ConnContext) (*Listener, error) { sl := &Listener{ listener: l, + addr: addr, } go func() { for { @@ -43,15 +61,6 @@ func New(addr string, in chan<- C.ConnContext) (*Listener, error) { return sl, nil } -func (l *Listener) Close() { - l.closed = true - l.listener.Close() -} - -func (l *Listener) Address() string { - return l.listener.Addr().String() -} - func handleSocks(conn net.Conn, in chan<- C.ConnContext) { bufConn := N.NewBufferedConn(conn) head, err := bufConn.Peek(1) diff --git a/listener/socks/udp.go b/listener/socks/udp.go index f822d76af..a2d215083 100644 --- a/listener/socks/udp.go +++ b/listener/socks/udp.go @@ -13,9 +13,26 @@ import ( type UDPListener struct { packetConn net.PacketConn + addr string closed bool } +// RawAddress implements C.Listener +func (l *UDPListener) RawAddress() string { + return l.addr +} + +// Address implements C.Listener +func (l *UDPListener) Address() string { + return l.packetConn.LocalAddr().String() +} + +// Close implements C.Listener +func (l *UDPListener) Close() error { + l.closed = true + return l.packetConn.Close() +} + func NewUDP(addr string, in chan<- *inbound.PacketAdapter) (*UDPListener, error) { l, err := net.ListenPacket("udp", addr) if err != nil { @@ -28,6 +45,7 @@ func NewUDP(addr string, in chan<- *inbound.PacketAdapter) (*UDPListener, error) sl := &UDPListener{ packetConn: l, + addr: addr, } go func() { for { @@ -47,15 +65,6 @@ func NewUDP(addr string, in chan<- *inbound.PacketAdapter) (*UDPListener, error) return sl, nil } -func (l *UDPListener) Close() error { - l.closed = true - return l.packetConn.Close() -} - -func (l *UDPListener) Address() string { - return l.packetConn.LocalAddr().String() -} - func handleSocksUDP(pc net.PacketConn, in chan<- *inbound.PacketAdapter, buf []byte, addr net.Addr) { target, payload, err := socks5.DecodeUDPPacket(buf) if err != nil { diff --git a/listener/tproxy/tproxy.go b/listener/tproxy/tproxy.go index 87f2d7d67..1a09f3663 100644 --- a/listener/tproxy/tproxy.go +++ b/listener/tproxy/tproxy.go @@ -10,9 +10,32 @@ import ( type Listener struct { listener net.Listener + addr string closed bool } +// RawAddress implements C.Listener +func (l *Listener) RawAddress() string { + return l.addr +} + +// Address implements C.Listener +func (l *Listener) Address() string { + return l.listener.Addr().String() +} + +// Close implements C.Listener +func (l *Listener) Close() error { + l.closed = true + return l.listener.Close() +} + +func (l *Listener) handleTProxy(conn net.Conn, in chan<- C.ConnContext) { + target := socks5.ParseAddrToSocksAddr(conn.LocalAddr()) + conn.(*net.TCPConn).SetKeepAlive(true) + in <- inbound.NewSocket(target, conn, C.TPROXY) +} + func New(addr string, in chan<- C.ConnContext) (*Listener, error) { l, err := net.Listen("tcp", addr) if err != nil { @@ -32,6 +55,7 @@ func New(addr string, in chan<- C.ConnContext) (*Listener, error) { rl := &Listener{ listener: l, + addr: addr, } go func() { @@ -49,18 +73,3 @@ func New(addr string, in chan<- C.ConnContext) (*Listener, error) { return rl, nil } - -func (l *Listener) Close() { - l.closed = true - l.listener.Close() -} - -func (l *Listener) Address() string { - return l.listener.Addr().String() -} - -func (l *Listener) handleTProxy(conn net.Conn, in chan<- C.ConnContext) { - target := socks5.ParseAddrToSocksAddr(conn.LocalAddr()) - conn.(*net.TCPConn).SetKeepAlive(true) - in <- inbound.NewSocket(target, conn, C.TPROXY) -} diff --git a/listener/tproxy/udp.go b/listener/tproxy/udp.go index 6f9de6f54..f3d8dbb3c 100644 --- a/listener/tproxy/udp.go +++ b/listener/tproxy/udp.go @@ -11,9 +11,26 @@ import ( type UDPListener struct { packetConn net.PacketConn + addr string closed bool } +// RawAddress implements C.Listener +func (l *UDPListener) RawAddress() string { + return l.addr +} + +// Address implements C.Listener +func (l *UDPListener) Address() string { + return l.packetConn.LocalAddr().String() +} + +// Close implements C.Listener +func (l *UDPListener) Close() error { + l.closed = true + return l.packetConn.Close() +} + func NewUDP(addr string, in chan<- *inbound.PacketAdapter) (*UDPListener, error) { l, err := net.ListenPacket("udp", addr) if err != nil { @@ -22,6 +39,7 @@ func NewUDP(addr string, in chan<- *inbound.PacketAdapter) (*UDPListener, error) rl := &UDPListener{ packetConn: l, + addr: addr, } c := l.(*net.UDPConn) @@ -60,15 +78,6 @@ func NewUDP(addr string, in chan<- *inbound.PacketAdapter) (*UDPListener, error) return rl, nil } -func (l *UDPListener) Close() error { - l.closed = true - return l.packetConn.Close() -} - -func (l *UDPListener) Address() string { - return l.packetConn.LocalAddr().String() -} - func handlePacketConn(pc net.PacketConn, in chan<- *inbound.PacketAdapter, buf []byte, lAddr *net.UDPAddr, rAddr *net.UDPAddr) { target := socks5.ParseAddrToSocksAddr(rAddr) pkt := &packet{ From 588645a2c3eda1afcde9e93fc2d01b7c7357338a Mon Sep 17 00:00:00 2001 From: Dreamacro <8615343+Dreamacro@users.noreply.github.com> Date: Wed, 4 Aug 2021 23:52:50 +0800 Subject: [PATCH 35/96] Fix: interface nil check panic from previous commit --- listener/listener.go | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/listener/listener.go b/listener/listener.go index f9fffdf45..d20af99db 100644 --- a/listener/listener.go +++ b/listener/listener.go @@ -20,15 +20,15 @@ var ( allowLan = false bindAddress = "*" - socksListener C.Listener - socksUDPListener C.Listener - httpListener C.Listener - redirListener C.Listener - redirUDPListener C.Listener - tproxyListener C.Listener - tproxyUDPListener C.Listener - mixedListener C.Listener - mixedUDPLister C.Listener + socksListener *socks.Listener + socksUDPListener *socks.UDPListener + httpListener *http.Listener + redirListener *redir.Listener + redirUDPListener *tproxy.UDPListener + tproxyListener *tproxy.Listener + tproxyUDPListener *tproxy.UDPListener + mixedListener *mixed.Listener + mixedUDPLister *socks.UDPListener // lock for recreate function socksMux sync.Mutex From 9b0bbb90ff2741cc7b2e3a54ad47a8c403acf70c Mon Sep 17 00:00:00 2001 From: Dreamacro <8615343+Dreamacro@users.noreply.github.com> Date: Sat, 7 Aug 2021 22:27:23 +0800 Subject: [PATCH 36/96] Chore: upgrade github actions --- .github/workflows/docker.yml | 2 +- .github/workflows/go.yml | 2 -- .github/workflows/stale.yml | 3 +-- 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 002a9cb35..35083e518 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -52,7 +52,7 @@ jobs: - name: Get all docker tags if: startsWith(github.ref, 'refs/tags/') - uses: actions/github-script@v3 + uses: actions/github-script@v4 id: tags with: script: | diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index a52be1e9a..343e31ba1 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -39,8 +39,6 @@ jobs: - name: Upload Release uses: softprops/action-gh-release@v1 if: startsWith(github.ref, 'refs/tags/') - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: files: bin/* draft: true diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 7581fc403..68f986ffc 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -11,9 +11,8 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/stale@v3 + - uses: actions/stale@v4 with: - repo-token: ${{ secrets.GITHUB_TOKEN }} stale-issue-message: 'This issue is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 5 days' days-before-stale: 60 days-before-close: 5 From 2663cb2e6e69700527565683216f6d99ce60aeae Mon Sep 17 00:00:00 2001 From: Dreamacro <8615343+Dreamacro@users.noreply.github.com> Date: Fri, 13 Aug 2021 22:35:07 +0800 Subject: [PATCH 37/96] Chore: update github issue template --- .github/ISSUE_TEMPLATE/bug_report.md | 100 --------------------- .github/ISSUE_TEMPLATE/bug_report.yml | 77 ++++++++++++++++ .github/ISSUE_TEMPLATE/config.yml | 6 ++ .github/ISSUE_TEMPLATE/feature_request.md | 78 ---------------- .github/ISSUE_TEMPLATE/feature_request.yml | 36 ++++++++ 5 files changed, 119 insertions(+), 178 deletions(-) delete mode 100644 .github/ISSUE_TEMPLATE/bug_report.md create mode 100644 .github/ISSUE_TEMPLATE/bug_report.yml create mode 100644 .github/ISSUE_TEMPLATE/config.yml delete mode 100644 .github/ISSUE_TEMPLATE/feature_request.md create mode 100644 .github/ISSUE_TEMPLATE/feature_request.yml diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md deleted file mode 100644 index 2e5b75545..000000000 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ /dev/null @@ -1,100 +0,0 @@ ---- -name: Bug report -about: Create a report to help us improve -title: "[Bug]" -labels: '' -assignees: '' - ---- - - - ------------------------------------------------------------------- - - - -### Clash config - -
- config.yaml - -```yaml -…… -``` - -
- -### Clash log - -``` -…… -``` - -### 环境 Environment - -* 操作系统 (the OS that the Clash core is running on) -…… -* 网路环境或拓扑 (network conditions/topology) -…… -* iptables,如果适用 (if applicable) -…… -* ISP 有没有进行 DNS 污染 (is your ISP performing DNS pollution?) -…… -* 其他 (any other information that would be useful) -…… - -### 说明 Description - - - -### 重现问题的具体布骤 Steps to Reproduce - -1. [First Step] -2. [Second Step] -3. …… - -**我预期会发生……?** - - -**实际上发生了什么?** - - -### 可能的解决方案 Possible Solution - - - - -### 更多信息 More Information diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 000000000..0876a7a7e --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,77 @@ +name: Bug report +description: Create a report to help us improve +title: '[Bug] ' +body: + - type: checkboxes + id: ensure + attributes: + label: Verify steps + description: " +在提交之前,请确认 +Please verify that you've followed these steps +" + options: + - label: " +如果你可以自己 debug 并解决的话,提交 PR 吧 +Is this something you can **debug and fix**? Send a pull request! Bug fixes and documentation fixes are welcome. +" + required: true + - label: " +我已经在 [Issue Tracker](……/) 中找过我要提出的问题 +I have searched on the [issue tracker](……/) for a related issue. +" + required: true + - label: " +我已经使用 dev 分支版本测试过,问题依旧存在 +I have tested using the dev branch, and the issue still exists. +" + required: true + - label: " +我已经仔细看过 [Documentation](https://github.com/Dreamacro/clash/wiki/) 并无法自行解决问题 +I have read the [documentation](https://github.com/Dreamacro/clash/wiki/) and was unable to solve the issue. +" + required: true + - label: " +这是 Clash 核心的问题,并非我所使用的 Clash 衍生版本(如 OpenClash、KoolClash 等)的特定问题 +This is an issue of the Clash core *per se*, not to the derivatives of Clash, like OpenClash or KoolClash. +" + required: true + - type: textarea + attributes: + render: yaml + label: "Clash version" + validations: + required: true + - type: dropdown + id: os + attributes: + label: What OS are you seeing the problem on? + multiple: true + options: + - macOS + - Windows + - Linux + - OpenBSD/FreeBSD + - type: textarea + attributes: + render: yaml + label: "Clash config" + description: " +在下方附上 Clash core 脱敏后配置文件的内容 +Paste the Clash core configuration below. +" + validations: + required: true + - type: textarea + attributes: + render: yaml + label: "Clash log" + description: " +在下方附上 Clash Core 的日志,log level 使用 DEBUG +Paste the Clash core log below with the log level set to `DEBUG`. +" + - type: textarea + attributes: + label: "Description" + validations: + required: true diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 000000000..7404fe27c --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,6 @@ +blank_issues_enabled: false + +contact_links: + - name: Get help in GitHub Discussions + url: https://github.com/Dreamacro/clash/discussions + about: Have a question? Not sure if your issue affects everyone reproducibly? The quickest way to get help is on Clash's GitHub Discussions! diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md deleted file mode 100644 index d5ddc956a..000000000 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ /dev/null @@ -1,78 +0,0 @@ ---- -name: Feature request -about: Suggest an idea for this project -title: "[Feature]" -labels: '' -assignees: '' - ---- - - -感谢你向 Clash Core 提交 Feature Request! -在提交之前,请确认: - -- [ ] 我已经在 [Issue Tracker](……/) 中找过我要提出的请求 - -请注意,如果你并没有遵照这个 issue template 填写内容,我们将直接关闭这个 issue。 - - - -我都确认过了,我要继续提交。 - ------------------------------------------------------------------- - -请附上任何可以帮助我们解决这个问题的信息,如果我们收到的信息不足,我们将对这个 issue 加上 *Needs more information* 标记并在收到更多资讯之前关闭 issue。 - - -### Clash core config - -``` -…… -``` - -### Clash log - -``` -…… -``` - -### 环境 Environment - -* Clash Core 的操作系统 (the OS that the Clash core is running on) -…… -* 使用者的操作系统 (the OS running on the client) -…… -* 网路环境或拓扑 (network conditions/topology) -…… -* iptables,如果适用 (if applicable) -…… -* ISP 有没有进行 DNS 污染 (is your ISP performing DNS pollution?) -…… -* 其他 -…… - -### 说明 Description - - - -### 可能的解决方案 Possible Solution - - - - -### 更多信息 More Information diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml new file mode 100644 index 000000000..b00d5b9a9 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -0,0 +1,36 @@ +name: Feature request +description: Suggest an idea for this project +title: "[Feature] " +body: + - type: checkboxes + id: ensure + attributes: + label: Verify steps + description: " +在提交之前,请确认 +Please verify that you've followed these steps +" + options: + - label: " +我已经在 [Issue Tracker](……/) 中找过我要提出的请求 +I have searched on the [issue tracker](……/) for a related feature request. +" + required: true + - label: " +我已经仔细看过 [Documentation](https://github.com/Dreamacro/clash/wiki/) 并无法自行解决问题 +I have read the [documentation](https://github.com/Dreamacro/clash/wiki/) and was unable to solve the issue. +" + required: true + - type: textarea + attributes: + label: "Description" + description: 请详细、清晰地表达你要提出的论述,例如这个问题如何影响到你?你想实现什么功能?目前 Clash Core 的行为是什麽? + validations: + required: true + - type: textarea + attributes: + label: "Possible Solution" + description: " +此项非必须,但是如果你有想法的话欢迎提出。 +Not obligatory, but suggest a fix/reason for the bug, or ideas how to implement the addition or change +" From 1be09f57515f6aefd0f26633ee15ffe3e2c320cb Mon Sep 17 00:00:00 2001 From: Dreamacro <8615343+Dreamacro@users.noreply.github.com> Date: Fri, 13 Aug 2021 22:44:22 +0800 Subject: [PATCH 38/96] Chore: fix issue template render type --- .github/ISSUE_TEMPLATE/bug_report.yml | 13 ++++++------- .github/ISSUE_TEMPLATE/feature_request.yml | 4 ++-- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 0876a7a7e..b56b98651 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -1,6 +1,6 @@ name: Bug report description: Create a report to help us improve -title: '[Bug] ' +title: "[Bug] " body: - type: checkboxes id: ensure @@ -36,10 +36,9 @@ I have read the [documentation](https://github.com/Dreamacro/clash/wiki/) and wa This is an issue of the Clash core *per se*, not to the derivatives of Clash, like OpenClash or KoolClash. " required: true - - type: textarea + - type: input attributes: - render: yaml - label: "Clash version" + label: Clash version validations: required: true - type: dropdown @@ -64,14 +63,14 @@ Paste the Clash core configuration below. required: true - type: textarea attributes: - render: yaml - label: "Clash log" + render: shell + label: Clash log description: " 在下方附上 Clash Core 的日志,log level 使用 DEBUG Paste the Clash core log below with the log level set to `DEBUG`. " - type: textarea attributes: - label: "Description" + label: Description validations: required: true diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml index b00d5b9a9..34668d1ab 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.yml +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -23,13 +23,13 @@ I have read the [documentation](https://github.com/Dreamacro/clash/wiki/) and wa required: true - type: textarea attributes: - label: "Description" + label: Description description: 请详细、清晰地表达你要提出的论述,例如这个问题如何影响到你?你想实现什么功能?目前 Clash Core 的行为是什麽? validations: required: true - type: textarea attributes: - label: "Possible Solution" + label: Possible Solution description: " 此项非必须,但是如果你有想法的话欢迎提出。 Not obligatory, but suggest a fix/reason for the bug, or ideas how to implement the addition or change From 571d2a00755287afad5b0a93b36f1d75a3d55895 Mon Sep 17 00:00:00 2001 From: Dreamacro <8615343+Dreamacro@users.noreply.github.com> Date: Wed, 18 Aug 2021 13:26:23 +0800 Subject: [PATCH 39/96] Migration: go 1.17 --- .github/workflows/go.yml | 2 +- Makefile | 6 +++++- common/sockopt/reuseaddr_other.go | 1 + component/dialer/bind_others.go | 1 + component/process/process_other.go | 5 ++++- dns/filters.go | 2 +- go.mod | 18 +++++++++++++----- go.sum | 16 ++++++++-------- listener/redir/tcp_linux_other.go | 1 + listener/redir/tcp_other.go | 1 + listener/tproxy/setsockopt_linux.go | 1 + listener/tproxy/setsockopt_other.go | 1 + listener/tproxy/udp_linux.go | 1 + listener/tproxy/udp_other.go | 1 + rule/geoip.go | 4 ++++ 15 files changed, 44 insertions(+), 17 deletions(-) diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index 343e31ba1..d8a514eae 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -9,7 +9,7 @@ jobs: - name: Setup Go uses: actions/setup-go@v2 with: - go-version: 1.16 + go-version: 1.17 - name: Check out code into the Go module directory uses: actions/checkout@v2 diff --git a/Makefile b/Makefile index 686514460..97328bc23 100644 --- a/Makefile +++ b/Makefile @@ -28,6 +28,7 @@ PLATFORM_LIST = \ WINDOWS_ARCH_LIST = \ windows-386 \ windows-amd64 \ + windows-arm64 \ windows-arm32v7 all: linux-amd64 darwin-amd64 windows-amd64 # Most used @@ -91,7 +92,10 @@ windows-386: windows-amd64: GOARCH=amd64 GOOS=windows $(GOBUILD) -o $(BINDIR)/$(NAME)-$@.exe - + +windows-arm64: + GOARCH=arm64 GOOS=windows $(GOBUILD) -o $(BINDIR)/$(NAME)-$@.exe + windows-arm32v7: GOARCH=arm GOOS=windows GOARM=7 $(GOBUILD) -o $(BINDIR)/$(NAME)-$@.exe diff --git a/common/sockopt/reuseaddr_other.go b/common/sockopt/reuseaddr_other.go index 2b1369508..c07083de0 100644 --- a/common/sockopt/reuseaddr_other.go +++ b/common/sockopt/reuseaddr_other.go @@ -1,3 +1,4 @@ +//go:build !linux // +build !linux package sockopt diff --git a/component/dialer/bind_others.go b/component/dialer/bind_others.go index be30bae84..e09b5ff84 100644 --- a/component/dialer/bind_others.go +++ b/component/dialer/bind_others.go @@ -1,3 +1,4 @@ +//go:build !linux && !darwin // +build !linux,!darwin package dialer diff --git a/component/process/process_other.go b/component/process/process_other.go index 1e0bd4478..f8a6ebbb4 100644 --- a/component/process/process_other.go +++ b/component/process/process_other.go @@ -1,4 +1,7 @@ -// +build !darwin,!linux,!windows +//go:build !darwin && !linux && !windows && (!freebsd || !amd64) +// +build !darwin +// +build !linux +// +build !windows // +build !freebsd !amd64 package process diff --git a/dns/filters.go b/dns/filters.go index 583883fab..a6bc6c544 100644 --- a/dns/filters.go +++ b/dns/filters.go @@ -15,7 +15,7 @@ type geoipFilter struct{} func (gf *geoipFilter) Match(ip net.IP) bool { record, _ := mmdb.Instance().Country(ip) - return record.Country.IsoCode != "CN" && record.Country.IsoCode != "" + return record.Country.IsoCode != "CN" && !ip.IsPrivate() } type ipnetFilter struct { diff --git a/go.mod b/go.mod index 28e4d44ba..34915dd7a 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/Dreamacro/clash -go 1.16 +go 1.17 require ( github.com/Dreamacro/go-shadowsocks2 v0.1.7 @@ -13,10 +13,18 @@ require ( github.com/oschwald/geoip2-golang v1.5.0 github.com/sirupsen/logrus v1.8.1 github.com/stretchr/testify v1.7.0 - go.uber.org/atomic v1.8.0 - golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e - golang.org/x/net v0.0.0-20210614182718-04defd469f4e + go.uber.org/atomic v1.9.0 + golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 + golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d golang.org/x/sync v0.0.0-20210220032951-036812b2e83c - golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c + golang.org/x/sys v0.0.0-20210817190340-bfb29a6856f2 gopkg.in/yaml.v2 v2.4.0 ) + +require ( + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/oschwald/maxminddb-golang v1.8.0 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + golang.org/x/text v0.3.6 // indirect + gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect +) diff --git a/go.sum b/go.sum index fa37dc3be..2c433ac0a 100644 --- a/go.sum +++ b/go.sum @@ -29,14 +29,14 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -go.uber.org/atomic v1.8.0 h1:CUhrE4N1rqSE6FM9ecihEjRkLQu8cDfgDyoOs83mEY4= -go.uber.org/atomic v1.8.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= +go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= golang.org/x/crypto v0.0.0-20210317152858-513c2a44f670/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= -golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e h1:gsTQYXdTw2Gq7RBsWvlQ91b+aEQ6bXFUngBGuR8sPpI= -golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 h1:HWj/xjIHfjYU5nVXpTM0s39J9CbLn7Cc5a7IC5rwsMQ= +golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210614182718-04defd469f4e h1:XpT3nA5TvE525Ne3hInMh6+GETgn27Zfm9dxsThnX2Q= -golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d h1:LO7XpTYMwTqxjLcGWPijK3vRXg1aWdlNOVOHRq45d7c= +golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -45,8 +45,8 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c h1:F1jZWGFhYfh0Ci55sIpILtKKK8p3i2/krTr0H1rg74I= -golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210817190340-bfb29a6856f2 h1:c8PlLMqBbOHoqtjteWm5/kbe6rNY2pbRfbIMVnepueo= +golang.org/x/sys v0.0.0-20210817190340-bfb29a6856f2/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= diff --git a/listener/redir/tcp_linux_other.go b/listener/redir/tcp_linux_other.go index 95472823c..3299843d0 100644 --- a/listener/redir/tcp_linux_other.go +++ b/listener/redir/tcp_linux_other.go @@ -1,3 +1,4 @@ +//go:build linux && !386 // +build linux,!386 package redir diff --git a/listener/redir/tcp_other.go b/listener/redir/tcp_other.go index 50968e9ab..592e9584f 100644 --- a/listener/redir/tcp_other.go +++ b/listener/redir/tcp_other.go @@ -1,3 +1,4 @@ +//go:build !darwin && !linux && !freebsd // +build !darwin,!linux,!freebsd package redir diff --git a/listener/tproxy/setsockopt_linux.go b/listener/tproxy/setsockopt_linux.go index a70223f7f..1e92db128 100644 --- a/listener/tproxy/setsockopt_linux.go +++ b/listener/tproxy/setsockopt_linux.go @@ -1,3 +1,4 @@ +//go:build linux // +build linux package tproxy diff --git a/listener/tproxy/setsockopt_other.go b/listener/tproxy/setsockopt_other.go index 059477284..24fb7c7b4 100644 --- a/listener/tproxy/setsockopt_other.go +++ b/listener/tproxy/setsockopt_other.go @@ -1,3 +1,4 @@ +//go:build !linux // +build !linux package tproxy diff --git a/listener/tproxy/udp_linux.go b/listener/tproxy/udp_linux.go index 40c177e7e..f68ce8f1f 100644 --- a/listener/tproxy/udp_linux.go +++ b/listener/tproxy/udp_linux.go @@ -1,3 +1,4 @@ +//go:build linux // +build linux package tproxy diff --git a/listener/tproxy/udp_other.go b/listener/tproxy/udp_other.go index a4531b5d0..f899fc3d2 100644 --- a/listener/tproxy/udp_other.go +++ b/listener/tproxy/udp_other.go @@ -1,3 +1,4 @@ +//go:build !linux // +build !linux package tproxy diff --git a/rule/geoip.go b/rule/geoip.go index be4b5029f..0b94c4c28 100644 --- a/rule/geoip.go +++ b/rule/geoip.go @@ -20,6 +20,10 @@ func (g *GEOIP) Match(metadata *C.Metadata) bool { if ip == nil { return false } + + if g.country == "LAN" { + return ip.IsPrivate() + } record, _ := mmdb.Instance().Country(ip) return record.Country.IsoCode == g.country } From 426ca361186950940c62af4b27f284c2ac3d6857 Mon Sep 17 00:00:00 2001 From: Dreamacro <8615343+Dreamacro@users.noreply.github.com> Date: Wed, 18 Aug 2021 13:31:34 +0800 Subject: [PATCH 40/96] Chore: upgrade test package --- test/go.mod | 33 ++++++++++++++++++++++++++++++--- test/go.sum | 7 ++++--- 2 files changed, 34 insertions(+), 6 deletions(-) diff --git a/test/go.mod b/test/go.mod index 88db62292..8ee679f4d 100644 --- a/test/go.mod +++ b/test/go.mod @@ -1,19 +1,46 @@ module clash-test -go 1.16 +go 1.17 require ( github.com/Dreamacro/clash v1.6.5 github.com/Microsoft/go-winio v0.5.0 // indirect github.com/containerd/containerd v1.5.3 // indirect - github.com/docker/docker v20.10.7+incompatible + github.com/docker/docker v20.10.8+incompatible github.com/docker/go-connections v0.4.0 github.com/gorilla/mux v1.8.0 // indirect github.com/miekg/dns v1.1.43 github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 // indirect github.com/morikuni/aec v1.0.0 // indirect github.com/stretchr/testify v1.7.0 - golang.org/x/net v0.0.0-20210614182718-04defd469f4e + golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d golang.org/x/time v0.0.0-20210611083556-38a9dc6acbc6 // indirect google.golang.org/grpc v1.39.0 // indirect ) + +require ( + github.com/Dreamacro/go-shadowsocks2 v0.1.7 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/docker/distribution v2.7.1+incompatible // indirect + github.com/docker/go-units v0.4.0 // indirect + github.com/gofrs/uuid v4.0.0+incompatible // indirect + github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang/protobuf v1.4.3 // indirect + github.com/gorilla/websocket v1.4.2 // indirect + github.com/opencontainers/go-digest v1.0.0 // indirect + github.com/opencontainers/image-spec v1.0.1 // indirect + github.com/oschwald/geoip2-golang v1.5.0 // indirect + github.com/oschwald/maxminddb-golang v1.8.0 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/sirupsen/logrus v1.8.1 // indirect + go.uber.org/atomic v1.8.0 // indirect + golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e // indirect + golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect + golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c // indirect + golang.org/x/text v0.3.6 // indirect + google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a // indirect + google.golang.org/protobuf v1.25.0 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect + gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect +) diff --git a/test/go.sum b/test/go.sum index 0b460241b..e97659260 100644 --- a/test/go.sum +++ b/test/go.sum @@ -224,8 +224,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+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug= github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/docker v20.10.7+incompatible h1:Z6O9Nhsjv+ayUEeI1IojKbYcsGdgYSNqxe1s2MYzUhQ= -github.com/docker/docker v20.10.7+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v20.10.8+incompatible h1:RVqD337BgQicVCzYrrlhLDWhq6OAD2PJDUg2LsEUvKM= +github.com/docker/docker v20.10.8+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/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= github.com/docker/go-events v0.0.0-20170721190031-9461782956ad/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= @@ -697,8 +697,9 @@ 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-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-20210614182718-04defd469f4e h1:XpT3nA5TvE525Ne3hInMh6+GETgn27Zfm9dxsThnX2Q= golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d h1:LO7XpTYMwTqxjLcGWPijK3vRXg1aWdlNOVOHRq45d7c= +golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/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-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= From 47044ec0d81dc0dc92a2dafc834f2b658177dee8 Mon Sep 17 00:00:00 2001 From: Dreamacro <8615343+Dreamacro@users.noreply.github.com> Date: Wed, 18 Aug 2021 20:20:00 +0800 Subject: [PATCH 41/96] Fix: dependabot alerts --- test/go.mod | 18 +++++++++--------- test/go.sum | 31 ++++++++++++++++++++++--------- 2 files changed, 31 insertions(+), 18 deletions(-) diff --git a/test/go.mod b/test/go.mod index 8ee679f4d..f096b468d 100644 --- a/test/go.mod +++ b/test/go.mod @@ -4,29 +4,27 @@ go 1.17 require ( github.com/Dreamacro/clash v1.6.5 - github.com/Microsoft/go-winio v0.5.0 // indirect - github.com/containerd/containerd v1.5.3 // indirect github.com/docker/docker v20.10.8+incompatible github.com/docker/go-connections v0.4.0 - github.com/gorilla/mux v1.8.0 // indirect github.com/miekg/dns v1.1.43 - github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 // indirect - github.com/morikuni/aec v1.0.0 // indirect github.com/stretchr/testify v1.7.0 golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d - golang.org/x/time v0.0.0-20210611083556-38a9dc6acbc6 // indirect - google.golang.org/grpc v1.39.0 // indirect ) require ( github.com/Dreamacro/go-shadowsocks2 v0.1.7 // indirect + github.com/Microsoft/go-winio v0.5.0 // indirect + github.com/containerd/containerd v1.5.5 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/docker/distribution v2.7.1+incompatible // indirect github.com/docker/go-units v0.4.0 // indirect github.com/gofrs/uuid v4.0.0+incompatible // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang/protobuf v1.4.3 // indirect + github.com/golang/protobuf v1.5.0 // indirect + github.com/gorilla/mux v1.8.0 // indirect github.com/gorilla/websocket v1.4.2 // indirect + github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 // indirect + github.com/morikuni/aec v1.0.0 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.0.1 // indirect github.com/oschwald/geoip2-golang v1.5.0 // indirect @@ -39,8 +37,10 @@ require ( golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c // indirect golang.org/x/text v0.3.6 // indirect + golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a // indirect - google.golang.org/protobuf v1.25.0 // indirect + google.golang.org/grpc v1.40.0 // indirect + google.golang.org/protobuf v1.26.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect ) diff --git a/test/go.sum b/test/go.sum index e97659260..e6b3582ea 100644 --- a/test/go.sum +++ b/test/go.sum @@ -82,6 +82,7 @@ github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+Ce github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA= +github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA= github.com/blang/semver v3.1.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= @@ -94,6 +95,7 @@ github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA 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/checkpoint-restore/go-criu/v4 v4.1.0/go.mod h1:xUQBLp4RLc5zJtWY++yjOoMoB5lihDt7fai+75m+rGw= +github.com/checkpoint-restore/go-criu/v5 v5.0.0/go.mod h1:cfwC0EG7HMUenopBsUf9d89JlCLQIfgVcNsNN0t6T2M= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= @@ -101,6 +103,7 @@ github.com/cilium/ebpf v0.0.0-20200110133405-4032b1d8aae3/go.mod h1:MA5e5Lr8slmE github.com/cilium/ebpf v0.0.0-20200702112145-1c8d4c9ef775/go.mod h1:7cR51M8ViRLIdUjrmSXlK9pkrsDlLHbO8jiB8X8JnOc= github.com/cilium/ebpf v0.2.0/go.mod h1:To2CFviqOWL/M0gIMsvSMlqe7em/l1ALkX1PyjrX2Qs= github.com/cilium/ebpf v0.4.0/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs= +github.com/cilium/ebpf v0.6.2/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= @@ -138,8 +141,8 @@ github.com/containerd/containerd v1.5.0-beta.3/go.mod h1:/wr9AVtEM7x9c+n0+stptlo 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.1/go.mod h1:0DOxVqwDy2iZvrZp2JUx/E+hS0UNTVn7dJnIOwtYR4g= -github.com/containerd/containerd v1.5.3 h1:mfKOepNDIJ3EiBTEyHFpEqB6YSOSkGcjPDIu7cD+YzY= -github.com/containerd/containerd v1.5.3/go.mod h1:sx18RgvW6ABJ4iYUw7Q5x7bgFOAB9B6G7+yO0XBc4zw= +github.com/containerd/containerd v1.5.5 h1:q1gxsZsGZ8ddVe98yO6pR21b5xQSMiR61lD0W96pgQo= +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-20190815185530-f2a389ac0a02/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= github.com/containerd/continuity v0.0.0-20191127005431-f65d91d395eb/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= @@ -201,6 +204,7 @@ github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7 github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd/v22 v22.0.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= github.com/coreos/go-systemd/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= +github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= @@ -283,6 +287,7 @@ github.com/godbus/dbus v0.0.0-20151105175453-c7fdd8b5cd55/go.mod h1:/YcGZj5zSblf github.com/godbus/dbus v0.0.0-20180201030542-885f9cc04c9c/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw= github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= 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/gofrs/uuid v4.0.0+incompatible h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPhW6m+TnJw= github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gogo/googleapis v1.2.0/go.mod h1:Njal3psf3qN6dwBtQfUmBZh2ybovJ0tlu3o/AC7HYjU= @@ -318,8 +323,9 @@ github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:W github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0 h1:LUVKkCeviFUMKqHa4tXIIij/lbhnMbP7Fn5wKdKkRh4= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= @@ -329,8 +335,9 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.4 h1:L8R9j+yAqZuZjsqh/z+F1NCffTKKLShY6zXTItVIZ8M= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= @@ -472,14 +479,17 @@ github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59P 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-rc93/go.mod h1:3NOsor4w32B2tC0Zbl8Knk4Wg84SM2ImC1fxBuqJ/H0= +github.com/opencontainers/runc v1.0.1/go.mod h1:aTaHFFwQXuA71CiyxOdFFIorAoemI04suvGRQFzWTD0= github.com/opencontainers/runtime-spec v0.1.2-0.20190507144316-5b71a03e2700/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/runtime-spec 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/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/runtime-spec v1.0.3-0.20200929063507-e6143ca7d51d/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/runtime-tools v0.0.0-20181011054405-1d69bd0f9c39/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs= github.com/opencontainers/selinux v1.6.0/go.mod h1:VVGKuOLlE7v4PJyT6h7mNWvq1rzqiriPsEqVhc+svHE= github.com/opencontainers/selinux v1.8.0/go.mod h1:RScLhm78qiWa2gbVCcGkC7tCGdgk3ogry1nUQF8Evvo= +github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8= github.com/oschwald/geoip2-golang v1.5.0 h1:igg2yQIrrcRccB1ytFXqBfOHCjXWIoMv85lVJ1ONZzw= github.com/oschwald/geoip2-golang v1.5.0/go.mod h1:xdvYt5xQzB8ORWFqPnqMwZpCpgNagttWdoZLlJQzg7s= github.com/oschwald/maxminddb-golang v1.8.0 h1:Uh/DSnGoxsyp/KYbY1AuP0tYEwfs0sCph9p/UMXK/Hk= @@ -778,6 +788,7 @@ golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7w 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-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c h1:F1jZWGFhYfh0Ci55sIpILtKKK8p3i2/krTr0H1rg74I= @@ -796,8 +807,8 @@ golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxb 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-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20210611083556-38a9dc6acbc6 h1:Vv0JUPWTyeqUq42B2WJ1FeIDjjvGKoA2Ss+Ts0lAVbs= -golang.org/x/time v0.0.0-20210611083556-38a9dc6acbc6/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac h1:7zkz7BUtwNFFqcowJ+RIgu2MaV/MapERkDIy+mwPyjs= +golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-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-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -897,8 +908,8 @@ google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.39.0 h1:Klz8I9kdtkIN6EpHHUOMLCYhTn/2WAe5a0s1hcBkdTI= -google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= +google.golang.org/grpc v1.40.0 h1:AGJ0Ih4mHjSeibYkFGh1dD9KJ/eOtZ93I6hoHhukQ5Q= +google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -908,8 +919,10 @@ google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2 google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= -google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= From 847f41952e97996bc5f4358a2df2ec8a1e4a8739 Mon Sep 17 00:00:00 2001 From: Dreamacro <8615343+Dreamacro@users.noreply.github.com> Date: Thu, 19 Aug 2021 22:11:56 +0800 Subject: [PATCH 42/96] Fix: grpc transport path should not escape --- test/config/vmess-grpc.json | 2 +- test/vmess_test.go | 2 +- transport/gun/gun.go | 2 ++ 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/test/config/vmess-grpc.json b/test/config/vmess-grpc.json index 1b3a8e9a7..22e117634 100644 --- a/test/config/vmess-grpc.json +++ b/test/config/vmess-grpc.json @@ -24,7 +24,7 @@ ] }, "grpcSettings": { - "serviceName": "example" + "serviceName": "example!" } } } diff --git a/test/vmess_test.go b/test/vmess_test.go index de3b2ba6a..7791abee8 100644 --- a/test/vmess_test.go +++ b/test/vmess_test.go @@ -335,7 +335,7 @@ func TestClash_VmessGrpc(t *testing.T) { UDP: true, ServerName: "example.org", GrpcOpts: outbound.GrpcOptions{ - GrpcServiceName: "example", + GrpcServiceName: "example!", }, }) if err != nil { diff --git a/transport/gun/gun.go b/transport/gun/gun.go index f19006adf..3f97121f8 100644 --- a/transport/gun/gun.go +++ b/transport/gun/gun.go @@ -211,6 +211,8 @@ func StreamGunWithTransport(transport *http2.Transport, cfg *Config) (net.Conn, Scheme: "https", Host: cfg.Host, Path: fmt.Sprintf("/%s/Tun", serviceName), + // for unescape path + Opaque: fmt.Sprintf("//%s/%s/Tun", cfg.Host, serviceName), }, Proto: "HTTP/2", ProtoMajor: 2, From c6d375eda257d6617d57ed9b7eb8c5e72f88981c Mon Sep 17 00:00:00 2001 From: Digital Pencil Date: Fri, 20 Aug 2021 23:38:47 +0800 Subject: [PATCH 43/96] Fix: HTTP proxy internal linkage signature (#1555) --- listener/http/hack.go | 2 +- listener/http/proxy.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/listener/http/hack.go b/listener/http/hack.go index 14a725383..c33eb6f1b 100644 --- a/listener/http/hack.go +++ b/listener/http/hack.go @@ -7,4 +7,4 @@ import ( ) //go:linkname ReadRequest net/http.readRequest -func ReadRequest(b *bufio.Reader, deleteHostHeader bool) (req *http.Request, err error) +func ReadRequest(b *bufio.Reader) (req *http.Request, err error) diff --git a/listener/http/proxy.go b/listener/http/proxy.go index 9ac95cb49..449658cac 100644 --- a/listener/http/proxy.go +++ b/listener/http/proxy.go @@ -24,7 +24,7 @@ func HandleConn(c net.Conn, in chan<- C.ConnContext, cache *cache.Cache) { trusted := cache == nil // disable authenticate if cache is nil for keepAlive { - request, err := ReadRequest(conn.Reader(), false) + request, err := ReadRequest(conn.Reader()) if err != nil { break } From 0267b2efad9a6b0f447efde20589e124ad369a15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A7=8B=E3=81=AE=E3=81=8B=E3=81=88=E3=81=A7?= Date: Sun, 22 Aug 2021 00:25:29 +0800 Subject: [PATCH 44/96] Feature: add vmess WebSocket early data (#1505) Co-authored-by: ShinyGwyn <79344143+ShinyGwyn@users.noreply.github.com> --- adapter/outbound/vmess.go | 29 +++++-- transport/vmess/conn.go | 9 +- transport/vmess/websocket.go | 161 +++++++++++++++++++++++++++++++++-- 3 files changed, 181 insertions(+), 18 deletions(-) diff --git a/adapter/outbound/vmess.go b/adapter/outbound/vmess.go index 5ee4abbc3..445b1ef47 100644 --- a/adapter/outbound/vmess.go +++ b/adapter/outbound/vmess.go @@ -43,6 +43,7 @@ type VmessOption struct { HTTPOpts HTTPOptions `proxy:"http-opts,omitempty"` HTTP2Opts HTTP2Options `proxy:"h2-opts,omitempty"` GrpcOpts GrpcOptions `proxy:"grpc-opts,omitempty"` + WSOpts WSOptions `proxy:"ws-opts,omitempty"` WSPath string `proxy:"ws-path,omitempty"` WSHeaders map[string]string `proxy:"ws-headers,omitempty"` SkipCertVerify bool `proxy:"skip-cert-verify,omitempty"` @@ -64,19 +65,35 @@ type GrpcOptions struct { GrpcServiceName string `proxy:"grpc-service-name,omitempty"` } +type WSOptions struct { + Path string `proxy:"path,omitempty"` + Headers map[string]string `proxy:"headers,omitempty"` + MaxEarlyData int `proxy:"max-early-data,omitempty"` + EarlyDataHeaderName string `proxy:"early-data-header-name,omitempty"` +} + // StreamConn implements C.ProxyAdapter func (v *Vmess) StreamConn(c net.Conn, metadata *C.Metadata) (net.Conn, error) { var err error switch v.option.Network { case "ws": - host, port, _ := net.SplitHostPort(v.addr) - wsOpts := &vmess.WebsocketConfig{ - Host: host, - Port: port, - Path: v.option.WSPath, + 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 } - if len(v.option.WSHeaders) != 0 { + host, port, _ := net.SplitHostPort(v.addr) + wsOpts := &vmess.WebsocketConfig{ + Host: host, + Port: port, + Path: v.option.WSOpts.Path, + MaxEarlyData: v.option.WSOpts.MaxEarlyData, + EarlyDataHeaderName: v.option.WSOpts.EarlyDataHeaderName, + } + + if len(v.option.WSOpts.Headers) != 0 { header := http.Header{} for key, value := range v.option.WSHeaders { header.Add(key, value) diff --git a/transport/vmess/conn.go b/transport/vmess/conn.go index e6e57be61..cc3155ee4 100644 --- a/transport/vmess/conn.go +++ b/transport/vmess/conn.go @@ -59,12 +59,12 @@ func (vc *Conn) Read(b []byte) (int, error) { func (vc *Conn) sendRequest() error { timestamp := time.Now() + mbuf := &bytes.Buffer{} + if !vc.isAead { h := hmac.New(md5.New, vc.id.UUID.Bytes()) binary.Write(h, binary.BigEndian, uint64(timestamp.Unix())) - if _, err := vc.Conn.Write(h.Sum(nil)); err != nil { - return err - } + mbuf.Write(h.Sum(nil)) } buf := &bytes.Buffer{} @@ -110,7 +110,8 @@ func (vc *Conn) sendRequest() error { stream := cipher.NewCFBEncrypter(block, hashTimestamp(timestamp)) stream.XORKeyStream(buf.Bytes(), buf.Bytes()) - _, err = vc.Conn.Write(buf.Bytes()) + mbuf.Write(buf.Bytes()) + _, err = vc.Conn.Write(mbuf.Bytes()) return err } diff --git a/transport/vmess/websocket.go b/transport/vmess/websocket.go index 6ed353e76..956b6d957 100644 --- a/transport/vmess/websocket.go +++ b/transport/vmess/websocket.go @@ -1,7 +1,11 @@ package vmess import ( + "bytes" + "context" "crypto/tls" + "encoding/base64" + "errors" "fmt" "io" "net" @@ -23,15 +27,26 @@ type websocketConn struct { rMux sync.Mutex wMux sync.Mutex } +type websocketWithEarlyDataConn struct { + net.Conn + underlay net.Conn + closed bool + dialed chan bool + cancel context.CancelFunc + ctx context.Context + config *WebsocketConfig +} type WebsocketConfig struct { - Host string - Port string - Path string - Headers http.Header - TLS bool - SkipCertVerify bool - ServerName string + Host string + Port string + Path string + Headers http.Header + TLS bool + SkipCertVerify bool + ServerName string + MaxEarlyData int + EarlyDataHeaderName string } // Read implements net.Conn.Read() @@ -113,7 +128,121 @@ func (wsc *websocketConn) SetWriteDeadline(t time.Time) error { return wsc.conn.SetWriteDeadline(t) } -func StreamWebsocketConn(conn net.Conn, c *WebsocketConfig) (net.Conn, error) { +func (wsedc *websocketWithEarlyDataConn) Dial(earlyData []byte) error { + earlyDataBuf := bytes.NewBuffer(nil) + base64EarlyDataEncoder := base64.NewEncoder(base64.RawURLEncoding, earlyDataBuf) + + earlydata := bytes.NewReader(earlyData) + limitedEarlyDatareader := io.LimitReader(earlydata, int64(wsedc.config.MaxEarlyData)) + n, encerr := io.Copy(base64EarlyDataEncoder, limitedEarlyDatareader) + if encerr != nil { + return errors.New("failed to encode early data: " + encerr.Error()) + } + + if errc := base64EarlyDataEncoder.Close(); errc != nil { + return errors.New("failed to encode early data tail: " + errc.Error()) + } + + var err error + if wsedc.Conn, err = streamWebsocketConn(wsedc.underlay, wsedc.config, earlyDataBuf); err != nil { + wsedc.Close() + return errors.New("failed to dial WebSocket: " + err.Error()) + } + + wsedc.dialed <- true + + if n != int64(len(earlyData)) { + _, err = wsedc.Conn.Write(earlyData[n:]) + } + + return err +} + +func (wsedc *websocketWithEarlyDataConn) Write(b []byte) (int, error) { + if wsedc.closed { + return 0, io.ErrClosedPipe + } + if wsedc.Conn == nil { + if err := wsedc.Dial(b); err != nil { + return 0, err + } + return len(b), nil + } + + return wsedc.Conn.Write(b) +} + +func (wsedc *websocketWithEarlyDataConn) Read(b []byte) (int, error) { + if wsedc.closed { + return 0, io.ErrClosedPipe + } + if wsedc.Conn == nil { + select { + case <-wsedc.ctx.Done(): + return 0, io.ErrUnexpectedEOF + case <-wsedc.dialed: + } + } + return wsedc.Conn.Read(b) +} + +func (wsedc *websocketWithEarlyDataConn) Close() error { + wsedc.closed = true + wsedc.cancel() + if wsedc.Conn == nil { + return nil + } + return wsedc.Conn.Close() +} + +func (wsedc *websocketWithEarlyDataConn) LocalAddr() net.Addr { + if wsedc.Conn == nil { + return wsedc.underlay.LocalAddr() + } + return wsedc.Conn.LocalAddr() +} + +func (wsedc *websocketWithEarlyDataConn) RemoteAddr() net.Addr { + if wsedc.Conn == nil { + return wsedc.underlay.RemoteAddr() + } + return wsedc.Conn.RemoteAddr() +} + +func (wsedc *websocketWithEarlyDataConn) SetDeadline(t time.Time) error { + if err := wsedc.SetReadDeadline(t); err != nil { + return err + } + return wsedc.SetWriteDeadline(t) +} + +func (wsedc *websocketWithEarlyDataConn) SetReadDeadline(t time.Time) error { + if wsedc.Conn == nil { + return nil + } + return wsedc.Conn.SetReadDeadline(t) +} + +func (wsedc *websocketWithEarlyDataConn) SetWriteDeadline(t time.Time) error { + if wsedc.Conn == nil { + return nil + } + return wsedc.Conn.SetWriteDeadline(t) +} + +func streamWebsocketWithEarlyDataConn(conn net.Conn, c *WebsocketConfig) (net.Conn, error) { + ctx, cancel := context.WithCancel(context.Background()) + conn = &websocketWithEarlyDataConn{ + dialed: make(chan bool, 1), + cancel: cancel, + ctx: ctx, + underlay: conn, + config: c, + } + return conn, nil +} + +func streamWebsocketConn(conn net.Conn, c *WebsocketConfig, earlyData *bytes.Buffer) (net.Conn, error) { dialer := &websocket.Dialer{ NetDial: func(network, addr string) (net.Conn, error) { return conn, nil @@ -152,6 +281,14 @@ func StreamWebsocketConn(conn net.Conn, c *WebsocketConfig) (net.Conn, error) { } } + if earlyData != nil { + if c.EarlyDataHeaderName == "" { + uri.Path += earlyData.String() + } else { + headers.Set(c.EarlyDataHeaderName, earlyData.String()) + } + } + wsConn, resp, err := dialer.Dial(uri.String(), headers) if err != nil { reason := err.Error() @@ -166,3 +303,11 @@ func StreamWebsocketConn(conn net.Conn, c *WebsocketConfig) (net.Conn, error) { remoteAddr: conn.RemoteAddr(), }, nil } + +func StreamWebsocketConn(conn net.Conn, c *WebsocketConfig) (net.Conn, error) { + if c.MaxEarlyData > 0 { + return streamWebsocketWithEarlyDataConn(conn, c) + } + + return streamWebsocketConn(conn, c, nil) +} From 410772e81c1c2f212616d367bd0e25e2ec1508a8 Mon Sep 17 00:00:00 2001 From: Dreamacro <8615343+Dreamacro@users.noreply.github.com> Date: Sun, 22 Aug 2021 01:17:29 +0800 Subject: [PATCH 45/96] Test: add vmess ws 0-rtt test --- test/config/vmess-ws-0rtt.json | 30 +++++++++++++++++++++++++ test/go.mod | 8 +++---- test/go.sum | 17 +++++++------- test/vmess_test.go | 41 ++++++++++++++++++++++++++++++++++ 4 files changed, 83 insertions(+), 13 deletions(-) create mode 100644 test/config/vmess-ws-0rtt.json diff --git a/test/config/vmess-ws-0rtt.json b/test/config/vmess-ws-0rtt.json new file mode 100644 index 000000000..7e2876d0c --- /dev/null +++ b/test/config/vmess-ws-0rtt.json @@ -0,0 +1,30 @@ +{ + "inbounds": [ + { + "port": 10002, + "listen": "0.0.0.0", + "protocol": "vmess", + "settings": { + "clients": [ + { + "id": "b831381d-6324-4d53-ad4f-8cda48b30811", + "alterId": 32 + } + ] + }, + "streamSettings": { + "network": "ws", + "security": "none", + "wsSettings": { + "maxEarlyData": 128, + "earlyDataHeaderName": "Sec-WebSocket-Protocol" + } + } + } + ], + "outbounds": [ + { + "protocol": "freedom" + } + ] +} \ No newline at end of file diff --git a/test/go.mod b/test/go.mod index f096b468d..5d86eda93 100644 --- a/test/go.mod +++ b/test/go.mod @@ -3,7 +3,7 @@ module clash-test go 1.17 require ( - github.com/Dreamacro/clash v1.6.5 + github.com/Dreamacro/clash v1.6.6-0.20210821162529-0267b2efad9a github.com/docker/docker v20.10.8+incompatible github.com/docker/go-connections v0.4.0 github.com/miekg/dns v1.1.43 @@ -32,10 +32,10 @@ require ( github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/sirupsen/logrus v1.8.1 // indirect - go.uber.org/atomic v1.8.0 // indirect - golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e // indirect + go.uber.org/atomic v1.9.0 // indirect + golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 // indirect golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect - golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c // indirect + golang.org/x/sys v0.0.0-20210817190340-bfb29a6856f2 // indirect golang.org/x/text v0.3.6 // indirect golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a // indirect diff --git a/test/go.sum b/test/go.sum index e6b3582ea..e83047937 100644 --- a/test/go.sum +++ b/test/go.sum @@ -38,8 +38,8 @@ github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZ github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/Dreamacro/clash v1.6.5 h1:bO8MJpfDOqZsgiK32x2xe9fjniujqVabQOWEYAg5Rac= -github.com/Dreamacro/clash v1.6.5/go.mod h1:AqwqYq0ibcW8j14Re3/uY0bido9PzAuME7Dj+7zst/o= +github.com/Dreamacro/clash v1.6.6-0.20210821162529-0267b2efad9a h1:Y+EWU18ZaK9ZxcZGv2O3nUzGk3XYLZe2r5i8FMku7wA= +github.com/Dreamacro/clash v1.6.6-0.20210821162529-0267b2efad9a/go.mod h1:eN07P85tFwbnkHnEQPYlFsyTc8spXBNa4fOFUea6F58= github.com/Dreamacro/go-shadowsocks2 v0.1.7 h1:8CtbE1HoPPMfrQZGXmlluq6dO2lL31W6WRRE8fabc4Q= github.com/Dreamacro/go-shadowsocks2 v0.1.7/go.mod h1:8p5G4cAj5ZlXwUR+Ww63gfSikr8kvw8uw3TDwLAJpUc= github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA= @@ -622,8 +622,8 @@ go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/atomic v1.8.0 h1:CUhrE4N1rqSE6FM9ecihEjRkLQu8cDfgDyoOs83mEY4= -go.uber.org/atomic v1.8.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= +go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= golang.org/x/crypto v0.0.0-20171113213409-9f005a07e0d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -640,8 +640,8 @@ 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-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-20210616213533-5ff15b29337e h1:gsTQYXdTw2Gq7RBsWvlQ91b+aEQ6bXFUngBGuR8sPpI= -golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 h1:HWj/xjIHfjYU5nVXpTM0s39J9CbLn7Cc5a7IC5rwsMQ= +golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -707,7 +707,6 @@ 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-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-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d h1:LO7XpTYMwTqxjLcGWPijK3vRXg1aWdlNOVOHRq45d7c= golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -791,8 +790,8 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c h1:F1jZWGFhYfh0Ci55sIpILtKKK8p3i2/krTr0H1rg74I= -golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210817190340-bfb29a6856f2 h1:c8PlLMqBbOHoqtjteWm5/kbe6rNY2pbRfbIMVnepueo= +golang.org/x/sys v0.0.0-20210817190340-bfb29a6856f2/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= diff --git a/test/vmess_test.go b/test/vmess_test.go index 7791abee8..6070354af 100644 --- a/test/vmess_test.go +++ b/test/vmess_test.go @@ -346,6 +346,47 @@ func TestClash_VmessGrpc(t *testing.T) { testSuit(t, proxy) } +func TestClash_VmessWebsocket0RTT(t *testing.T) { + cfg := &container.Config{ + Image: ImageXray, + ExposedPorts: defaultExposedPorts, + } + hostCfg := &container.HostConfig{ + PortBindings: defaultPortBindings, + Binds: []string{ + fmt.Sprintf("%s:/etc/xray/config.json", C.Path.Resolve("vmess-ws-0rtt.json")), + }, + } + + id, err := startContainer(cfg, hostCfg, "vmess-ws-0rtt") + if err != nil { + assert.FailNow(t, err.Error()) + } + defer cleanContainer(id) + + proxy, err := outbound.NewVmess(outbound.VmessOption{ + Name: "vmess", + Server: localIP.String(), + Port: 10002, + UUID: "b831381d-6324-4d53-ad4f-8cda48b30811", + Cipher: "auto", + AlterID: 32, + Network: "ws", + UDP: true, + ServerName: "example.org", + WSOpts: outbound.WSOptions{ + MaxEarlyData: 2048, + EarlyDataHeaderName: "Sec-WebSocket-Protocol", + }, + }) + if err != nil { + assert.FailNow(t, err.Error()) + } + + time.Sleep(waitTime) + testSuit(t, proxy) +} + func Benchmark_Vmess(b *testing.B) { configPath := C.Path.Resolve("vmess-aead.json") From 4522cdc55170b85d5ed185244e01492296ef5d4f Mon Sep 17 00:00:00 2001 From: wwqgtxx Date: Sun, 22 Aug 2021 16:03:46 +0800 Subject: [PATCH 46/96] Feature: support xray's ws-0rtt path (#1558) --- transport/vmess/websocket.go | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/transport/vmess/websocket.go b/transport/vmess/websocket.go index 956b6d957..7d7a75bb5 100644 --- a/transport/vmess/websocket.go +++ b/transport/vmess/websocket.go @@ -11,6 +11,7 @@ import ( "net" "net/http" "net/url" + "strconv" "strings" "sync" "time" @@ -305,6 +306,18 @@ func streamWebsocketConn(conn net.Conn, c *WebsocketConfig, earlyData *bytes.Buf } func StreamWebsocketConn(conn net.Conn, c *WebsocketConfig) (net.Conn, error) { + if u, err := url.Parse(c.Path); err == nil { + if q := u.Query(); q.Get("ed") != "" { + if ed, err := strconv.Atoi(q.Get("ed")); err == nil { + c.MaxEarlyData = ed + c.EarlyDataHeaderName = "Sec-WebSocket-Protocol" + q.Del("ed") + u.RawQuery = q.Encode() + c.Path = u.String() + } + } + } + if c.MaxEarlyData > 0 { return streamWebsocketWithEarlyDataConn(conn, c) } From 121bc910f6e5a5faa38c0e3f87e4eea1f0bd8f1b Mon Sep 17 00:00:00 2001 From: Dreamacro <8615343+Dreamacro@users.noreply.github.com> Date: Sun, 22 Aug 2021 16:16:45 +0800 Subject: [PATCH 47/96] Chore: adjust vmess 0rtt code and split xray test --- test/vmess_test.go | 44 ++++++++++++++++++++++++++++++++++-- transport/vmess/websocket.go | 19 +++++++--------- 2 files changed, 50 insertions(+), 13 deletions(-) diff --git a/test/vmess_test.go b/test/vmess_test.go index 6070354af..b696fcea7 100644 --- a/test/vmess_test.go +++ b/test/vmess_test.go @@ -348,13 +348,13 @@ func TestClash_VmessGrpc(t *testing.T) { func TestClash_VmessWebsocket0RTT(t *testing.T) { cfg := &container.Config{ - Image: ImageXray, + Image: ImageVmess, ExposedPorts: defaultExposedPorts, } hostCfg := &container.HostConfig{ PortBindings: defaultPortBindings, Binds: []string{ - fmt.Sprintf("%s:/etc/xray/config.json", C.Path.Resolve("vmess-ws-0rtt.json")), + fmt.Sprintf("%s:/etc/v2ray/config.json", C.Path.Resolve("vmess-ws-0rtt.json")), }, } @@ -387,6 +387,46 @@ func TestClash_VmessWebsocket0RTT(t *testing.T) { testSuit(t, proxy) } +func TestClash_VmessWebsocketXray0RTT(t *testing.T) { + cfg := &container.Config{ + Image: ImageXray, + ExposedPorts: defaultExposedPorts, + } + hostCfg := &container.HostConfig{ + PortBindings: defaultPortBindings, + Binds: []string{ + fmt.Sprintf("%s:/etc/xray/config.json", C.Path.Resolve("vmess-ws-0rtt.json")), + }, + } + + id, err := startContainer(cfg, hostCfg, "vmess-xray-ws-0rtt") + if err != nil { + assert.FailNow(t, err.Error()) + } + defer cleanContainer(id) + + proxy, err := outbound.NewVmess(outbound.VmessOption{ + Name: "vmess", + Server: localIP.String(), + Port: 10002, + UUID: "b831381d-6324-4d53-ad4f-8cda48b30811", + Cipher: "auto", + AlterID: 32, + Network: "ws", + UDP: true, + ServerName: "example.org", + WSOpts: outbound.WSOptions{ + Path: "/?ed=2048", + }, + }) + if err != nil { + assert.FailNow(t, err.Error()) + } + + time.Sleep(waitTime) + testSuit(t, proxy) +} + func Benchmark_Vmess(b *testing.B) { configPath := C.Path.Resolve("vmess-aead.json") diff --git a/transport/vmess/websocket.go b/transport/vmess/websocket.go index 7d7a75bb5..f00e4c4bf 100644 --- a/transport/vmess/websocket.go +++ b/transport/vmess/websocket.go @@ -130,14 +130,12 @@ func (wsc *websocketConn) SetWriteDeadline(t time.Time) error { } func (wsedc *websocketWithEarlyDataConn) Dial(earlyData []byte) error { - earlyDataBuf := bytes.NewBuffer(nil) - base64EarlyDataEncoder := base64.NewEncoder(base64.RawURLEncoding, earlyDataBuf) + base64DataBuf := &bytes.Buffer{} + base64EarlyDataEncoder := base64.NewEncoder(base64.RawURLEncoding, base64DataBuf) - earlydata := bytes.NewReader(earlyData) - limitedEarlyDatareader := io.LimitReader(earlydata, int64(wsedc.config.MaxEarlyData)) - n, encerr := io.Copy(base64EarlyDataEncoder, limitedEarlyDatareader) - if encerr != nil { - return errors.New("failed to encode early data: " + encerr.Error()) + earlyDataBuf := bytes.NewBuffer(earlyData) + if _, err := base64EarlyDataEncoder.Write(earlyDataBuf.Next(wsedc.config.MaxEarlyData)); err != nil { + return errors.New("failed to encode early data: " + err.Error()) } if errc := base64EarlyDataEncoder.Close(); errc != nil { @@ -145,15 +143,14 @@ func (wsedc *websocketWithEarlyDataConn) Dial(earlyData []byte) error { } var err error - if wsedc.Conn, err = streamWebsocketConn(wsedc.underlay, wsedc.config, earlyDataBuf); err != nil { + if wsedc.Conn, err = streamWebsocketConn(wsedc.underlay, wsedc.config, base64DataBuf); err != nil { wsedc.Close() return errors.New("failed to dial WebSocket: " + err.Error()) } wsedc.dialed <- true - - if n != int64(len(earlyData)) { - _, err = wsedc.Conn.Write(earlyData[n:]) + if earlyDataBuf.Len() != 0 { + _, err = wsedc.Conn.Write(earlyDataBuf.Bytes()) } return err From e0d3f926b752a0f22a8c7b77f6b349819051939c Mon Sep 17 00:00:00 2001 From: Dreamacro <8615343+Dreamacro@users.noreply.github.com> Date: Wed, 25 Aug 2021 15:15:13 +0800 Subject: [PATCH 48/96] Feature: add geoip-code option --- config/config.go | 20 ++++++++++++-------- dns/filters.go | 6 ++++-- dns/resolver.go | 11 +++++++---- hub/executor/executor.go | 7 ++++--- 4 files changed, 27 insertions(+), 17 deletions(-) diff --git a/config/config.go b/config/config.go index a9628192b..dc559ecf5 100644 --- a/config/config.go +++ b/config/config.go @@ -71,9 +71,10 @@ type DNS struct { // FallbackFilter config type FallbackFilter struct { - GeoIP bool `yaml:"geoip"` - IPCIDR []*net.IPNet `yaml:"ipcidr"` - Domain []string `yaml:"domain"` + GeoIP bool `yaml:"geoip"` + GeoIPCode string `yaml:"geoip-code"` + IPCIDR []*net.IPNet `yaml:"ipcidr"` + Domain []string `yaml:"domain"` } // Profile config @@ -113,9 +114,10 @@ type RawDNS struct { } type RawFallbackFilter struct { - GeoIP bool `yaml:"geoip"` - IPCIDR []string `yaml:"ipcidr"` - Domain []string `yaml:"domain"` + GeoIP bool `yaml:"geoip"` + GeoIPCode string `yaml:"geoip-code"` + IPCIDR []string `yaml:"ipcidr"` + Domain []string `yaml:"domain"` } type RawConfig struct { @@ -172,8 +174,9 @@ func UnmarshalRawConfig(buf []byte) (*RawConfig, error) { UseHosts: true, FakeIPRange: "198.18.0.1/16", FallbackFilter: RawFallbackFilter{ - GeoIP: true, - IPCIDR: []string{}, + GeoIP: true, + GeoIPCode: "CN", + IPCIDR: []string{}, }, DefaultNameserver: []string{ "114.114.114.114", @@ -600,6 +603,7 @@ func parseDNS(cfg RawDNS, hosts *trie.DomainTrie) (*DNS, error) { } dnsCfg.FallbackFilter.GeoIP = cfg.FallbackFilter.GeoIP + dnsCfg.FallbackFilter.GeoIPCode = cfg.FallbackFilter.GeoIPCode if fallbackip, err := parseFallbackIPCIDR(cfg.FallbackFilter.IPCIDR); err == nil { dnsCfg.FallbackFilter.IPCIDR = fallbackip } diff --git a/dns/filters.go b/dns/filters.go index a6bc6c544..c9cece05c 100644 --- a/dns/filters.go +++ b/dns/filters.go @@ -11,11 +11,13 @@ type fallbackIPFilter interface { Match(net.IP) bool } -type geoipFilter struct{} +type geoipFilter struct { + code string +} func (gf *geoipFilter) Match(ip net.IP) bool { record, _ := mmdb.Instance().Country(ip) - return record.Country.IsoCode != "CN" && !ip.IsPrivate() + return record.Country.IsoCode != gf.code && !ip.IsPrivate() } type ipnetFilter struct { diff --git a/dns/resolver.go b/dns/resolver.go index 1ca0293ea..56b5e3268 100644 --- a/dns/resolver.go +++ b/dns/resolver.go @@ -302,9 +302,10 @@ type NameServer struct { } type FallbackFilter struct { - GeoIP bool - IPCIDR []*net.IPNet - Domain []string + GeoIP bool + GeoIPCode string + IPCIDR []*net.IPNet + Domain []string } type Config struct { @@ -344,7 +345,9 @@ func NewResolver(config Config) *Resolver { fallbackIPFilters := []fallbackIPFilter{} if config.FallbackFilter.GeoIP { - fallbackIPFilters = append(fallbackIPFilters, &geoipFilter{}) + fallbackIPFilters = append(fallbackIPFilters, &geoipFilter{ + code: config.FallbackFilter.GeoIPCode, + }) } for _, ipnet := range config.FallbackFilter.IPCIDR { fallbackIPFilters = append(fallbackIPFilters, &ipnetFilter{ipnet: ipnet}) diff --git a/hub/executor/executor.go b/hub/executor/executor.go index b3772211f..121e1d01d 100644 --- a/hub/executor/executor.go +++ b/hub/executor/executor.go @@ -123,9 +123,10 @@ func updateDNS(c *config.DNS) { Pool: c.FakeIPRange, Hosts: c.Hosts, FallbackFilter: dns.FallbackFilter{ - GeoIP: c.FallbackFilter.GeoIP, - IPCIDR: c.FallbackFilter.IPCIDR, - Domain: c.FallbackFilter.Domain, + GeoIP: c.FallbackFilter.GeoIP, + GeoIPCode: c.FallbackFilter.GeoIPCode, + IPCIDR: c.FallbackFilter.IPCIDR, + Domain: c.FallbackFilter.Domain, }, Default: c.DefaultNameserver, Policy: c.NameServerPolicy, From a20b9a3960658fb2844e5c52200705f1fc5cb90e Mon Sep 17 00:00:00 2001 From: Loyalsoldier <10487845+Loyalsoldier@users.noreply.github.com> Date: Sun, 29 Aug 2021 22:19:22 +0800 Subject: [PATCH 49/96] Chore: make geoip match case-insensitive (#1574) --- dns/filters.go | 3 ++- rule/geoip.go | 6 ++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/dns/filters.go b/dns/filters.go index c9cece05c..bacd7727f 100644 --- a/dns/filters.go +++ b/dns/filters.go @@ -2,6 +2,7 @@ package dns import ( "net" + "strings" "github.com/Dreamacro/clash/component/mmdb" "github.com/Dreamacro/clash/component/trie" @@ -17,7 +18,7 @@ type geoipFilter struct { func (gf *geoipFilter) Match(ip net.IP) bool { record, _ := mmdb.Instance().Country(ip) - return record.Country.IsoCode != gf.code && !ip.IsPrivate() + return !strings.EqualFold(record.Country.IsoCode, gf.code) && !ip.IsPrivate() } type ipnetFilter struct { diff --git a/rule/geoip.go b/rule/geoip.go index 0b94c4c28..3b6fbe6b8 100644 --- a/rule/geoip.go +++ b/rule/geoip.go @@ -1,6 +1,8 @@ package rules import ( + "strings" + "github.com/Dreamacro/clash/component/mmdb" C "github.com/Dreamacro/clash/constant" ) @@ -21,11 +23,11 @@ func (g *GEOIP) Match(metadata *C.Metadata) bool { return false } - if g.country == "LAN" { + if strings.EqualFold(g.country, "LAN") { return ip.IsPrivate() } record, _ := mmdb.Instance().Country(ip) - return record.Country.IsoCode == g.country + return strings.EqualFold(record.Country.IsoCode, g.country) } func (g *GEOIP) Adapter() string { From 7d20097465fc0e8d91b8a3f2434b471fcc144e3d Mon Sep 17 00:00:00 2001 From: Dreamacro <8615343+Dreamacro@users.noreply.github.com> Date: Mon, 30 Aug 2021 00:15:57 +0800 Subject: [PATCH 50/96] Fix: ssr auth aes128 udp hmac verify --- transport/ssr/protocol/auth_aes128_sha1.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/transport/ssr/protocol/auth_aes128_sha1.go b/transport/ssr/protocol/auth_aes128_sha1.go index 65bcd7416..fab9d0081 100644 --- a/transport/ssr/protocol/auth_aes128_sha1.go +++ b/transport/ssr/protocol/auth_aes128_sha1.go @@ -152,7 +152,7 @@ func (a *authAES128) Encode(buf *bytes.Buffer, b []byte) error { } func (a *authAES128) DecodePacket(b []byte) ([]byte, error) { - if !bytes.Equal(a.hmac(a.Key, b[:len(b)-4])[:4], b[len(b)-4:]) { + if !bytes.Equal(a.hmac(a.userKey, b[:len(b)-4])[:4], b[len(b)-4:]) { return nil, errAuthAES128ChksumError } return b[:len(b)-4], nil From 661c417fceae6fd5f6c9f21a32bbacd6ff528c46 Mon Sep 17 00:00:00 2001 From: Dreamacro <8615343+Dreamacro@users.noreply.github.com> Date: Sat, 4 Sep 2021 22:31:08 +0800 Subject: [PATCH 51/96] Test: use shadowsocks-rust for ss benchmark --- test/clash_test.go | 11 ++++++----- test/ss_test.go | 10 ++++++---- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/test/clash_test.go b/test/clash_test.go index 366cc260b..b31922832 100644 --- a/test/clash_test.go +++ b/test/clash_test.go @@ -27,11 +27,12 @@ import ( ) const ( - ImageShadowsocks = "mritd/shadowsocks:latest" - ImageVmess = "v2fly/v2fly-core:latest" - ImageTrojan = "trojangfw/trojan:latest" - ImageSnell = "icpz/snell-server:latest" - ImageXray = "teddysun/xray:latest" + ImageShadowsocks = "mritd/shadowsocks:latest" + ImageShadowsocksRust = "ghcr.io/shadowsocks/ssserver-rust:latest" + ImageVmess = "v2fly/v2fly-core:latest" + ImageTrojan = "trojangfw/trojan:latest" + ImageSnell = "icpz/snell-server:latest" + ImageXray = "teddysun/xray:latest" ) var ( diff --git a/test/ss_test.go b/test/ss_test.go index 7cba7efd9..446bae938 100644 --- a/test/ss_test.go +++ b/test/ss_test.go @@ -12,8 +12,9 @@ import ( func TestClash_Shadowsocks(t *testing.T) { cfg := &container.Config{ - Image: ImageShadowsocks, - Env: []string{"SS_MODULE=ss-server", "SS_CONFIG=-s 0.0.0.0 -u -v -p 10002 -m chacha20-ietf-poly1305 -k FzcLbKs2dY9mhL"}, + Image: ImageShadowsocksRust, + Entrypoint: []string{"ssserver"}, + Cmd: []string{"-s", "0.0.0.0:10002", "-m", "chacha20-ietf-poly1305", "-k", "FzcLbKs2dY9mhL", "-U"}, ExposedPorts: defaultExposedPorts, } hostCfg := &container.HostConfig{ @@ -173,8 +174,9 @@ func TestClash_ShadowsocksV2RayPlugin(t *testing.T) { func Benchmark_Shadowsocks(b *testing.B) { cfg := &container.Config{ - Image: ImageShadowsocks, - Env: []string{"SS_MODULE=ss-server", "SS_CONFIG=-s 0.0.0.0 -u -v -p 10002 -m aes-256-gcm -k FzcLbKs2dY9mhL"}, + Image: ImageShadowsocksRust, + Entrypoint: []string{"ssserver"}, + Cmd: []string{"-s", "0.0.0.0:10002", "-m", "aes-256-gcm", "-k", "FzcLbKs2dY9mhL", "-U"}, ExposedPorts: defaultExposedPorts, } hostCfg := &container.HostConfig{ From ff56e5c5de10c70dfd8b9c674ed2e322a902baeb Mon Sep 17 00:00:00 2001 From: Dreamacro <8615343+Dreamacro@users.noreply.github.com> Date: Sat, 4 Sep 2021 22:44:18 +0800 Subject: [PATCH 52/96] Test: fix direct listen fail --- test/clash_test.go | 13 +++++++------ test/util.go | 37 +++++++++++++++++++++++++++++++++++++ test/util_other_test.go | 1 + 3 files changed, 45 insertions(+), 6 deletions(-) create mode 100644 test/util.go diff --git a/test/clash_test.go b/test/clash_test.go index b31922832..e6cb14a15 100644 --- a/test/clash_test.go +++ b/test/clash_test.go @@ -210,7 +210,7 @@ func newLargeDataPair() (chan hashPair, chan hashPair, func(t *testing.T) error) func testPingPongWithSocksPort(t *testing.T, port int) { pingCh, pongCh, test := newPingPongPair() go func() { - l, err := net.Listen("tcp", ":10001") + l, err := Listen("tcp", ":10001") if err != nil { assert.FailNow(t, err.Error()) } @@ -259,7 +259,7 @@ func testPingPongWithSocksPort(t *testing.T, port int) { } func testPingPongWithConn(t *testing.T, c net.Conn) error { - l, err := net.Listen("tcp", ":10001") + l, err := Listen("tcp", ":10001") if err != nil { return err } @@ -300,7 +300,7 @@ func testPingPongWithConn(t *testing.T, c net.Conn) error { } func testPingPongWithPacketConn(t *testing.T, pc net.PacketConn) error { - l, err := net.ListenPacket("udp", ":10001") + l, err := ListenPacket("udp", ":10001") if err != nil { return err } @@ -345,7 +345,7 @@ type hashPair struct { } func testLargeDataWithConn(t *testing.T, c net.Conn) error { - l, err := net.Listen("tcp", ":10001") + l, err := Listen("tcp", ":10001") if err != nil { return err } @@ -438,7 +438,7 @@ func testLargeDataWithConn(t *testing.T, c net.Conn) error { } func testLargeDataWithPacketConn(t *testing.T, pc net.PacketConn) error { - l, err := net.ListenPacket("udp", ":10001") + l, err := ListenPacket("udp", ":10001") if err != nil { return err } @@ -622,7 +622,7 @@ func testSuit(t *testing.T, proxy C.ProxyAdapter) { } func benchmarkProxy(b *testing.B, proxy C.ProxyAdapter) { - l, err := net.Listen("tcp", ":10001") + l, err := Listen("tcp", ":10001") if err != nil { assert.FailNow(b, err.Error()) } @@ -639,6 +639,7 @@ func benchmarkProxy(b *testing.B, proxy C.ProxyAdapter) { chunkSize := int64(16 * 1024) chunk := make([]byte, chunkSize) + rand.Read(chunk) conn, err := proxy.DialContext(context.Background(), &C.Metadata{ Host: localIP.String(), DstPort: "10001", diff --git a/test/util.go b/test/util.go new file mode 100644 index 000000000..f3325aeb6 --- /dev/null +++ b/test/util.go @@ -0,0 +1,37 @@ +package main + +import ( + "context" + "net" + "time" +) + +func Listen(network, address string) (net.Listener, error) { + lc := net.ListenConfig{} + + var lastErr error + for i := 0; i < 5; i++ { + l, err := lc.Listen(context.Background(), network, address) + if err == nil { + return l, nil + } + + lastErr = err + time.Sleep(time.Millisecond * 200) + } + return nil, lastErr +} + +func ListenPacket(network, address string) (net.PacketConn, error) { + var lastErr error + for i := 0; i < 5; i++ { + l, err := net.ListenPacket(network, address) + if err == nil { + return l, nil + } + + lastErr = err + time.Sleep(time.Millisecond * 200) + } + return nil, lastErr +} diff --git a/test/util_other_test.go b/test/util_other_test.go index e325bd8ba..13ba87f33 100644 --- a/test/util_other_test.go +++ b/test/util_other_test.go @@ -1,3 +1,4 @@ +//go:build !darwin // +build !darwin package main From c7b718f6512d612e1f342da3c3b7876e6d301a82 Mon Sep 17 00:00:00 2001 From: Dreamacro <8615343+Dreamacro@users.noreply.github.com> Date: Sun, 5 Sep 2021 14:25:55 +0800 Subject: [PATCH 53/96] Test: release resources correctly --- test/clash_test.go | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/test/clash_test.go b/test/clash_test.go index e6cb14a15..4011b04a4 100644 --- a/test/clash_test.go +++ b/test/clash_test.go @@ -214,6 +214,7 @@ func testPingPongWithSocksPort(t *testing.T, port int) { if err != nil { assert.FailNow(t, err.Error()) } + defer l.Close() c, err := l.Accept() if err != nil { @@ -229,7 +230,6 @@ func testPingPongWithSocksPort(t *testing.T, port int) { if _, err := c.Write([]byte("pong")); err != nil { assert.FailNow(t, err.Error()) } - l.Close() }() go func() { @@ -237,6 +237,7 @@ func testPingPongWithSocksPort(t *testing.T, port int) { if err != nil { assert.FailNow(t, err.Error()) } + defer c.Close() if _, err := socks5.ClientHandshake(c, socks5.ParseAddr("127.0.0.1:10001"), socks5.CmdConnect, nil); err != nil { assert.FailNow(t, err.Error()) @@ -252,7 +253,6 @@ func testPingPongWithSocksPort(t *testing.T, port int) { } pongCh <- buf - c.Close() }() test(t) @@ -380,6 +380,7 @@ func testLargeDataWithConn(t *testing.T, c net.Conn) error { if err != nil { return } + defer c.Close() hashMap := map[int][]byte{} buf := make([]byte, chunkSize) @@ -626,15 +627,16 @@ func benchmarkProxy(b *testing.B, proxy C.ProxyAdapter) { if err != nil { assert.FailNow(b, err.Error()) } + defer l.Close() go func() { c, err := l.Accept() if err != nil { assert.FailNow(b, err.Error()) } + defer c.Close() io.Copy(io.Discard, c) - c.Close() }() chunkSize := int64(16 * 1024) From 8ef5cdb8be15e1a5f1c084ea81f83cf166772509 Mon Sep 17 00:00:00 2001 From: Dreamacro <8615343+Dreamacro@users.noreply.github.com> Date: Sun, 5 Sep 2021 14:38:07 +0800 Subject: [PATCH 54/96] Test: use local clash pkg --- test/go.mod | 4 +++- test/go.sum | 2 -- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/test/go.mod b/test/go.mod index 5d86eda93..97d3a79c6 100644 --- a/test/go.mod +++ b/test/go.mod @@ -3,7 +3,7 @@ module clash-test go 1.17 require ( - github.com/Dreamacro/clash v1.6.6-0.20210821162529-0267b2efad9a + github.com/Dreamacro/clash v1.6.6-0.20210905062555-c7b718f6512d github.com/docker/docker v20.10.8+incompatible github.com/docker/go-connections v0.4.0 github.com/miekg/dns v1.1.43 @@ -11,6 +11,8 @@ require ( golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d ) +replace github.com/Dreamacro/clash => ../ + require ( github.com/Dreamacro/go-shadowsocks2 v0.1.7 // indirect github.com/Microsoft/go-winio v0.5.0 // indirect diff --git a/test/go.sum b/test/go.sum index e83047937..c2b68eafd 100644 --- a/test/go.sum +++ b/test/go.sum @@ -38,8 +38,6 @@ github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZ github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/Dreamacro/clash v1.6.6-0.20210821162529-0267b2efad9a h1:Y+EWU18ZaK9ZxcZGv2O3nUzGk3XYLZe2r5i8FMku7wA= -github.com/Dreamacro/clash v1.6.6-0.20210821162529-0267b2efad9a/go.mod h1:eN07P85tFwbnkHnEQPYlFsyTc8spXBNa4fOFUea6F58= github.com/Dreamacro/go-shadowsocks2 v0.1.7 h1:8CtbE1HoPPMfrQZGXmlluq6dO2lL31W6WRRE8fabc4Q= github.com/Dreamacro/go-shadowsocks2 v0.1.7/go.mod h1:8p5G4cAj5ZlXwUR+Ww63gfSikr8kvw8uw3TDwLAJpUc= github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA= From a2d59d6ef540e9e6831e988e6c43e2a3efc6e9ea Mon Sep 17 00:00:00 2001 From: Excited Codes <61885669+ExcitedCodes@users.noreply.github.com> Date: Mon, 6 Sep 2021 21:39:28 +0800 Subject: [PATCH 55/96] Feature: skip DIRECT proxies in relay (#1583) --- adapter/outboundgroup/relay.go | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/adapter/outboundgroup/relay.go b/adapter/outboundgroup/relay.go index 8d8128bac..78410a449 100644 --- a/adapter/outboundgroup/relay.go +++ b/adapter/outboundgroup/relay.go @@ -3,7 +3,6 @@ package outboundgroup import ( "context" "encoding/json" - "errors" "fmt" "github.com/Dreamacro/clash/adapter/outbound" @@ -21,10 +20,20 @@ type Relay struct { // DialContext implements C.ProxyAdapter func (r *Relay) DialContext(ctx context.Context, metadata *C.Metadata) (C.Conn, error) { - proxies := r.proxies(metadata, true) - if len(proxies) == 0 { - return nil, errors.New("proxy does not exist") + var proxies []C.Proxy + for _, proxy := range r.proxies(metadata, true) { + if proxy.Type() != C.Direct { + proxies = append(proxies, proxy) + } } + + switch len(proxies) { + case 0: + return outbound.NewDirect().DialContext(ctx, metadata) + case 1: + return proxies[0].DialContext(ctx, metadata) + } + first := proxies[0] last := proxies[len(proxies)-1] From a5b950a779871ae7045653a242bc7b3906011cdd Mon Sep 17 00:00:00 2001 From: Kr328 Date: Mon, 6 Sep 2021 23:07:34 +0800 Subject: [PATCH 56/96] Feature: add dhcp type dns client (#1509) --- adapter/outbound/direct.go | 2 +- adapter/outbound/shadowsocks.go | 2 +- adapter/outbound/shadowsocksr.go | 2 +- adapter/outbound/socks5.go | 2 +- adapter/provider/vehicle.go | 5 +- component/dhcp/conn.go | 18 ++++ component/dhcp/dhcp.go | 94 +++++++++++++++++++ component/dialer/bind.go | 118 ------------------------ component/dialer/bind_darwin.go | 40 +++++---- component/dialer/bind_linux.go | 26 ++++-- component/dialer/bind_others.go | 89 ++++++++++++++++-- component/dialer/dialer.go | 97 ++++++++++---------- component/dialer/hook.go | 43 --------- component/dialer/options.go | 31 +++++++ component/dialer/reuse_others.go | 10 +++ component/dialer/reuse_unix.go | 28 ++++++ component/dialer/reuse_windows.go | 24 +++++ component/iface/iface.go | 113 +++++++++++++++++++++++ config/config.go | 3 + dns/client.go | 33 ++++--- dns/dhcp.go | 144 ++++++++++++++++++++++++++++++ dns/resolver.go | 35 ++++---- dns/util.go | 6 +- go.mod | 8 +- go.sum | 65 ++++++++++++-- hub/executor/executor.go | 9 +- 26 files changed, 759 insertions(+), 288 deletions(-) create mode 100644 component/dhcp/conn.go create mode 100644 component/dhcp/dhcp.go delete mode 100644 component/dialer/bind.go delete mode 100644 component/dialer/hook.go create mode 100644 component/dialer/options.go create mode 100644 component/dialer/reuse_others.go create mode 100644 component/dialer/reuse_unix.go create mode 100644 component/dialer/reuse_windows.go create mode 100644 component/iface/iface.go create mode 100644 dns/dhcp.go diff --git a/adapter/outbound/direct.go b/adapter/outbound/direct.go index 83ea22eb8..4b53e306c 100644 --- a/adapter/outbound/direct.go +++ b/adapter/outbound/direct.go @@ -24,7 +24,7 @@ func (d *Direct) DialContext(ctx context.Context, metadata *C.Metadata) (C.Conn, // DialUDP implements C.ProxyAdapter func (d *Direct) DialUDP(metadata *C.Metadata) (C.PacketConn, error) { - pc, err := dialer.ListenPacket("udp", "") + pc, err := dialer.ListenPacket(context.Background(), "udp", "") if err != nil { return nil, err } diff --git a/adapter/outbound/shadowsocks.go b/adapter/outbound/shadowsocks.go index 39d1e36d0..64b431a9b 100644 --- a/adapter/outbound/shadowsocks.go +++ b/adapter/outbound/shadowsocks.go @@ -89,7 +89,7 @@ func (ss *ShadowSocks) DialContext(ctx context.Context, metadata *C.Metadata) (_ // DialUDP implements C.ProxyAdapter func (ss *ShadowSocks) DialUDP(metadata *C.Metadata) (C.PacketConn, error) { - pc, err := dialer.ListenPacket("udp", "") + pc, err := dialer.ListenPacket(context.Background(), "udp", "") if err != nil { return nil, err } diff --git a/adapter/outbound/shadowsocksr.go b/adapter/outbound/shadowsocksr.go index b44f46e56..9ba8bc229 100644 --- a/adapter/outbound/shadowsocksr.go +++ b/adapter/outbound/shadowsocksr.go @@ -74,7 +74,7 @@ func (ssr *ShadowSocksR) DialContext(ctx context.Context, metadata *C.Metadata) // DialUDP implements C.ProxyAdapter func (ssr *ShadowSocksR) DialUDP(metadata *C.Metadata) (C.PacketConn, error) { - pc, err := dialer.ListenPacket("udp", "") + pc, err := dialer.ListenPacket(context.Background(), "udp", "") if err != nil { return nil, err } diff --git a/adapter/outbound/socks5.go b/adapter/outbound/socks5.go index 8106e0e2e..1402c6186 100644 --- a/adapter/outbound/socks5.go +++ b/adapter/outbound/socks5.go @@ -110,7 +110,7 @@ func (ss *Socks5) DialUDP(metadata *C.Metadata) (_ C.PacketConn, err error) { return } - pc, err := dialer.ListenPacket("udp", "") + pc, err := dialer.ListenPacket(context.Background(), "udp", "") if err != nil { return } diff --git a/adapter/provider/vehicle.go b/adapter/provider/vehicle.go index ea6a835a2..f556e69c4 100644 --- a/adapter/provider/vehicle.go +++ b/adapter/provider/vehicle.go @@ -3,6 +3,7 @@ package provider import ( "context" "io/ioutil" + "net" "net/http" "net/url" "time" @@ -71,7 +72,9 @@ func (h *HTTPVehicle) Read() ([]byte, error) { IdleConnTimeout: 90 * time.Second, TLSHandshakeTimeout: 10 * time.Second, ExpectContinueTimeout: 1 * time.Second, - DialContext: dialer.DialContext, + DialContext: func(ctx context.Context, network, address string) (net.Conn, error) { + return dialer.DialContext(ctx, network, address) + }, } client := http.Client{Transport: transport} diff --git a/component/dhcp/conn.go b/component/dhcp/conn.go new file mode 100644 index 000000000..90a9e25b5 --- /dev/null +++ b/component/dhcp/conn.go @@ -0,0 +1,18 @@ +package dhcp + +import ( + "context" + "net" + "runtime" + + "github.com/Dreamacro/clash/component/dialer" +) + +func ListenDHCPClient(ctx context.Context, ifaceName string) (net.PacketConn, error) { + listenAddr := "0.0.0.0:68" + if runtime.GOOS == "linux" || runtime.GOOS == "android" { + listenAddr = "255.255.255.255:68" + } + + return dialer.ListenPacket(ctx, "udp4", listenAddr, dialer.WithInterface(ifaceName), dialer.WithAddrReuse(true)) +} diff --git a/component/dhcp/dhcp.go b/component/dhcp/dhcp.go new file mode 100644 index 000000000..b2ca6928f --- /dev/null +++ b/component/dhcp/dhcp.go @@ -0,0 +1,94 @@ +package dhcp + +import ( + "context" + "errors" + "math/rand" + "net" + + "github.com/insomniacslk/dhcp/dhcpv4" +) + +var ( + ErrNotResponding = errors.New("DHCP not responding") + ErrNotFound = errors.New("DNS option not found") +) + +func ResolveDNSFromDHCP(context context.Context, ifaceName string) ([]net.IP, error) { + conn, err := ListenDHCPClient(context, ifaceName) + if err != nil { + return nil, err + } + defer conn.Close() + + result := make(chan []net.IP, 1) + + discovery, err := dhcpv4.NewDiscovery(randomHardware(), dhcpv4.WithBroadcast(true), dhcpv4.WithRequestedOptions(dhcpv4.OptionDomainNameServer)) + if err != nil { + return nil, err + } + + go receiveOffer(conn, discovery.TransactionID, result) + + _, err = conn.WriteTo(discovery.ToBytes(), &net.UDPAddr{IP: net.IPv4bcast, Port: 67}) + if err != nil { + return nil, err + } + + select { + case r, ok := <-result: + if !ok { + return nil, ErrNotFound + } + return r, nil + case <-context.Done(): + return nil, ErrNotResponding + } +} + +func receiveOffer(conn net.PacketConn, id dhcpv4.TransactionID, result chan<- []net.IP) { + defer close(result) + + buf := make([]byte, dhcpv4.MaxMessageSize) + + for { + n, _, err := conn.ReadFrom(buf) + if err != nil { + return + } + + pkt, err := dhcpv4.FromBytes(buf[:n]) + if err != nil { + continue + } + + if pkt.MessageType() != dhcpv4.MessageTypeOffer { + continue + } + + if pkt.TransactionID != id { + continue + } + + dns := pkt.DNS() + if len(dns) == 0 { + return + } + + result <- dns + + return + } +} + +func randomHardware() net.HardwareAddr { + addr := make(net.HardwareAddr, 6) + + addr[0] = 0xff + + for i := 1; i < len(addr); i++ { + addr[i] = byte(rand.Intn(254) + 1) + } + + return addr +} diff --git a/component/dialer/bind.go b/component/dialer/bind.go deleted file mode 100644 index 0ad520683..000000000 --- a/component/dialer/bind.go +++ /dev/null @@ -1,118 +0,0 @@ -package dialer - -import ( - "errors" - "net" - "time" - - "github.com/Dreamacro/clash/common/singledo" -) - -// In some OS, such as Windows, it takes a little longer to get interface information -var ifaceSingle = singledo.NewSingle(time.Second * 20) - -var ( - errPlatformNotSupport = errors.New("unsupport platform") -) - -func lookupTCPAddr(ip net.IP, addrs []net.Addr) (*net.TCPAddr, error) { - ipv4 := ip.To4() != nil - - for _, elm := range addrs { - addr, ok := elm.(*net.IPNet) - if !ok { - continue - } - - addrV4 := addr.IP.To4() != nil - - if addrV4 && ipv4 { - return &net.TCPAddr{IP: addr.IP, Port: 0}, nil - } else if !addrV4 && !ipv4 { - return &net.TCPAddr{IP: addr.IP, Port: 0}, nil - } - } - - return nil, ErrAddrNotFound -} - -func lookupUDPAddr(ip net.IP, addrs []net.Addr) (*net.UDPAddr, error) { - ipv4 := ip.To4() != nil - - for _, elm := range addrs { - addr, ok := elm.(*net.IPNet) - if !ok { - continue - } - - addrV4 := addr.IP.To4() != nil - - if addrV4 && ipv4 { - return &net.UDPAddr{IP: addr.IP, Port: 0}, nil - } else if !addrV4 && !ipv4 { - return &net.UDPAddr{IP: addr.IP, Port: 0}, nil - } - } - - return nil, ErrAddrNotFound -} - -func fallbackBindToDialer(dialer *net.Dialer, network string, ip net.IP, name string) error { - if !ip.IsGlobalUnicast() { - return nil - } - - iface, err, _ := ifaceSingle.Do(func() (interface{}, error) { - return net.InterfaceByName(name) - }) - if err != nil { - return err - } - - addrs, err := iface.(*net.Interface).Addrs() - if err != nil { - return err - } - - switch network { - case "tcp", "tcp4", "tcp6": - if addr, err := lookupTCPAddr(ip, addrs); err == nil { - dialer.LocalAddr = addr - } else { - return err - } - case "udp", "udp4", "udp6": - if addr, err := lookupUDPAddr(ip, addrs); err == nil { - dialer.LocalAddr = addr - } else { - return err - } - } - - return nil -} - -func fallbackBindToListenConfig(name string) (string, error) { - iface, err, _ := ifaceSingle.Do(func() (interface{}, error) { - return net.InterfaceByName(name) - }) - if err != nil { - return "", err - } - - addrs, err := iface.(*net.Interface).Addrs() - if err != nil { - return "", err - } - - for _, elm := range addrs { - addr, ok := elm.(*net.IPNet) - if !ok || addr.IP.To4() == nil { - continue - } - - return net.JoinHostPort(addr.IP.String(), "0"), nil - } - - return "", ErrAddrNotFound -} diff --git a/component/dialer/bind_darwin.go b/component/dialer/bind_darwin.go index 0ce505412..b3ae9d815 100644 --- a/component/dialer/bind_darwin.go +++ b/component/dialer/bind_darwin.go @@ -3,51 +3,57 @@ package dialer import ( "net" "syscall" + + "golang.org/x/sys/unix" + + "github.com/Dreamacro/clash/component/iface" ) type controlFn = func(network, address string, c syscall.RawConn) error -func bindControl(ifaceIdx int) controlFn { - return func(network, address string, c syscall.RawConn) error { +func bindControl(ifaceIdx 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 nil + return } } return c.Control(func(fd uintptr) { switch network { case "tcp4", "udp4": - syscall.SetsockoptInt(int(fd), syscall.IPPROTO_IP, syscall.IP_BOUND_IF, ifaceIdx) + unix.SetsockoptInt(int(fd), unix.IPPROTO_IP, unix.IP_BOUND_IF, ifaceIdx) case "tcp6", "udp6": - syscall.SetsockoptInt(int(fd), syscall.IPPROTO_IPV6, syscall.IPV6_BOUND_IF, ifaceIdx) + unix.SetsockoptInt(int(fd), unix.IPPROTO_IPV6, unix.IPV6_BOUND_IF, ifaceIdx) } }) } } -func bindIfaceToDialer(dialer *net.Dialer, ifaceName string) error { - iface, err, _ := ifaceSingle.Do(func() (interface{}, error) { - return net.InterfaceByName(ifaceName) - }) +func bindIfaceToDialer(ifaceName string, dialer *net.Dialer, _ string, _ net.IP) error { + ifaceObj, err := iface.ResolveInterface(ifaceName) if err != nil { return err } - dialer.Control = bindControl(iface.(*net.Interface).Index) + dialer.Control = bindControl(ifaceObj.Index, dialer.Control) return nil } -func bindIfaceToListenConfig(lc *net.ListenConfig, ifaceName string) error { - iface, err, _ := ifaceSingle.Do(func() (interface{}, error) { - return net.InterfaceByName(ifaceName) - }) +func bindIfaceToListenConfig(ifaceName string, lc *net.ListenConfig, _, address string) (string, error) { + ifaceObj, err := iface.ResolveInterface(ifaceName) if err != nil { - return err + return "", err } - lc.Control = bindControl(iface.(*net.Interface).Index) - return nil + lc.Control = bindControl(ifaceObj.Index, lc.Control) + return address, nil } diff --git a/component/dialer/bind_linux.go b/component/dialer/bind_linux.go index 7e9d308dd..ae772a71e 100644 --- a/component/dialer/bind_linux.go +++ b/component/dialer/bind_linux.go @@ -3,34 +3,42 @@ package dialer import ( "net" "syscall" + + "golang.org/x/sys/unix" ) type controlFn = func(network, address string, c syscall.RawConn) error -func bindControl(ifaceName string) controlFn { - return func(network, address string, c syscall.RawConn) error { +func bindControl(ifaceName string, 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 nil + return } } return c.Control(func(fd uintptr) { - syscall.BindToDevice(int(fd), ifaceName) + unix.BindToDevice(int(fd), ifaceName) }) } } -func bindIfaceToDialer(dialer *net.Dialer, ifaceName string) error { - dialer.Control = bindControl(ifaceName) +func bindIfaceToDialer(ifaceName string, dialer *net.Dialer, _ string, _ net.IP) error { + dialer.Control = bindControl(ifaceName, dialer.Control) return nil } -func bindIfaceToListenConfig(lc *net.ListenConfig, ifaceName string) error { - lc.Control = bindControl(ifaceName) +func bindIfaceToListenConfig(ifaceName string, lc *net.ListenConfig, _, address string) (string, error) { + lc.Control = bindControl(ifaceName, lc.Control) - return nil + return address, nil } diff --git a/component/dialer/bind_others.go b/component/dialer/bind_others.go index e09b5ff84..7f1923aa2 100644 --- a/component/dialer/bind_others.go +++ b/component/dialer/bind_others.go @@ -3,12 +3,91 @@ package dialer -import "net" +import ( + "net" + "strconv" + "strings" -func bindIfaceToDialer(dialer *net.Dialer, ifaceName string) error { - return errPlatformNotSupport + "github.com/Dreamacro/clash/component/iface" +) + +func lookupLocalAddr(ifaceName string, network string, destination net.IP, port int) (net.Addr, error) { + ifaceObj, err := iface.ResolveInterface(ifaceName) + if err != nil { + return nil, err + } + + var addr *net.IPNet + switch network { + case "udp4", "tcp4": + addr, err = ifaceObj.PickIPv4Addr(destination) + case "tcp6", "udp6": + addr, err = ifaceObj.PickIPv6Addr(destination) + default: + if destination != nil { + if destination.To4() != nil { + addr, err = ifaceObj.PickIPv4Addr(destination) + } else { + addr, err = ifaceObj.PickIPv6Addr(destination) + } + } else { + addr, err = ifaceObj.PickIPv4Addr(destination) + } + } + if err != nil { + return nil, err + } + + if strings.HasPrefix(network, "tcp") { + return &net.TCPAddr{ + IP: addr.IP, + Port: port, + }, nil + } else if strings.HasPrefix(network, "udp") { + return &net.UDPAddr{ + IP: addr.IP, + Port: port, + }, nil + } + + return nil, iface.ErrAddrNotFound } -func bindIfaceToListenConfig(lc *net.ListenConfig, ifaceName string) error { - return errPlatformNotSupport +func bindIfaceToDialer(ifaceName string, dialer *net.Dialer, network string, destination net.IP) error { + if !destination.IsGlobalUnicast() { + return nil + } + + local := 0 + if dialer.LocalAddr != nil { + _, port, err := net.SplitHostPort(dialer.LocalAddr.String()) + if err == nil { + local, _ = strconv.Atoi(port) + } + } + + addr, err := lookupLocalAddr(ifaceName, network, destination, local) + if err != nil { + return err + } + + dialer.LocalAddr = addr + + return nil +} + +func bindIfaceToListenConfig(ifaceName string, _ *net.ListenConfig, network, address string) (string, error) { + _, port, err := net.SplitHostPort(address) + if err != nil { + port = "0" + } + + local, _ := strconv.Atoi(port) + + addr, err := lookupLocalAddr(ifaceName, network, nil, local) + if err != nil { + return "", err + } + + return addr.String(), nil } diff --git a/component/dialer/dialer.go b/component/dialer/dialer.go index be26681a7..75bbb8687 100644 --- a/component/dialer/dialer.go +++ b/component/dialer/dialer.go @@ -8,22 +8,7 @@ import ( "github.com/Dreamacro/clash/component/resolver" ) -func Dialer() (*net.Dialer, error) { - dialer := &net.Dialer{} - if DialerHook != nil { - if err := DialerHook(dialer); err != nil { - return nil, err - } - } - - return dialer, nil -} - -func Dial(network, address string) (net.Conn, error) { - return DialContext(context.Background(), network, address) -} - -func DialContext(ctx context.Context, network, address string) (net.Conn, error) { +func DialContext(ctx context.Context, network, address string, options ...Option) (net.Conn, error) { switch network { case "tcp4", "tcp6", "udp4", "udp6": host, port, err := net.SplitHostPort(address) @@ -31,11 +16,6 @@ func DialContext(ctx context.Context, network, address string) (net.Conn, error) return nil, err } - dialer, err := Dialer() - if err != nil { - return nil, err - } - var ip net.IP switch network { case "tcp4", "udp4": @@ -43,38 +23,70 @@ func DialContext(ctx context.Context, network, address string) (net.Conn, error) default: ip, err = resolver.ResolveIPv6(host) } - if err != nil { return nil, err } - if DialHook != nil { - if err := DialHook(dialer, network, ip); err != nil { - return nil, err - } - } - return dialer.DialContext(ctx, network, net.JoinHostPort(ip.String(), port)) + return dialContext(ctx, network, ip, port, options) case "tcp", "udp": - return dualStackDialContext(ctx, network, address) + return dualStackDialContext(ctx, network, address, options) default: return nil, errors.New("network invalid") } } -func ListenPacket(network, address string) (net.PacketConn, error) { - cfg := &net.ListenConfig{} - if ListenPacketHook != nil { - var err error - address, err = ListenPacketHook(cfg, address) +func ListenPacket(ctx context.Context, network, address string, options ...Option) (net.PacketConn, error) { + cfg := &config{} + + if !cfg.skipDefault { + for _, o := range DefaultOptions { + o(cfg) + } + } + + for _, o := range options { + o(cfg) + } + + lc := &net.ListenConfig{} + if cfg.interfaceName != "" { + addr, err := bindIfaceToListenConfig(cfg.interfaceName, lc, network, address) if err != nil { return nil, err } + address = addr + } + if cfg.addrReuse { + addrReuseToListenConfig(lc) + } + + return lc.ListenPacket(ctx, network, address) +} + +func dialContext(ctx context.Context, network string, destination net.IP, port string, options []Option) (net.Conn, error) { + opt := &config{} + + if !opt.skipDefault { + for _, o := range DefaultOptions { + o(opt) + } + } + + for _, o := range options { + o(opt) + } + + dialer := &net.Dialer{} + if opt.interfaceName != "" { + if err := bindIfaceToDialer(opt.interfaceName, dialer, network, destination); err != nil { + return nil, err + } } - return cfg.ListenPacket(context.Background(), network, address) + return dialer.DialContext(ctx, network, net.JoinHostPort(destination.String(), port)) } -func dualStackDialContext(ctx context.Context, network, address string) (net.Conn, error) { +func dualStackDialContext(ctx context.Context, network, address string, options []Option) (net.Conn, error) { host, port, err := net.SplitHostPort(address) if err != nil { return nil, err @@ -105,12 +117,6 @@ func dualStackDialContext(ctx context.Context, network, address string) (net.Con } }() - dialer, err := Dialer() - if err != nil { - result.error = err - return - } - var ip net.IP if ipv6 { ip, result.error = resolver.ResolveIPv6(host) @@ -122,12 +128,7 @@ func dualStackDialContext(ctx context.Context, network, address string) (net.Con } result.resolved = true - if DialHook != nil { - if result.error = DialHook(dialer, network, ip); result.error != nil { - return - } - } - result.Conn, result.error = dialer.DialContext(ctx, network, net.JoinHostPort(ip.String(), port)) + result.Conn, result.error = dialContext(ctx, network, ip, port, options) } go startRacer(ctx, network+"4", host, false) diff --git a/component/dialer/hook.go b/component/dialer/hook.go deleted file mode 100644 index 356e4b25f..000000000 --- a/component/dialer/hook.go +++ /dev/null @@ -1,43 +0,0 @@ -package dialer - -import ( - "errors" - "net" -) - -type DialerHookFunc = func(dialer *net.Dialer) error -type DialHookFunc = func(dialer *net.Dialer, network string, ip net.IP) error -type ListenPacketHookFunc = func(lc *net.ListenConfig, address string) (string, error) - -var ( - DialerHook DialerHookFunc - DialHook DialHookFunc - ListenPacketHook ListenPacketHookFunc -) - -var ( - ErrAddrNotFound = errors.New("addr not found") - ErrNetworkNotSupport = errors.New("network not support") -) - -func ListenPacketWithInterface(name string) ListenPacketHookFunc { - return func(lc *net.ListenConfig, address string) (string, error) { - err := bindIfaceToListenConfig(lc, name) - if err == errPlatformNotSupport { - address, err = fallbackBindToListenConfig(name) - } - - return address, err - } -} - -func DialerWithInterface(name string) DialHookFunc { - return func(dialer *net.Dialer, network string, ip net.IP) error { - err := bindIfaceToDialer(dialer, name) - if err == errPlatformNotSupport { - err = fallbackBindToDialer(dialer, network, ip, name) - } - - return err - } -} diff --git a/component/dialer/options.go b/component/dialer/options.go new file mode 100644 index 000000000..4b5d64c0e --- /dev/null +++ b/component/dialer/options.go @@ -0,0 +1,31 @@ +package dialer + +var ( + DefaultOptions []Option +) + +type config struct { + skipDefault bool + interfaceName string + addrReuse bool +} + +type Option func(opt *config) + +func WithInterface(name string) Option { + return func(opt *config) { + opt.interfaceName = name + } +} + +func WithAddrReuse(reuse bool) Option { + return func(opt *config) { + opt.addrReuse = reuse + } +} + +func WithSkipDefault(skip bool) Option { + return func(opt *config) { + opt.skipDefault = skip + } +} diff --git a/component/dialer/reuse_others.go b/component/dialer/reuse_others.go new file mode 100644 index 000000000..b76213a7f --- /dev/null +++ b/component/dialer/reuse_others.go @@ -0,0 +1,10 @@ +//go:build !darwin && !dragonfly && !freebsd && !linux && !netbsd && !openbsd && !solaris && !windows +// +build !darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris,!windows + +package dialer + +import ( + "net" +) + +func addrReuseToListenConfig(*net.ListenConfig) {} diff --git a/component/dialer/reuse_unix.go b/component/dialer/reuse_unix.go new file mode 100644 index 000000000..d5f43d8fe --- /dev/null +++ b/component/dialer/reuse_unix.go @@ -0,0 +1,28 @@ +//go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris +// +build darwin dragonfly freebsd linux netbsd openbsd solaris + +package dialer + +import ( + "net" + "syscall" + + "golang.org/x/sys/unix" +) + +func addrReuseToListenConfig(lc *net.ListenConfig) { + chain := lc.Control + + lc.Control = func(network, address string, c syscall.RawConn) (err error) { + defer func() { + if err == nil && chain != nil { + err = chain(network, address, c) + } + }() + + return c.Control(func(fd uintptr) { + unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_REUSEADDR, 1) + unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_REUSEPORT, 1) + }) + } +} diff --git a/component/dialer/reuse_windows.go b/component/dialer/reuse_windows.go new file mode 100644 index 000000000..77fcf7ab2 --- /dev/null +++ b/component/dialer/reuse_windows.go @@ -0,0 +1,24 @@ +package dialer + +import ( + "net" + "syscall" + + "golang.org/x/sys/windows" +) + +func addrReuseToListenConfig(lc *net.ListenConfig) { + chain := lc.Control + + lc.Control = func(network, address string, c syscall.RawConn) (err error) { + defer func() { + if err == nil && chain != nil { + err = chain(network, address, c) + } + }() + + return c.Control(func(fd uintptr) { + windows.SetsockoptInt(windows.Handle(fd), windows.SOL_SOCKET, windows.SO_REUSEADDR, 1) + }) + } +} diff --git a/component/iface/iface.go b/component/iface/iface.go new file mode 100644 index 000000000..30c6a6bcb --- /dev/null +++ b/component/iface/iface.go @@ -0,0 +1,113 @@ +package iface + +import ( + "errors" + "net" + "time" + + "github.com/Dreamacro/clash/common/singledo" +) + +type Interface struct { + Index int + Name string + Addrs []*net.IPNet + HardwareAddr net.HardwareAddr +} + +var ErrIfaceNotFound = errors.New("interface not found") +var ErrAddrNotFound = errors.New("addr not found") + +var interfaces = singledo.NewSingle(time.Second * 20) + +func ResolveInterface(name string) (*Interface, error) { + value, err, _ := interfaces.Do(func() (interface{}, error) { + ifaces, err := net.Interfaces() + if err != nil { + return nil, err + } + + r := map[string]*Interface{} + + for _, iface := range ifaces { + addrs, err := iface.Addrs() + if err != nil { + continue + } + + ipNets := make([]*net.IPNet, 0, len(addrs)) + for _, addr := range addrs { + ipNet := addr.(*net.IPNet) + if v4 := ipNet.IP.To4(); v4 != nil { + ipNet.IP = v4 + } + + ipNets = append(ipNets, ipNet) + } + + r[iface.Name] = &Interface{ + Index: iface.Index, + Name: iface.Name, + Addrs: ipNets, + HardwareAddr: iface.HardwareAddr, + } + } + + return r, nil + }) + if err != nil { + return nil, err + } + + ifaces := value.(map[string]*Interface) + iface, ok := ifaces[name] + if !ok { + return nil, ErrIfaceNotFound + } + + return iface, nil +} + +func FlushCache() { + interfaces.Reset() +} + +func (iface *Interface) PickIPv4Addr(destination net.IP) (*net.IPNet, error) { + return iface.pickIPAddr(destination, func(addr *net.IPNet) bool { + return addr.IP.To4() != nil + }) +} + +func (iface *Interface) PickIPv6Addr(destination net.IP) (*net.IPNet, error) { + return iface.pickIPAddr(destination, func(addr *net.IPNet) bool { + return addr.IP.To4() == nil + }) +} + +func (iface *Interface) pickIPAddr(destination net.IP, accept func(addr *net.IPNet) bool) (*net.IPNet, error) { + var fallback *net.IPNet + + for _, addr := range iface.Addrs { + if !accept(addr) { + continue + } + + if fallback == nil && !addr.IP.IsLinkLocalUnicast() { + fallback = addr + + if destination == nil { + break + } + } + + if destination != nil && addr.Contains(destination) { + return addr, nil + } + } + + if fallback == nil { + return nil, ErrAddrNotFound + } + + return fallback, nil +} diff --git a/config/config.go b/config/config.go index dc559ecf5..824175129 100644 --- a/config/config.go +++ b/config/config.go @@ -488,6 +488,9 @@ func parseNameServer(servers []string) ([]dns.NameServer, error) { clearURL := url.URL{Scheme: "https", Host: u.Host, Path: u.Path} addr = clearURL.String() dnsNetType = "https" // DNS over HTTPS + case "dhcp": + addr = u.Host + dnsNetType = "dhcp" // UDP from DHCP default: return nil, fmt.Errorf("DNS NameServer[%d] unsupport scheme: %s", idx, u.Scheme) } diff --git a/dns/client.go b/dns/client.go index 405b3a989..d386ed4c3 100644 --- a/dns/client.go +++ b/dns/client.go @@ -2,6 +2,7 @@ package dns import ( "context" + "crypto/tls" "fmt" "net" "strings" @@ -34,22 +35,16 @@ func (c *client) ExchangeContext(ctx context.Context, m *D.Msg) (msg *D.Msg, err } } - d, err := dialer.Dialer() + network := "udp" + if strings.HasPrefix(c.Client.Net, "tcp") { + network = "tcp" + } + + conn, err := dialer.DialContext(ctx, network, net.JoinHostPort(ip.String(), c.port)) if err != nil { return nil, err } - - if ip != nil && ip.IsGlobalUnicast() && dialer.DialHook != nil { - network := "udp" - if strings.HasPrefix(c.Client.Net, "tcp") { - network = "tcp" - } - if err := dialer.DialHook(d, network, ip); err != nil { - return nil, err - } - } - - c.Client.Dialer = d + defer conn.Close() // miekg/dns ExchangeContext doesn't respond to context cancel. // this is a workaround @@ -59,7 +54,17 @@ func (c *client) ExchangeContext(ctx context.Context, m *D.Msg) (msg *D.Msg, err } ch := make(chan result, 1) go func() { - msg, _, err := c.Client.Exchange(m, net.JoinHostPort(ip.String(), c.port)) + if strings.HasSuffix(c.Client.Net, "tls") { + conn = tls.Client(conn, c.Client.TLSConfig) + } + + msg, _, err = c.Client.ExchangeWithConn(m, &D.Conn{ + Conn: conn, + UDPSize: c.Client.UDPSize, + TsigSecret: c.Client.TsigSecret, + TsigProvider: c.Client.TsigProvider, + }) + ch <- result{msg, err} }() diff --git a/dns/dhcp.go b/dns/dhcp.go new file mode 100644 index 000000000..94f8a36ce --- /dev/null +++ b/dns/dhcp.go @@ -0,0 +1,144 @@ +package dns + +import ( + "bytes" + "context" + "net" + "sync" + "time" + + "github.com/Dreamacro/clash/component/dhcp" + "github.com/Dreamacro/clash/component/iface" + "github.com/Dreamacro/clash/component/resolver" + + D "github.com/miekg/dns" +) + +const ( + IfaceTTL = time.Second * 20 + DHCPTTL = time.Hour + DHCPTimeout = time.Minute +) + +type dhcpClient struct { + ifaceName string + + lock sync.Mutex + ifaceInvalidate time.Time + dnsInvalidate time.Time + + ifaceAddr *net.IPNet + done chan struct{} + resolver *Resolver + err error +} + +func (d *dhcpClient) Exchange(m *D.Msg) (msg *D.Msg, err error) { + ctx, cancel := context.WithTimeout(context.Background(), resolver.DefaultDNSTimeout) + defer cancel() + + return d.ExchangeContext(ctx, m) +} + +func (d *dhcpClient) ExchangeContext(ctx context.Context, m *D.Msg) (msg *D.Msg, err error) { + res, err := d.resolve(ctx) + if err != nil { + return nil, err + } + + return res.ExchangeContext(ctx, m) +} + +func (d *dhcpClient) resolve(ctx context.Context) (*Resolver, error) { + d.lock.Lock() + + invalidated, err := d.invalidate() + if err != nil { + d.err = err + } else if invalidated { + done := make(chan struct{}) + + d.done = done + + go func() { + ctx, cancel := context.WithTimeout(context.Background(), DHCPTimeout) + defer cancel() + + var res *Resolver + dns, err := dhcp.ResolveDNSFromDHCP(ctx, d.ifaceName) + if err == nil { + nameserver := make([]NameServer, 0, len(dns)) + for _, d := range dns { + nameserver = append(nameserver, NameServer{Addr: net.JoinHostPort(d.String(), "53")}) + } + + res = NewResolver(Config{ + Main: nameserver, + }) + } + + d.lock.Lock() + defer d.lock.Unlock() + + close(done) + + d.done = nil + d.resolver = res + d.err = err + }() + } + + d.lock.Unlock() + + for { + d.lock.Lock() + + res, err, done := d.resolver, d.err, d.done + + d.lock.Unlock() + + // initializing + if res == nil && err == nil { + select { + case <-done: + continue + case <-ctx.Done(): + return nil, ctx.Err() + } + } + + // dirty return + return res, err + } +} + +func (d *dhcpClient) invalidate() (bool, error) { + if time.Now().Before(d.ifaceInvalidate) { + return false, nil + } + + d.ifaceInvalidate = time.Now().Add(IfaceTTL) + + ifaceObj, err := iface.ResolveInterface(d.ifaceName) + if err != nil { + return false, err + } + + addr, err := ifaceObj.PickIPv4Addr(nil) + if err != nil { + return false, err + } + + if time.Now().Before(d.dnsInvalidate) && d.ifaceAddr.IP.Equal(addr.IP) && bytes.Equal(d.ifaceAddr.Mask, addr.Mask) { + return false, nil + } + + d.dnsInvalidate = time.Now().Add(DHCPTTL) + d.ifaceAddr = addr + + return d.done == nil, nil +} + +func newDHCPClient(ifaceName string) *dhcpClient { + return &dhcpClient{ifaceName: ifaceName} +} diff --git a/dns/resolver.go b/dns/resolver.go index 56b5e3268..914f1418e 100644 --- a/dns/resolver.go +++ b/dns/resolver.go @@ -87,6 +87,11 @@ func (r *Resolver) shouldIPFallback(ip net.IP) bool { // Exchange a batch of dns request, and it use cache func (r *Resolver) Exchange(m *D.Msg) (msg *D.Msg, err error) { + return r.ExchangeContext(context.Background(), m) +} + +// ExchangeContext a batch of dns request with context.Context, and it use cache +func (r *Resolver) ExchangeContext(ctx context.Context, m *D.Msg) (msg *D.Msg, err error) { if len(m.Question) == 0 { return nil, errors.New("should have one question at least") } @@ -98,17 +103,17 @@ func (r *Resolver) Exchange(m *D.Msg) (msg *D.Msg, err error) { msg = cache.(*D.Msg).Copy() if expireTime.Before(now) { setMsgTTL(msg, uint32(1)) // Continue fetch - go r.exchangeWithoutCache(m) + go r.exchangeWithoutCache(ctx, m) } else { setMsgTTL(msg, uint32(time.Until(expireTime).Seconds())) } return } - return r.exchangeWithoutCache(m) + return r.exchangeWithoutCache(ctx, m) } // ExchangeWithoutCache a batch of dns request, and it do NOT GET from cache -func (r *Resolver) exchangeWithoutCache(m *D.Msg) (msg *D.Msg, err error) { +func (r *Resolver) exchangeWithoutCache(ctx context.Context, m *D.Msg) (msg *D.Msg, err error) { q := m.Question[0] ret, err, shared := r.group.Do(q.String(), func() (result interface{}, err error) { @@ -124,13 +129,13 @@ func (r *Resolver) exchangeWithoutCache(m *D.Msg) (msg *D.Msg, err error) { isIPReq := isIPRequest(q) if isIPReq { - return r.ipExchange(m) + return r.ipExchange(ctx, m) } if matched := r.matchPolicy(m); len(matched) != 0 { - return r.batchExchange(matched, m) + return r.batchExchange(ctx, matched, m) } - return r.batchExchange(r.main, m) + return r.batchExchange(ctx, r.main, m) }) if err == nil { @@ -143,8 +148,8 @@ func (r *Resolver) exchangeWithoutCache(m *D.Msg) (msg *D.Msg, err error) { return } -func (r *Resolver) batchExchange(clients []dnsClient, m *D.Msg) (msg *D.Msg, err error) { - fast, ctx := picker.WithTimeout(context.Background(), resolver.DefaultDNSTimeout) +func (r *Resolver) batchExchange(ctx context.Context, clients []dnsClient, m *D.Msg) (msg *D.Msg, err error) { + fast, ctx := picker.WithTimeout(ctx, resolver.DefaultDNSTimeout) for _, client := range clients { r := client fast.Go(func() (interface{}, error) { @@ -209,21 +214,21 @@ func (r *Resolver) shouldOnlyQueryFallback(m *D.Msg) bool { return false } -func (r *Resolver) ipExchange(m *D.Msg) (msg *D.Msg, err error) { +func (r *Resolver) ipExchange(ctx context.Context, m *D.Msg) (msg *D.Msg, err error) { if matched := r.matchPolicy(m); len(matched) != 0 { - res := <-r.asyncExchange(matched, m) + res := <-r.asyncExchange(ctx, matched, m) return res.Msg, res.Error } onlyFallback := r.shouldOnlyQueryFallback(m) if onlyFallback { - res := <-r.asyncExchange(r.fallback, m) + res := <-r.asyncExchange(ctx, r.fallback, m) return res.Msg, res.Error } - msgCh := r.asyncExchange(r.main, m) + msgCh := r.asyncExchange(ctx, r.main, m) if r.fallback == nil { // directly return if no fallback servers are available res := <-msgCh @@ -231,7 +236,7 @@ func (r *Resolver) ipExchange(m *D.Msg) (msg *D.Msg, err error) { return } - fallbackMsg := r.asyncExchange(r.fallback, m) + fallbackMsg := r.asyncExchange(ctx, r.fallback, m) res := <-msgCh if res.Error == nil { if ips := msgToIP(res.Msg); len(ips) != 0 { @@ -287,10 +292,10 @@ func (r *Resolver) msgToDomain(msg *D.Msg) string { return "" } -func (r *Resolver) asyncExchange(client []dnsClient, msg *D.Msg) <-chan *result { +func (r *Resolver) asyncExchange(ctx context.Context, client []dnsClient, msg *D.Msg) <-chan *result { ch := make(chan *result, 1) go func() { - res, err := r.batchExchange(client, msg) + res, err := r.batchExchange(ctx, client, msg) ch <- &result{Msg: res, Error: err} }() return ch diff --git a/dns/util.go b/dns/util.go index e56aaeb5a..0c3f42e59 100644 --- a/dns/util.go +++ b/dns/util.go @@ -117,9 +117,13 @@ func isIPRequest(q D.Question) bool { func transform(servers []NameServer, resolver *Resolver) []dnsClient { ret := []dnsClient{} for _, s := range servers { - if s.Net == "https" { + switch s.Net { + case "https": ret = append(ret, newDoHClient(s.Addr, resolver)) continue + case "dhcp": + ret = append(ret, newDHCPClient(s.Addr)) + continue } host, port, _ := net.SplitHostPort(s.Addr) diff --git a/go.mod b/go.mod index 34915dd7a..d288f5fee 100644 --- a/go.mod +++ b/go.mod @@ -4,20 +4,21 @@ go 1.17 require ( github.com/Dreamacro/go-shadowsocks2 v0.1.7 - github.com/go-chi/chi/v5 v5.0.3 + github.com/go-chi/chi/v5 v5.0.4 github.com/go-chi/cors v1.2.0 github.com/go-chi/render v1.0.1 github.com/gofrs/uuid v4.0.0+incompatible github.com/gorilla/websocket v1.4.2 + github.com/insomniacslk/dhcp v0.0.0-20210827173440-b95caade3eac github.com/miekg/dns v1.1.43 github.com/oschwald/geoip2-golang v1.5.0 github.com/sirupsen/logrus v1.8.1 github.com/stretchr/testify v1.7.0 go.uber.org/atomic v1.9.0 golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 - golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d + golang.org/x/net v0.0.0-20210825183410-e898025ed96a golang.org/x/sync v0.0.0-20210220032951-036812b2e83c - golang.org/x/sys v0.0.0-20210817190340-bfb29a6856f2 + golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e gopkg.in/yaml.v2 v2.4.0 ) @@ -25,6 +26,7 @@ require ( github.com/davecgh/go-spew v1.1.1 // indirect github.com/oschwald/maxminddb-golang v1.8.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/u-root/uio v0.0.0-20210528114334-82958018845c // indirect golang.org/x/text v0.3.6 // indirect gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect ) diff --git a/go.sum b/go.sum index 2c433ac0a..f5346e536 100644 --- a/go.sum +++ b/go.sum @@ -3,16 +3,38 @@ github.com/Dreamacro/go-shadowsocks2 v0.1.7/go.mod h1:8p5G4cAj5ZlXwUR+Ww63gfSikr github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/go-chi/chi/v5 v5.0.3 h1:khYQBdPivkYG1s1TAzDQG1f6eX4kD2TItYVZexL5rS4= -github.com/go-chi/chi/v5 v5.0.3/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= +github.com/fanliao/go-promise v0.0.0-20141029170127-1890db352a72/go.mod h1:PjfxuH4FZdUyfMdtBio2lsRr1AKEaVPwelzuHuh8Lqc= +github.com/go-chi/chi/v5 v5.0.4 h1:5e494iHzsYBiyXQAHHuI4tyJS9M3V84OuX3ufIIGHFo= +github.com/go-chi/chi/v5 v5.0.4/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= github.com/go-chi/cors v1.2.0 h1:tV1g1XENQ8ku4Bq3K9ub2AtgG+p16SmzeMSGTwrOKdE= github.com/go-chi/cors v1.2.0/go.mod h1:sSbTewc+6wYHBBCW7ytsFSn836hqM7JxpglAy2Vzc58= github.com/go-chi/render v1.0.1 h1:4/5tis2cKaNdnv9zFLfXzcquC9HbeZgCnxGnKrltBS8= github.com/go-chi/render v1.0.1/go.mod h1:pq4Rr7HbnsdaeHagklXub+p6Wd16Af5l9koip1OvJns= github.com/gofrs/uuid v4.0.0+incompatible h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPhW6m+TnJw= github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/hugelgupf/socketpair v0.0.0-20190730060125-05d35a94e714/go.mod h1:2Goc3h8EklBH5mspfHFxBnEoURQCGzQQH1ga9Myjvis= +github.com/insomniacslk/dhcp v0.0.0-20210827173440-b95caade3eac h1:IO6EfdRnPhxgKOsk9DbewdtQZHKZKnGlW7QCUttvNys= +github.com/insomniacslk/dhcp v0.0.0-20210827173440-b95caade3eac/go.mod h1:h+MxyHxRg9NH3terB1nfRIUaQEcI0XOVkdR9LNBlp8E= +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-20201009170750-9c6f07d100c1/go.mod h1:hqoO/u39cqLeBLebZ8fWdE96O7FxrAsRYhnVOdgHxok= +github.com/jsimonetti/rtnetlink v0.0.0-20201110080708-d2c240429e6c/go.mod h1:huN4d1phzjhlOsNIjFsw2SVRbwIHj3fJDMEU2SDPTmg= +github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/mdlayher/ethernet v0.0.0-20190606142754-0394541c37b7/go.mod h1:U6ZQobyTjI/tJyq2HG+i/dfSoFUt8/aZCM+GKtmFk/Y= +github.com/mdlayher/netlink v0.0.0-20190409211403-11939a169225/go.mod h1:eQB3mZE4aiYnlUsyGGCOpPETfdQq4Jhsgf1fk3cwQaA= +github.com/mdlayher/netlink v1.0.0/go.mod h1:KxeJAFOFLG6AjpyDkQ/iIhxygIUKD+vcwqcnu43w/+M= +github.com/mdlayher/netlink v1.1.0/go.mod h1:H4WCitaheIsdF9yOYu8CFmCgQthAPIWZmcKp9uZHgmY= +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-20191009151244-50f2db8cc065/go.mod h1:7EpbotpCmVZcu+KCX4g9WaRNuu11uyhiW7+Le1dKawg= github.com/miekg/dns v1.1.43 h1:JKfpVSCB84vrAmHzyrsxB5NAr5kLoMXZArPSw7Qlgyg= github.com/miekg/dns v1.1.43/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4= github.com/oschwald/geoip2-golang v1.5.0 h1:igg2yQIrrcRccB1ytFXqBfOHCjXWIoMv85lVJ1ONZzw= @@ -23,35 +45,66 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/u-root/uio v0.0.0-20210528114334-82958018845c h1:BFvcl34IGnw8yvJi8hlqLFo9EshRInwWBs2M5fGWzQA= +github.com/u-root/uio v0.0.0-20210528114334-82958018845c/go.mod h1:LpEX5FO/cB+WF4TYGY1V5qktpaZLkKkSegbr0V4eYXA= go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +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-20210817164053-32db794688a5 h1:HWj/xjIHfjYU5nVXpTM0s39J9CbLn7Cc5a7IC5rwsMQ= golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190419010253-1f3472d942ba/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191007182048-72f939374954/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/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-20210813160813-60bc85c4be6d h1:LO7XpTYMwTqxjLcGWPijK3vRXg1aWdlNOVOHRq45d7c= -golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210825183410-e898025ed96a h1:bRuuGXV8wwSdGTB+CtJf+FjgO1APK1CoO39T4BN/XBw= +golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190411185658-b44545bcd369/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190418153312-f0ce4c0180be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606122018-79a91cf218c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191224085550-c709ea063b76/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201009025420-dfb3f7c4e634/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201101102859-da207088b7d1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +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-20210817190340-bfb29a6856f2 h1:c8PlLMqBbOHoqtjteWm5/kbe6rNY2pbRfbIMVnepueo= -golang.org/x/sys v0.0.0-20210817190340-bfb29a6856f2/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e h1:XMgFehsDnnLGtjvjOfqWSUzt0alpTR1RSEuznObga2c= +golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= diff --git a/hub/executor/executor.go b/hub/executor/executor.go index 121e1d01d..5c002b64f 100644 --- a/hub/executor/executor.go +++ b/hub/executor/executor.go @@ -10,6 +10,7 @@ import ( "github.com/Dreamacro/clash/adapter/outboundgroup" "github.com/Dreamacro/clash/component/auth" "github.com/Dreamacro/clash/component/dialer" + "github.com/Dreamacro/clash/component/iface" "github.com/Dreamacro/clash/component/profile" "github.com/Dreamacro/clash/component/profile/cachefile" "github.com/Dreamacro/clash/component/resolver" @@ -171,13 +172,13 @@ func updateGeneral(general *config.General, force bool) { resolver.DisableIPv6 = !general.IPv6 if general.Interface != "" { - dialer.DialHook = dialer.DialerWithInterface(general.Interface) - dialer.ListenPacketHook = dialer.ListenPacketWithInterface(general.Interface) + dialer.DefaultOptions = []dialer.Option{dialer.WithInterface(general.Interface)} } else { - dialer.DialHook = nil - dialer.ListenPacketHook = nil + dialer.DefaultOptions = nil } + iface.FlushCache() + if !force { return } From 5b7f0de48b6f26ce1ec5f54422b2b5e50e956c5c Mon Sep 17 00:00:00 2001 From: Dreamacro <8615343+Dreamacro@users.noreply.github.com> Date: Tue, 7 Sep 2021 20:16:07 +0800 Subject: [PATCH 57/96] Chore: update dependencies --- go.mod | 4 ++-- go.sum | 8 ++++---- test/go.mod | 6 ++++-- test/go.sum | 38 +++++++++++++++++++++++++++++++++----- 4 files changed, 43 insertions(+), 13 deletions(-) diff --git a/go.mod b/go.mod index d288f5fee..e955449b8 100644 --- a/go.mod +++ b/go.mod @@ -16,9 +16,9 @@ require ( github.com/stretchr/testify v1.7.0 go.uber.org/atomic v1.9.0 golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 - golang.org/x/net v0.0.0-20210825183410-e898025ed96a + golang.org/x/net v0.0.0-20210903162142-ad29c8ab022f golang.org/x/sync v0.0.0-20210220032951-036812b2e83c - golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e + golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34 gopkg.in/yaml.v2 v2.4.0 ) diff --git a/go.sum b/go.sum index f5346e536..d1d97cfc4 100644 --- a/go.sum +++ b/go.sum @@ -72,8 +72,8 @@ golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/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-20210825183410-e898025ed96a h1:bRuuGXV8wwSdGTB+CtJf+FjgO1APK1CoO39T4BN/XBw= -golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210903162142-ad29c8ab022f h1:w6wWR0H+nyVpbSAQbzVEIACVyr/h8l/BEkY6Sokc7Eg= +golang.org/x/net v0.0.0-20210903162142-ad29c8ab022f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -95,8 +95,8 @@ golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 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-20210831042530-f4d43177bf5e h1:XMgFehsDnnLGtjvjOfqWSUzt0alpTR1RSEuznObga2c= -golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34 h1:GkvMjFtXUmahfDtashnc1mnrCtuBVcwse5QV2lUk/tI= +golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= diff --git a/test/go.mod b/test/go.mod index 97d3a79c6..990edb6c5 100644 --- a/test/go.mod +++ b/test/go.mod @@ -8,7 +8,7 @@ require ( github.com/docker/go-connections v0.4.0 github.com/miekg/dns v1.1.43 github.com/stretchr/testify v1.7.0 - golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d + golang.org/x/net v0.0.0-20210903162142-ad29c8ab022f ) replace github.com/Dreamacro/clash => ../ @@ -25,6 +25,7 @@ require ( github.com/golang/protobuf v1.5.0 // indirect github.com/gorilla/mux v1.8.0 // indirect github.com/gorilla/websocket v1.4.2 // indirect + github.com/insomniacslk/dhcp v0.0.0-20210827173440-b95caade3eac // indirect github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 // indirect github.com/morikuni/aec v1.0.0 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect @@ -34,10 +35,11 @@ require ( github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/sirupsen/logrus v1.8.1 // indirect + github.com/u-root/uio v0.0.0-20210528114334-82958018845c // indirect go.uber.org/atomic v1.9.0 // indirect golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 // indirect golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect - golang.org/x/sys v0.0.0-20210817190340-bfb29a6856f2 // indirect + golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34 // indirect golang.org/x/text v0.3.6 // indirect golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a // indirect diff --git a/test/go.sum b/test/go.sum index c2b68eafd..27d2c4de2 100644 --- a/test/go.sum +++ b/test/go.sum @@ -251,6 +251,7 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.m github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/fanliao/go-promise v0.0.0-20141029170127-1890db352a72/go.mod h1:PjfxuH4FZdUyfMdtBio2lsRr1AKEaVPwelzuHuh8Lqc= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= @@ -260,7 +261,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/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/go-chi/chi/v5 v5.0.3/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= +github.com/go-chi/chi/v5 v5.0.4/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= 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-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= @@ -376,16 +377,23 @@ github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/hugelgupf/socketpair v0.0.0-20190730060125-05d35a94e714/go.mod h1:2Goc3h8EklBH5mspfHFxBnEoURQCGzQQH1ga9Myjvis= 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.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.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= 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-20210827173440-b95caade3eac/go.mod h1:h+MxyHxRg9NH3terB1nfRIUaQEcI0XOVkdR9LNBlp8E= 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-20160803190731-bd40a432e4c7/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= 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-20200117123717-f846d4f6c1f4/go.mod h1:WGuG/smIU4J/54PblvSbh+xvCZmpJnFgr3ds6Z55XMQ= +github.com/jsimonetti/rtnetlink v0.0.0-20201009170750-9c6f07d100c1/go.mod h1:hqoO/u39cqLeBLebZ8fWdE96O7FxrAsRYhnVOdgHxok= +github.com/jsimonetti/rtnetlink v0.0.0-20201110080708-d2c240429e6c/go.mod h1:huN4d1phzjhlOsNIjFsw2SVRbwIHj3fJDMEU2SDPTmg= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= @@ -422,6 +430,13 @@ github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzp github.com/mattn/go-shellwords v1.0.3/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +github.com/mdlayher/ethernet v0.0.0-20190606142754-0394541c37b7/go.mod h1:U6ZQobyTjI/tJyq2HG+i/dfSoFUt8/aZCM+GKtmFk/Y= +github.com/mdlayher/netlink v0.0.0-20190409211403-11939a169225/go.mod h1:eQB3mZE4aiYnlUsyGGCOpPETfdQq4Jhsgf1fk3cwQaA= +github.com/mdlayher/netlink v1.0.0/go.mod h1:KxeJAFOFLG6AjpyDkQ/iIhxygIUKD+vcwqcnu43w/+M= +github.com/mdlayher/netlink v1.1.0/go.mod h1:H4WCitaheIsdF9yOYu8CFmCgQthAPIWZmcKp9uZHgmY= +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-20191009151244-50f2db8cc065/go.mod h1:7EpbotpCmVZcu+KCX4g9WaRNuu11uyhiW7+Le1dKawg= github.com/miekg/dns v1.1.43 h1:JKfpVSCB84vrAmHzyrsxB5NAr5kLoMXZArPSw7Qlgyg= github.com/miekg/dns v1.1.43/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4= github.com/miekg/pkcs11 v1.0.3/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= @@ -551,6 +566,7 @@ github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= @@ -585,6 +601,8 @@ github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG github.com/tchap/go-patricia v2.2.6+incompatible/go.mod h1:bmLyhP68RS6kStMGxByiQ23RP/odRBOTVjwp2cDyi6I= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/u-root/uio v0.0.0-20210528114334-82958018845c h1:BFvcl34IGnw8yvJi8hlqLFo9EshRInwWBs2M5fGWzQA= +github.com/u-root/uio v0.0.0-20210528114334-82958018845c/go.mod h1:LpEX5FO/cB+WF4TYGY1V5qktpaZLkKkSegbr0V4eYXA= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= @@ -680,6 +698,7 @@ golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73r golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190419010253-1f3472d942ba/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= @@ -691,6 +710,7 @@ golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191007182048-72f939374954/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -701,12 +721,13 @@ golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d h1:LO7XpTYMwTqxjLcGWPijK3vRXg1aWdlNOVOHRq45d7c= -golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210903162142-ad29c8ab022f h1:w6wWR0H+nyVpbSAQbzVEIACVyr/h8l/BEkY6Sokc7Eg= +golang.org/x/net v0.0.0-20210903162142-ad29c8ab022f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -730,13 +751,16 @@ golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190411185658-b44545bcd369/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190418153312-f0ce4c0180be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190514135907-3a4b5fb9f71f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190522044717-8097e1b27ff5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190602015325-4c4f7f33c9ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606122018-79a91cf218c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -749,6 +773,7 @@ golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -776,6 +801,8 @@ golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200916030750-2334cc1a136f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200922070232-aee5d888a860/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201009025420-dfb3f7c4e634/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201101102859-da207088b7d1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201112073958-5cba982894dd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201117170446-d9b008d0a637/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -786,10 +813,11 @@ golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +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-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210817190340-bfb29a6856f2 h1:c8PlLMqBbOHoqtjteWm5/kbe6rNY2pbRfbIMVnepueo= -golang.org/x/sys v0.0.0-20210817190340-bfb29a6856f2/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34 h1:GkvMjFtXUmahfDtashnc1mnrCtuBVcwse5QV2lUk/tI= +golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= From 400dc923e0643d28b9b62405d5d5968f043659b2 Mon Sep 17 00:00:00 2001 From: maskedeken <52683904+maskedeken@users.noreply.github.com> Date: Wed, 8 Sep 2021 14:44:24 +0800 Subject: [PATCH 58/96] Fix: vmess ws headers not set properly (#1595) --- adapter/outbound/vmess.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/adapter/outbound/vmess.go b/adapter/outbound/vmess.go index 445b1ef47..6ca82c15e 100644 --- a/adapter/outbound/vmess.go +++ b/adapter/outbound/vmess.go @@ -95,7 +95,7 @@ func (v *Vmess) StreamConn(c net.Conn, metadata *C.Metadata) (net.Conn, error) { if len(v.option.WSOpts.Headers) != 0 { header := http.Header{} - for key, value := range v.option.WSHeaders { + for key, value := range v.option.WSOpts.Headers { header.Add(key, value) } wsOpts.Headers = header From 0c79d1207ef884c98458f62081d03f94a3c274ee Mon Sep 17 00:00:00 2001 From: bobo liu <7552030+fakeboboliu@users.noreply.github.com> Date: Thu, 9 Sep 2021 20:30:34 +0800 Subject: [PATCH 59/96] Fix: potential overflow in ssr (#1600) --- transport/ssr/protocol/auth_chain_a.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/transport/ssr/protocol/auth_chain_a.go b/transport/ssr/protocol/auth_chain_a.go index 4ce55c1a6..906f8deb3 100644 --- a/transport/ssr/protocol/auth_chain_a.go +++ b/transport/ssr/protocol/auth_chain_a.go @@ -278,7 +278,7 @@ func getRandStartPos(length int, random *tools.XorShift128Plus) int { if length == 0 { return 0 } - return int(random.Next()%8589934609) % length + return int(int64(random.Next()%8589934609) % int64(length)) } func (a *authChainA) getRandLength(length int, lastHash []byte, random *tools.XorShift128Plus) int { From d49b38b00f03c7c5a2f29fb7f639dcbee46c9461 Mon Sep 17 00:00:00 2001 From: Kr328 Date: Mon, 13 Sep 2021 23:43:28 +0800 Subject: [PATCH 60/96] Fix: should not unmarshal to pointer (#1615) --- config/config.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config/config.go b/config/config.go index 824175129..004a935f0 100644 --- a/config/config.go +++ b/config/config.go @@ -22,7 +22,7 @@ import ( R "github.com/Dreamacro/clash/rule" T "github.com/Dreamacro/clash/tunnel" - yaml "gopkg.in/yaml.v2" + "gopkg.in/yaml.v2" ) // General config @@ -188,7 +188,7 @@ func UnmarshalRawConfig(buf []byte) (*RawConfig, error) { }, } - if err := yaml.Unmarshal(buf, &rawCfg); err != nil { + if err := yaml.Unmarshal(buf, rawCfg); err != nil { return nil, err } From beb88cc46f01e2215934441287f1a553a9290e16 Mon Sep 17 00:00:00 2001 From: Kr328 Date: Mon, 13 Sep 2021 23:46:39 +0800 Subject: [PATCH 61/96] Fix: should not trust address of http.Client (#1616) --- adapter/inbound/http.go | 4 ++-- listener/http/client.go | 8 +++++++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/adapter/inbound/http.go b/adapter/inbound/http.go index 94b9fc21f..89960cf34 100644 --- a/adapter/inbound/http.go +++ b/adapter/inbound/http.go @@ -9,8 +9,8 @@ import ( ) // NewHTTP receive normal http request and return HTTPContext -func NewHTTP(target string, source net.Addr, conn net.Conn) *context.ConnContext { - metadata := parseSocksAddr(socks5.ParseAddr(target)) +func NewHTTP(target socks5.Addr, source net.Addr, conn net.Conn) *context.ConnContext { + metadata := parseSocksAddr(target) metadata.NetWork = C.TCP metadata.Type = C.HTTP if ip, port, err := parseAddr(source.String()); err == nil { diff --git a/listener/http/client.go b/listener/http/client.go index 3b5fd3842..15078b0ac 100644 --- a/listener/http/client.go +++ b/listener/http/client.go @@ -9,6 +9,7 @@ import ( "github.com/Dreamacro/clash/adapter/inbound" C "github.com/Dreamacro/clash/constant" + "github.com/Dreamacro/clash/transport/socks5" ) func newClient(source net.Addr, in chan<- C.ConnContext) *http.Client { @@ -25,9 +26,14 @@ func newClient(source net.Addr, in chan<- C.ConnContext) *http.Client { return nil, errors.New("unsupported network " + network) } + dstAddr := socks5.ParseAddr(address) + if dstAddr == nil { + return nil, socks5.ErrAddressNotSupported + } + left, right := net.Pipe() - in <- inbound.NewHTTP(address, source, right) + in <- inbound.NewHTTP(dstAddr, source, right) return left, nil }, From 55600c49c9299744c2c3d67dc72ac0d798bc3437 Mon Sep 17 00:00:00 2001 From: Dreamacro <8615343+Dreamacro@users.noreply.github.com> Date: Mon, 13 Sep 2021 23:58:34 +0800 Subject: [PATCH 62/96] Fix: potential pitfalls --- dns/client.go | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/dns/client.go b/dns/client.go index d386ed4c3..6a54f9fad 100644 --- a/dns/client.go +++ b/dns/client.go @@ -20,15 +20,20 @@ type client struct { host string } -func (c *client) Exchange(m *D.Msg) (msg *D.Msg, err error) { +func (c *client) Exchange(m *D.Msg) (*D.Msg, error) { return c.ExchangeContext(context.Background(), m) } -func (c *client) ExchangeContext(ctx context.Context, m *D.Msg) (msg *D.Msg, err error) { - var ip net.IP +func (c *client) ExchangeContext(ctx context.Context, m *D.Msg) (*D.Msg, error) { + var ( + ip net.IP + err error + ) if c.r == nil { // a default ip dns - ip = net.ParseIP(c.host) + if ip = net.ParseIP(c.host); ip == nil { + return nil, fmt.Errorf("dns %s not a valid ip", c.host) + } } else { if ip, err = resolver.ResolveIPWithResolver(c.host, c.r); err != nil { return nil, fmt.Errorf("use default dns resolve failed: %w", err) @@ -58,7 +63,7 @@ func (c *client) ExchangeContext(ctx context.Context, m *D.Msg) (msg *D.Msg, err conn = tls.Client(conn, c.Client.TLSConfig) } - msg, _, err = c.Client.ExchangeWithConn(m, &D.Conn{ + msg, _, err := c.Client.ExchangeWithConn(m, &D.Conn{ Conn: conn, UDPSize: c.Client.UDPSize, TsigSecret: c.Client.TsigSecret, From f5806d92639db21a86a8f8418995ba7a47d8bcf3 Mon Sep 17 00:00:00 2001 From: Xuen Li Date: Tue, 14 Sep 2021 00:08:23 +0800 Subject: [PATCH 63/96] Fix: http/https proxy authentication (#1613) --- listener/http/proxy.go | 12 ++++++------ listener/http/utils.go | 16 ++++++++-------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/listener/http/proxy.go b/listener/http/proxy.go index 449658cac..229106dfe 100644 --- a/listener/http/proxy.go +++ b/listener/http/proxy.go @@ -63,8 +63,8 @@ func HandleConn(c net.Conn, in chan<- C.ConnContext, cache *cache.Cache) { request.RequestURI = "" - RemoveHopByHopHeaders(request.Header) - RemoveExtraHTTPHostPort(request) + removeHopByHopHeaders(request.Header) + removeExtraHTTPHostPort(request) if request.URL.Scheme == "" || request.URL.Host == "" { resp = responseWith(http.StatusBadRequest) @@ -74,9 +74,9 @@ func HandleConn(c net.Conn, in chan<- C.ConnContext, cache *cache.Cache) { resp = responseWith(http.StatusBadGateway) } } - } - RemoveHopByHopHeaders(resp.Header) + removeHopByHopHeaders(resp.Header) + } if keepAlive { resp.Header.Set("Proxy-Connection", "keep-alive") @@ -98,7 +98,7 @@ func HandleConn(c net.Conn, in chan<- C.ConnContext, cache *cache.Cache) { func authenticate(request *http.Request, cache *cache.Cache) *http.Response { authenticator := authStore.Authenticator() if authenticator != nil { - credential := ParseBasicProxyAuthorization(request) + credential := parseBasicProxyAuthorization(request) if credential == "" { resp := responseWith(http.StatusProxyAuthRequired) resp.Header.Set("Proxy-Authenticate", "Basic") @@ -107,7 +107,7 @@ func authenticate(request *http.Request, cache *cache.Cache) *http.Response { var authed interface{} if authed = cache.Get(credential); authed == nil { - user, pass, err := DecodeBasicProxyAuthorization(credential) + user, pass, err := decodeBasicProxyAuthorization(credential) authed = err == nil && authenticator.Verify(user, pass) cache.Put(credential, authed, time.Minute) } diff --git a/listener/http/utils.go b/listener/http/utils.go index f3d7840c6..177607991 100644 --- a/listener/http/utils.go +++ b/listener/http/utils.go @@ -8,8 +8,8 @@ import ( "strings" ) -// RemoveHopByHopHeaders remove hop-by-hop header -func RemoveHopByHopHeaders(header http.Header) { +// removeHopByHopHeaders remove hop-by-hop header +func removeHopByHopHeaders(header http.Header) { // Strip hop-by-hop header based on RFC: // http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.5.1 // https://www.mnot.net/blog/2011/07/11/what_proxies_must_do @@ -32,9 +32,9 @@ func RemoveHopByHopHeaders(header http.Header) { } } -// RemoveExtraHTTPHostPort remove extra host port (example.com:80 --> example.com) +// removeExtraHTTPHostPort remove extra host port (example.com:80 --> example.com) // It resolves the behavior of some HTTP servers that do not handle host:80 (e.g. baidu.com) -func RemoveExtraHTTPHostPort(req *http.Request) { +func removeExtraHTTPHostPort(req *http.Request) { host := req.Host if host == "" { host = req.URL.Host @@ -48,8 +48,8 @@ func RemoveExtraHTTPHostPort(req *http.Request) { req.URL.Host = host } -// ParseBasicProxyAuthorization parse header Proxy-Authorization and return base64-encoded credential -func ParseBasicProxyAuthorization(request *http.Request) string { +// parseBasicProxyAuthorization parse header Proxy-Authorization and return base64-encoded credential +func parseBasicProxyAuthorization(request *http.Request) string { value := request.Header.Get("Proxy-Authorization") if !strings.HasPrefix(value, "Basic ") { return "" @@ -58,8 +58,8 @@ func ParseBasicProxyAuthorization(request *http.Request) string { return value[6:] // value[len("Basic "):] } -// DecodeBasicProxyAuthorization decode base64-encoded credential -func DecodeBasicProxyAuthorization(credential string) (string, string, error) { +// decodeBasicProxyAuthorization decode base64-encoded credential +func decodeBasicProxyAuthorization(credential string) (string, string, error) { plain, err := base64.StdEncoding.DecodeString(credential) if err != nil { return "", "", err From b0f83e401f612d294d456730286be2ca44c82bf8 Mon Sep 17 00:00:00 2001 From: Excited Codes <61885669+ExcitedCodes@users.noreply.github.com> Date: Wed, 15 Sep 2021 16:45:57 +0800 Subject: [PATCH 64/96] Fix: socks4 request continues after authentication failed (#1624) --- transport/socks4/socks4.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/transport/socks4/socks4.go b/transport/socks4/socks4.go index c6b2f2db5..c06bea20f 100644 --- a/transport/socks4/socks4.go +++ b/transport/socks4/socks4.go @@ -91,6 +91,7 @@ func ServerHandshake(rw io.ReadWriter, authenticator auth.Authenticator) (addr s code = RequestGranted } else { code = RequestIdentdMismatched + err = ErrRequestIdentdMismatched } var reply [8]byte @@ -99,7 +100,10 @@ func ServerHandshake(rw io.ReadWriter, authenticator auth.Authenticator) (addr s copy(reply[4:8], dstIP) copy(reply[2:4], dstPort) - _, err = rw.Write(reply[:]) + _, wErr := rw.Write(reply[:]) + if err == nil { + err = wErr + } return } From b3cd4ebbd3c34697c9fe87f7f536421ada5004cf Mon Sep 17 00:00:00 2001 From: Dreamacro <8615343+Dreamacro@users.noreply.github.com> Date: Wed, 15 Sep 2021 20:21:30 +0800 Subject: [PATCH 65/96] Fix: use 1.17.x on github actions --- .github/workflows/go.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index d8a514eae..2b9366f9f 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -9,7 +9,7 @@ jobs: - name: Setup Go uses: actions/setup-go@v2 with: - go-version: 1.17 + go-version: 1.17.x - name: Check out code into the Go module directory uses: actions/checkout@v2 From b398f1e6f37bde03da73c34994ccb62f831feb51 Mon Sep 17 00:00:00 2001 From: Dreamacro <8615343+Dreamacro@users.noreply.github.com> Date: Sat, 18 Sep 2021 00:18:47 +0800 Subject: [PATCH 66/96] Chore: force set latest go version to action --- .github/workflows/go.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index 2b9366f9f..1058dd4f4 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -6,10 +6,15 @@ jobs: name: Build runs-on: ubuntu-latest steps: + - name: Get latest go version + id: version + run: | + echo ::set-output name=go_version::$(curl -s https://raw.githubusercontent.com/actions/go-versions/main/versions-manifest.json | grep -oE '"version": "[0-9]{1}.[0-9]{1,}(.[0-9]{1,})?"' | head -1 | cut -d':' -f2 | sed 's/ //g; s/"//g') + - name: Setup Go uses: actions/setup-go@v2 with: - go-version: 1.17.x + go-version: ${{ steps.version.outputs.go_version }} - name: Check out code into the Go module directory uses: actions/checkout@v2 From 5b1a0a523fd0efadb8ef6199f1aee67ddaade34a Mon Sep 17 00:00:00 2001 From: Dreamacro <8615343+Dreamacro@users.noreply.github.com> Date: Mon, 20 Sep 2021 17:22:40 +0800 Subject: [PATCH 67/96] Chore: update README.md --- README.md | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index b948b49d0..c0d7c7f72 100644 --- a/README.md +++ b/README.md @@ -12,9 +12,13 @@ + + + +

## Features @@ -22,7 +26,7 @@ - Local HTTP/HTTPS/SOCKS server with authentication support - VMess, Shadowsocks, Trojan, Snell protocol support for remote connections - Built-in DNS server that aims to minimize DNS pollution attack impact, supports DoH/DoT upstream and fake IP. -- Rules based off domains, GEOIP, IP CIDR or ports to forward packets to different nodes +- Rules based off domains, GEOIP, IPCIDR or Process to forward packets to different nodes - Remote groups allow users to implement powerful rules. Supports automatic fallback, load balancing or auto select node based off latency - Remote providers, allowing users to get node lists remotely instead of hardcoding in config - Netfilter TCP redirecting. Deploy Clash on your Internet gateway with `iptables`. @@ -47,16 +51,10 @@ If you want to build an application that uses clash as a library, check out the * [riobard/go-shadowsocks2](https://github.com/riobard/go-shadowsocks2) * [v2ray/v2ray-core](https://github.com/v2ray/v2ray-core) +* [WireGuard/wireguard-go](https://github.com/WireGuard/wireguard-go) ## License This software is released under the GPL-3.0 license. [![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2FDreamacro%2Fclash.svg?type=large)](https://app.fossa.io/projects/git%2Bgithub.com%2FDreamacro%2Fclash?ref=badge_large) - -## TODO - -- [x] Complementing the necessary rule operators -- [x] Redir proxy -- [x] UDP support -- [x] Connection manager From 70c8605cca3b9cba8598bad52d3bb6a36d77d032 Mon Sep 17 00:00:00 2001 From: Dreamacro <8615343+Dreamacro@users.noreply.github.com> Date: Mon, 20 Sep 2021 21:02:18 +0800 Subject: [PATCH 68/96] Improve: use one bytes.Buffer pool --- common/pool/buffer.go | 17 ++++++++++++++++ transport/gun/gun.go | 9 ++++----- transport/simple-obfs/tls.go | 3 ++- transport/snell/snell.go | 12 +++++------- transport/ssr/obfs/http_simple.go | 6 ++---- transport/ssr/obfs/tls1.2_ticket_auth.go | 25 ++++++++++-------------- transport/ssr/protocol/packet.go | 8 +++----- transport/ssr/protocol/stream.go | 6 ++---- transport/ssr/tools/bufPool.go | 13 +++--------- transport/trojan/trojan.go | 14 +++++-------- 10 files changed, 53 insertions(+), 60 deletions(-) create mode 100644 common/pool/buffer.go diff --git a/common/pool/buffer.go b/common/pool/buffer.go new file mode 100644 index 000000000..fb328b766 --- /dev/null +++ b/common/pool/buffer.go @@ -0,0 +1,17 @@ +package pool + +import ( + "bytes" + "sync" +) + +var bufferPool = sync.Pool{New: func() interface{} { return &bytes.Buffer{} }} + +func GetBuffer() *bytes.Buffer { + return bufferPool.Get().(*bytes.Buffer) +} + +func PutBuffer(buf *bytes.Buffer) { + buf.Reset() + bufferPool.Put(buf) +} diff --git a/transport/gun/gun.go b/transport/gun/gun.go index 3f97121f8..e60d13d75 100644 --- a/transport/gun/gun.go +++ b/transport/gun/gun.go @@ -5,7 +5,6 @@ package gun import ( "bufio" - "bytes" "crypto/tls" "encoding/binary" "errors" @@ -17,6 +16,8 @@ import ( "sync" "time" + "github.com/Dreamacro/clash/common/pool" + "go.uber.org/atomic" "golang.org/x/net/http2" ) @@ -31,7 +32,6 @@ var ( "content-type": []string{"application/grpc"}, "user-agent": []string{"grpc-go/1.36.0"}, } - bufferPool = sync.Pool{New: func() interface{} { return &bytes.Buffer{} }} ) type DialFn = func(network, addr string) (net.Conn, error) @@ -127,9 +127,8 @@ func (g *Conn) Write(b []byte) (n int, err error) { grpcPayloadLen := uint32(varuintSize + 1 + len(b)) binary.BigEndian.PutUint32(grpcHeader[1:5], grpcPayloadLen) - buf := bufferPool.Get().(*bytes.Buffer) - defer bufferPool.Put(buf) - defer buf.Reset() + buf := pool.GetBuffer() + defer pool.PutBuffer(buf) buf.Write(grpcHeader) buf.Write(protobufHeader[:varuintSize+1]) buf.Write(b) diff --git a/transport/simple-obfs/tls.go b/transport/simple-obfs/tls.go index 6484eb6c4..914cfe4af 100644 --- a/transport/simple-obfs/tls.go +++ b/transport/simple-obfs/tls.go @@ -102,7 +102,8 @@ func (to *TLSObfs) write(b []byte) (int, error) { return len(b), err } - buf := &bytes.Buffer{} + buf := pool.GetBuffer() + defer pool.PutBuffer(buf) buf.Write([]byte{0x17, 0x03, 0x03}) binary.Write(buf, binary.BigEndian, uint16(len(b))) buf.Write(b) diff --git a/transport/snell/snell.go b/transport/snell/snell.go index ecbc90ee8..8966b4bb7 100644 --- a/transport/snell/snell.go +++ b/transport/snell/snell.go @@ -1,13 +1,13 @@ package snell import ( - "bytes" "encoding/binary" "errors" "fmt" "io" "net" - "sync" + + "github.com/Dreamacro/clash/common/pool" "github.com/Dreamacro/go-shadowsocks2/shadowaead" ) @@ -31,8 +31,7 @@ const ( ) var ( - bufferPool = sync.Pool{New: func() interface{} { return &bytes.Buffer{} }} - endSignal = []byte{} + endSignal = []byte{} ) type Snell struct { @@ -79,9 +78,8 @@ func (s *Snell) Read(b []byte) (int, error) { } func WriteHeader(conn net.Conn, host string, port uint, version int) error { - buf := bufferPool.Get().(*bytes.Buffer) - buf.Reset() - defer bufferPool.Put(buf) + buf := pool.GetBuffer() + defer pool.PutBuffer(buf) buf.WriteByte(Version) if version == Version2 { buf.WriteByte(CommandConnectV2) diff --git a/transport/ssr/obfs/http_simple.go b/transport/ssr/obfs/http_simple.go index 26fb31247..c1ea76738 100644 --- a/transport/ssr/obfs/http_simple.go +++ b/transport/ssr/obfs/http_simple.go @@ -10,7 +10,6 @@ import ( "strings" "github.com/Dreamacro/clash/common/pool" - "github.com/Dreamacro/clash/transport/ssr/tools" ) func init() { @@ -102,9 +101,8 @@ func (c *httpConn) Write(b []byte) (int, error) { hosts := strings.Split(host, ",") host = hosts[rand.Intn(len(hosts))] - buf := tools.BufPool.Get().(*bytes.Buffer) - defer tools.BufPool.Put(buf) - defer buf.Reset() + buf := pool.GetBuffer() + defer pool.PutBuffer(buf) if c.post { buf.WriteString("POST /") } else { diff --git a/transport/ssr/obfs/tls1.2_ticket_auth.go b/transport/ssr/obfs/tls1.2_ticket_auth.go index d9141121c..10f2786ad 100644 --- a/transport/ssr/obfs/tls1.2_ticket_auth.go +++ b/transport/ssr/obfs/tls1.2_ticket_auth.go @@ -87,9 +87,8 @@ func (c *tls12TicketConn) Read(b []byte) (int, error) { func (c *tls12TicketConn) Write(b []byte) (int, error) { length := len(b) if c.handshakeStatus == 8 { - buf := tools.BufPool.Get().(*bytes.Buffer) - defer tools.BufPool.Put(buf) - defer buf.Reset() + buf := pool.GetBuffer() + defer pool.PutBuffer(buf) for len(b) > 2048 { size := rand.Intn(4096) + 100 if len(b) < size { @@ -115,9 +114,8 @@ func (c *tls12TicketConn) Write(b []byte) (int, error) { if c.handshakeStatus == 0 { c.handshakeStatus = 1 - data := tools.BufPool.Get().(*bytes.Buffer) - defer tools.BufPool.Put(data) - defer data.Reset() + data := pool.GetBuffer() + defer pool.PutBuffer(data) data.Write([]byte{3, 3}) c.packAuthData(data) @@ -126,9 +124,8 @@ func (c *tls12TicketConn) Write(b []byte) (int, error) { data.Write([]byte{0x00, 0x1c, 0xc0, 0x2b, 0xc0, 0x2f, 0xcc, 0xa9, 0xcc, 0xa8, 0xcc, 0x14, 0xcc, 0x13, 0xc0, 0x0a, 0xc0, 0x14, 0xc0, 0x09, 0xc0, 0x13, 0x00, 0x9c, 0x00, 0x35, 0x00, 0x2f, 0x00, 0x0a}) data.Write([]byte{0x1, 0x0}) - ext := tools.BufPool.Get().(*bytes.Buffer) - defer tools.BufPool.Put(ext) - defer ext.Reset() + ext := pool.GetBuffer() + defer pool.PutBuffer(ext) host := c.getHost() ext.Write([]byte{0xff, 0x01, 0x00, 0x01, 0x00}) @@ -145,9 +142,8 @@ func (c *tls12TicketConn) Write(b []byte) (int, error) { binary.Write(data, binary.BigEndian, uint16(ext.Len())) data.ReadFrom(ext) - ret := tools.BufPool.Get().(*bytes.Buffer) - defer tools.BufPool.Put(ret) - defer ret.Reset() + ret := pool.GetBuffer() + defer pool.PutBuffer(ret) ret.Write([]byte{0x16, 3, 1}) binary.Write(ret, binary.BigEndian, uint16(data.Len()+4)) @@ -161,9 +157,8 @@ func (c *tls12TicketConn) Write(b []byte) (int, error) { } return length, nil } else if c.handshakeStatus == 1 && len(b) == 0 { - buf := tools.BufPool.Get().(*bytes.Buffer) - defer tools.BufPool.Put(buf) - defer buf.Reset() + buf := pool.GetBuffer() + defer pool.PutBuffer(buf) buf.Write([]byte{0x14, 3, 3, 0, 1, 1, 0x16, 3, 3, 0, 0x20}) tools.AppendRandBytes(buf, 22) diff --git a/transport/ssr/protocol/packet.go b/transport/ssr/protocol/packet.go index 621dc8c8f..249db70a2 100644 --- a/transport/ssr/protocol/packet.go +++ b/transport/ssr/protocol/packet.go @@ -1,10 +1,9 @@ package protocol import ( - "bytes" "net" - "github.com/Dreamacro/clash/transport/ssr/tools" + "github.com/Dreamacro/clash/common/pool" ) type PacketConn struct { @@ -13,9 +12,8 @@ type PacketConn struct { } func (c *PacketConn) WriteTo(b []byte, addr net.Addr) (int, error) { - buf := tools.BufPool.Get().(*bytes.Buffer) - defer tools.BufPool.Put(buf) - defer buf.Reset() + buf := pool.GetBuffer() + defer pool.PutBuffer(buf) err := c.EncodePacket(buf, b) if err != nil { return 0, err diff --git a/transport/ssr/protocol/stream.go b/transport/ssr/protocol/stream.go index 25d46f74a..3c846157a 100644 --- a/transport/ssr/protocol/stream.go +++ b/transport/ssr/protocol/stream.go @@ -5,7 +5,6 @@ import ( "net" "github.com/Dreamacro/clash/common/pool" - "github.com/Dreamacro/clash/transport/ssr/tools" ) type Conn struct { @@ -37,9 +36,8 @@ func (c *Conn) Read(b []byte) (int, error) { func (c *Conn) Write(b []byte) (int, error) { bLength := len(b) - buf := tools.BufPool.Get().(*bytes.Buffer) - defer tools.BufPool.Put(buf) - defer buf.Reset() + buf := pool.GetBuffer() + defer pool.PutBuffer(buf) err := c.Encode(buf, b) if err != nil { return 0, err diff --git a/transport/ssr/tools/bufPool.go b/transport/ssr/tools/bufPool.go index f3c45c469..ac15c97db 100644 --- a/transport/ssr/tools/bufPool.go +++ b/transport/ssr/tools/bufPool.go @@ -2,17 +2,10 @@ package tools import ( "bytes" - "math/rand" - "sync" - - "github.com/Dreamacro/clash/common/pool" + "crypto/rand" + "io" ) -var BufPool = sync.Pool{New: func() interface{} { return &bytes.Buffer{} }} - func AppendRandBytes(b *bytes.Buffer, length int) { - randBytes := pool.Get(length) - defer pool.Put(randBytes) - rand.Read(randBytes) - b.Write(randBytes) + b.ReadFrom(io.LimitReader(rand.Reader, int64(length))) } diff --git a/transport/trojan/trojan.go b/transport/trojan/trojan.go index d62e3f80d..d39cbec1e 100644 --- a/transport/trojan/trojan.go +++ b/transport/trojan/trojan.go @@ -1,7 +1,6 @@ package trojan import ( - "bytes" "crypto/sha256" "crypto/tls" "encoding/binary" @@ -11,6 +10,7 @@ import ( "net" "sync" + "github.com/Dreamacro/clash/common/pool" "github.com/Dreamacro/clash/transport/socks5" ) @@ -22,8 +22,6 @@ const ( var ( defaultALPN = []string{"h2", "http/1.1"} crlf = []byte{'\r', '\n'} - - bufPool = sync.Pool{New: func() interface{} { return &bytes.Buffer{} }} ) type Command = byte @@ -67,9 +65,8 @@ func (t *Trojan) StreamConn(conn net.Conn) (net.Conn, error) { } func (t *Trojan) WriteHeader(w io.Writer, command Command, socks5Addr []byte) error { - buf := bufPool.Get().(*bytes.Buffer) - defer bufPool.Put(buf) - defer buf.Reset() + buf := pool.GetBuffer() + defer pool.PutBuffer(buf) buf.Write(t.hexPassword) buf.Write(crlf) @@ -89,9 +86,8 @@ func (t *Trojan) PacketConn(conn net.Conn) net.PacketConn { } func writePacket(w io.Writer, socks5Addr, payload []byte) (int, error) { - buf := bufPool.Get().(*bytes.Buffer) - defer bufPool.Put(buf) - defer buf.Reset() + buf := pool.GetBuffer() + defer pool.PutBuffer(buf) buf.Write(socks5Addr) binary.Write(buf, binary.BigEndian, uint16(len(payload))) From 9aeb4c8cfe83e77caef46594e27797dd8f30bec3 Mon Sep 17 00:00:00 2001 From: bobo liu <7552030+fakeboboliu@users.noreply.github.com> Date: Tue, 28 Sep 2021 23:15:53 +0800 Subject: [PATCH 69/96] Improve: avoid bufconn twice (#1650) --- common/net/bufconn.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/common/net/bufconn.go b/common/net/bufconn.go index cb7433d2e..a50c7f030 100644 --- a/common/net/bufconn.go +++ b/common/net/bufconn.go @@ -11,6 +11,9 @@ type BufferedConn struct { } func NewBufferedConn(c net.Conn) *BufferedConn { + if bc, ok := c.(*BufferedConn); ok { + return bc + } return &BufferedConn{bufio.NewReader(c), c} } From ced9749104e47d717a849a4ae18fd9c6ed0a0658 Mon Sep 17 00:00:00 2001 From: Kr328 Date: Thu, 30 Sep 2021 16:30:07 +0800 Subject: [PATCH 70/96] Fix: http proxy should response correct http version (#1651) --- listener/http/proxy.go | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/listener/http/proxy.go b/listener/http/proxy.go index 229106dfe..23a73739a 100644 --- a/listener/http/proxy.go +++ b/listener/http/proxy.go @@ -1,6 +1,7 @@ package http import ( + "fmt" "net" "net/http" "strings" @@ -43,11 +44,8 @@ func HandleConn(c net.Conn, in chan<- C.ConnContext, cache *cache.Cache) { if trusted { if request.Method == http.MethodConnect { - resp = responseWith(200) - resp.Status = "Connection established" - resp.ContentLength = -1 - - if resp.Write(conn) != nil { + // Manual writing to support CONNECT for http 1.0 (workaround for uplay client) + if _, err = fmt.Fprintf(conn, "HTTP/%d.%d %03d %s\r\n\r\n", request.ProtoMajor, request.ProtoMinor, http.StatusOK, "Connection established"); err != nil { break // close connection } @@ -67,11 +65,11 @@ func HandleConn(c net.Conn, in chan<- C.ConnContext, cache *cache.Cache) { removeExtraHTTPHostPort(request) if request.URL.Scheme == "" || request.URL.Host == "" { - resp = responseWith(http.StatusBadRequest) + resp = responseWith(request, http.StatusBadRequest) } else { resp, err = client.Do(request) if err != nil { - resp = responseWith(http.StatusBadGateway) + resp = responseWith(request, http.StatusBadGateway) } } @@ -100,7 +98,7 @@ func authenticate(request *http.Request, cache *cache.Cache) *http.Response { if authenticator != nil { credential := parseBasicProxyAuthorization(request) if credential == "" { - resp := responseWith(http.StatusProxyAuthRequired) + resp := responseWith(request, http.StatusProxyAuthRequired) resp.Header.Set("Proxy-Authenticate", "Basic") return resp } @@ -114,20 +112,20 @@ func authenticate(request *http.Request, cache *cache.Cache) *http.Response { if !authed.(bool) { log.Infoln("Auth failed from %s", request.RemoteAddr) - return responseWith(http.StatusForbidden) + return responseWith(request, http.StatusForbidden) } } return nil } -func responseWith(statusCode int) *http.Response { +func responseWith(request *http.Request, statusCode int) *http.Response { return &http.Response{ StatusCode: statusCode, Status: http.StatusText(statusCode), - Proto: "HTTP/1.1", - ProtoMajor: 1, - ProtoMinor: 1, + Proto: request.Proto, + ProtoMajor: request.ProtoMajor, + ProtoMinor: request.ProtoMinor, Header: http.Header{}, } } From 537b672fcf9917c51003291bc73145d6713520f2 Mon Sep 17 00:00:00 2001 From: Dreamacro <8615343+Dreamacro@users.noreply.github.com> Date: Mon, 4 Oct 2021 19:20:11 +0800 Subject: [PATCH 71/96] Change: use bbolt as cache db --- component/profile/cachefile/cache.go | 119 +++++++++++++++++---------- constant/path.go | 6 +- go.mod | 1 + go.sum | 3 + 4 files changed, 83 insertions(+), 46 deletions(-) diff --git a/component/profile/cachefile/cache.go b/component/profile/cachefile/cache.go index b23eeb97f..e78e0cca6 100644 --- a/component/profile/cachefile/cache.go +++ b/component/profile/cachefile/cache.go @@ -10,45 +10,40 @@ import ( "github.com/Dreamacro/clash/component/profile" C "github.com/Dreamacro/clash/constant" "github.com/Dreamacro/clash/log" + + bolt "go.etcd.io/bbolt" ) var ( initOnce sync.Once fileMode os.FileMode = 0666 defaultCache *CacheFile -) -type cache struct { - Selected map[string]string -} + bucketSelected = []byte("selected") +) // CacheFile store and update the cache file type CacheFile struct { - path string - model *cache - buf *bytes.Buffer - mux sync.Mutex + db *bolt.DB } func (c *CacheFile) SetSelected(group, selected string) { if !profile.StoreSelected.Load() { return - } - - c.mux.Lock() - defer c.mux.Unlock() - - model := c.element() - - model.Selected[group] = selected - c.buf.Reset() - if err := gob.NewEncoder(c.buf).Encode(model); err != nil { - log.Warnln("[CacheFile] encode gob failed: %s", err.Error()) + } else if c.db == nil { return } - if err := ioutil.WriteFile(c.path, c.buf.Bytes(), fileMode); err != nil { - log.Warnln("[CacheFile] write cache to %s failed: %s", c.path, err.Error()) + err := c.db.Batch(func(t *bolt.Tx) error { + bucket, err := t.CreateBucketIfNotExists(bucketSelected) + if err != nil { + return err + } + return bucket.Put([]byte(group), []byte(selected)) + }) + + if err != nil { + log.Warnln("[CacheFile] write cache to %s failed: %s", c.db.Path(), err.Error()) return } } @@ -56,46 +51,80 @@ func (c *CacheFile) SetSelected(group, selected string) { func (c *CacheFile) SelectedMap() map[string]string { if !profile.StoreSelected.Load() { return nil + } else if c.db == nil { + return nil } - c.mux.Lock() - defer c.mux.Unlock() - - model := c.element() - mapping := map[string]string{} - for k, v := range model.Selected { - mapping[k] = v - } + c.db.View(func(t *bolt.Tx) error { + bucket := t.Bucket(bucketSelected) + if bucket == nil { + return nil + } + + c := bucket.Cursor() + for k, v := c.First(); k != nil; k, v = c.Next() { + mapping[string(k)] = string(v) + } + return nil + }) return mapping } -func (c *CacheFile) element() *cache { - if c.model != nil { - return c.model - } +func (c *CacheFile) Close() error { + return c.db.Close() +} +func migrateCache() { + defer func() { + db, err := bolt.Open(C.Path.Cache(), fileMode, nil) + if err != nil { + log.Warnln("[CacheFile] can't open cache file: %s", err.Error()) + } + defaultCache = &CacheFile{ + db: db, + } + }() + + buf, err := ioutil.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) - if buf, err := ioutil.ReadFile(c.path); err == nil { - bufReader := bytes.NewBuffer(buf) - gob.NewDecoder(bufReader).Decode(model) + // write to new cache file + db, err := bolt.Open(C.Path.Cache(), fileMode, nil) + if err != nil { + return } - - c.model = model - return c.model + defer db.Close() + db.Batch(func(t *bolt.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 func Cache() *CacheFile { - initOnce.Do(func() { - defaultCache = &CacheFile{ - path: C.Path.Cache(), - buf: &bytes.Buffer{}, - } - }) + initOnce.Do(migrateCache) return defaultCache } diff --git a/constant/path.go b/constant/path.go index ba0e8c23b..781cc5f7c 100644 --- a/constant/path.go +++ b/constant/path.go @@ -55,6 +55,10 @@ func (p *path) MMDB() string { return P.Join(p.homeDir, "Country.mmdb") } -func (p *path) Cache() string { +func (p *path) OldCache() string { return P.Join(p.homeDir, ".cache") } + +func (p *path) Cache() string { + return P.Join(p.homeDir, "cache.db") +} diff --git a/go.mod b/go.mod index e955449b8..dc79d77af 100644 --- a/go.mod +++ b/go.mod @@ -14,6 +14,7 @@ require ( github.com/oschwald/geoip2-golang v1.5.0 github.com/sirupsen/logrus v1.8.1 github.com/stretchr/testify v1.7.0 + go.etcd.io/bbolt v1.3.6 go.uber.org/atomic v1.9.0 golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 golang.org/x/net v0.0.0-20210903162142-ad29c8ab022f diff --git a/go.sum b/go.sum index d1d97cfc4..1fbae8ce4 100644 --- a/go.sum +++ b/go.sum @@ -55,6 +55,8 @@ github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5Cc github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/u-root/uio v0.0.0-20210528114334-82958018845c h1:BFvcl34IGnw8yvJi8hlqLFo9EshRInwWBs2M5fGWzQA= github.com/u-root/uio v0.0.0-20210528114334-82958018845c/go.mod h1:LpEX5FO/cB+WF4TYGY1V5qktpaZLkKkSegbr0V4eYXA= +go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU= +go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= @@ -87,6 +89,7 @@ golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191224085550-c709ea063b76/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201009025420-dfb3f7c4e634/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201101102859-da207088b7d1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= From 4f1fac02abe706926f2f8139ec1752e24649fc39 Mon Sep 17 00:00:00 2001 From: Dreamacro <8615343+Dreamacro@users.noreply.github.com> Date: Tue, 5 Oct 2021 12:42:21 +0800 Subject: [PATCH 72/96] Chore: add remove TODO --- adapter/outbound/vmess.go | 36 +++++++++++++++------------- component/profile/cachefile/cache.go | 1 + test/go.mod | 1 + test/go.sum | 3 +++ 4 files changed, 24 insertions(+), 17 deletions(-) diff --git a/adapter/outbound/vmess.go b/adapter/outbound/vmess.go index 6ca82c15e..0dbb0f1bf 100644 --- a/adapter/outbound/vmess.go +++ b/adapter/outbound/vmess.go @@ -31,23 +31,25 @@ type Vmess struct { } type VmessOption struct { - Name string `proxy:"name"` - Server string `proxy:"server"` - Port int `proxy:"port"` - UUID string `proxy:"uuid"` - AlterID int `proxy:"alterId"` - Cipher string `proxy:"cipher"` - TLS bool `proxy:"tls,omitempty"` - UDP bool `proxy:"udp,omitempty"` - Network string `proxy:"network,omitempty"` - HTTPOpts HTTPOptions `proxy:"http-opts,omitempty"` - HTTP2Opts HTTP2Options `proxy:"h2-opts,omitempty"` - GrpcOpts GrpcOptions `proxy:"grpc-opts,omitempty"` - WSOpts WSOptions `proxy:"ws-opts,omitempty"` - WSPath string `proxy:"ws-path,omitempty"` - WSHeaders map[string]string `proxy:"ws-headers,omitempty"` - SkipCertVerify bool `proxy:"skip-cert-verify,omitempty"` - ServerName string `proxy:"servername,omitempty"` + Name string `proxy:"name"` + Server string `proxy:"server"` + Port int `proxy:"port"` + UUID string `proxy:"uuid"` + AlterID int `proxy:"alterId"` + Cipher string `proxy:"cipher"` + UDP bool `proxy:"udp,omitempty"` + Network string `proxy:"network,omitempty"` + TLS bool `proxy:"tls,omitempty"` + SkipCertVerify bool `proxy:"skip-cert-verify,omitempty"` + ServerName string `proxy:"servername,omitempty"` + HTTPOpts HTTPOptions `proxy:"http-opts,omitempty"` + HTTP2Opts HTTP2Options `proxy:"h2-opts,omitempty"` + GrpcOpts GrpcOptions `proxy:"grpc-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 { diff --git a/component/profile/cachefile/cache.go b/component/profile/cachefile/cache.go index e78e0cca6..ffd588615 100644 --- a/component/profile/cachefile/cache.go +++ b/component/profile/cachefile/cache.go @@ -75,6 +75,7 @@ func (c *CacheFile) Close() error { return c.db.Close() } +// TODO: remove migrateCache until 2022 func migrateCache() { defer func() { db, err := bolt.Open(C.Path.Cache(), fileMode, nil) diff --git a/test/go.mod b/test/go.mod index 990edb6c5..3a8781517 100644 --- a/test/go.mod +++ b/test/go.mod @@ -36,6 +36,7 @@ require ( github.com/pmezard/go-difflib v1.0.0 // indirect github.com/sirupsen/logrus v1.8.1 // indirect github.com/u-root/uio v0.0.0-20210528114334-82958018845c // indirect + go.etcd.io/bbolt v1.3.6 // indirect go.uber.org/atomic v1.9.0 // indirect golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 // indirect golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect diff --git a/test/go.sum b/test/go.sum index 27d2c4de2..e018f54c7 100644 --- a/test/go.sum +++ b/test/go.sum @@ -629,6 +629,8 @@ github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= +go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU= +go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= go.etcd.io/etcd v0.5.0-alpha.5.0.20200910180754-dd1b699fc489/go.mod h1:yVHk9ub3CSBatqGNg7GRmsnfLWtoW60w4eDYfh7vHDg= go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= @@ -800,6 +802,7 @@ golang.org/x/sys v0.0.0-20200817155316-9781c653f443/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200916030750-2334cc1a136f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200922070232-aee5d888a860/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201009025420-dfb3f7c4e634/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201101102859-da207088b7d1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= From b9d470cf79d145736fc87f73e3b7f58119e684a0 Mon Sep 17 00:00:00 2001 From: Dreamacro <8615343+Dreamacro@users.noreply.github.com> Date: Tue, 5 Oct 2021 13:31:19 +0800 Subject: [PATCH 73/96] Fix: dhcp client should request special interface --- dns/client.go | 13 +++++++++---- dns/dhcp.go | 7 +++++-- dns/resolver.go | 5 +++-- dns/util.go | 7 ++++--- 4 files changed, 21 insertions(+), 11 deletions(-) diff --git a/dns/client.go b/dns/client.go index 6a54f9fad..5cb1fe029 100644 --- a/dns/client.go +++ b/dns/client.go @@ -15,9 +15,10 @@ import ( type client struct { *D.Client - r *Resolver - port string - host string + r *Resolver + port string + host string + iface string } func (c *client) Exchange(m *D.Msg) (*D.Msg, error) { @@ -45,7 +46,11 @@ func (c *client) ExchangeContext(ctx context.Context, m *D.Msg) (*D.Msg, error) network = "tcp" } - conn, err := dialer.DialContext(ctx, network, net.JoinHostPort(ip.String(), c.port)) + options := []dialer.Option{} + if c.iface != "" { + options = append(options, dialer.WithInterface(c.iface)) + } + conn, err := dialer.DialContext(ctx, network, net.JoinHostPort(ip.String(), c.port), options...) if err != nil { return nil, err } diff --git a/dns/dhcp.go b/dns/dhcp.go index 94f8a36ce..f964cec8c 100644 --- a/dns/dhcp.go +++ b/dns/dhcp.go @@ -68,8 +68,11 @@ func (d *dhcpClient) resolve(ctx context.Context) (*Resolver, error) { dns, err := dhcp.ResolveDNSFromDHCP(ctx, d.ifaceName) if err == nil { nameserver := make([]NameServer, 0, len(dns)) - for _, d := range dns { - nameserver = append(nameserver, NameServer{Addr: net.JoinHostPort(d.String(), "53")}) + for _, item := range dns { + nameserver = append(nameserver, NameServer{ + Addr: net.JoinHostPort(item.String(), "53"), + Interface: d.ifaceName, + }) } res = NewResolver(Config{ diff --git a/dns/resolver.go b/dns/resolver.go index 914f1418e..8bbd0e8b2 100644 --- a/dns/resolver.go +++ b/dns/resolver.go @@ -302,8 +302,9 @@ func (r *Resolver) asyncExchange(ctx context.Context, client []dnsClient, msg *D } type NameServer struct { - Net string - Addr string + Net string + Addr string + Interface string } type FallbackFilter struct { diff --git a/dns/util.go b/dns/util.go index 0c3f42e59..b167809a4 100644 --- a/dns/util.go +++ b/dns/util.go @@ -138,9 +138,10 @@ func transform(servers []NameServer, resolver *Resolver) []dnsClient { UDPSize: 4096, Timeout: 5 * time.Second, }, - port: port, - host: host, - r: resolver, + port: port, + host: host, + iface: s.Interface, + r: resolver, }) } return ret From 66cb0b1218aecb2ea56852e6fba2933044f3dc10 Mon Sep 17 00:00:00 2001 From: Dreamacro <8615343+Dreamacro@users.noreply.github.com> Date: Tue, 5 Oct 2021 22:47:26 +0800 Subject: [PATCH 74/96] Fix: cache kv db should not block on init --- component/profile/cachefile/cache.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/component/profile/cachefile/cache.go b/component/profile/cachefile/cache.go index ffd588615..28b05ee02 100644 --- a/component/profile/cachefile/cache.go +++ b/component/profile/cachefile/cache.go @@ -6,6 +6,7 @@ import ( "io/ioutil" "os" "sync" + "time" "github.com/Dreamacro/clash/component/profile" C "github.com/Dreamacro/clash/constant" @@ -78,7 +79,7 @@ func (c *CacheFile) Close() error { // TODO: remove migrateCache until 2022 func migrateCache() { defer func() { - db, err := bolt.Open(C.Path.Cache(), fileMode, nil) + db, err := bolt.Open(C.Path.Cache(), fileMode, &bolt.Options{Timeout: time.Second}) if err != nil { log.Warnln("[CacheFile] can't open cache file: %s", err.Error()) } From 1996bef9e6cad6ee954facc186ea70e411eb108c Mon Sep 17 00:00:00 2001 From: beyondkmp Date: Thu, 7 Oct 2021 22:57:55 +0800 Subject: [PATCH 75/96] Chore: doh request should with id 0 (#1660) --- dns/doh.go | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/dns/doh.go b/dns/doh.go index 34375017d..53b0fb331 100644 --- a/dns/doh.go +++ b/dns/doh.go @@ -28,13 +28,19 @@ func (dc *dohClient) Exchange(m *D.Msg) (msg *D.Msg, err error) { } func (dc *dohClient) ExchangeContext(ctx context.Context, m *D.Msg) (msg *D.Msg, err error) { - req, err := dc.newRequest(m) + // https://datatracker.ietf.org/doc/html/rfc8484#section-4.1 + // In order to maximize cache friendliness, SHOULD use a DNS ID of 0 in every DNS request. + newM := *m + newM.Id = 0 + req, err := dc.newRequest(&newM) if err != nil { return nil, err } req = req.WithContext(ctx) - return dc.doRequest(req) + msg, err = dc.doRequest(req) + msg.Id = m.Id + return } // newRequest returns a new DoH request given a dns.Msg. From 4ce35870fea0eeceb212f83110b9ab4be88e9281 Mon Sep 17 00:00:00 2001 From: Dreamacro <8615343+Dreamacro@users.noreply.github.com> Date: Sat, 9 Oct 2021 20:35:06 +0800 Subject: [PATCH 76/96] Chore: remove deprecated ioutil --- adapter/outbound/socks5.go | 3 +-- adapter/provider/fetcher.go | 5 ++--- adapter/provider/vehicle.go | 7 ++++--- component/process/process_linux.go | 14 +++++++++----- component/profile/cachefile/cache.go | 3 +-- dns/doh.go | 4 ++-- hub/executor/executor.go | 3 +-- listener/socks/tcp.go | 3 +-- 8 files changed, 21 insertions(+), 21 deletions(-) diff --git a/adapter/outbound/socks5.go b/adapter/outbound/socks5.go index 1402c6186..d97395575 100644 --- a/adapter/outbound/socks5.go +++ b/adapter/outbound/socks5.go @@ -6,7 +6,6 @@ import ( "errors" "fmt" "io" - "io/ioutil" "net" "strconv" @@ -116,7 +115,7 @@ func (ss *Socks5) DialUDP(metadata *C.Metadata) (_ C.PacketConn, err error) { } go func() { - io.Copy(ioutil.Discard, c) + io.Copy(io.Discard, c) c.Close() // A UDP association terminates when the TCP connection that the UDP // ASSOCIATE request arrived on terminates. RFC1928 diff --git a/adapter/provider/fetcher.go b/adapter/provider/fetcher.go index 777e3aa54..d3c85ab56 100644 --- a/adapter/provider/fetcher.go +++ b/adapter/provider/fetcher.go @@ -3,7 +3,6 @@ package provider import ( "bytes" "crypto/md5" - "io/ioutil" "os" "path/filepath" "time" @@ -45,7 +44,7 @@ func (f *fetcher) Initial() (interface{}, error) { isLocal bool ) if stat, fErr := os.Stat(f.vehicle.Path()); fErr == nil { - buf, err = ioutil.ReadFile(f.vehicle.Path()) + buf, err = os.ReadFile(f.vehicle.Path()) modTime := stat.ModTime() f.updatedAt = &modTime isLocal = true @@ -165,7 +164,7 @@ func safeWrite(path string, buf []byte) error { } } - return ioutil.WriteFile(path, buf, fileMode) + return os.WriteFile(path, buf, fileMode) } func newFetcher(name string, interval time.Duration, vehicle types.Vehicle, parser parser, onUpdate func(interface{})) *fetcher { diff --git a/adapter/provider/vehicle.go b/adapter/provider/vehicle.go index f556e69c4..4f08c317e 100644 --- a/adapter/provider/vehicle.go +++ b/adapter/provider/vehicle.go @@ -2,10 +2,11 @@ package provider import ( "context" - "io/ioutil" + "io" "net" "net/http" "net/url" + "os" "time" "github.com/Dreamacro/clash/component/dialer" @@ -25,7 +26,7 @@ func (f *FileVehicle) Path() string { } func (f *FileVehicle) Read() ([]byte, error) { - return ioutil.ReadFile(f.path) + return os.ReadFile(f.path) } func NewFileVehicle(path string) *FileVehicle { @@ -84,7 +85,7 @@ func (h *HTTPVehicle) Read() ([]byte, error) { } defer resp.Body.Close() - buf, err := ioutil.ReadAll(resp.Body) + buf, err := io.ReadAll(resp.Body) if err != nil { return nil, err } diff --git a/component/process/process_linux.go b/component/process/process_linux.go index fabe969c8..f77c10597 100644 --- a/component/process/process_linux.go +++ b/component/process/process_linux.go @@ -5,8 +5,8 @@ import ( "encoding/binary" "fmt" "io" - "io/ioutil" "net" + "os" "path" "path/filepath" "syscall" @@ -167,7 +167,7 @@ func unpackSocketDiagResponse(msg *syscall.NetlinkMessage) (inode, uid uint32) { } func resolveProcessNameByProcSearch(inode, uid int) (string, error) { - files, err := ioutil.ReadDir(pathProc) + files, err := os.ReadDir(pathProc) if err != nil { return "", err } @@ -180,14 +180,18 @@ func resolveProcessNameByProcSearch(inode, uid int) (string, error) { continue } - if f.Sys().(*syscall.Stat_t).Uid != uint32(uid) { + info, err := f.Info() + if err != nil { + return "", err + } + if info.Sys().(*syscall.Stat_t).Uid != uint32(uid) { continue } processPath := path.Join(pathProc, f.Name()) fdPath := path.Join(processPath, "fd") - fds, err := ioutil.ReadDir(fdPath) + fds, err := os.ReadDir(fdPath) if err != nil { continue } @@ -199,7 +203,7 @@ func resolveProcessNameByProcSearch(inode, uid int) (string, error) { } if bytes.Equal(buffer[:n], socket) { - cmdline, err := ioutil.ReadFile(path.Join(processPath, "cmdline")) + cmdline, err := os.ReadFile(path.Join(processPath, "cmdline")) if err != nil { return "", err } diff --git a/component/profile/cachefile/cache.go b/component/profile/cachefile/cache.go index 28b05ee02..a9d1bc5b9 100644 --- a/component/profile/cachefile/cache.go +++ b/component/profile/cachefile/cache.go @@ -3,7 +3,6 @@ package cachefile import ( "bytes" "encoding/gob" - "io/ioutil" "os" "sync" "time" @@ -88,7 +87,7 @@ func migrateCache() { } }() - buf, err := ioutil.ReadFile(C.Path.OldCache()) + buf, err := os.ReadFile(C.Path.OldCache()) if err != nil { return } diff --git a/dns/doh.go b/dns/doh.go index 53b0fb331..3daa7f22b 100644 --- a/dns/doh.go +++ b/dns/doh.go @@ -3,7 +3,7 @@ package dns import ( "bytes" "context" - "io/ioutil" + "io" "net" "net/http" @@ -68,7 +68,7 @@ func (dc *dohClient) doRequest(req *http.Request) (msg *D.Msg, err error) { } defer resp.Body.Close() - buf, err := ioutil.ReadAll(resp.Body) + buf, err := io.ReadAll(resp.Body) if err != nil { return nil, err } diff --git a/hub/executor/executor.go b/hub/executor/executor.go index 5c002b64f..2147906f1 100644 --- a/hub/executor/executor.go +++ b/hub/executor/executor.go @@ -2,7 +2,6 @@ package executor import ( "fmt" - "io/ioutil" "os" "sync" @@ -33,7 +32,7 @@ func readConfig(path string) ([]byte, error) { if _, err := os.Stat(path); os.IsNotExist(err) { return nil, err } - data, err := ioutil.ReadFile(path) + data, err := os.ReadFile(path) if err != nil { return nil, err } diff --git a/listener/socks/tcp.go b/listener/socks/tcp.go index 49d0a1e31..29016f5b1 100644 --- a/listener/socks/tcp.go +++ b/listener/socks/tcp.go @@ -2,7 +2,6 @@ package socks import ( "io" - "io/ioutil" "net" "github.com/Dreamacro/clash/adapter/inbound" @@ -102,7 +101,7 @@ func HandleSocks5(conn net.Conn, in chan<- C.ConnContext) { } if command == socks5.CmdUDPAssociate { defer conn.Close() - io.Copy(ioutil.Discard, conn) + io.Copy(io.Discard, conn) return } in <- inbound.NewSocket(target, conn, C.SOCKS5) From f1cf7e926972e8d0a3e2042bec89f0175d987e39 Mon Sep 17 00:00:00 2001 From: Dreamacro <8615343+Dreamacro@users.noreply.github.com> Date: Sun, 10 Oct 2021 23:44:09 +0800 Subject: [PATCH 77/96] Style: use gofumpt for fmt --- .github/workflows/go.yml | 5 ++--- Makefile | 4 ++++ adapter/provider/fetcher.go | 4 ++-- adapter/provider/parser.go | 4 +--- common/cache/lrucache_test.go | 1 - common/murmur3/murmur32.go | 1 - common/observable/observable_test.go | 2 +- common/pool/alloc.go | 1 + common/singledo/singledo_test.go | 2 +- common/structure/structure_test.go | 6 ++++-- component/dialer/options.go | 4 +--- component/iface/iface.go | 6 ++++-- component/mmdb/mmdb.go | 6 ++++-- component/process/process_linux.go | 6 ++++-- component/profile/cachefile/cache.go | 3 +-- component/profile/profile.go | 6 ++---- component/trie/domain.go | 6 ++---- config/initial.go | 6 +++--- dns/filters.go | 1 + dns/middleware.go | 6 ++++-- dns/resolver.go | 1 - dns/util.go | 14 ++++++-------- hub/executor/executor.go | 4 +--- listener/auth/auth.go | 4 +--- log/level.go | 18 ++++++++---------- transport/gun/gun.go | 10 ++++------ transport/simple-obfs/tls.go | 1 + transport/snell/cipher.go | 1 + transport/snell/snell.go | 4 +--- transport/socks4/socks4.go | 2 +- transport/ssr/protocol/auth_aes128_sha1.go | 6 ++++-- transport/vmess/header.go | 2 +- transport/vmess/websocket.go | 1 + tunnel/mode.go | 14 ++++++-------- 34 files changed, 78 insertions(+), 84 deletions(-) diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index 1058dd4f4..af6f9a91d 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -30,9 +30,8 @@ jobs: - name: Get dependencies, run test and static check run: | go test ./... - go vet ./... - go install honnef.co/go/tools/cmd/staticcheck@latest - staticcheck -- $(go list ./...) + go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest + golangci-lint run --disable-all -E govet -E gofumpt -E megacheck ./... - name: Build if: startsWith(github.ref, 'refs/tags/') diff --git a/Makefile b/Makefile index 97328bc23..b6a5b22af 100644 --- a/Makefile +++ b/Makefile @@ -112,5 +112,9 @@ $(zip_releases): %.zip : % all-arch: $(PLATFORM_LIST) $(WINDOWS_ARCH_LIST) releases: $(gz_releases) $(zip_releases) + +lint: + golangci-lint run --disable-all -E govet -E gofumpt -E megacheck ./... + clean: rm $(BINDIR)/* diff --git a/adapter/provider/fetcher.go b/adapter/provider/fetcher.go index d3c85ab56..6c1e96b43 100644 --- a/adapter/provider/fetcher.go +++ b/adapter/provider/fetcher.go @@ -12,8 +12,8 @@ import ( ) var ( - fileMode os.FileMode = 0666 - dirMode os.FileMode = 0755 + fileMode os.FileMode = 0o666 + dirMode os.FileMode = 0o755 ) type parser = func([]byte) (interface{}, error) diff --git a/adapter/provider/parser.go b/adapter/provider/parser.go index f326d4ccb..8a1739669 100644 --- a/adapter/provider/parser.go +++ b/adapter/provider/parser.go @@ -10,9 +10,7 @@ import ( types "github.com/Dreamacro/clash/constant/provider" ) -var ( - errVehicleType = errors.New("unsupport vehicle type") -) +var errVehicleType = errors.New("unsupport vehicle type") type healthCheckSchema struct { Enable bool `provider:"enable"` diff --git a/common/cache/lrucache_test.go b/common/cache/lrucache_test.go index 13675bff3..8a04f7464 100644 --- a/common/cache/lrucache_test.go +++ b/common/cache/lrucache_test.go @@ -149,7 +149,6 @@ func TestSetWithExpire(t *testing.T) { assert.Equal(t, nil, res) assert.Equal(t, time.Time{}, expires) assert.Equal(t, false, exist) - } func TestStale(t *testing.T) { diff --git a/common/murmur3/murmur32.go b/common/murmur3/murmur32.go index 9861eecd8..e52b7937d 100644 --- a/common/murmur3/murmur32.go +++ b/common/murmur3/murmur32.go @@ -67,7 +67,6 @@ func (d *digest32) bmix(p []byte) (tail []byte) { } func (d *digest32) Sum32() (h1 uint32) { - h1 = d.h1 var k1 uint32 diff --git a/common/observable/observable_test.go b/common/observable/observable_test.go index cb16ad399..b70feec87 100644 --- a/common/observable/observable_test.go +++ b/common/observable/observable_test.go @@ -38,7 +38,7 @@ func TestObservable_MultiSubscribe(t *testing.T) { src := NewObservable(iter) ch1, _ := src.Subscribe() ch2, _ := src.Subscribe() - var count = atomic.NewInt32(0) + count := atomic.NewInt32(0) var wg sync.WaitGroup wg.Add(2) diff --git a/common/pool/alloc.go b/common/pool/alloc.go index 6ae53c1db..710639af8 100644 --- a/common/pool/alloc.go +++ b/common/pool/alloc.go @@ -53,6 +53,7 @@ func (alloc *Allocator) Put(buf []byte) error { } //lint:ignore SA6002 ignore temporarily + //nolint alloc.buffers[bits].Put(buf) return nil } diff --git a/common/singledo/singledo_test.go b/common/singledo/singledo_test.go index 2b0d5988b..c85795c20 100644 --- a/common/singledo/singledo_test.go +++ b/common/singledo/singledo_test.go @@ -12,7 +12,7 @@ import ( func TestBasic(t *testing.T) { single := NewSingle(time.Millisecond * 30) foo := 0 - var shardCount = atomic.NewInt32(0) + shardCount := atomic.NewInt32(0) call := func() (interface{}, error) { foo++ time.Sleep(time.Millisecond * 5) diff --git a/common/structure/structure_test.go b/common/structure/structure_test.go index 6e3e6290d..0feef28e8 100644 --- a/common/structure/structure_test.go +++ b/common/structure/structure_test.go @@ -5,8 +5,10 @@ import ( "testing" ) -var decoder = NewDecoder(Option{TagName: "test"}) -var weakTypeDecoder = NewDecoder(Option{TagName: "test", WeaklyTypedInput: true}) +var ( + decoder = NewDecoder(Option{TagName: "test"}) + weakTypeDecoder = NewDecoder(Option{TagName: "test", WeaklyTypedInput: true}) +) type Baz struct { Foo int `test:"foo"` diff --git a/component/dialer/options.go b/component/dialer/options.go index 4b5d64c0e..33083864a 100644 --- a/component/dialer/options.go +++ b/component/dialer/options.go @@ -1,8 +1,6 @@ package dialer -var ( - DefaultOptions []Option -) +var DefaultOptions []Option type config struct { skipDefault bool diff --git a/component/iface/iface.go b/component/iface/iface.go index 30c6a6bcb..4e9162601 100644 --- a/component/iface/iface.go +++ b/component/iface/iface.go @@ -15,8 +15,10 @@ type Interface struct { HardwareAddr net.HardwareAddr } -var ErrIfaceNotFound = errors.New("interface not found") -var ErrAddrNotFound = errors.New("addr not found") +var ( + ErrIfaceNotFound = errors.New("interface not found") + ErrAddrNotFound = errors.New("addr not found") +) var interfaces = singledo.NewSingle(time.Second * 20) diff --git a/component/mmdb/mmdb.go b/component/mmdb/mmdb.go index 08743985a..e120055d8 100644 --- a/component/mmdb/mmdb.go +++ b/component/mmdb/mmdb.go @@ -9,8 +9,10 @@ import ( "github.com/oschwald/geoip2-golang" ) -var mmdb *geoip2.Reader -var once sync.Once +var ( + mmdb *geoip2.Reader + once sync.Once +) func LoadFromBytes(buffer []byte) { once.Do(func() { diff --git a/component/process/process_linux.go b/component/process/process_linux.go index f77c10597..be758a692 100644 --- a/component/process/process_linux.go +++ b/component/process/process_linux.go @@ -25,8 +25,10 @@ var nativeEndian = func() binary.ByteOrder { return binary.LittleEndian }() -type SocketResolver func(network string, ip net.IP, srcPort int) (inode, uid int, err error) -type ProcessNameResolver func(inode, uid int) (name string, err error) +type ( + SocketResolver func(network string, ip net.IP, srcPort int) (inode, uid int, err error) + ProcessNameResolver func(inode, uid int) (name string, err error) +) // export for android var ( diff --git a/component/profile/cachefile/cache.go b/component/profile/cachefile/cache.go index a9d1bc5b9..03f389a3a 100644 --- a/component/profile/cachefile/cache.go +++ b/component/profile/cachefile/cache.go @@ -16,7 +16,7 @@ import ( var ( initOnce sync.Once - fileMode os.FileMode = 0666 + fileMode os.FileMode = 0o666 defaultCache *CacheFile bucketSelected = []byte("selected") @@ -41,7 +41,6 @@ func (c *CacheFile) SetSelected(group, selected string) { } return bucket.Put([]byte(group), []byte(selected)) }) - if err != nil { log.Warnln("[CacheFile] write cache to %s failed: %s", c.db.Path(), err.Error()) return diff --git a/component/profile/profile.go b/component/profile/profile.go index ca9b1b884..e3d9e78cf 100644 --- a/component/profile/profile.go +++ b/component/profile/profile.go @@ -4,7 +4,5 @@ import ( "go.uber.org/atomic" ) -var ( - // StoreSelected is a global switch for storing selected proxy to cache - StoreSelected = atomic.NewBool(true) -) +// StoreSelected is a global switch for storing selected proxy to cache +var StoreSelected = atomic.NewBool(true) diff --git a/component/trie/domain.go b/component/trie/domain.go index b4de4a707..ffd0b754a 100644 --- a/component/trie/domain.go +++ b/component/trie/domain.go @@ -12,10 +12,8 @@ const ( domainStep = "." ) -var ( - // ErrInvalidDomain means insert domain is invalid - ErrInvalidDomain = errors.New("invalid domain") -) +// ErrInvalidDomain means insert domain is invalid +var ErrInvalidDomain = errors.New("invalid domain") // DomainTrie contains the main logic for adding and searching nodes for domain segments. // support wildcard domain (e.g *.google.com) diff --git a/config/initial.go b/config/initial.go index df8452b93..9d1a2db10 100644 --- a/config/initial.go +++ b/config/initial.go @@ -18,7 +18,7 @@ func downloadMMDB(path string) (err error) { } defer resp.Body.Close() - f, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY, 0644) + f, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY, 0o644) if err != nil { return err } @@ -54,7 +54,7 @@ func initMMDB() error { func Init(dir string) error { // initial homedir if _, err := os.Stat(dir); os.IsNotExist(err) { - if err := os.MkdirAll(dir, 0777); err != nil { + if err := os.MkdirAll(dir, 0o777); err != nil { return fmt.Errorf("can't create config directory %s: %s", dir, err.Error()) } } @@ -62,7 +62,7 @@ func Init(dir string) error { // initial config.yaml if _, err := os.Stat(C.Path.Config()); os.IsNotExist(err) { log.Infoln("Can't find config, create a initial config file") - f, err := os.OpenFile(C.Path.Config(), os.O_CREATE|os.O_WRONLY, 0644) + f, err := os.OpenFile(C.Path.Config(), os.O_CREATE|os.O_WRONLY, 0o644) if err != nil { return fmt.Errorf("can't create file %s: %s", C.Path.Config(), err.Error()) } diff --git a/dns/filters.go b/dns/filters.go index bacd7727f..30825a44a 100644 --- a/dns/filters.go +++ b/dns/filters.go @@ -32,6 +32,7 @@ func (inf *ipnetFilter) Match(ip net.IP) bool { type fallbackDomainFilter interface { Match(domain string) bool } + type domainFilter struct { tree *trie.DomainTrie } diff --git a/dns/middleware.go b/dns/middleware.go index 782c0ef07..da84788d7 100644 --- a/dns/middleware.go +++ b/dns/middleware.go @@ -14,8 +14,10 @@ import ( D "github.com/miekg/dns" ) -type handler func(ctx *context.DNSContext, r *D.Msg) (*D.Msg, error) -type middleware func(next handler) handler +type ( + handler func(ctx *context.DNSContext, r *D.Msg) (*D.Msg, error) + middleware func(next handler) handler +) func withHosts(hosts *trie.DomainTrie) middleware { return func(next handler) handler { diff --git a/dns/resolver.go b/dns/resolver.go index 8bbd0e8b2..bf544cb99 100644 --- a/dns/resolver.go +++ b/dns/resolver.go @@ -215,7 +215,6 @@ func (r *Resolver) shouldOnlyQueryFallback(m *D.Msg) bool { } func (r *Resolver) ipExchange(ctx context.Context, m *D.Msg) (msg *D.Msg, err error) { - if matched := r.matchPolicy(m); len(matched) != 0 { res := <-r.asyncExchange(ctx, matched, m) return res.Msg, res.Error diff --git a/dns/util.go b/dns/util.go index b167809a4..0e1badabc 100644 --- a/dns/util.go +++ b/dns/util.go @@ -13,14 +13,12 @@ import ( D "github.com/miekg/dns" ) -var ( - // EnhancedModeMapping is a mapping for EnhancedMode enum - EnhancedModeMapping = map[string]EnhancedMode{ - NORMAL.String(): NORMAL, - FAKEIP.String(): FAKEIP, - MAPPING.String(): MAPPING, - } -) +// EnhancedModeMapping is a mapping for EnhancedMode enum +var EnhancedModeMapping = map[string]EnhancedMode{ + NORMAL.String(): NORMAL, + FAKEIP.String(): FAKEIP, + MAPPING.String(): MAPPING, +} const ( NORMAL EnhancedMode = iota diff --git a/hub/executor/executor.go b/hub/executor/executor.go index 2147906f1..ca8ee95de 100644 --- a/hub/executor/executor.go +++ b/hub/executor/executor.go @@ -24,9 +24,7 @@ import ( "github.com/Dreamacro/clash/tunnel" ) -var ( - mux sync.Mutex -) +var mux sync.Mutex func readConfig(path string) ([]byte, error) { if _, err := os.Stat(path); os.IsNotExist(err) { diff --git a/listener/auth/auth.go b/listener/auth/auth.go index 2c29e186e..70473114d 100644 --- a/listener/auth/auth.go +++ b/listener/auth/auth.go @@ -4,9 +4,7 @@ import ( "github.com/Dreamacro/clash/component/auth" ) -var ( - authenticator auth.Authenticator -) +var authenticator auth.Authenticator func Authenticator() auth.Authenticator { return authenticator diff --git a/log/level.go b/log/level.go index ea223c127..f70116a32 100644 --- a/log/level.go +++ b/log/level.go @@ -5,16 +5,14 @@ import ( "errors" ) -var ( - // LogLevelMapping is a mapping for LogLevel enum - LogLevelMapping = map[string]LogLevel{ - ERROR.String(): ERROR, - WARNING.String(): WARNING, - INFO.String(): INFO, - DEBUG.String(): DEBUG, - SILENT.String(): SILENT, - } -) +// LogLevelMapping is a mapping for LogLevel enum +var LogLevelMapping = map[string]LogLevel{ + ERROR.String(): ERROR, + WARNING.String(): WARNING, + INFO.String(): INFO, + DEBUG.String(): DEBUG, + SILENT.String(): SILENT, +} const ( DEBUG LogLevel = iota diff --git a/transport/gun/gun.go b/transport/gun/gun.go index e60d13d75..f6f761166 100644 --- a/transport/gun/gun.go +++ b/transport/gun/gun.go @@ -27,12 +27,10 @@ var ( ErrSmallBuffer = errors.New("buffer too small") ) -var ( - defaultHeader = http.Header{ - "content-type": []string{"application/grpc"}, - "user-agent": []string{"grpc-go/1.36.0"}, - } -) +var defaultHeader = http.Header{ + "content-type": []string{"application/grpc"}, + "user-agent": []string{"grpc-go/1.36.0"}, +} type DialFn = func(network, addr string) (net.Conn, error) diff --git a/transport/simple-obfs/tls.go b/transport/simple-obfs/tls.go index 914cfe4af..1c609c15a 100644 --- a/transport/simple-obfs/tls.go +++ b/transport/simple-obfs/tls.go @@ -78,6 +78,7 @@ func (to *TLSObfs) Read(b []byte) (int, error) { // type + ver = 3 return to.read(b, 3) } + func (to *TLSObfs) Write(b []byte) (int, error) { length := len(b) for i := 0; i < length; i += chunkSize { diff --git a/transport/snell/cipher.go b/transport/snell/cipher.go index f778e6471..0f31aea53 100644 --- a/transport/snell/cipher.go +++ b/transport/snell/cipher.go @@ -20,6 +20,7 @@ func (sc *snellCipher) SaltSize() int { return 16 } func (sc *snellCipher) Encrypter(salt []byte) (cipher.AEAD, error) { return sc.makeAEAD(snellKDF(sc.psk, salt, sc.KeySize())) } + func (sc *snellCipher) Decrypter(salt []byte) (cipher.AEAD, error) { return sc.makeAEAD(snellKDF(sc.psk, salt, sc.KeySize())) } diff --git a/transport/snell/snell.go b/transport/snell/snell.go index 8966b4bb7..64807b819 100644 --- a/transport/snell/snell.go +++ b/transport/snell/snell.go @@ -30,9 +30,7 @@ const ( Version byte = 1 ) -var ( - endSignal = []byte{} -) +var endSignal = []byte{} type Snell struct { net.Conn diff --git a/transport/socks4/socks4.go b/transport/socks4/socks4.go index c06bea20f..a29416241 100644 --- a/transport/socks4/socks4.go +++ b/transport/socks4/socks4.go @@ -184,7 +184,7 @@ func isReservedIP(ip net.IP) bool { } func readUntilNull(r io.Reader) ([]byte, error) { - var buf = &bytes.Buffer{} + buf := &bytes.Buffer{} var data [1]byte for { diff --git a/transport/ssr/protocol/auth_aes128_sha1.go b/transport/ssr/protocol/auth_aes128_sha1.go index fab9d0081..8ce57d288 100644 --- a/transport/ssr/protocol/auth_aes128_sha1.go +++ b/transport/ssr/protocol/auth_aes128_sha1.go @@ -14,8 +14,10 @@ import ( "github.com/Dreamacro/clash/transport/ssr/tools" ) -type hmacMethod func(key, data []byte) []byte -type hashDigestMethod func([]byte) []byte +type ( + hmacMethod func(key, data []byte) []byte + hashDigestMethod func([]byte) []byte +) func init() { register("auth_aes128_sha1", newAuthAES128SHA1, 9) diff --git a/transport/vmess/header.go b/transport/vmess/header.go index 27a734bed..67d407e6f 100644 --- a/transport/vmess/header.go +++ b/transport/vmess/header.go @@ -92,7 +92,7 @@ func sealVMessAEADHeader(key [16]byte, data []byte, t time.Time) []byte { payloadHeaderAEADEncrypted = payloadHeaderAEAD.Seal(nil, payloadHeaderAEADNonce, data, generatedAuthID[:]) } - var outputBuffer = &bytes.Buffer{} + outputBuffer := &bytes.Buffer{} outputBuffer.Write(generatedAuthID[:]) outputBuffer.Write(payloadHeaderLengthAEADEncrypted) diff --git a/transport/vmess/websocket.go b/transport/vmess/websocket.go index f00e4c4bf..951fb5d0a 100644 --- a/transport/vmess/websocket.go +++ b/transport/vmess/websocket.go @@ -28,6 +28,7 @@ type websocketConn struct { rMux sync.Mutex wMux sync.Mutex } + type websocketWithEarlyDataConn struct { net.Conn underlay net.Conn diff --git a/tunnel/mode.go b/tunnel/mode.go index 6e07a060a..696607215 100644 --- a/tunnel/mode.go +++ b/tunnel/mode.go @@ -8,14 +8,12 @@ import ( type TunnelMode int -var ( - // ModeMapping is a mapping for Mode enum - ModeMapping = map[string]TunnelMode{ - Global.String(): Global, - Rule.String(): Rule, - Direct.String(): Direct, - } -) +// ModeMapping is a mapping for Mode enum +var ModeMapping = map[string]TunnelMode{ + Global.String(): Global, + Rule.String(): Rule, + Direct.String(): Direct, +} const ( Global TunnelMode = iota From a1c2478e74a86b7160c558aef1ae6980a7d36f88 Mon Sep 17 00:00:00 2001 From: Dreamacro <8615343+Dreamacro@users.noreply.github.com> Date: Mon, 11 Oct 2021 20:08:18 +0800 Subject: [PATCH 78/96] Chore: actions split lint and release --- .github/workflows/linter.yml | 12 ++++++++++++ .github/workflows/{go.yml => release.yml} | 10 +++------- 2 files changed, 15 insertions(+), 7 deletions(-) create mode 100644 .github/workflows/linter.yml rename .github/workflows/{go.yml => release.yml} (81%) diff --git a/.github/workflows/linter.yml b/.github/workflows/linter.yml new file mode 100644 index 000000000..26d318c30 --- /dev/null +++ b/.github/workflows/linter.yml @@ -0,0 +1,12 @@ +name: Linter +on: [push, pull_request] +jobs: + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: golangci-lint + uses: golangci/golangci-lint-action@v2 + with: + version: latest + args: --disable-all -E govet -E gofumpt -E megacheck ./... diff --git a/.github/workflows/go.yml b/.github/workflows/release.yml similarity index 81% rename from .github/workflows/go.yml rename to .github/workflows/release.yml index af6f9a91d..d4bad8a37 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/release.yml @@ -1,9 +1,7 @@ -name: Go -on: [push, pull_request] +name: Release +on: [push] jobs: - build: - name: Build runs-on: ubuntu-latest steps: - name: Get latest go version @@ -27,11 +25,9 @@ jobs: restore-keys: | ${{ runner.os }}-go- - - name: Get dependencies, run test and static check + - name: Get dependencies, run test run: | go test ./... - go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest - golangci-lint run --disable-all -E govet -E gofumpt -E megacheck ./... - name: Build if: startsWith(github.ref, 'refs/tags/') From 3d5681cffd371ecdb9b340fd963872e8416d32e9 Mon Sep 17 00:00:00 2001 From: Dreamacro Date: Mon, 11 Oct 2021 20:48:58 +0800 Subject: [PATCH 79/96] Feature: persistence fakeip (#1662) --- component/fakeip/cachefile.go | 49 ++++++++++ component/fakeip/memory.go | 60 ++++++++++++ component/fakeip/pool.go | 95 ++++++++++-------- component/fakeip/pool_test.go | 141 ++++++++++++++++++++++++--- component/profile/cachefile/cache.go | 75 +++++++++++--- config/config.go | 13 ++- dns/enhancer.go | 2 +- dns/middleware.go | 2 +- 8 files changed, 364 insertions(+), 73 deletions(-) create mode 100644 component/fakeip/cachefile.go create mode 100644 component/fakeip/memory.go diff --git a/component/fakeip/cachefile.go b/component/fakeip/cachefile.go new file mode 100644 index 000000000..7ee889812 --- /dev/null +++ b/component/fakeip/cachefile.go @@ -0,0 +1,49 @@ +package fakeip + +import ( + "net" + + "github.com/Dreamacro/clash/component/profile/cachefile" +) + +type cachefileStore struct { + cache *cachefile.CacheFile +} + +// GetByHost implements store.GetByHost +func (c *cachefileStore) GetByHost(host string) (net.IP, bool) { + elm := c.cache.GetFakeip([]byte(host)) + if elm == nil { + return nil, false + } + return net.IP(elm), true +} + +// PutByHost implements store.PutByHost +func (c *cachefileStore) PutByHost(host string, ip net.IP) { + c.cache.PutFakeip([]byte(host), ip) +} + +// GetByIP implements store.GetByIP +func (c *cachefileStore) GetByIP(ip net.IP) (string, bool) { + elm := c.cache.GetFakeip(ip.To4()) + if elm == nil { + return "", false + } + return string(elm), true +} + +// PutByIP implements store.PutByIP +func (c *cachefileStore) PutByIP(ip net.IP, host string) { + c.cache.PutFakeip(ip.To4(), []byte(host)) +} + +// Exist implements store.Exist +func (c *cachefileStore) Exist(ip net.IP) bool { + _, exist := c.GetByIP(ip) + return exist +} + +// CloneTo implements store.CloneTo +// already persistence +func (c *cachefileStore) CloneTo(store store) {} diff --git a/component/fakeip/memory.go b/component/fakeip/memory.go new file mode 100644 index 000000000..75d4a3b24 --- /dev/null +++ b/component/fakeip/memory.go @@ -0,0 +1,60 @@ +package fakeip + +import ( + "net" + + "github.com/Dreamacro/clash/common/cache" +) + +type memoryStore struct { + cache *cache.LruCache +} + +// GetByHost implements store.GetByHost +func (m *memoryStore) GetByHost(host string) (net.IP, bool) { + if elm, exist := m.cache.Get(host); exist { + ip := elm.(net.IP) + + // ensure ip --> host on head of linked list + m.cache.Get(ipToUint(ip.To4())) + return ip, true + } + + return nil, false +} + +// PutByHost implements store.PutByHost +func (m *memoryStore) PutByHost(host string, ip net.IP) { + m.cache.Set(host, ip) +} + +// GetByIP implements store.GetByIP +func (m *memoryStore) GetByIP(ip net.IP) (string, bool) { + if elm, exist := m.cache.Get(ipToUint(ip.To4())); exist { + host := elm.(string) + + // ensure host --> ip on head of linked list + m.cache.Get(host) + return host, true + } + + return "", false +} + +// PutByIP implements store.PutByIP +func (m *memoryStore) PutByIP(ip net.IP, host string) { + m.cache.Set(ipToUint(ip.To4()), host) +} + +// Exist implements store.Exist +func (m *memoryStore) Exist(ip net.IP) bool { + return m.cache.Exist(ipToUint(ip.To4())) +} + +// CloneTo implements store.CloneTo +// only for memoryStore to memoryStore +func (m *memoryStore) CloneTo(store store) { + if ms, ok := store.(*memoryStore); ok { + m.cache.CloneTo(ms.cache) + } +} diff --git a/component/fakeip/pool.go b/component/fakeip/pool.go index 97d812ac3..180d5eb18 100644 --- a/component/fakeip/pool.go +++ b/component/fakeip/pool.go @@ -6,9 +6,19 @@ import ( "sync" "github.com/Dreamacro/clash/common/cache" + "github.com/Dreamacro/clash/component/profile/cachefile" "github.com/Dreamacro/clash/component/trie" ) +type store interface { + GetByHost(host string) (net.IP, bool) + PutByHost(host string, ip net.IP) + GetByIP(ip net.IP) (string, bool) + PutByIP(ip net.IP, host string) + Exist(ip net.IP) bool + CloneTo(store) +} + // Pool is a implementation about fake ip generator without storage type Pool struct { max uint32 @@ -18,25 +28,19 @@ type Pool struct { mux sync.Mutex host *trie.DomainTrie ipnet *net.IPNet - cache *cache.LruCache + store store } // Lookup return a fake ip with host func (p *Pool) Lookup(host string) net.IP { p.mux.Lock() defer p.mux.Unlock() - if elm, exist := p.cache.Get(host); exist { - ip := elm.(net.IP) - - // ensure ip --> host on head of linked list - n := ipToUint(ip.To4()) - offset := n - p.min + 1 - p.cache.Get(offset) + if ip, exist := p.store.GetByHost(host); exist { return ip } ip := p.get(host) - p.cache.Set(host, ip) + p.store.PutByHost(host, ip) return ip } @@ -49,22 +53,11 @@ func (p *Pool) LookBack(ip net.IP) (string, bool) { return "", false } - n := ipToUint(ip.To4()) - offset := n - p.min + 1 - - if elm, exist := p.cache.Get(offset); exist { - host := elm.(string) - - // ensure host --> ip on head of linked list - p.cache.Get(host) - return host, true - } - - return "", false + return p.store.GetByIP(ip) } -// LookupHost return if domain in host -func (p *Pool) LookupHost(domain string) bool { +// ShouldSkipped return if domain should be skipped +func (p *Pool) ShouldSkipped(domain string) bool { if p.host == nil { return false } @@ -80,9 +73,7 @@ func (p *Pool) Exist(ip net.IP) bool { return false } - n := ipToUint(ip.To4()) - offset := n - p.min + 1 - return p.cache.Exist(offset) + return p.store.Exist(ip) } // Gateway return gateway ip @@ -95,9 +86,9 @@ func (p *Pool) IPNet() *net.IPNet { return p.ipnet } -// PatchFrom clone cache from old pool -func (p *Pool) PatchFrom(o *Pool) { - o.cache.CloneTo(p.cache) +// CloneFrom clone cache from old pool +func (p *Pool) CloneFrom(o *Pool) { + o.store.CloneTo(p.store) } func (p *Pool) get(host string) net.IP { @@ -109,12 +100,13 @@ func (p *Pool) get(host string) net.IP { break } - if !p.cache.Exist(p.offset) { + ip := uintToIP(p.min + p.offset - 1) + if !p.store.Exist(ip) { break } } ip := uintToIP(p.min + p.offset - 1) - p.cache.Set(p.offset, host) + p.store.PutByIP(ip, host) return ip } @@ -130,11 +122,24 @@ func uintToIP(v uint32) net.IP { return net.IP{byte(v >> 24), byte(v >> 16), byte(v >> 8), byte(v)} } -// New return Pool instance -func New(ipnet *net.IPNet, size int, host *trie.DomainTrie) (*Pool, error) { - min := ipToUint(ipnet.IP) + 2 +type Options struct { + IPNet *net.IPNet + Host *trie.DomainTrie - ones, bits := ipnet.Mask.Size() + // Size sets the maximum number of entries in memory + // and does not work if Persistence is true + Size int + + // Persistence will save the data to disk. + // Size will not work and record will be fully stored. + Persistence bool +} + +// New return Pool instance +func New(options Options) (*Pool, error) { + min := ipToUint(options.IPNet.IP) + 2 + + ones, bits := options.IPNet.Mask.Size() total := 1< Date: Mon, 11 Oct 2021 21:05:38 +0800 Subject: [PATCH 80/96] Fix: #1660 panic --- dns/doh.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/dns/doh.go b/dns/doh.go index 3daa7f22b..943123551 100644 --- a/dns/doh.go +++ b/dns/doh.go @@ -39,7 +39,9 @@ func (dc *dohClient) ExchangeContext(ctx context.Context, m *D.Msg) (msg *D.Msg, req = req.WithContext(ctx) msg, err = dc.doRequest(req) - msg.Id = m.Id + if err == nil { + msg.Id = m.Id + } return } From 583b2a5ace5be91abf64c2073275d2bf4ca61e46 Mon Sep 17 00:00:00 2001 From: Dreamacro <8615343+Dreamacro@users.noreply.github.com> Date: Thu, 14 Oct 2021 22:54:43 +0800 Subject: [PATCH 81/96] Change: use interface HardwareAddr for dhcp discovery --- component/dhcp/dhcp.go | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/component/dhcp/dhcp.go b/component/dhcp/dhcp.go index b2ca6928f..b7e9f5069 100644 --- a/component/dhcp/dhcp.go +++ b/component/dhcp/dhcp.go @@ -3,9 +3,10 @@ package dhcp import ( "context" "errors" - "math/rand" "net" + "github.com/Dreamacro/clash/component/iface" + "github.com/insomniacslk/dhcp/dhcpv4" ) @@ -23,7 +24,12 @@ func ResolveDNSFromDHCP(context context.Context, ifaceName string) ([]net.IP, er result := make(chan []net.IP, 1) - discovery, err := dhcpv4.NewDiscovery(randomHardware(), dhcpv4.WithBroadcast(true), dhcpv4.WithRequestedOptions(dhcpv4.OptionDomainNameServer)) + ifaceObj, err := iface.ResolveInterface(ifaceName) + if err != nil { + return nil, err + } + + discovery, err := dhcpv4.NewDiscovery(ifaceObj.HardwareAddr, dhcpv4.WithBroadcast(true), dhcpv4.WithRequestedOptions(dhcpv4.OptionDomainNameServer)) if err != nil { return nil, err } @@ -80,15 +86,3 @@ func receiveOffer(conn net.PacketConn, id dhcpv4.TransactionID, result chan<- [] return } } - -func randomHardware() net.HardwareAddr { - addr := make(net.HardwareAddr, 6) - - addr[0] = 0xff - - for i := 1; i < len(addr); i++ { - addr[i] = byte(rand.Intn(254) + 1) - } - - return addr -} From 68753b4ae11c7ca508bf422180e248b3ccd81068 Mon Sep 17 00:00:00 2001 From: Dreamacro <8615343+Dreamacro@users.noreply.github.com> Date: Fri, 15 Oct 2021 21:44:53 +0800 Subject: [PATCH 82/96] Chore: contexify ProxyAdapter ListenPacket --- .gitignore | 5 ++++- adapter/adapter.go | 18 +++++++++++++++--- adapter/outbound/base.go | 5 +++-- adapter/outbound/direct.go | 6 +++--- adapter/outbound/reject.go | 4 ++-- adapter/outbound/shadowsocks.go | 6 +++--- adapter/outbound/shadowsocksr.go | 6 +++--- adapter/outbound/socks5.go | 8 +++----- adapter/outbound/trojan.go | 6 ++---- adapter/outbound/vmess.go | 6 ++---- adapter/outboundgroup/fallback.go | 6 +++--- adapter/outboundgroup/loadbalance.go | 7 +++---- adapter/outboundgroup/selector.go | 6 +++--- adapter/outboundgroup/urltest.go | 6 +++--- constant/adapters.go | 19 +++++++++++++------ constant/provider/interface.go | 2 +- test/Makefile | 8 ++++++++ test/README.md | 4 ++-- test/clash_test.go | 7 ++++--- tunnel/tunnel.go | 27 ++++++++++++++++----------- 20 files changed, 96 insertions(+), 66 deletions(-) create mode 100644 test/Makefile diff --git a/.gitignore b/.gitignore index 0593cfd05..52efcc9bf 100644 --- a/.gitignore +++ b/.gitignore @@ -12,7 +12,7 @@ bin/* # Output of the go coverage tool, specifically when used with LiteIDE *.out -# dep +# go mod vendor vendor # GoLand @@ -20,3 +20,6 @@ vendor # macOS file .DS_Store + +# test suite +test/config/cache* diff --git a/adapter/adapter.go b/adapter/adapter.go index 526866a5c..263301636 100644 --- a/adapter/adapter.go +++ b/adapter/adapter.go @@ -36,12 +36,24 @@ func (p *Proxy) Dial(metadata *C.Metadata) (C.Conn, error) { // DialContext implements C.ProxyAdapter func (p *Proxy) DialContext(ctx context.Context, metadata *C.Metadata) (C.Conn, error) { conn, err := p.ProxyAdapter.DialContext(ctx, metadata) - if err != nil { - p.alive.Store(false) - } + p.alive.Store(err == nil) return conn, err } +// DialUDP implements C.ProxyAdapter +func (p *Proxy) DialUDP(metadata *C.Metadata) (C.PacketConn, error) { + ctx, cancel := context.WithTimeout(context.Background(), C.DefaultUDPTimeout) + defer cancel() + return p.ListenPacketContext(ctx, metadata) +} + +// ListenPacketContext implements C.ProxyAdapter +func (p *Proxy) ListenPacketContext(ctx context.Context, metadata *C.Metadata) (C.PacketConn, error) { + pc, err := p.ProxyAdapter.ListenPacketContext(ctx, metadata) + p.alive.Store(err == nil) + return pc, err +} + // DelayHistory implements C.Proxy func (p *Proxy) DelayHistory() []C.DelayHistory { queue := p.history.Copy() diff --git a/adapter/outbound/base.go b/adapter/outbound/base.go index a001d799e..22c0142b0 100644 --- a/adapter/outbound/base.go +++ b/adapter/outbound/base.go @@ -1,6 +1,7 @@ package outbound import ( + "context" "encoding/json" "errors" "net" @@ -30,8 +31,8 @@ func (b *Base) StreamConn(c net.Conn, metadata *C.Metadata) (net.Conn, error) { return c, errors.New("no support") } -// DialUDP implements C.ProxyAdapter -func (b *Base) DialUDP(metadata *C.Metadata) (C.PacketConn, error) { +// ListenPacketContext implements C.ProxyAdapter +func (b *Base) ListenPacketContext(ctx context.Context, metadata *C.Metadata) (C.PacketConn, error) { return nil, errors.New("no support") } diff --git a/adapter/outbound/direct.go b/adapter/outbound/direct.go index 4b53e306c..42433c410 100644 --- a/adapter/outbound/direct.go +++ b/adapter/outbound/direct.go @@ -22,9 +22,9 @@ func (d *Direct) DialContext(ctx context.Context, metadata *C.Metadata) (C.Conn, return NewConn(c, d), nil } -// DialUDP implements C.ProxyAdapter -func (d *Direct) DialUDP(metadata *C.Metadata) (C.PacketConn, error) { - pc, err := dialer.ListenPacket(context.Background(), "udp", "") +// ListenPacketContext implements C.ProxyAdapter +func (d *Direct) ListenPacketContext(ctx context.Context, metadata *C.Metadata) (C.PacketConn, error) { + pc, err := dialer.ListenPacket(ctx, "udp", "") if err != nil { return nil, err } diff --git a/adapter/outbound/reject.go b/adapter/outbound/reject.go index 367504964..a97c6c711 100644 --- a/adapter/outbound/reject.go +++ b/adapter/outbound/reject.go @@ -19,8 +19,8 @@ func (r *Reject) DialContext(ctx context.Context, metadata *C.Metadata) (C.Conn, return NewConn(&NopConn{}, r), nil } -// DialUDP implements C.ProxyAdapter -func (r *Reject) DialUDP(metadata *C.Metadata) (C.PacketConn, error) { +// ListenPacketContext implements C.ProxyAdapter +func (r *Reject) ListenPacketContext(ctx context.Context, metadata *C.Metadata) (C.PacketConn, error) { return nil, errors.New("match reject rule") } diff --git a/adapter/outbound/shadowsocks.go b/adapter/outbound/shadowsocks.go index 64b431a9b..0194954e7 100644 --- a/adapter/outbound/shadowsocks.go +++ b/adapter/outbound/shadowsocks.go @@ -87,9 +87,9 @@ func (ss *ShadowSocks) DialContext(ctx context.Context, metadata *C.Metadata) (_ return NewConn(c, ss), err } -// DialUDP implements C.ProxyAdapter -func (ss *ShadowSocks) DialUDP(metadata *C.Metadata) (C.PacketConn, error) { - pc, err := dialer.ListenPacket(context.Background(), "udp", "") +// ListenPacketContext implements C.ProxyAdapter +func (ss *ShadowSocks) ListenPacketContext(ctx context.Context, metadata *C.Metadata) (C.PacketConn, error) { + pc, err := dialer.ListenPacket(ctx, "udp", "") if err != nil { return nil, err } diff --git a/adapter/outbound/shadowsocksr.go b/adapter/outbound/shadowsocksr.go index 9ba8bc229..fb0dd7a5f 100644 --- a/adapter/outbound/shadowsocksr.go +++ b/adapter/outbound/shadowsocksr.go @@ -72,9 +72,9 @@ func (ssr *ShadowSocksR) DialContext(ctx context.Context, metadata *C.Metadata) return NewConn(c, ssr), err } -// DialUDP implements C.ProxyAdapter -func (ssr *ShadowSocksR) DialUDP(metadata *C.Metadata) (C.PacketConn, error) { - pc, err := dialer.ListenPacket(context.Background(), "udp", "") +// ListenPacketContext implements C.ProxyAdapter +func (ssr *ShadowSocksR) ListenPacketContext(ctx context.Context, metadata *C.Metadata) (C.PacketConn, error) { + pc, err := dialer.ListenPacket(ctx, "udp", "") if err != nil { return nil, err } diff --git a/adapter/outbound/socks5.go b/adapter/outbound/socks5.go index d97395575..7714c5c52 100644 --- a/adapter/outbound/socks5.go +++ b/adapter/outbound/socks5.go @@ -76,10 +76,8 @@ func (ss *Socks5) DialContext(ctx context.Context, metadata *C.Metadata) (_ C.Co return NewConn(c, ss), nil } -// DialUDP implements C.ProxyAdapter -func (ss *Socks5) DialUDP(metadata *C.Metadata) (_ C.PacketConn, err error) { - ctx, cancel := context.WithTimeout(context.Background(), C.DefaultTCPTimeout) - defer cancel() +// ListenPacketContext implements C.ProxyAdapter +func (ss *Socks5) ListenPacketContext(ctx context.Context, metadata *C.Metadata) (_ C.PacketConn, err error) { c, err := dialer.DialContext(ctx, "tcp", ss.addr) if err != nil { err = fmt.Errorf("%s connect error: %w", ss.addr, err) @@ -109,7 +107,7 @@ func (ss *Socks5) DialUDP(metadata *C.Metadata) (_ C.PacketConn, err error) { return } - pc, err := dialer.ListenPacket(context.Background(), "udp", "") + pc, err := dialer.ListenPacket(ctx, "udp", "") if err != nil { return } diff --git a/adapter/outbound/trojan.go b/adapter/outbound/trojan.go index afed410fb..b8ea49e65 100644 --- a/adapter/outbound/trojan.go +++ b/adapter/outbound/trojan.go @@ -88,8 +88,8 @@ func (t *Trojan) DialContext(ctx context.Context, metadata *C.Metadata) (_ C.Con return NewConn(c, t), err } -// DialUDP implements C.ProxyAdapter -func (t *Trojan) DialUDP(metadata *C.Metadata) (_ C.PacketConn, err error) { +// ListenPacketContext implements C.ProxyAdapter +func (t *Trojan) ListenPacketContext(ctx context.Context, metadata *C.Metadata) (_ C.PacketConn, err error) { var c net.Conn // grpc transport @@ -100,8 +100,6 @@ func (t *Trojan) DialUDP(metadata *C.Metadata) (_ C.PacketConn, err error) { } defer safeConnClose(c, err) } else { - ctx, cancel := context.WithTimeout(context.Background(), C.DefaultTCPTimeout) - defer cancel() c, err = dialer.DialContext(ctx, "tcp", t.addr) if err != nil { return nil, fmt.Errorf("%s connect error: %w", t.addr, err) diff --git a/adapter/outbound/vmess.go b/adapter/outbound/vmess.go index 0dbb0f1bf..209084ca8 100644 --- a/adapter/outbound/vmess.go +++ b/adapter/outbound/vmess.go @@ -215,8 +215,8 @@ func (v *Vmess) DialContext(ctx context.Context, metadata *C.Metadata) (_ C.Conn return NewConn(c, v), err } -// DialUDP implements C.ProxyAdapter -func (v *Vmess) DialUDP(metadata *C.Metadata) (_ C.PacketConn, err error) { +// ListenPacketContext implements C.ProxyAdapter +func (v *Vmess) ListenPacketContext(ctx context.Context, metadata *C.Metadata) (_ C.PacketConn, err error) { // vmess use stream-oriented udp with a special address, so we needs a net.UDPAddr if !metadata.Resolved() { ip, err := resolver.ResolveIP(metadata.Host) @@ -237,8 +237,6 @@ func (v *Vmess) DialUDP(metadata *C.Metadata) (_ C.PacketConn, err error) { c, err = v.client.StreamConn(c, parseVmessAddr(metadata)) } else { - ctx, cancel := context.WithTimeout(context.Background(), C.DefaultTCPTimeout) - defer cancel() c, err = dialer.DialContext(ctx, "tcp", v.addr) if err != nil { return nil, fmt.Errorf("%s connect error: %s", v.addr, err.Error()) diff --git a/adapter/outboundgroup/fallback.go b/adapter/outboundgroup/fallback.go index da01d4de1..3221b5527 100644 --- a/adapter/outboundgroup/fallback.go +++ b/adapter/outboundgroup/fallback.go @@ -32,10 +32,10 @@ func (f *Fallback) DialContext(ctx context.Context, metadata *C.Metadata) (C.Con return c, err } -// DialUDP implements C.ProxyAdapter -func (f *Fallback) DialUDP(metadata *C.Metadata) (C.PacketConn, error) { +// ListenPacketContext implements C.ProxyAdapter +func (f *Fallback) ListenPacketContext(ctx context.Context, metadata *C.Metadata) (C.PacketConn, error) { proxy := f.findAliveProxy(true) - pc, err := proxy.DialUDP(metadata) + pc, err := proxy.ListenPacketContext(ctx, metadata) if err == nil { pc.AppendToChains(f) } diff --git a/adapter/outboundgroup/loadbalance.go b/adapter/outboundgroup/loadbalance.go index e529b53be..fb2840102 100644 --- a/adapter/outboundgroup/loadbalance.go +++ b/adapter/outboundgroup/loadbalance.go @@ -82,8 +82,8 @@ func (lb *LoadBalance) DialContext(ctx context.Context, metadata *C.Metadata) (c return } -// DialUDP implements C.ProxyAdapter -func (lb *LoadBalance) DialUDP(metadata *C.Metadata) (pc C.PacketConn, err error) { +// ListenPacketContext implements C.ProxyAdapter +func (lb *LoadBalance) ListenPacketContext(ctx context.Context, metadata *C.Metadata) (pc C.PacketConn, err error) { defer func() { if err == nil { pc.AppendToChains(lb) @@ -91,8 +91,7 @@ func (lb *LoadBalance) DialUDP(metadata *C.Metadata) (pc C.PacketConn, err error }() proxy := lb.Unwrap(metadata) - - return proxy.DialUDP(metadata) + return proxy.ListenPacketContext(ctx, metadata) } // SupportUDP implements C.ProxyAdapter diff --git a/adapter/outboundgroup/selector.go b/adapter/outboundgroup/selector.go index 124539278..008e8af8d 100644 --- a/adapter/outboundgroup/selector.go +++ b/adapter/outboundgroup/selector.go @@ -28,9 +28,9 @@ func (s *Selector) DialContext(ctx context.Context, metadata *C.Metadata) (C.Con return c, err } -// DialUDP implements C.ProxyAdapter -func (s *Selector) DialUDP(metadata *C.Metadata) (C.PacketConn, error) { - pc, err := s.selectedProxy(true).DialUDP(metadata) +// ListenPacketContext implements C.ProxyAdapter +func (s *Selector) ListenPacketContext(ctx context.Context, metadata *C.Metadata) (C.PacketConn, error) { + pc, err := s.selectedProxy(true).ListenPacketContext(ctx, metadata) if err == nil { pc.AppendToChains(s) } diff --git a/adapter/outboundgroup/urltest.go b/adapter/outboundgroup/urltest.go index 2a11cd23b..b27f12a44 100644 --- a/adapter/outboundgroup/urltest.go +++ b/adapter/outboundgroup/urltest.go @@ -42,9 +42,9 @@ func (u *URLTest) DialContext(ctx context.Context, metadata *C.Metadata) (c C.Co return c, err } -// DialUDP implements C.ProxyAdapter -func (u *URLTest) DialUDP(metadata *C.Metadata) (C.PacketConn, error) { - pc, err := u.fast(true).DialUDP(metadata) +// ListenPacketContext implements C.ProxyAdapter +func (u *URLTest) ListenPacketContext(ctx context.Context, metadata *C.Metadata) (C.PacketConn, error) { + pc, err := u.fast(true).ListenPacketContext(ctx, metadata) if err == nil { pc.AppendToChains(u) } diff --git a/constant/adapters.go b/constant/adapters.go index 733d86b91..2f7006e96 100644 --- a/constant/adapters.go +++ b/constant/adapters.go @@ -29,6 +29,7 @@ const ( const ( DefaultTCPTimeout = 5 * time.Second + DefaultUDPTimeout = DefaultTCPTimeout ) type Connection interface { @@ -73,11 +74,14 @@ type PacketConn interface { type ProxyAdapter interface { Name() string Type() AdapterType + Addr() string + SupportUDP() bool + MarshalJSON() ([]byte, error) // StreamConn wraps a protocol around net.Conn with Metadata. // // Examples: - // conn, _ := net.Dial("tcp", "host:port") + // conn, _ := net.DialContext(context.Background(), "tcp", "host:port") // conn, _ = adapter.StreamConn(conn, metadata) // // It returns a C.Conn with protocol which start with @@ -88,10 +92,8 @@ type ProxyAdapter interface { // contains multiplexing-related reuse logic (if any) DialContext(ctx context.Context, metadata *Metadata) (Conn, error) - DialUDP(metadata *Metadata) (PacketConn, error) - SupportUDP() bool - MarshalJSON() ([]byte, error) - Addr() string + ListenPacketContext(ctx context.Context, metadata *Metadata) (PacketConn, error) + // Unwrap extracts the proxy from a proxy-group. It returns nil when nothing to extract. Unwrap(metadata *Metadata) Proxy } @@ -105,9 +107,14 @@ type Proxy interface { ProxyAdapter Alive() bool DelayHistory() []DelayHistory - Dial(metadata *Metadata) (Conn, error) LastDelay() uint16 URLTest(ctx context.Context, url string) (uint16, error) + + // Deprecated: use DialContext instead. + Dial(metadata *Metadata) (Conn, error) + + // Deprecated: use DialPacketConn instead. + DialUDP(metadata *Metadata) (PacketConn, error) } // AdapterType is enum of adapter type diff --git a/constant/provider/interface.go b/constant/provider/interface.go index d3483cdcd..53bda7eac 100644 --- a/constant/provider/interface.go +++ b/constant/provider/interface.go @@ -67,7 +67,7 @@ type ProxyProvider interface { Provider Proxies() []constant.Proxy // ProxiesWithTouch is used to inform the provider that the proxy is actually being used while getting the list of proxies. - // Commonly used in Dial and DialUDP + // Commonly used in DialContext and DialPacketConn ProxiesWithTouch() []constant.Proxy HealthCheck() } diff --git a/test/Makefile b/test/Makefile new file mode 100644 index 000000000..012d88d52 --- /dev/null +++ b/test/Makefile @@ -0,0 +1,8 @@ +lint: + golangci-lint run --disable-all -E govet -E gofumpt -E megacheck ./... + +test: + go test -p 1 -v ./... + +benchmark: + go test -benchmem -run=^$ -bench . diff --git a/test/README.md b/test/README.md index 823fc5446..a95f3aea6 100644 --- a/test/README.md +++ b/test/README.md @@ -45,7 +45,7 @@ Prerequisite * docker (support Linux and macOS) ``` -$ go test -p 1 -v +$ make test ``` benchmark (Linux) @@ -55,5 +55,5 @@ benchmark (Linux) > (change chunkSize to measure the maximum throughput of clash on your machine) ``` -$ go test -benchmem -run=^$ -bench . +$ make benchmark ``` diff --git a/test/clash_test.go b/test/clash_test.go index 4011b04a4..a3303a239 100644 --- a/test/clash_test.go +++ b/test/clash_test.go @@ -96,6 +96,7 @@ func init() { images := []string{ ImageShadowsocks, + ImageShadowsocksRust, ImageVmess, ImageTrojan, ImageSnell, @@ -582,7 +583,7 @@ func testSuit(t *testing.T, proxy C.ProxyAdapter) { return } - pc, err := proxy.DialUDP(&C.Metadata{ + pc, err := proxy.ListenPacketContext(context.Background(), &C.Metadata{ NetWork: C.UDP, DstIP: localIP, DstPort: "10001", @@ -595,7 +596,7 @@ func testSuit(t *testing.T, proxy C.ProxyAdapter) { assert.NoError(t, testPingPongWithPacketConn(t, pc)) - pc, err = proxy.DialUDP(&C.Metadata{ + pc, err = proxy.ListenPacketContext(context.Background(), &C.Metadata{ NetWork: C.UDP, DstIP: localIP, DstPort: "10001", @@ -608,7 +609,7 @@ func testSuit(t *testing.T, proxy C.ProxyAdapter) { assert.NoError(t, testLargeDataWithPacketConn(t, pc)) - pc, err = proxy.DialUDP(&C.Metadata{ + pc, err = proxy.ListenPacketContext(context.Background(), &C.Metadata{ NetWork: C.UDP, DstIP: localIP, DstPort: "10001", diff --git a/tunnel/tunnel.go b/tunnel/tunnel.go index 2a35f0960..ccd6a58bd 100644 --- a/tunnel/tunnel.go +++ b/tunnel/tunnel.go @@ -1,6 +1,7 @@ package tunnel import ( + "context" "fmt" "net" "runtime" @@ -12,7 +13,7 @@ import ( "github.com/Dreamacro/clash/component/resolver" C "github.com/Dreamacro/clash/constant" "github.com/Dreamacro/clash/constant/provider" - "github.com/Dreamacro/clash/context" + icontext "github.com/Dreamacro/clash/context" "github.com/Dreamacro/clash/log" "github.com/Dreamacro/clash/tunnel/statistic" ) @@ -209,14 +210,16 @@ func handleUDPConn(packet *inbound.PacketAdapter) { cond.Broadcast() }() - ctx := context.NewPacketConnContext(metadata) - proxy, rule, err := resolveMetadata(ctx, metadata) + pCtx := icontext.NewPacketConnContext(metadata) + proxy, rule, err := resolveMetadata(pCtx, metadata) if err != nil { log.Warnln("[UDP] Parse metadata failed: %s", err.Error()) return } - rawPc, err := proxy.DialUDP(metadata) + ctx, cancel := context.WithTimeout(context.Background(), C.DefaultUDPTimeout) + defer cancel() + rawPc, err := proxy.ListenPacketContext(ctx, metadata) if err != nil { if rule == nil { log.Warnln("[UDP] dial %s to %s error: %s", proxy.Name(), metadata.RemoteAddress(), err.Error()) @@ -225,7 +228,7 @@ func handleUDPConn(packet *inbound.PacketAdapter) { } return } - ctx.InjectPacketConn(rawPc) + pCtx.InjectPacketConn(rawPc) pc := statistic.NewUDPTracker(rawPc, statistic.DefaultManager, metadata, rule) switch true { @@ -246,10 +249,10 @@ func handleUDPConn(packet *inbound.PacketAdapter) { }() } -func handleTCPConn(ctx C.ConnContext) { - defer ctx.Conn().Close() +func handleTCPConn(connCtx C.ConnContext) { + defer connCtx.Conn().Close() - metadata := ctx.Metadata() + metadata := connCtx.Metadata() if !metadata.Valid() { log.Warnln("[Metadata] not valid: %#v", metadata) return @@ -260,13 +263,15 @@ func handleTCPConn(ctx C.ConnContext) { return } - proxy, rule, err := resolveMetadata(ctx, metadata) + proxy, rule, err := resolveMetadata(connCtx, metadata) if err != nil { log.Warnln("[Metadata] parse failed: %s", err.Error()) return } - remoteConn, err := proxy.Dial(metadata) + ctx, cancel := context.WithTimeout(context.Background(), C.DefaultTCPTimeout) + defer cancel() + remoteConn, err := proxy.DialContext(ctx, metadata) if err != nil { if rule == nil { log.Warnln("[TCP] dial %s to %s error: %s", proxy.Name(), metadata.RemoteAddress(), err.Error()) @@ -289,7 +294,7 @@ func handleTCPConn(ctx C.ConnContext) { log.Infoln("[TCP] %s --> %s doesn't match any rule using DIRECT", metadata.SourceAddress(), metadata.RemoteAddress()) } - handleSocket(ctx, remoteConn) + handleSocket(connCtx, remoteConn) } func shouldResolveIP(rule C.Rule, metadata *C.Metadata) bool { From df3a491d40c28c309e2cad8ba6d23c811e0e35a3 Mon Sep 17 00:00:00 2001 From: Dreamacro <8615343+Dreamacro@users.noreply.github.com> Date: Sat, 16 Oct 2021 20:19:59 +0800 Subject: [PATCH 83/96] Feature: support trojan websocket --- adapter/outbound/trojan.go | 35 ++++++++++++++++++++++++-- adapter/outbound/vmess.go | 12 +++++++-- test/clash_test.go | 2 ++ test/config/trojan-ws.json | 20 +++++++++++++++ test/trojan_test.go | 38 +++++++++++++++++++++++++++++ transport/trojan/trojan.go | 32 ++++++++++++++++++++++++ transport/v2ray-plugin/websocket.go | 23 ++++++++++++----- transport/vmess/websocket.go | 15 ++---------- 8 files changed, 154 insertions(+), 23 deletions(-) create mode 100644 test/config/trojan-ws.json diff --git a/adapter/outbound/trojan.go b/adapter/outbound/trojan.go index b8ea49e65..8bea0cc8f 100644 --- a/adapter/outbound/trojan.go +++ b/adapter/outbound/trojan.go @@ -5,6 +5,7 @@ import ( "crypto/tls" "fmt" "net" + "net/http" "strconv" "github.com/Dreamacro/clash/component/dialer" @@ -18,6 +19,7 @@ import ( type Trojan struct { *Base instance *trojan.Trojan + option *TrojanOption // for gun mux gunTLSConfig *tls.Config @@ -36,6 +38,34 @@ type TrojanOption struct { UDP bool `proxy:"udp,omitempty"` Network string `proxy:"network,omitempty"` GrpcOpts GrpcOptions `proxy:"grpc-opts,omitempty"` + WSOpts WSOptions `proxy:"ws-opts,omitempty"` +} + +func (t *Trojan) plainStream(c net.Conn) (net.Conn, error) { + if t.option.Network == "ws" { + host, port, _ := net.SplitHostPort(t.addr) + wsOpts := &trojan.WebsocketOption{ + Host: host, + Port: port, + Path: t.option.WSOpts.Path, + } + + if t.option.SNI != "" { + wsOpts.Host = t.option.SNI + } + + if len(t.option.WSOpts.Headers) != 0 { + header := http.Header{} + for key, value := range t.option.WSOpts.Headers { + header.Add(key, value) + } + wsOpts.Headers = header + } + + return t.instance.StreamWebsocketConn(c, wsOpts) + } + + return t.instance.StreamConn(c) } // StreamConn implements C.ProxyAdapter @@ -44,7 +74,7 @@ func (t *Trojan) StreamConn(c net.Conn, metadata *C.Metadata) (net.Conn, error) if t.transport != nil { c, err = gun.StreamGunWithConn(c, t.gunTLSConfig, t.gunConfig) } else { - c, err = t.instance.StreamConn(c) + c, err = t.plainStream(c) } if err != nil { @@ -106,7 +136,7 @@ func (t *Trojan) ListenPacketContext(ctx context.Context, metadata *C.Metadata) } defer safeConnClose(c, err) tcpKeepAlive(c) - c, err = t.instance.StreamConn(c) + c, err = t.plainStream(c) if err != nil { return nil, fmt.Errorf("%s connect error: %w", t.addr, err) } @@ -143,6 +173,7 @@ func NewTrojan(option TrojanOption) (*Trojan, error) { udp: option.UDP, }, instance: trojan.New(tOption), + option: &option, } if option.Network == "grpc" { diff --git a/adapter/outbound/vmess.go b/adapter/outbound/vmess.go index 209084ca8..b4db00ad9 100644 --- a/adapter/outbound/vmess.go +++ b/adapter/outbound/vmess.go @@ -105,8 +105,16 @@ func (v *Vmess) StreamConn(c net.Conn, metadata *C.Metadata) (net.Conn, error) { if v.option.TLS { wsOpts.TLS = true - wsOpts.SkipCertVerify = v.option.SkipCertVerify - wsOpts.ServerName = v.option.ServerName + wsOpts.TLSConfig = &tls.Config{ + ServerName: host, + InsecureSkipVerify: v.option.SkipCertVerify, + NextProtos: []string{"http/1.1"}, + } + if v.option.ServerName != "" { + wsOpts.TLSConfig.ServerName = v.option.ServerName + } else if host := wsOpts.Headers.Get("Host"); host != "" { + wsOpts.TLSConfig.ServerName = host + } } c, err = vmess.StreamWebsocketConn(c, wsOpts) case "http": diff --git a/test/clash_test.go b/test/clash_test.go index a3303a239..5eb9d5bda 100644 --- a/test/clash_test.go +++ b/test/clash_test.go @@ -31,6 +31,7 @@ const ( ImageShadowsocksRust = "ghcr.io/shadowsocks/ssserver-rust:latest" ImageVmess = "v2fly/v2fly-core:latest" ImageTrojan = "trojangfw/trojan:latest" + ImageTrojanGo = "p4gefau1t/trojan-go:latest" ImageSnell = "icpz/snell-server:latest" ImageXray = "teddysun/xray:latest" ) @@ -99,6 +100,7 @@ func init() { ImageShadowsocksRust, ImageVmess, ImageTrojan, + ImageTrojanGo, ImageSnell, ImageXray, } diff --git a/test/config/trojan-ws.json b/test/config/trojan-ws.json new file mode 100644 index 000000000..efc0acbd0 --- /dev/null +++ b/test/config/trojan-ws.json @@ -0,0 +1,20 @@ +{ + "run_type": "server", + "local_addr": "0.0.0.0", + "local_port": 10002, + "disable_http_check": true, + "password": [ + "example" + ], + "websocket": { + "enabled": true, + "path": "/", + "host": "example.org" + }, + "ssl": { + "verify": true, + "cert": "/fullchain.pem", + "key": "/privkey.pem", + "sni": "example.org" + } +} \ No newline at end of file diff --git a/test/trojan_test.go b/test/trojan_test.go index a57dab99f..d1ab2a006 100644 --- a/test/trojan_test.go +++ b/test/trojan_test.go @@ -93,6 +93,44 @@ func TestClash_TrojanGrpc(t *testing.T) { testSuit(t, proxy) } +func TestClash_TrojanWebsocket(t *testing.T) { + cfg := &container.Config{ + Image: ImageTrojanGo, + ExposedPorts: defaultExposedPorts, + } + hostCfg := &container.HostConfig{ + PortBindings: defaultPortBindings, + Binds: []string{ + fmt.Sprintf("%s:/etc/trojan-go/config.json", C.Path.Resolve("trojan-ws.json")), + fmt.Sprintf("%s:/fullchain.pem", C.Path.Resolve("example.org.pem")), + fmt.Sprintf("%s:/privkey.pem", C.Path.Resolve("example.org-key.pem")), + }, + } + + id, err := startContainer(cfg, hostCfg, "trojan-ws") + if err != nil { + assert.FailNow(t, err.Error()) + } + defer cleanContainer(id) + + proxy, err := outbound.NewTrojan(outbound.TrojanOption{ + Name: "trojan", + Server: localIP.String(), + Port: 10002, + Password: "example", + SNI: "example.org", + SkipCertVerify: true, + UDP: true, + Network: "ws", + }) + if err != nil { + assert.FailNow(t, err.Error()) + } + + time.Sleep(waitTime) + testSuit(t, proxy) +} + func Benchmark_Trojan(b *testing.B) { cfg := &container.Config{ Image: ImageTrojan, diff --git a/transport/trojan/trojan.go b/transport/trojan/trojan.go index d39cbec1e..26e7adc7d 100644 --- a/transport/trojan/trojan.go +++ b/transport/trojan/trojan.go @@ -8,10 +8,12 @@ import ( "errors" "io" "net" + "net/http" "sync" "github.com/Dreamacro/clash/common/pool" "github.com/Dreamacro/clash/transport/socks5" + "github.com/Dreamacro/clash/transport/vmess" ) const ( @@ -38,6 +40,13 @@ type Option struct { SkipCertVerify bool } +type WebsocketOption struct { + Host string + Port string + Path string + Headers http.Header +} + type Trojan struct { option *Option hexPassword []byte @@ -64,6 +73,29 @@ func (t *Trojan) StreamConn(conn net.Conn) (net.Conn, error) { return tlsConn, nil } +func (t *Trojan) StreamWebsocketConn(conn net.Conn, wsOptions *WebsocketOption) (net.Conn, error) { + alpn := defaultALPN + if len(t.option.ALPN) != 0 { + alpn = t.option.ALPN + } + + tlsConfig := &tls.Config{ + NextProtos: alpn, + MinVersion: tls.VersionTLS12, + InsecureSkipVerify: t.option.SkipCertVerify, + ServerName: t.option.ServerName, + } + + return vmess.StreamWebsocketConn(conn, &vmess.WebsocketConfig{ + Host: wsOptions.Host, + Port: wsOptions.Port, + Path: wsOptions.Path, + Headers: wsOptions.Headers, + TLS: true, + TLSConfig: tlsConfig, + }) +} + func (t *Trojan) WriteHeader(w io.Writer, command Command, socks5Addr []byte) error { buf := pool.GetBuffer() defer pool.PutBuffer(buf) diff --git a/transport/v2ray-plugin/websocket.go b/transport/v2ray-plugin/websocket.go index 317c172fc..7591b4a86 100644 --- a/transport/v2ray-plugin/websocket.go +++ b/transport/v2ray-plugin/websocket.go @@ -1,6 +1,7 @@ package obfs import ( + "crypto/tls" "net" "net/http" @@ -26,12 +27,22 @@ func NewV2rayObfs(conn net.Conn, option *Option) (net.Conn, error) { } config := &vmess.WebsocketConfig{ - Host: option.Host, - Port: option.Port, - Path: option.Path, - TLS: option.TLS, - Headers: header, - SkipCertVerify: option.SkipCertVerify, + Host: option.Host, + Port: option.Port, + Path: option.Path, + Headers: header, + } + + if option.TLS { + config.TLS = true + config.TLSConfig = &tls.Config{ + ServerName: option.Host, + InsecureSkipVerify: option.SkipCertVerify, + NextProtos: []string{"http/1.1"}, + } + if host := config.Headers.Get("Host"); host != "" { + config.TLSConfig.ServerName = host + } } var err error diff --git a/transport/vmess/websocket.go b/transport/vmess/websocket.go index 951fb5d0a..f769dcce8 100644 --- a/transport/vmess/websocket.go +++ b/transport/vmess/websocket.go @@ -45,8 +45,7 @@ type WebsocketConfig struct { Path string Headers http.Header TLS bool - SkipCertVerify bool - ServerName string + TLSConfig *tls.Config MaxEarlyData int EarlyDataHeaderName string } @@ -254,17 +253,7 @@ func streamWebsocketConn(conn net.Conn, c *WebsocketConfig, earlyData *bytes.Buf scheme := "ws" if c.TLS { scheme = "wss" - dialer.TLSClientConfig = &tls.Config{ - ServerName: c.Host, - InsecureSkipVerify: c.SkipCertVerify, - NextProtos: []string{"http/1.1"}, - } - - if c.ServerName != "" { - dialer.TLSClientConfig.ServerName = c.ServerName - } else if host := c.Headers.Get("Host"); host != "" { - dialer.TLSClientConfig.ServerName = host - } + dialer.TLSClientConfig = c.TLSConfig } uri := url.URL{ From fea9d1c5e234d852e9cae41a51373ca44b2c08dc Mon Sep 17 00:00:00 2001 From: Dreamacro <8615343+Dreamacro@users.noreply.github.com> Date: Sat, 16 Oct 2021 20:35:06 +0800 Subject: [PATCH 84/96] Fix: replace vmess grpc test image --- test/vmess_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/vmess_test.go b/test/vmess_test.go index b696fcea7..1483cf0af 100644 --- a/test/vmess_test.go +++ b/test/vmess_test.go @@ -304,13 +304,13 @@ func TestClash_VmessWebsocketTLS(t *testing.T) { func TestClash_VmessGrpc(t *testing.T) { cfg := &container.Config{ - Image: ImageXray, + Image: ImageVmess, ExposedPorts: defaultExposedPorts, } hostCfg := &container.HostConfig{ PortBindings: defaultPortBindings, Binds: []string{ - fmt.Sprintf("%s:/etc/xray/config.json", C.Path.Resolve("vmess-grpc.json")), + fmt.Sprintf("%s:/etc/v2ray/config.json", C.Path.Resolve("vmess-grpc.json")), fmt.Sprintf("%s:/etc/ssl/v2ray/fullchain.pem", C.Path.Resolve("example.org.pem")), fmt.Sprintf("%s:/etc/ssl/v2ray/privkey.pem", C.Path.Resolve("example.org-key.pem")), }, From 81d5da51a3b0d84ed0a6f752c3e7c02e1065bce1 Mon Sep 17 00:00:00 2001 From: Dreamacro <8615343+Dreamacro@users.noreply.github.com> Date: Mon, 18 Oct 2021 21:08:27 +0800 Subject: [PATCH 85/96] Fix: unexpected proxy dial behavior on mapping mode --- config/config.go | 6 ++-- constant/dns.go | 70 ++++++++++++++++++++++++++++++++++++++++++++ constant/metadata.go | 18 ++++++++++++ dns/enhancer.go | 9 +++--- dns/middleware.go | 5 ++-- dns/resolver.go | 3 +- dns/util.go | 66 ----------------------------------------- tunnel/tunnel.go | 6 ++-- 8 files changed, 105 insertions(+), 78 deletions(-) create mode 100644 constant/dns.go diff --git a/config/config.go b/config/config.go index f532c61a1..603523ec6 100644 --- a/config/config.go +++ b/config/config.go @@ -62,7 +62,7 @@ type DNS struct { Fallback []dns.NameServer `yaml:"fallback"` FallbackFilter FallbackFilter `yaml:"fallback-filter"` Listen string `yaml:"listen"` - EnhancedMode dns.EnhancedMode `yaml:"enhanced-mode"` + EnhancedMode C.DNSMode `yaml:"enhanced-mode"` DefaultNameserver []dns.NameServer `yaml:"default-nameserver"` FakeIPRange *fakeip.Pool Hosts *trie.DomainTrie @@ -107,7 +107,7 @@ type RawDNS struct { Fallback []string `yaml:"fallback"` FallbackFilter RawFallbackFilter `yaml:"fallback-filter"` Listen string `yaml:"listen"` - EnhancedMode dns.EnhancedMode `yaml:"enhanced-mode"` + EnhancedMode C.DNSMode `yaml:"enhanced-mode"` FakeIPRange string `yaml:"fake-ip-range"` FakeIPFilter []string `yaml:"fake-ip-filter"` DefaultNameserver []string `yaml:"default-nameserver"` @@ -584,7 +584,7 @@ func parseDNS(rawCfg *RawConfig, hosts *trie.DomainTrie) (*DNS, error) { } } - if cfg.EnhancedMode == dns.FAKEIP { + if cfg.EnhancedMode == C.DNSFakeIP { _, ipnet, err := net.ParseCIDR(cfg.FakeIPRange) if err != nil { return nil, err diff --git a/constant/dns.go b/constant/dns.go new file mode 100644 index 000000000..d1cd7a61c --- /dev/null +++ b/constant/dns.go @@ -0,0 +1,70 @@ +package constant + +import ( + "encoding/json" + "errors" +) + +// DNSModeMapping is a mapping for EnhancedMode enum +var DNSModeMapping = map[string]DNSMode{ + DNSNormal.String(): DNSNormal, + DNSFakeIP.String(): DNSFakeIP, + DNSMapping.String(): DNSMapping, +} + +const ( + DNSNormal DNSMode = iota + DNSFakeIP + DNSMapping +) + +type DNSMode int + +// UnmarshalYAML unserialize EnhancedMode with yaml +func (e *DNSMode) UnmarshalYAML(unmarshal func(interface{}) error) error { + var tp string + if err := unmarshal(&tp); err != nil { + return err + } + mode, exist := DNSModeMapping[tp] + if !exist { + return errors.New("invalid mode") + } + *e = mode + return nil +} + +// MarshalYAML serialize EnhancedMode with yaml +func (e DNSMode) MarshalYAML() (interface{}, error) { + return e.String(), nil +} + +// UnmarshalJSON unserialize EnhancedMode with json +func (e *DNSMode) UnmarshalJSON(data []byte) error { + var tp string + json.Unmarshal(data, &tp) + mode, exist := DNSModeMapping[tp] + if !exist { + return errors.New("invalid mode") + } + *e = mode + return nil +} + +// MarshalJSON serialize EnhancedMode with json +func (e DNSMode) MarshalJSON() ([]byte, error) { + return json.Marshal(e.String()) +} + +func (e DNSMode) String() string { + switch e { + case DNSNormal: + return "normal" + case DNSFakeIP: + return "fake-ip" + case DNSMapping: + return "redir-host" + default: + return "unknown" + } +} diff --git a/constant/metadata.go b/constant/metadata.go index 9fff773b3..822b4714d 100644 --- a/constant/metadata.go +++ b/constant/metadata.go @@ -71,6 +71,7 @@ type Metadata struct { DstPort string `json:"destinationPort"` AddrType int `json:"-"` Host string `json:"host"` + DNSMode DNSMode `json:"dnsMode"` } func (m *Metadata) RemoteAddress() string { @@ -85,6 +86,23 @@ func (m *Metadata) Resolved() bool { return m.DstIP != nil } +// Pure is used to solve unexpected behavior +// when dialing proxy connection in DNSMapping mode. +func (m *Metadata) Pure() *Metadata { + if m.DNSMode == DNSMapping && m.DstIP != nil { + copy := *m + copy.Host = "" + if copy.DstIP.To4() != nil { + copy.AddrType = AtypIPv4 + } else { + copy.AddrType = AtypIPv6 + } + return © + } + + return m +} + func (m *Metadata) UDPAddr() *net.UDPAddr { if m.NetWork != UDP || m.DstIP == nil { return nil diff --git a/dns/enhancer.go b/dns/enhancer.go index d2592e6e9..76f0f2628 100644 --- a/dns/enhancer.go +++ b/dns/enhancer.go @@ -5,20 +5,21 @@ import ( "github.com/Dreamacro/clash/common/cache" "github.com/Dreamacro/clash/component/fakeip" + C "github.com/Dreamacro/clash/constant" ) type ResolverEnhancer struct { - mode EnhancedMode + mode C.DNSMode fakePool *fakeip.Pool mapping *cache.LruCache } func (h *ResolverEnhancer) FakeIPEnabled() bool { - return h.mode == FAKEIP + return h.mode == C.DNSFakeIP } func (h *ResolverEnhancer) MappingEnabled() bool { - return h.mode == FAKEIP || h.mode == MAPPING + return h.mode == C.DNSFakeIP || h.mode == C.DNSMapping } func (h *ResolverEnhancer) IsExistFakeIP(ip net.IP) bool { @@ -75,7 +76,7 @@ func NewEnhancer(cfg Config) *ResolverEnhancer { var fakePool *fakeip.Pool var mapping *cache.LruCache - if cfg.EnhancedMode != NORMAL { + if cfg.EnhancedMode != C.DNSNormal { fakePool = cfg.Pool mapping = cache.NewLRUCache(cache.WithSize(4096), cache.WithStale(true)) } diff --git a/dns/middleware.go b/dns/middleware.go index de0b3aff4..9d0da5968 100644 --- a/dns/middleware.go +++ b/dns/middleware.go @@ -8,6 +8,7 @@ import ( "github.com/Dreamacro/clash/common/cache" "github.com/Dreamacro/clash/component/fakeip" "github.com/Dreamacro/clash/component/trie" + C "github.com/Dreamacro/clash/constant" "github.com/Dreamacro/clash/context" "github.com/Dreamacro/clash/log" @@ -178,11 +179,11 @@ func newHandler(resolver *Resolver, mapper *ResolverEnhancer) handler { middlewares = append(middlewares, withHosts(resolver.hosts)) } - if mapper.mode == FAKEIP { + if mapper.mode == C.DNSFakeIP { middlewares = append(middlewares, withFakeIP(mapper.fakePool)) } - if mapper.mode != NORMAL { + if mapper.mode != C.DNSNormal { middlewares = append(middlewares, withMapping(mapper.mapping)) } diff --git a/dns/resolver.go b/dns/resolver.go index bf544cb99..91efbb8bc 100644 --- a/dns/resolver.go +++ b/dns/resolver.go @@ -14,6 +14,7 @@ import ( "github.com/Dreamacro/clash/component/fakeip" "github.com/Dreamacro/clash/component/resolver" "github.com/Dreamacro/clash/component/trie" + C "github.com/Dreamacro/clash/constant" D "github.com/miekg/dns" "golang.org/x/sync/singleflight" @@ -317,7 +318,7 @@ type Config struct { Main, Fallback []NameServer Default []NameServer IPv6 bool - EnhancedMode EnhancedMode + EnhancedMode C.DNSMode FallbackFilter FallbackFilter Pool *fakeip.Pool Hosts *trie.DomainTrie diff --git a/dns/util.go b/dns/util.go index 0e1badabc..d11870f81 100644 --- a/dns/util.go +++ b/dns/util.go @@ -2,8 +2,6 @@ package dns import ( "crypto/tls" - "encoding/json" - "errors" "net" "time" @@ -13,70 +11,6 @@ import ( D "github.com/miekg/dns" ) -// EnhancedModeMapping is a mapping for EnhancedMode enum -var EnhancedModeMapping = map[string]EnhancedMode{ - NORMAL.String(): NORMAL, - FAKEIP.String(): FAKEIP, - MAPPING.String(): MAPPING, -} - -const ( - NORMAL EnhancedMode = iota - FAKEIP - MAPPING -) - -type EnhancedMode int - -// UnmarshalYAML unserialize EnhancedMode with yaml -func (e *EnhancedMode) UnmarshalYAML(unmarshal func(interface{}) error) error { - var tp string - if err := unmarshal(&tp); err != nil { - return err - } - mode, exist := EnhancedModeMapping[tp] - if !exist { - return errors.New("invalid mode") - } - *e = mode - return nil -} - -// MarshalYAML serialize EnhancedMode with yaml -func (e EnhancedMode) MarshalYAML() (interface{}, error) { - return e.String(), nil -} - -// UnmarshalJSON unserialize EnhancedMode with json -func (e *EnhancedMode) UnmarshalJSON(data []byte) error { - var tp string - json.Unmarshal(data, &tp) - mode, exist := EnhancedModeMapping[tp] - if !exist { - return errors.New("invalid mode") - } - *e = mode - return nil -} - -// MarshalJSON serialize EnhancedMode with json -func (e EnhancedMode) MarshalJSON() ([]byte, error) { - return json.Marshal(e.String()) -} - -func (e EnhancedMode) String() string { - switch e { - case NORMAL: - return "normal" - case FAKEIP: - return "fake-ip" - case MAPPING: - return "redir-host" - default: - return "unknown" - } -} - func putMsgToCache(c *cache.LruCache, key string, msg *D.Msg) { var ttl uint32 switch { diff --git a/tunnel/tunnel.go b/tunnel/tunnel.go index ccd6a58bd..dd64b0155 100644 --- a/tunnel/tunnel.go +++ b/tunnel/tunnel.go @@ -135,9 +135,11 @@ func preHandleMetadata(metadata *C.Metadata) error { metadata.AddrType = C.AtypDomainName if resolver.FakeIPEnabled() { metadata.DstIP = nil + metadata.DNSMode = C.DNSFakeIP } else if node := resolver.DefaultHosts.Search(host); node != nil { // redir-host should lookup the hosts metadata.DstIP = node.Data.(net.IP) + metadata.DNSMode = C.DNSMapping } } else if resolver.IsFakeIP(metadata.DstIP) { return fmt.Errorf("fake DNS record %s missing", metadata.DstIP) @@ -219,7 +221,7 @@ func handleUDPConn(packet *inbound.PacketAdapter) { ctx, cancel := context.WithTimeout(context.Background(), C.DefaultUDPTimeout) defer cancel() - rawPc, err := proxy.ListenPacketContext(ctx, metadata) + rawPc, err := proxy.ListenPacketContext(ctx, metadata.Pure()) if err != nil { if rule == nil { log.Warnln("[UDP] dial %s to %s error: %s", proxy.Name(), metadata.RemoteAddress(), err.Error()) @@ -271,7 +273,7 @@ func handleTCPConn(connCtx C.ConnContext) { ctx, cancel := context.WithTimeout(context.Background(), C.DefaultTCPTimeout) defer cancel() - remoteConn, err := proxy.DialContext(ctx, metadata) + remoteConn, err := proxy.DialContext(ctx, metadata.Pure()) if err != nil { if rule == nil { log.Warnln("[TCP] dial %s to %s error: %s", proxy.Name(), metadata.RemoteAddress(), err.Error()) From 967932d02c14d45914c9dc106c483c55e380712f Mon Sep 17 00:00:00 2001 From: Dreamacro <8615343+Dreamacro@users.noreply.github.com> Date: Mon, 18 Oct 2021 22:58:16 +0800 Subject: [PATCH 86/96] Fix: set dnsmode behavior --- tunnel/tunnel.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tunnel/tunnel.go b/tunnel/tunnel.go index dd64b0155..1c0075549 100644 --- a/tunnel/tunnel.go +++ b/tunnel/tunnel.go @@ -133,13 +133,13 @@ func preHandleMetadata(metadata *C.Metadata) error { if exist { metadata.Host = host metadata.AddrType = C.AtypDomainName + metadata.DNSMode = C.DNSMapping if resolver.FakeIPEnabled() { metadata.DstIP = nil metadata.DNSMode = C.DNSFakeIP } else if node := resolver.DefaultHosts.Search(host); node != nil { // redir-host should lookup the hosts metadata.DstIP = node.Data.(net.IP) - metadata.DNSMode = C.DNSMapping } } else if resolver.IsFakeIP(metadata.DstIP) { return fmt.Errorf("fake DNS record %s missing", metadata.DstIP) From c6cceeb0c589983ee0758f1bbbe6fd7ad1f3a1eb Mon Sep 17 00:00:00 2001 From: Dreamacro <8615343+Dreamacro@users.noreply.github.com> Date: Tue, 19 Oct 2021 22:34:18 +0800 Subject: [PATCH 87/96] Chore: use alpn http 1.1 only on trojan websocket by default --- transport/trojan/trojan.go | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/transport/trojan/trojan.go b/transport/trojan/trojan.go index 26e7adc7d..9d9a33b99 100644 --- a/transport/trojan/trojan.go +++ b/transport/trojan/trojan.go @@ -22,8 +22,10 @@ const ( ) var ( - defaultALPN = []string{"h2", "http/1.1"} - crlf = []byte{'\r', '\n'} + defaultALPN = []string{"h2", "http/1.1"} + defaultWebsocketALPN = []string{"http/1.1"} + + crlf = []byte{'\r', '\n'} ) type Command = byte @@ -74,7 +76,7 @@ func (t *Trojan) StreamConn(conn net.Conn) (net.Conn, error) { } func (t *Trojan) StreamWebsocketConn(conn net.Conn, wsOptions *WebsocketOption) (net.Conn, error) { - alpn := defaultALPN + alpn := defaultWebsocketALPN if len(t.option.ALPN) != 0 { alpn = t.option.ALPN } From a7aea12aa69596edf9c3bad2352ebde303ea5d6e Mon Sep 17 00:00:00 2001 From: Blaise Wang Date: Wed, 20 Oct 2021 13:44:05 +0800 Subject: [PATCH 88/96] Fix: remove ResponseHeaderTimeout limitation (#1690) --- listener/http/client.go | 1 - 1 file changed, 1 deletion(-) diff --git a/listener/http/client.go b/listener/http/client.go index 15078b0ac..873a9a3c9 100644 --- a/listener/http/client.go +++ b/listener/http/client.go @@ -19,7 +19,6 @@ func newClient(source net.Addr, in chan<- C.ConnContext) *http.Client { MaxIdleConns: 100, IdleConnTimeout: 90 * time.Second, TLSHandshakeTimeout: 10 * time.Second, - ResponseHeaderTimeout: 10 * time.Second, ExpectContinueTimeout: 1 * time.Second, DialContext: func(context context.Context, network, address string) (net.Conn, error) { if network != "tcp" && network != "tcp4" && network != "tcp6" { From ebbc9604ce68b6484ab730a05cf02a639e619438 Mon Sep 17 00:00:00 2001 From: Dreamacro <8615343+Dreamacro@users.noreply.github.com> Date: Wed, 27 Oct 2021 21:27:19 +0800 Subject: [PATCH 89/96] Chore: use uber max procs --- go.mod | 1 + go.sum | 12 +++++++++++- main.go | 3 +++ tunnel/tunnel.go | 4 ++-- 4 files changed, 17 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index dc79d77af..c608f7ad2 100644 --- a/go.mod +++ b/go.mod @@ -16,6 +16,7 @@ require ( github.com/stretchr/testify v1.7.0 go.etcd.io/bbolt v1.3.6 go.uber.org/atomic v1.9.0 + go.uber.org/automaxprocs v1.4.0 golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 golang.org/x/net v0.0.0-20210903162142-ad29c8ab022f golang.org/x/sync v0.0.0-20210220032951-036812b2e83c diff --git a/go.sum b/go.sum index 1fbae8ce4..cccc8ba34 100644 --- a/go.sum +++ b/go.sum @@ -28,6 +28,11 @@ github.com/jsimonetti/rtnetlink v0.0.0-20200117123717-f846d4f6c1f4/go.mod h1:WGu github.com/jsimonetti/rtnetlink v0.0.0-20201009170750-9c6f07d100c1/go.mod h1:hqoO/u39cqLeBLebZ8fWdE96O7FxrAsRYhnVOdgHxok= github.com/jsimonetti/rtnetlink v0.0.0-20201110080708-d2c240429e6c/go.mod h1:huN4d1phzjhlOsNIjFsw2SVRbwIHj3fJDMEU2SDPTmg= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/mdlayher/ethernet v0.0.0-20190606142754-0394541c37b7/go.mod h1:U6ZQobyTjI/tJyq2HG+i/dfSoFUt8/aZCM+GKtmFk/Y= github.com/mdlayher/netlink v0.0.0-20190409211403-11939a169225/go.mod h1:eQB3mZE4aiYnlUsyGGCOpPETfdQq4Jhsgf1fk3cwQaA= github.com/mdlayher/netlink v1.0.0/go.mod h1:KxeJAFOFLG6AjpyDkQ/iIhxygIUKD+vcwqcnu43w/+M= @@ -50,6 +55,7 @@ github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= @@ -59,6 +65,8 @@ go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU= go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/automaxprocs v1.4.0 h1:CpDZl6aOlLhReez+8S3eEotD7Jx0Os++lemPlMULQP0= +go.uber.org/automaxprocs v1.4.0/go.mod h1:/mTEdr7LvHhs0v7mjdxDreTz1OG5zdZGqgOnhWiR/+Q= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 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= @@ -108,8 +116,10 @@ golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= diff --git a/main.go b/main.go index 4a7dff0be..5d953ed69 100644 --- a/main.go +++ b/main.go @@ -14,6 +14,8 @@ import ( "github.com/Dreamacro/clash/hub" "github.com/Dreamacro/clash/hub/executor" "github.com/Dreamacro/clash/log" + + "go.uber.org/automaxprocs/maxprocs" ) var ( @@ -44,6 +46,7 @@ func init() { } func main() { + maxprocs.Set(maxprocs.Logger(func(string, ...interface{}) {})) if version { fmt.Printf("Clash %s %s %s with %s %s\n", C.Version, runtime.GOOS, runtime.GOARCH, runtime.Version(), C.BuildTime) return diff --git a/tunnel/tunnel.go b/tunnel/tunnel.go index 1c0075549..f00a7bd02 100644 --- a/tunnel/tunnel.go +++ b/tunnel/tunnel.go @@ -98,8 +98,8 @@ func processUDP() { func process() { numUDPWorkers := 4 - if runtime.NumCPU() > numUDPWorkers { - numUDPWorkers = runtime.NumCPU() + if num := runtime.GOMAXPROCS(0); num > numUDPWorkers { + numUDPWorkers = num } for i := 0; i < numUDPWorkers; i++ { go processUDP() From bcb301b730de889295d7f90ccf8aa8102f133727 Mon Sep 17 00:00:00 2001 From: Dreamacro <8615343+Dreamacro@users.noreply.github.com> Date: Wed, 3 Nov 2021 22:26:51 +0800 Subject: [PATCH 90/96] Chore: adjust all udp alloc size --- common/pool/pool.go | 5 +++++ listener/socks/udp.go | 2 +- listener/tproxy/udp.go | 2 +- tunnel/connection.go | 2 +- 4 files changed, 8 insertions(+), 3 deletions(-) diff --git a/common/pool/pool.go b/common/pool/pool.go index e6354f119..bee4887f5 100644 --- a/common/pool/pool.go +++ b/common/pool/pool.go @@ -5,6 +5,11 @@ const ( // but the maximum packet size of vmess/shadowsocks is about 16 KiB // so define a buffer of 20 KiB to reduce the memory of each TCP relay RelayBufferSize = 20 * 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 { diff --git a/listener/socks/udp.go b/listener/socks/udp.go index a2d215083..8bc439fb4 100644 --- a/listener/socks/udp.go +++ b/listener/socks/udp.go @@ -49,7 +49,7 @@ func NewUDP(addr string, in chan<- *inbound.PacketAdapter) (*UDPListener, error) } go func() { for { - buf := pool.Get(pool.RelayBufferSize) + buf := pool.Get(pool.UDPBufferSize) n, remoteAddr, err := l.ReadFrom(buf) if err != nil { pool.Put(buf) diff --git a/listener/tproxy/udp.go b/listener/tproxy/udp.go index f3d8dbb3c..c7e6d99e3 100644 --- a/listener/tproxy/udp.go +++ b/listener/tproxy/udp.go @@ -57,7 +57,7 @@ func NewUDP(addr string, in chan<- *inbound.PacketAdapter) (*UDPListener, error) go func() { oob := make([]byte, 1024) for { - buf := pool.Get(pool.RelayBufferSize) + buf := pool.Get(pool.UDPBufferSize) n, oobn, _, lAddr, err := c.ReadMsgUDP(buf, oob) if err != nil { pool.Put(buf) diff --git a/tunnel/connection.go b/tunnel/connection.go index 8c3b4cb61..45de46d7f 100644 --- a/tunnel/connection.go +++ b/tunnel/connection.go @@ -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) { - buf := pool.Get(pool.RelayBufferSize) + buf := pool.Get(pool.UDPBufferSize) defer pool.Put(buf) defer natTable.Delete(key) defer pc.Close() From 1a7830f18ecd9185dedef1340b7d4fcd55c6e503 Mon Sep 17 00:00:00 2001 From: Dreamacro Date: Sun, 7 Nov 2021 16:48:51 +0800 Subject: [PATCH 91/96] Feature: dial different NIC for all proxies (#1714) --- adapter/adapter.go | 9 +++--- adapter/outbound/base.go | 43 +++++++++++++++++++++++----- adapter/outbound/direct.go | 8 +++--- adapter/outbound/http.go | 12 ++++---- adapter/outbound/reject.go | 5 ++-- adapter/outbound/shadowsocks.go | 18 ++++++------ adapter/outbound/shadowsocksr.go | 18 ++++++------ adapter/outbound/snell.go | 16 ++++++----- adapter/outbound/socks5.go | 20 +++++++------ adapter/outbound/trojan.go | 24 +++++++++------- adapter/outbound/vmess.go | 24 +++++++++------- adapter/outboundgroup/fallback.go | 19 +++++++----- adapter/outboundgroup/loadbalance.go | 19 +++++++----- adapter/outboundgroup/parser.go | 2 ++ adapter/outboundgroup/relay.go | 16 +++++++---- adapter/outboundgroup/selector.go | 19 +++++++----- adapter/outboundgroup/urltest.go | 19 +++++++----- component/dialer/dialer.go | 20 ++++++------- component/dialer/options.go | 22 +++++++------- constant/adapters.go | 6 ++-- hub/executor/executor.go | 6 +--- 21 files changed, 206 insertions(+), 139 deletions(-) diff --git a/adapter/adapter.go b/adapter/adapter.go index 263301636..76bbe2e3d 100644 --- a/adapter/adapter.go +++ b/adapter/adapter.go @@ -10,6 +10,7 @@ import ( "time" "github.com/Dreamacro/clash/common/queue" + "github.com/Dreamacro/clash/component/dialer" C "github.com/Dreamacro/clash/constant" "go.uber.org/atomic" @@ -34,8 +35,8 @@ func (p *Proxy) Dial(metadata *C.Metadata) (C.Conn, error) { } // DialContext implements C.ProxyAdapter -func (p *Proxy) DialContext(ctx context.Context, metadata *C.Metadata) (C.Conn, error) { - conn, err := p.ProxyAdapter.DialContext(ctx, metadata) +func (p *Proxy) DialContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (C.Conn, error) { + conn, err := p.ProxyAdapter.DialContext(ctx, metadata, opts...) p.alive.Store(err == nil) return conn, err } @@ -48,8 +49,8 @@ func (p *Proxy) DialUDP(metadata *C.Metadata) (C.PacketConn, error) { } // ListenPacketContext implements C.ProxyAdapter -func (p *Proxy) ListenPacketContext(ctx context.Context, metadata *C.Metadata) (C.PacketConn, error) { - pc, err := p.ProxyAdapter.ListenPacketContext(ctx, metadata) +func (p *Proxy) ListenPacketContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (C.PacketConn, error) { + pc, err := p.ProxyAdapter.ListenPacketContext(ctx, metadata, opts...) p.alive.Store(err == nil) return pc, err } diff --git a/adapter/outbound/base.go b/adapter/outbound/base.go index 22c0142b0..e028cd4e8 100644 --- a/adapter/outbound/base.go +++ b/adapter/outbound/base.go @@ -6,14 +6,16 @@ import ( "errors" "net" + "github.com/Dreamacro/clash/component/dialer" C "github.com/Dreamacro/clash/constant" ) type Base struct { - name string - addr string - tp C.AdapterType - udp bool + name string + addr string + iface string + tp C.AdapterType + udp bool } // Name implements C.ProxyAdapter @@ -32,7 +34,7 @@ func (b *Base) StreamConn(c net.Conn, metadata *C.Metadata) (net.Conn, error) { } // 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") } @@ -58,8 +60,35 @@ func (b *Base) Unwrap(metadata *C.Metadata) C.Proxy { return nil } -func NewBase(name string, addr string, tp C.AdapterType, udp bool) *Base { - return &Base{name, addr, tp, udp} +// DialOptions return []dialer.Option from struct +func (b *Base) DialOptions(opts ...dialer.Option) []dialer.Option { + if b.iface != "" { + opts = append(opts, dialer.WithInterface(b.iface)) + } + + return opts +} + +type BasicOption struct { + Interface string `proxy:"interface-name"` +} + +type BaseOption struct { + Name string + Addr string + Type C.AdapterType + UDP bool + Interface string +} + +func NewBase(opt BaseOption) *Base { + return &Base{ + name: opt.Name, + addr: opt.Addr, + tp: opt.Type, + udp: opt.UDP, + iface: opt.Interface, + } } type conn struct { diff --git a/adapter/outbound/direct.go b/adapter/outbound/direct.go index 42433c410..4c4305f57 100644 --- a/adapter/outbound/direct.go +++ b/adapter/outbound/direct.go @@ -13,8 +13,8 @@ type Direct struct { } // DialContext implements C.ProxyAdapter -func (d *Direct) DialContext(ctx context.Context, metadata *C.Metadata) (C.Conn, error) { - c, err := dialer.DialContext(ctx, "tcp", metadata.RemoteAddress()) +func (d *Direct) DialContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (C.Conn, error) { + c, err := dialer.DialContext(ctx, "tcp", metadata.RemoteAddress(), d.Base.DialOptions(opts...)...) if err != nil { return nil, err } @@ -23,8 +23,8 @@ func (d *Direct) DialContext(ctx context.Context, metadata *C.Metadata) (C.Conn, } // ListenPacketContext implements C.ProxyAdapter -func (d *Direct) ListenPacketContext(ctx context.Context, metadata *C.Metadata) (C.PacketConn, error) { - pc, err := dialer.ListenPacket(ctx, "udp", "") +func (d *Direct) ListenPacketContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (C.PacketConn, error) { + pc, err := dialer.ListenPacket(ctx, "udp", "", d.Base.DialOptions(opts...)...) if err != nil { return nil, err } diff --git a/adapter/outbound/http.go b/adapter/outbound/http.go index b4dffdf78..7f480ce6b 100644 --- a/adapter/outbound/http.go +++ b/adapter/outbound/http.go @@ -25,6 +25,7 @@ type Http struct { } type HttpOption struct { + BasicOption Name string `proxy:"name"` Server string `proxy:"server"` 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 -func (h *Http) DialContext(ctx context.Context, metadata *C.Metadata) (_ C.Conn, err error) { - c, err := dialer.DialContext(ctx, "tcp", h.addr) +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, h.Base.DialOptions(opts...)...) if err != nil { return nil, fmt.Errorf("%s connect error: %w", h.addr, err) } @@ -131,9 +132,10 @@ func NewHttp(option HttpOption) *Http { return &Http{ Base: &Base{ - name: option.Name, - addr: net.JoinHostPort(option.Server, strconv.Itoa(option.Port)), - tp: C.Http, + name: option.Name, + addr: net.JoinHostPort(option.Server, strconv.Itoa(option.Port)), + tp: C.Http, + iface: option.Interface, }, user: option.UserName, pass: option.Password, diff --git a/adapter/outbound/reject.go b/adapter/outbound/reject.go index a97c6c711..f1940d39a 100644 --- a/adapter/outbound/reject.go +++ b/adapter/outbound/reject.go @@ -7,6 +7,7 @@ import ( "net" "time" + "github.com/Dreamacro/clash/component/dialer" C "github.com/Dreamacro/clash/constant" ) @@ -15,12 +16,12 @@ type Reject struct { } // 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 } // 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") } diff --git a/adapter/outbound/shadowsocks.go b/adapter/outbound/shadowsocks.go index 0194954e7..5e5ebd7c4 100644 --- a/adapter/outbound/shadowsocks.go +++ b/adapter/outbound/shadowsocks.go @@ -28,6 +28,7 @@ type ShadowSocks struct { } type ShadowSocksOption struct { + BasicOption Name string `proxy:"name"` Server string `proxy:"server"` 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 -func (ss *ShadowSocks) DialContext(ctx context.Context, metadata *C.Metadata) (_ C.Conn, err error) { - c, err := dialer.DialContext(ctx, "tcp", ss.addr) +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, ss.Base.DialOptions(opts...)...) if err != nil { 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 -func (ss *ShadowSocks) ListenPacketContext(ctx context.Context, metadata *C.Metadata) (C.PacketConn, error) { - pc, err := dialer.ListenPacket(ctx, "udp", "") +func (ss *ShadowSocks) ListenPacketContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (C.PacketConn, error) { + pc, err := dialer.ListenPacket(ctx, "udp", "", ss.Base.DialOptions(opts...)...) if err != nil { return nil, err } @@ -154,10 +155,11 @@ func NewShadowSocks(option ShadowSocksOption) (*ShadowSocks, error) { return &ShadowSocks{ Base: &Base{ - name: option.Name, - addr: addr, - tp: C.Shadowsocks, - udp: option.UDP, + name: option.Name, + addr: addr, + tp: C.Shadowsocks, + udp: option.UDP, + iface: option.Interface, }, cipher: ciph, diff --git a/adapter/outbound/shadowsocksr.go b/adapter/outbound/shadowsocksr.go index fb0dd7a5f..d244df406 100644 --- a/adapter/outbound/shadowsocksr.go +++ b/adapter/outbound/shadowsocksr.go @@ -24,6 +24,7 @@ type ShadowSocksR struct { } type ShadowSocksROption struct { + BasicOption Name string `proxy:"name"` Server string `proxy:"server"` Port int `proxy:"port"` @@ -59,8 +60,8 @@ func (ssr *ShadowSocksR) StreamConn(c net.Conn, metadata *C.Metadata) (net.Conn, } // DialContext implements C.ProxyAdapter -func (ssr *ShadowSocksR) DialContext(ctx context.Context, metadata *C.Metadata) (_ C.Conn, err error) { - c, err := dialer.DialContext(ctx, "tcp", ssr.addr) +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, ssr.Base.DialOptions(opts...)...) if err != nil { 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 -func (ssr *ShadowSocksR) ListenPacketContext(ctx context.Context, metadata *C.Metadata) (C.PacketConn, error) { - pc, err := dialer.ListenPacket(ctx, "udp", "") +func (ssr *ShadowSocksR) ListenPacketContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (C.PacketConn, error) { + pc, err := dialer.ListenPacket(ctx, "udp", "", ssr.Base.DialOptions(opts...)...) if err != nil { return nil, err } @@ -136,10 +137,11 @@ func NewShadowSocksR(option ShadowSocksROption) (*ShadowSocksR, error) { return &ShadowSocksR{ Base: &Base{ - name: option.Name, - addr: addr, - tp: C.ShadowsocksR, - udp: option.UDP, + name: option.Name, + addr: addr, + tp: C.ShadowsocksR, + udp: option.UDP, + iface: option.Interface, }, cipher: coreCiph, obfs: obfs, diff --git a/adapter/outbound/snell.go b/adapter/outbound/snell.go index 2dc16a511..40dcf0664 100644 --- a/adapter/outbound/snell.go +++ b/adapter/outbound/snell.go @@ -22,6 +22,7 @@ type Snell struct { } type SnellOption struct { + BasicOption Name string `proxy:"name"` Server string `proxy:"server"` Port int `proxy:"port"` @@ -57,8 +58,8 @@ func (s *Snell) StreamConn(c net.Conn, metadata *C.Metadata) (net.Conn, error) { } // DialContext implements C.ProxyAdapter -func (s *Snell) DialContext(ctx context.Context, metadata *C.Metadata) (_ C.Conn, err error) { - if s.version == snell.Version2 { +func (s *Snell) DialContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (_ C.Conn, err error) { + if s.version == snell.Version2 && len(opts) == 0 { c, err := s.pool.Get() if err != nil { return nil, err @@ -72,7 +73,7 @@ func (s *Snell) DialContext(ctx context.Context, metadata *C.Metadata) (_ C.Conn 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 { return nil, fmt.Errorf("%s connect error: %w", s.addr, err) } @@ -111,9 +112,10 @@ func NewSnell(option SnellOption) (*Snell, error) { s := &Snell{ Base: &Base{ - name: option.Name, - addr: addr, - tp: C.Snell, + name: option.Name, + addr: addr, + tp: C.Snell, + iface: option.Interface, }, psk: psk, obfsOption: obfsOption, @@ -122,7 +124,7 @@ func NewSnell(option SnellOption) (*Snell, error) { if option.Version == snell.Version2 { 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 { return nil, err } diff --git a/adapter/outbound/socks5.go b/adapter/outbound/socks5.go index 7714c5c52..874da9f14 100644 --- a/adapter/outbound/socks5.go +++ b/adapter/outbound/socks5.go @@ -24,6 +24,7 @@ type Socks5 struct { } type Socks5Option struct { + *BaseOption Name string `proxy:"name"` Server string `proxy:"server"` 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 -func (ss *Socks5) DialContext(ctx context.Context, metadata *C.Metadata) (_ C.Conn, err error) { - c, err := dialer.DialContext(ctx, "tcp", ss.addr) +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, ss.Base.DialOptions(opts...)...) if err != nil { 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 -func (ss *Socks5) ListenPacketContext(ctx context.Context, metadata *C.Metadata) (_ C.PacketConn, err error) { - c, err := dialer.DialContext(ctx, "tcp", ss.addr) +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, ss.Base.DialOptions(opts...)...) if err != nil { err = fmt.Errorf("%s connect error: %w", ss.addr, err) return @@ -107,7 +108,7 @@ func (ss *Socks5) ListenPacketContext(ctx context.Context, metadata *C.Metadata) return } - pc, err := dialer.ListenPacket(ctx, "udp", "") + pc, err := dialer.ListenPacket(ctx, "udp", "", ss.Base.DialOptions(opts...)...) if err != nil { return } @@ -148,10 +149,11 @@ func NewSocks5(option Socks5Option) *Socks5 { return &Socks5{ Base: &Base{ - name: option.Name, - addr: net.JoinHostPort(option.Server, strconv.Itoa(option.Port)), - tp: C.Socks5, - udp: option.UDP, + name: option.Name, + addr: net.JoinHostPort(option.Server, strconv.Itoa(option.Port)), + tp: C.Socks5, + udp: option.UDP, + iface: option.Interface, }, user: option.UserName, pass: option.Password, diff --git a/adapter/outbound/trojan.go b/adapter/outbound/trojan.go index 8bea0cc8f..35dbea1e0 100644 --- a/adapter/outbound/trojan.go +++ b/adapter/outbound/trojan.go @@ -28,6 +28,7 @@ type Trojan struct { } type TrojanOption struct { + BasicOption Name string `proxy:"name"` Server string `proxy:"server"` 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 -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 - if t.transport != nil { + if t.transport != nil && len(opts) == 0 { c, err := gun.StreamGunWithTransport(t.transport, t.gunConfig) if err != nil { return nil, err @@ -102,7 +103,7 @@ func (t *Trojan) DialContext(ctx context.Context, metadata *C.Metadata) (_ C.Con 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 { 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 -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 // grpc transport - if t.transport != nil { + if t.transport != nil && len(opts) == 0 { c, err = gun.StreamGunWithTransport(t.transport, t.gunConfig) if err != nil { return nil, fmt.Errorf("%s connect error: %w", t.addr, err) } defer safeConnClose(c, err) } else { - c, err = dialer.DialContext(ctx, "tcp", t.addr) + c, err = dialer.DialContext(ctx, "tcp", t.addr, t.Base.DialOptions(opts...)...) if err != nil { return nil, fmt.Errorf("%s connect error: %w", t.addr, err) } @@ -167,10 +168,11 @@ func NewTrojan(option TrojanOption) (*Trojan, error) { t := &Trojan{ Base: &Base{ - name: option.Name, - addr: addr, - tp: C.Trojan, - udp: option.UDP, + name: option.Name, + addr: addr, + tp: C.Trojan, + udp: option.UDP, + iface: option.Interface, }, instance: trojan.New(tOption), option: &option, @@ -178,7 +180,7 @@ func NewTrojan(option TrojanOption) (*Trojan, error) { if option.Network == "grpc" { 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 { return nil, fmt.Errorf("%s connect error: %s", t.addr, err.Error()) } diff --git a/adapter/outbound/vmess.go b/adapter/outbound/vmess.go index b4db00ad9..6746eb518 100644 --- a/adapter/outbound/vmess.go +++ b/adapter/outbound/vmess.go @@ -31,6 +31,7 @@ type Vmess struct { } type VmessOption struct { + BasicOption Name string `proxy:"name"` Server string `proxy:"server"` Port int `proxy:"port"` @@ -195,9 +196,9 @@ func (v *Vmess) StreamConn(c net.Conn, metadata *C.Metadata) (net.Conn, error) { } // 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 - if v.transport != nil { + if v.transport != nil && len(opts) == 0 { c, err := gun.StreamGunWithTransport(v.transport, v.gunConfig) if err != nil { return nil, err @@ -212,7 +213,7 @@ func (v *Vmess) DialContext(ctx context.Context, metadata *C.Metadata) (_ C.Conn 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 { return nil, fmt.Errorf("%s connect error: %s", v.addr, err.Error()) } @@ -224,7 +225,7 @@ func (v *Vmess) DialContext(ctx context.Context, metadata *C.Metadata) (_ C.Conn } // 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 if !metadata.Resolved() { ip, err := resolver.ResolveIP(metadata.Host) @@ -236,7 +237,7 @@ func (v *Vmess) ListenPacketContext(ctx context.Context, metadata *C.Metadata) ( var c net.Conn // gun transport - if v.transport != nil { + if v.transport != nil && len(opts) == 0 { c, err = gun.StreamGunWithTransport(v.transport, v.gunConfig) if err != nil { return nil, err @@ -245,7 +246,7 @@ func (v *Vmess) ListenPacketContext(ctx context.Context, metadata *C.Metadata) ( c, err = v.client.StreamConn(c, parseVmessAddr(metadata)) } else { - c, err = dialer.DialContext(ctx, "tcp", v.addr) + c, err = dialer.DialContext(ctx, "tcp", v.addr, v.Base.DialOptions(opts...)...) if err != nil { return nil, fmt.Errorf("%s connect error: %s", v.addr, err.Error()) } @@ -285,10 +286,11 @@ func NewVmess(option VmessOption) (*Vmess, error) { v := &Vmess{ Base: &Base{ - name: option.Name, - addr: net.JoinHostPort(option.Server, strconv.Itoa(option.Port)), - tp: C.Vmess, - udp: option.UDP, + name: option.Name, + addr: net.JoinHostPort(option.Server, strconv.Itoa(option.Port)), + tp: C.Vmess, + udp: option.UDP, + iface: option.Interface, }, client: client, option: &option, @@ -301,7 +303,7 @@ func NewVmess(option VmessOption) (*Vmess, error) { } case "grpc": 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 { return nil, fmt.Errorf("%s connect error: %s", v.addr, err.Error()) } diff --git a/adapter/outboundgroup/fallback.go b/adapter/outboundgroup/fallback.go index 3221b5527..2f9f0887f 100644 --- a/adapter/outboundgroup/fallback.go +++ b/adapter/outboundgroup/fallback.go @@ -6,6 +6,7 @@ import ( "github.com/Dreamacro/clash/adapter/outbound" "github.com/Dreamacro/clash/common/singledo" + "github.com/Dreamacro/clash/component/dialer" C "github.com/Dreamacro/clash/constant" "github.com/Dreamacro/clash/constant/provider" ) @@ -23,9 +24,9 @@ func (f *Fallback) Now() string { } // 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) - c, err := proxy.DialContext(ctx, metadata) + c, err := proxy.DialContext(ctx, metadata, f.Base.DialOptions(opts...)...) if err == nil { c.AppendToChains(f) } @@ -33,9 +34,9 @@ func (f *Fallback) DialContext(ctx context.Context, metadata *C.Metadata) (C.Con } // 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) - pc, err := proxy.ListenPacketContext(ctx, metadata) + pc, err := proxy.ListenPacketContext(ctx, metadata, f.Base.DialOptions(opts...)...) if err == nil { pc.AppendToChains(f) } @@ -90,11 +91,15 @@ func (f *Fallback) findAliveProxy(touch bool) C.Proxy { return proxies[0] } -func NewFallback(options *GroupCommonOption, providers []provider.ProxyProvider) *Fallback { +func NewFallback(option *GroupCommonOption, providers []provider.ProxyProvider) *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, + }), single: singledo.NewSingle(defaultGetProxiesDuration), providers: providers, - disableUDP: options.DisableUDP, + disableUDP: option.DisableUDP, } } diff --git a/adapter/outboundgroup/loadbalance.go b/adapter/outboundgroup/loadbalance.go index fb2840102..df1c2ba49 100644 --- a/adapter/outboundgroup/loadbalance.go +++ b/adapter/outboundgroup/loadbalance.go @@ -10,6 +10,7 @@ import ( "github.com/Dreamacro/clash/adapter/outbound" "github.com/Dreamacro/clash/common/murmur3" "github.com/Dreamacro/clash/common/singledo" + "github.com/Dreamacro/clash/component/dialer" C "github.com/Dreamacro/clash/constant" "github.com/Dreamacro/clash/constant/provider" @@ -69,7 +70,7 @@ func jumpHash(key uint64, buckets int32) int32 { } // 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() { if err == nil { c.AppendToChains(lb) @@ -78,12 +79,12 @@ func (lb *LoadBalance) DialContext(ctx context.Context, metadata *C.Metadata) (c proxy := lb.Unwrap(metadata) - c, err = proxy.DialContext(ctx, metadata) + c, err = proxy.DialContext(ctx, metadata, lb.Base.DialOptions(opts...)...) return } // 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() { if err == nil { pc.AppendToChains(lb) @@ -91,7 +92,7 @@ func (lb *LoadBalance) ListenPacketContext(ctx context.Context, metadata *C.Meta }() proxy := lb.Unwrap(metadata) - return proxy.ListenPacketContext(ctx, metadata) + return proxy.ListenPacketContext(ctx, metadata, lb.Base.DialOptions(opts...)...) } // 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 switch strategy { case "consistent-hashing": @@ -169,10 +170,14 @@ func NewLoadBalance(options *GroupCommonOption, providers []provider.ProxyProvid return nil, fmt.Errorf("%w: %s", errStrategy, strategy) } return &LoadBalance{ - Base: outbound.NewBase(options.Name, "", C.LoadBalance, false), + Base: outbound.NewBase(outbound.BaseOption{ + Name: option.Name, + Type: C.LoadBalance, + Interface: option.Interface, + }), single: singledo.NewSingle(defaultGetProxiesDuration), providers: providers, strategyFn: strategyFn, - disableUDP: options.DisableUDP, + disableUDP: option.DisableUDP, }, nil } diff --git a/adapter/outboundgroup/parser.go b/adapter/outboundgroup/parser.go index cf97579f9..190d333de 100644 --- a/adapter/outboundgroup/parser.go +++ b/adapter/outboundgroup/parser.go @@ -4,6 +4,7 @@ import ( "errors" "fmt" + "github.com/Dreamacro/clash/adapter/outbound" "github.com/Dreamacro/clash/adapter/provider" "github.com/Dreamacro/clash/common/structure" C "github.com/Dreamacro/clash/constant" @@ -19,6 +20,7 @@ var ( ) type GroupCommonOption struct { + outbound.BasicOption Name string `group:"name"` Type string `group:"type"` Proxies []string `group:"proxies,omitempty"` diff --git a/adapter/outboundgroup/relay.go b/adapter/outboundgroup/relay.go index 78410a449..4ec4ffacf 100644 --- a/adapter/outboundgroup/relay.go +++ b/adapter/outboundgroup/relay.go @@ -19,7 +19,7 @@ type Relay struct { } // 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 for _, proxy := range r.proxies(metadata, true) { if proxy.Type() != C.Direct { @@ -29,15 +29,15 @@ func (r *Relay) DialContext(ctx context.Context, metadata *C.Metadata) (C.Conn, switch len(proxies) { case 0: - return outbound.NewDirect().DialContext(ctx, metadata) + return outbound.NewDirect().DialContext(ctx, metadata, r.Base.DialOptions(opts...)...) case 1: - return proxies[0].DialContext(ctx, metadata) + return proxies[0].DialContext(ctx, metadata, r.Base.DialOptions(opts...)...) } first := proxies[0] 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 { return nil, fmt.Errorf("%s connect error: %w", first.Addr(), err) } @@ -100,9 +100,13 @@ func (r *Relay) proxies(metadata *C.Metadata, touch bool) []C.Proxy { return proxies } -func NewRelay(options *GroupCommonOption, providers []provider.ProxyProvider) *Relay { +func NewRelay(option *GroupCommonOption, providers []provider.ProxyProvider) *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, + }), single: singledo.NewSingle(defaultGetProxiesDuration), providers: providers, } diff --git a/adapter/outboundgroup/selector.go b/adapter/outboundgroup/selector.go index 008e8af8d..4ec67cd1d 100644 --- a/adapter/outboundgroup/selector.go +++ b/adapter/outboundgroup/selector.go @@ -7,6 +7,7 @@ import ( "github.com/Dreamacro/clash/adapter/outbound" "github.com/Dreamacro/clash/common/singledo" + "github.com/Dreamacro/clash/component/dialer" C "github.com/Dreamacro/clash/constant" "github.com/Dreamacro/clash/constant/provider" ) @@ -20,8 +21,8 @@ type Selector struct { } // DialContext implements C.ProxyAdapter -func (s *Selector) DialContext(ctx context.Context, metadata *C.Metadata) (C.Conn, error) { - c, err := s.selectedProxy(true).DialContext(ctx, metadata) +func (s *Selector) DialContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (C.Conn, error) { + c, err := s.selectedProxy(true).DialContext(ctx, metadata, s.Base.DialOptions(opts...)...) if err == nil { c.AppendToChains(s) } @@ -29,8 +30,8 @@ func (s *Selector) DialContext(ctx context.Context, metadata *C.Metadata) (C.Con } // ListenPacketContext implements C.ProxyAdapter -func (s *Selector) ListenPacketContext(ctx context.Context, metadata *C.Metadata) (C.PacketConn, error) { - pc, err := s.selectedProxy(true).ListenPacketContext(ctx, metadata) +func (s *Selector) ListenPacketContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (C.PacketConn, error) { + pc, err := s.selectedProxy(true).ListenPacketContext(ctx, metadata, s.Base.DialOptions(opts...)...) if err == nil { pc.AppendToChains(s) } @@ -96,13 +97,17 @@ func (s *Selector) selectedProxy(touch bool) 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() return &Selector{ - Base: outbound.NewBase(options.Name, "", C.Selector, false), + Base: outbound.NewBase(outbound.BaseOption{ + Name: option.Name, + Type: C.Selector, + Interface: option.Interface, + }), single: singledo.NewSingle(defaultGetProxiesDuration), providers: providers, selected: selected, - disableUDP: options.DisableUDP, + disableUDP: option.DisableUDP, } } diff --git a/adapter/outboundgroup/urltest.go b/adapter/outboundgroup/urltest.go index b27f12a44..6866db0df 100644 --- a/adapter/outboundgroup/urltest.go +++ b/adapter/outboundgroup/urltest.go @@ -7,6 +7,7 @@ import ( "github.com/Dreamacro/clash/adapter/outbound" "github.com/Dreamacro/clash/common/singledo" + "github.com/Dreamacro/clash/component/dialer" C "github.com/Dreamacro/clash/constant" "github.com/Dreamacro/clash/constant/provider" ) @@ -34,8 +35,8 @@ func (u *URLTest) Now() string { } // DialContext implements C.ProxyAdapter -func (u *URLTest) DialContext(ctx context.Context, metadata *C.Metadata) (c C.Conn, err error) { - c, err = u.fast(true).DialContext(ctx, metadata) +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, u.Base.DialOptions(opts...)...) if err == nil { c.AppendToChains(u) } @@ -43,8 +44,8 @@ func (u *URLTest) DialContext(ctx context.Context, metadata *C.Metadata) (c C.Co } // ListenPacketContext implements C.ProxyAdapter -func (u *URLTest) ListenPacketContext(ctx context.Context, metadata *C.Metadata) (C.PacketConn, error) { - pc, err := u.fast(true).ListenPacketContext(ctx, metadata) +func (u *URLTest) ListenPacketContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (C.PacketConn, error) { + pc, err := u.fast(true).ListenPacketContext(ctx, metadata, u.Base.DialOptions(opts...)...) if err == nil { pc.AppendToChains(u) } @@ -133,13 +134,17 @@ func parseURLTestOption(config map[string]interface{}) []urlTestOption { return opts } -func NewURLTest(commonOptions *GroupCommonOption, providers []provider.ProxyProvider, options ...urlTestOption) *URLTest { +func NewURLTest(option *GroupCommonOption, providers []provider.ProxyProvider, options ...urlTestOption) *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, + }), single: singledo.NewSingle(defaultGetProxiesDuration), fastSingle: singledo.NewSingle(time.Second * 10), providers: providers, - disableUDP: commonOptions.DisableUDP, + disableUDP: option.DisableUDP, } for _, option := range options { diff --git a/component/dialer/dialer.go b/component/dialer/dialer.go index 75bbb8687..87b62dd65 100644 --- a/component/dialer/dialer.go +++ b/component/dialer/dialer.go @@ -36,12 +36,12 @@ func DialContext(ctx context.Context, network, address string, options ...Option } func ListenPacket(ctx context.Context, network, address string, options ...Option) (net.PacketConn, error) { - cfg := &config{} + cfg := &option{ + interfaceName: DefaultInterface.Load(), + } - if !cfg.skipDefault { - for _, o := range DefaultOptions { - o(cfg) - } + for _, o := range DefaultOptions { + o(cfg) } for _, o := range options { @@ -64,12 +64,12 @@ func ListenPacket(ctx context.Context, network, address string, options ...Optio } func dialContext(ctx context.Context, network string, destination net.IP, port string, options []Option) (net.Conn, error) { - opt := &config{} + opt := &option{ + interfaceName: DefaultInterface.Load(), + } - if !opt.skipDefault { - for _, o := range DefaultOptions { - o(opt) - } + for _, o := range DefaultOptions { + o(opt) } for _, o := range options { diff --git a/component/dialer/options.go b/component/dialer/options.go index 33083864a..96d9eb751 100644 --- a/component/dialer/options.go +++ b/component/dialer/options.go @@ -1,29 +1,27 @@ package dialer -var DefaultOptions []Option +import "go.uber.org/atomic" -type config struct { - skipDefault bool +var ( + DefaultOptions []Option + DefaultInterface = atomic.NewString("") +) + +type option struct { interfaceName string addrReuse bool } -type Option func(opt *config) +type Option func(opt *option) func WithInterface(name string) Option { - return func(opt *config) { + return func(opt *option) { opt.interfaceName = name } } func WithAddrReuse(reuse bool) Option { - return func(opt *config) { + return func(opt *option) { opt.addrReuse = reuse } } - -func WithSkipDefault(skip bool) Option { - return func(opt *config) { - opt.skipDefault = skip - } -} diff --git a/constant/adapters.go b/constant/adapters.go index 2f7006e96..59fde9601 100644 --- a/constant/adapters.go +++ b/constant/adapters.go @@ -5,6 +5,8 @@ import ( "fmt" "net" "time" + + "github.com/Dreamacro/clash/component/dialer" ) // Adapter Type @@ -90,9 +92,9 @@ type ProxyAdapter interface { // DialContext return a C.Conn with protocol which // 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) (PacketConn, error) + ListenPacketContext(ctx context.Context, metadata *Metadata, opts ...dialer.Option) (PacketConn, error) // Unwrap extracts the proxy from a proxy-group. It returns nil when nothing to extract. Unwrap(metadata *Metadata) Proxy diff --git a/hub/executor/executor.go b/hub/executor/executor.go index ca8ee95de..59f948817 100644 --- a/hub/executor/executor.go +++ b/hub/executor/executor.go @@ -168,11 +168,7 @@ func updateGeneral(general *config.General, force bool) { tunnel.SetMode(general.Mode) resolver.DisableIPv6 = !general.IPv6 - if general.Interface != "" { - dialer.DefaultOptions = []dialer.Option{dialer.WithInterface(general.Interface)} - } else { - dialer.DefaultOptions = nil - } + dialer.DefaultInterface.Store(general.Interface) iface.FlushCache() From d40e5e4fe6c11311ee1de82779a985c3ca47d03a Mon Sep 17 00:00:00 2001 From: Dreamacro <8615343+Dreamacro@users.noreply.github.com> Date: Mon, 8 Nov 2021 00:31:08 +0800 Subject: [PATCH 92/96] Fix: codeql alerts --- adapter/outbound/snell.go | 4 ++-- adapter/outbound/util.go | 2 +- adapter/outbound/vmess.go | 2 +- component/dialer/bind_others.go | 4 ++-- constant/metadata.go | 4 ++-- rule/port.go | 2 +- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/adapter/outbound/snell.go b/adapter/outbound/snell.go index 40dcf0664..d0a26ecc1 100644 --- a/adapter/outbound/snell.go +++ b/adapter/outbound/snell.go @@ -52,7 +52,7 @@ func streamConn(c net.Conn, option streamOption) *snell.Snell { // StreamConn implements C.ProxyAdapter 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}) - port, _ := strconv.Atoi(metadata.DstPort) + port, _ := strconv.ParseInt(metadata.DstPort, 10, 16) err := snell.WriteHeader(c, metadata.String(), uint(port), s.version) return c, err } @@ -65,7 +65,7 @@ func (s *Snell) DialContext(ctx context.Context, metadata *C.Metadata, opts ...d 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 { c.Close() return nil, err diff --git a/adapter/outbound/util.go b/adapter/outbound/util.go index 0e1d4c8e5..b376522fa 100644 --- a/adapter/outbound/util.go +++ b/adapter/outbound/util.go @@ -21,7 +21,7 @@ func tcpKeepAlive(c net.Conn) { func serializesSocksAddr(metadata *C.Metadata) []byte { var buf [][]byte aType := uint8(metadata.AddrType) - p, _ := strconv.Atoi(metadata.DstPort) + p, _ := strconv.ParseUint(metadata.DstPort, 10, 16) port := []byte{uint8(p >> 8), uint8(p & 0xff)} switch metadata.AddrType { case socks5.AtypDomainName: diff --git a/adapter/outbound/vmess.go b/adapter/outbound/vmess.go index 6746eb518..99ea531ca 100644 --- a/adapter/outbound/vmess.go +++ b/adapter/outbound/vmess.go @@ -353,7 +353,7 @@ func parseVmessAddr(metadata *C.Metadata) *vmess.DstAddr { copy(addr[1:], []byte(metadata.Host)) } - port, _ := strconv.Atoi(metadata.DstPort) + port, _ := strconv.ParseUint(metadata.DstPort, 10, 16) return &vmess.DstAddr{ UDP: metadata.NetWork == C.UDP, AddrType: addrType, diff --git a/component/dialer/bind_others.go b/component/dialer/bind_others.go index 7f1923aa2..e94946739 100644 --- a/component/dialer/bind_others.go +++ b/component/dialer/bind_others.go @@ -62,7 +62,7 @@ func bindIfaceToDialer(ifaceName string, dialer *net.Dialer, network string, des if dialer.LocalAddr != nil { _, port, err := net.SplitHostPort(dialer.LocalAddr.String()) if err == nil { - local, _ = strconv.Atoi(port) + local, _ = strconv.ParseInt(port, 10, 16) } } @@ -82,7 +82,7 @@ func bindIfaceToListenConfig(ifaceName string, _ *net.ListenConfig, network, add port = "0" } - local, _ := strconv.Atoi(port) + local, _ := strconv.ParseInt(port, 10, 16) addr, err := lookupLocalAddr(ifaceName, network, nil, local) if err != nil { diff --git a/constant/metadata.go b/constant/metadata.go index 822b4714d..9cc49973f 100644 --- a/constant/metadata.go +++ b/constant/metadata.go @@ -107,10 +107,10 @@ func (m *Metadata) UDPAddr() *net.UDPAddr { if m.NetWork != UDP || m.DstIP == nil { return nil } - port, _ := strconv.Atoi(m.DstPort) + port, _ := strconv.ParseInt(m.DstPort, 10, 16) return &net.UDPAddr{ IP: m.DstIP, - Port: port, + Port: int(port), } } diff --git a/rule/port.go b/rule/port.go index 281a4c4df..b6e8abb1c 100644 --- a/rule/port.go +++ b/rule/port.go @@ -39,7 +39,7 @@ func (p *Port) ShouldResolveIP() bool { } func NewPort(port string, adapter string, isSource bool) (*Port, error) { - _, err := strconv.Atoi(port) + _, err := strconv.ParseUint(port, 10, 16) if err != nil { return nil, errPayload } From e622d8dd38086f96c49726f4d6572135ce9847f6 Mon Sep 17 00:00:00 2001 From: Dreamacro <8615343+Dreamacro@users.noreply.github.com> Date: Mon, 8 Nov 2021 13:29:37 +0800 Subject: [PATCH 93/96] Fix: parse dial interface option --- adapter/outbound/base.go | 2 +- common/structure/structure.go | 6 +++ common/structure/structure_test.go | 64 ++++++++++++++---------------- 3 files changed, 37 insertions(+), 35 deletions(-) diff --git a/adapter/outbound/base.go b/adapter/outbound/base.go index e028cd4e8..15eedd1ae 100644 --- a/adapter/outbound/base.go +++ b/adapter/outbound/base.go @@ -70,7 +70,7 @@ func (b *Base) DialOptions(opts ...dialer.Option) []dialer.Option { } type BasicOption struct { - Interface string `proxy:"interface-name"` + Interface string `proxy:"interface-name,omitempty" group:"interface-name,omitempty"` } type BaseOption struct { diff --git a/common/structure/structure.go b/common/structure/structure.go index 75579ffcb..07043abc4 100644 --- a/common/structure/structure.go +++ b/common/structure/structure.go @@ -37,6 +37,12 @@ func (d *Decoder) Decode(src map[string]interface{}, dst interface{}) error { v := reflect.ValueOf(dst).Elem() for idx := 0; idx < v.NumField(); 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) str := strings.SplitN(tag, ",", 2) diff --git a/common/structure/structure_test.go b/common/structure/structure_test.go index 0feef28e8..69268fa60 100644 --- a/common/structure/structure_test.go +++ b/common/structure/structure_test.go @@ -1,8 +1,9 @@ package structure import ( - "reflect" "testing" + + "github.com/stretchr/testify/assert" ) var ( @@ -39,12 +40,8 @@ func TestStructure_Basic(t *testing.T) { s := &Baz{} err := decoder.Decode(rawMap, s) - if err != nil { - t.Fatal(err.Error()) - } - if !reflect.DeepEqual(s, goal) { - t.Fatalf("bad: %#v", s) - } + assert.Nil(t, err) + assert.Equal(t, goal, s) } func TestStructure_Slice(t *testing.T) { @@ -60,12 +57,8 @@ func TestStructure_Slice(t *testing.T) { s := &BazSlice{} err := decoder.Decode(rawMap, s) - if err != nil { - t.Fatal(err.Error()) - } - if !reflect.DeepEqual(s, goal) { - t.Fatalf("bad: %#v", s) - } + assert.Nil(t, err) + assert.Equal(t, goal, s) } func TestStructure_Optional(t *testing.T) { @@ -79,12 +72,8 @@ func TestStructure_Optional(t *testing.T) { s := &BazOptional{} err := decoder.Decode(rawMap, s) - if err != nil { - t.Fatal(err.Error()) - } - if !reflect.DeepEqual(s, goal) { - t.Fatalf("bad: %#v", s) - } + assert.Nil(t, err) + assert.Equal(t, goal, s) } func TestStructure_MissingKey(t *testing.T) { @@ -94,18 +83,14 @@ func TestStructure_MissingKey(t *testing.T) { s := &Baz{} err := decoder.Decode(rawMap, s) - if err == nil { - t.Fatalf("should throw error: %#v", s) - } + assert.NotNilf(t, err, "should throw error: %#v", s) } func TestStructure_ParamError(t *testing.T) { rawMap := map[string]interface{}{} s := Baz{} err := decoder.Decode(rawMap, s) - if err == nil { - t.Fatalf("should throw error: %#v", s) - } + assert.NotNilf(t, err, "should throw error: %#v", s) } func TestStructure_SliceTypeError(t *testing.T) { @@ -116,9 +101,7 @@ func TestStructure_SliceTypeError(t *testing.T) { s := &BazSlice{} err := decoder.Decode(rawMap, s) - if err == nil { - t.Fatalf("should throw error: %#v", s) - } + assert.NotNilf(t, err, "should throw error: %#v", s) } func TestStructure_WeakType(t *testing.T) { @@ -134,10 +117,23 @@ func TestStructure_WeakType(t *testing.T) { s := &BazSlice{} err := weakTypeDecoder.Decode(rawMap, s) - if err != nil { - t.Fatal(err.Error()) - } - if !reflect.DeepEqual(s, goal) { - t.Fatalf("bad: %#v", s) - } + assert.Nil(t, err) + assert.Equal(t, goal, 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) } From bd2ea2b917aa84b7b91272a8197555e4710f4cd7 Mon Sep 17 00:00:00 2001 From: bobo liu <7552030+fakeboboliu@users.noreply.github.com> Date: Mon, 8 Nov 2021 16:59:48 +0800 Subject: [PATCH 94/96] Feature: mark on socket (#1705) --- adapter/outbound/base.go | 20 +++++++++---- adapter/outbound/socks5.go | 2 +- adapter/outboundgroup/fallback.go | 7 +++-- adapter/outboundgroup/loadbalance.go | 7 +++-- adapter/outboundgroup/relay.go | 7 +++-- adapter/outboundgroup/selector.go | 7 +++-- adapter/outboundgroup/urltest.go | 7 +++-- component/dialer/dialer.go | 6 ++++ component/dialer/mark_linux.go | 44 ++++++++++++++++++++++++++++ component/dialer/mark_nonlinux.go | 27 +++++++++++++++++ component/dialer/options.go | 7 +++++ 11 files changed, 119 insertions(+), 22 deletions(-) create mode 100644 component/dialer/mark_linux.go create mode 100644 component/dialer/mark_nonlinux.go diff --git a/adapter/outbound/base.go b/adapter/outbound/base.go index 15eedd1ae..e9119415e 100644 --- a/adapter/outbound/base.go +++ b/adapter/outbound/base.go @@ -16,6 +16,7 @@ type Base struct { iface string tp C.AdapterType udp bool + rmark int } // Name implements C.ProxyAdapter @@ -66,19 +67,25 @@ func (b *Base) DialOptions(opts ...dialer.Option) []dialer.Option { 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"` + 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 + Name string + Addr string + Type C.AdapterType + UDP bool + Interface string + RoutingMark int } func NewBase(opt BaseOption) *Base { @@ -88,6 +95,7 @@ func NewBase(opt BaseOption) *Base { tp: opt.Type, udp: opt.UDP, iface: opt.Interface, + rmark: opt.RoutingMark, } } diff --git a/adapter/outbound/socks5.go b/adapter/outbound/socks5.go index 874da9f14..d81c76140 100644 --- a/adapter/outbound/socks5.go +++ b/adapter/outbound/socks5.go @@ -24,7 +24,7 @@ type Socks5 struct { } type Socks5Option struct { - *BaseOption + BasicOption Name string `proxy:"name"` Server string `proxy:"server"` Port int `proxy:"port"` diff --git a/adapter/outboundgroup/fallback.go b/adapter/outboundgroup/fallback.go index 2f9f0887f..b08af487f 100644 --- a/adapter/outboundgroup/fallback.go +++ b/adapter/outboundgroup/fallback.go @@ -94,9 +94,10 @@ func (f *Fallback) findAliveProxy(touch bool) C.Proxy { func NewFallback(option *GroupCommonOption, providers []provider.ProxyProvider) *Fallback { return &Fallback{ Base: outbound.NewBase(outbound.BaseOption{ - Name: option.Name, - Type: C.Fallback, - Interface: option.Interface, + Name: option.Name, + Type: C.Fallback, + Interface: option.Interface, + RoutingMark: option.RoutingMark, }), single: singledo.NewSingle(defaultGetProxiesDuration), providers: providers, diff --git a/adapter/outboundgroup/loadbalance.go b/adapter/outboundgroup/loadbalance.go index df1c2ba49..26c8052ad 100644 --- a/adapter/outboundgroup/loadbalance.go +++ b/adapter/outboundgroup/loadbalance.go @@ -171,9 +171,10 @@ func NewLoadBalance(option *GroupCommonOption, providers []provider.ProxyProvide } return &LoadBalance{ Base: outbound.NewBase(outbound.BaseOption{ - Name: option.Name, - Type: C.LoadBalance, - Interface: option.Interface, + Name: option.Name, + Type: C.LoadBalance, + Interface: option.Interface, + RoutingMark: option.RoutingMark, }), single: singledo.NewSingle(defaultGetProxiesDuration), providers: providers, diff --git a/adapter/outboundgroup/relay.go b/adapter/outboundgroup/relay.go index 4ec4ffacf..393a69bb9 100644 --- a/adapter/outboundgroup/relay.go +++ b/adapter/outboundgroup/relay.go @@ -103,9 +103,10 @@ func (r *Relay) proxies(metadata *C.Metadata, touch bool) []C.Proxy { func NewRelay(option *GroupCommonOption, providers []provider.ProxyProvider) *Relay { return &Relay{ Base: outbound.NewBase(outbound.BaseOption{ - Name: option.Name, - Type: C.Relay, - Interface: option.Interface, + Name: option.Name, + Type: C.Relay, + Interface: option.Interface, + RoutingMark: option.RoutingMark, }), single: singledo.NewSingle(defaultGetProxiesDuration), providers: providers, diff --git a/adapter/outboundgroup/selector.go b/adapter/outboundgroup/selector.go index 4ec67cd1d..47e4b87d0 100644 --- a/adapter/outboundgroup/selector.go +++ b/adapter/outboundgroup/selector.go @@ -101,9 +101,10 @@ func NewSelector(option *GroupCommonOption, providers []provider.ProxyProvider) selected := providers[0].Proxies()[0].Name() return &Selector{ Base: outbound.NewBase(outbound.BaseOption{ - Name: option.Name, - Type: C.Selector, - Interface: option.Interface, + Name: option.Name, + Type: C.Selector, + Interface: option.Interface, + RoutingMark: option.RoutingMark, }), single: singledo.NewSingle(defaultGetProxiesDuration), providers: providers, diff --git a/adapter/outboundgroup/urltest.go b/adapter/outboundgroup/urltest.go index 6866db0df..47144c046 100644 --- a/adapter/outboundgroup/urltest.go +++ b/adapter/outboundgroup/urltest.go @@ -137,9 +137,10 @@ func parseURLTestOption(config map[string]interface{}) []urlTestOption { func NewURLTest(option *GroupCommonOption, providers []provider.ProxyProvider, options ...urlTestOption) *URLTest { urlTest := &URLTest{ Base: outbound.NewBase(outbound.BaseOption{ - Name: option.Name, - Type: C.URLTest, - Interface: option.Interface, + Name: option.Name, + Type: C.URLTest, + Interface: option.Interface, + RoutingMark: option.RoutingMark, }), single: singledo.NewSingle(defaultGetProxiesDuration), fastSingle: singledo.NewSingle(time.Second * 10), diff --git a/component/dialer/dialer.go b/component/dialer/dialer.go index 87b62dd65..c84fcaa46 100644 --- a/component/dialer/dialer.go +++ b/component/dialer/dialer.go @@ -59,6 +59,9 @@ func ListenPacket(ctx context.Context, network, address string, options ...Optio if cfg.addrReuse { addrReuseToListenConfig(lc) } + if cfg.routingMark != 0 { + bindMarkToListenConfig(cfg.routingMark, lc, network, address) + } return lc.ListenPacket(ctx, network, address) } @@ -82,6 +85,9 @@ func dialContext(ctx context.Context, network string, destination net.IP, port s return nil, err } } + if opt.routingMark != 0 { + bindMarkToDialer(opt.routingMark, dialer, network, destination) + } return dialer.DialContext(ctx, network, net.JoinHostPort(destination.String(), port)) } diff --git a/component/dialer/mark_linux.go b/component/dialer/mark_linux.go new file mode 100644 index 000000000..79a2185e4 --- /dev/null +++ b/component/dialer/mark_linux.go @@ -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) + } + }) + } +} diff --git a/component/dialer/mark_nonlinux.go b/component/dialer/mark_nonlinux.go new file mode 100644 index 000000000..5d9befb1a --- /dev/null +++ b/component/dialer/mark_nonlinux.go @@ -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() +} diff --git a/component/dialer/options.go b/component/dialer/options.go index 96d9eb751..b3cca8105 100644 --- a/component/dialer/options.go +++ b/component/dialer/options.go @@ -10,6 +10,7 @@ var ( type option struct { interfaceName string addrReuse bool + routingMark int } type Option func(opt *option) @@ -25,3 +26,9 @@ func WithAddrReuse(reuse bool) Option { opt.addrReuse = reuse } } + +func WithRoutingMark(mark int) Option { + return func(opt *option) { + opt.routingMark = mark + } +} From b56d35040d38df288eb58a6b0a752cd84598817a Mon Sep 17 00:00:00 2001 From: Dreamacro <8615343+Dreamacro@users.noreply.github.com> Date: Mon, 8 Nov 2021 20:48:29 +0800 Subject: [PATCH 95/96] Chore: update dependencies and rename profile props --- config/config.go | 2 +- go.mod | 12 ++++++------ go.sum | 24 +++++++++++------------ test/go.mod | 20 +++++++++---------- test/go.sum | 51 ++++++++++++++++++++++++++---------------------- 5 files changed, 57 insertions(+), 52 deletions(-) diff --git a/config/config.go b/config/config.go index 603523ec6..a9abe71f8 100644 --- a/config/config.go +++ b/config/config.go @@ -80,7 +80,7 @@ type FallbackFilter struct { // Profile config type Profile struct { StoreSelected bool `yaml:"store-selected"` - StoreFakeIP bool `yaml:"store-fakeip"` + StoreFakeIP bool `yaml:"store-fake-ip"` } // Experimental config diff --git a/go.mod b/go.mod index c608f7ad2..e2ac4f2d9 100644 --- a/go.mod +++ b/go.mod @@ -4,12 +4,12 @@ go 1.17 require ( 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.5 github.com/go-chi/cors v1.2.0 github.com/go-chi/render v1.0.1 - github.com/gofrs/uuid v4.0.0+incompatible + github.com/gofrs/uuid v4.1.0+incompatible github.com/gorilla/websocket v1.4.2 - github.com/insomniacslk/dhcp v0.0.0-20210827173440-b95caade3eac + github.com/insomniacslk/dhcp v0.0.0-20211026125128-ad197bcd36fd github.com/miekg/dns v1.1.43 github.com/oschwald/geoip2-golang v1.5.0 github.com/sirupsen/logrus v1.8.1 @@ -17,10 +17,10 @@ require ( go.etcd.io/bbolt v1.3.6 go.uber.org/atomic v1.9.0 go.uber.org/automaxprocs v1.4.0 - golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 - golang.org/x/net v0.0.0-20210903162142-ad29c8ab022f + golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 + golang.org/x/net v0.0.0-20211105192438-b53810dc28af golang.org/x/sync v0.0.0-20210220032951-036812b2e83c - golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34 + golang.org/x/sys v0.0.0-20211107104306-e0b2ad06fe42 gopkg.in/yaml.v2 v2.4.0 ) diff --git a/go.sum b/go.sum index cccc8ba34..6ef69f45f 100644 --- a/go.sum +++ b/go.sum @@ -4,14 +4,14 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/fanliao/go-promise v0.0.0-20141029170127-1890db352a72/go.mod h1:PjfxuH4FZdUyfMdtBio2lsRr1AKEaVPwelzuHuh8Lqc= -github.com/go-chi/chi/v5 v5.0.4 h1:5e494iHzsYBiyXQAHHuI4tyJS9M3V84OuX3ufIIGHFo= -github.com/go-chi/chi/v5 v5.0.4/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= +github.com/go-chi/chi/v5 v5.0.5 h1:l3RJ8T8TAqLsXFfah+RA6N4pydMbPwSdvNM+AFWvLUM= +github.com/go-chi/chi/v5 v5.0.5/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= github.com/go-chi/cors v1.2.0 h1:tV1g1XENQ8ku4Bq3K9ub2AtgG+p16SmzeMSGTwrOKdE= github.com/go-chi/cors v1.2.0/go.mod h1:sSbTewc+6wYHBBCW7ytsFSn836hqM7JxpglAy2Vzc58= github.com/go-chi/render v1.0.1 h1:4/5tis2cKaNdnv9zFLfXzcquC9HbeZgCnxGnKrltBS8= github.com/go-chi/render v1.0.1/go.mod h1:pq4Rr7HbnsdaeHagklXub+p6Wd16Af5l9koip1OvJns= -github.com/gofrs/uuid v4.0.0+incompatible h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPhW6m+TnJw= -github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/gofrs/uuid v4.1.0+incompatible h1:sIa2eCvUTwgjbqXrPLfNwUf9S3i3mpH1O1atV+iL/Wk= +github.com/gofrs/uuid v4.1.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= @@ -21,8 +21,8 @@ github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORR github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/hugelgupf/socketpair v0.0.0-20190730060125-05d35a94e714/go.mod h1:2Goc3h8EklBH5mspfHFxBnEoURQCGzQQH1ga9Myjvis= -github.com/insomniacslk/dhcp v0.0.0-20210827173440-b95caade3eac h1:IO6EfdRnPhxgKOsk9DbewdtQZHKZKnGlW7QCUttvNys= -github.com/insomniacslk/dhcp v0.0.0-20210827173440-b95caade3eac/go.mod h1:h+MxyHxRg9NH3terB1nfRIUaQEcI0XOVkdR9LNBlp8E= +github.com/insomniacslk/dhcp v0.0.0-20211026125128-ad197bcd36fd h1:jupbuQFZtwOBg/3EmK91/rGaYFkqCb9bwHOnwn7Cav0= +github.com/insomniacslk/dhcp v0.0.0-20211026125128-ad197bcd36fd/go.mod h1:h+MxyHxRg9NH3terB1nfRIUaQEcI0XOVkdR9LNBlp8E= 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-20201009170750-9c6f07d100c1/go.mod h1:hqoO/u39cqLeBLebZ8fWdE96O7FxrAsRYhnVOdgHxok= @@ -70,8 +70,8 @@ go.uber.org/automaxprocs v1.4.0/go.mod h1:/mTEdr7LvHhs0v7mjdxDreTz1OG5zdZGqgOnhW golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 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-20210817164053-32db794688a5 h1:HWj/xjIHfjYU5nVXpTM0s39J9CbLn7Cc5a7IC5rwsMQ= -golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 h1:7I4JAnoQBe7ZtJcBaYHi5UtiO8tQHbUSXxL+pnGRANg= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190419010253-1f3472d942ba/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -82,8 +82,8 @@ golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/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-20210903162142-ad29c8ab022f h1:w6wWR0H+nyVpbSAQbzVEIACVyr/h8l/BEkY6Sokc7Eg= -golang.org/x/net v0.0.0-20210903162142-ad29c8ab022f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211105192438-b53810dc28af h1:SMeNJG/vclJ5wyBBd4xupMsSJIHTd1coW9g7q6KOjmY= +golang.org/x/net v0.0.0-20211105192438-b53810dc28af/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -106,8 +106,8 @@ golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 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-20210906170528-6f6e22806c34 h1:GkvMjFtXUmahfDtashnc1mnrCtuBVcwse5QV2lUk/tI= -golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211107104306-e0b2ad06fe42 h1:G2DDmludOQZoWbpCr7OKDxnl478ZBGMcOhrv+ooX/Q4= +golang.org/x/sys v0.0.0-20211107104306-e0b2ad06fe42/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= diff --git a/test/go.mod b/test/go.mod index 3a8781517..a43e4f5c9 100644 --- a/test/go.mod +++ b/test/go.mod @@ -3,29 +3,29 @@ module clash-test go 1.17 require ( - github.com/Dreamacro/clash v1.6.6-0.20210905062555-c7b718f6512d - github.com/docker/docker v20.10.8+incompatible + github.com/Dreamacro/clash v1.7.2-0.20211108085948-bd2ea2b917aa + github.com/docker/docker v20.10.10+incompatible github.com/docker/go-connections v0.4.0 github.com/miekg/dns v1.1.43 github.com/stretchr/testify v1.7.0 - golang.org/x/net v0.0.0-20210903162142-ad29c8ab022f + golang.org/x/net v0.0.0-20211105192438-b53810dc28af ) replace github.com/Dreamacro/clash => ../ require ( github.com/Dreamacro/go-shadowsocks2 v0.1.7 // indirect - github.com/Microsoft/go-winio v0.5.0 // indirect - github.com/containerd/containerd v1.5.5 // indirect + github.com/Microsoft/go-winio v0.5.1 // indirect + github.com/containerd/containerd v1.5.7 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/docker/distribution v2.7.1+incompatible // indirect github.com/docker/go-units v0.4.0 // indirect - github.com/gofrs/uuid v4.0.0+incompatible // indirect + github.com/gofrs/uuid v4.1.0+incompatible // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/protobuf v1.5.0 // indirect github.com/gorilla/mux v1.8.0 // 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-20211026125128-ad197bcd36fd // indirect github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 // indirect github.com/morikuni/aec v1.0.0 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect @@ -38,13 +38,13 @@ require ( github.com/u-root/uio v0.0.0-20210528114334-82958018845c // indirect go.etcd.io/bbolt v1.3.6 // indirect go.uber.org/atomic v1.9.0 // indirect - golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 // indirect + golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 // indirect golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect - golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34 // indirect + golang.org/x/sys v0.0.0-20211107104306-e0b2ad06fe42 // indirect golang.org/x/text v0.3.6 // indirect golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a // indirect - google.golang.org/grpc v1.40.0 // indirect + google.golang.org/grpc v1.42.0 // indirect google.golang.org/protobuf v1.26.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect diff --git a/test/go.sum b/test/go.sum index e018f54c7..061bb3a4d 100644 --- a/test/go.sum +++ b/test/go.sum @@ -48,8 +48,8 @@ github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugX github.com/Microsoft/go-winio v0.4.17-0.20210211115548-6eac466e5fa3/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= github.com/Microsoft/go-winio v0.4.17-0.20210324224401-5516f17a5958/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= github.com/Microsoft/go-winio v0.4.17/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= -github.com/Microsoft/go-winio v0.5.0 h1:Elr9Wn+sGKPlkaBvwu4mTrxtmOp3F3yV9qhaHbXGjwU= -github.com/Microsoft/go-winio v0.5.0/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= +github.com/Microsoft/go-winio v0.5.1 h1:aPJp2QD7OOrhO5tQXqQoGSJc+DjDtWTGLOmNyAm6FgY= +github.com/Microsoft/go-winio v0.5.1/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= github.com/Microsoft/hcsshim v0.8.6/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg= github.com/Microsoft/hcsshim v0.8.7-0.20190325164909-8abdbb8205e4/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg= github.com/Microsoft/hcsshim v0.8.7/go.mod h1:OHd7sQqRFrYd3RmSgbgji+ctCwkbq2wbEYNSzOYtcBQ= @@ -57,7 +57,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.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.18/go.mod h1:+w2gRZ5ReXQhFOrvSQeNfhrYB/dg3oDwTOcER2fw4I4= +github.com/Microsoft/hcsshim v0.8.21/go.mod h1:+w2gRZ5ReXQhFOrvSQeNfhrYB/dg3oDwTOcER2fw4I4= 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/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= @@ -105,7 +105,10 @@ github.com/cilium/ebpf v0.6.2/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= +github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= github.com/containerd/aufs v0.0.0-20200908144142-dab0cbea06f4/go.mod h1:nukgQABAEopAHvB6j7cnP5zJ+/3aVcE7hCYqvIwAHyE= github.com/containerd/aufs v0.0.0-20201003224125-76a6863f2989/go.mod h1:AkGGQs9NM2vtYHaUen+NljV0/baGCAPELGm2q9ZXpWU= @@ -139,8 +142,8 @@ github.com/containerd/containerd v1.5.0-beta.3/go.mod h1:/wr9AVtEM7x9c+n0+stptlo 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.1/go.mod h1:0DOxVqwDy2iZvrZp2JUx/E+hS0UNTVn7dJnIOwtYR4g= -github.com/containerd/containerd v1.5.5 h1:q1gxsZsGZ8ddVe98yO6pR21b5xQSMiR61lD0W96pgQo= -github.com/containerd/containerd v1.5.5/go.mod h1:oSTh0QpT1w6jYcGmbiSbxv9OSQYaa88mPyWIuU79zyo= +github.com/containerd/containerd v1.5.7 h1:rQyoYtj4KddB3bxG6SAqd4+08gePNyJjRqvOIfV3rkM= +github.com/containerd/containerd v1.5.7/go.mod h1:gyvv6+ugqY25TiXxcZC3L5yOeYgEw0QMhscqVp1AR9c= 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-20191127005431-f65d91d395eb/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= @@ -226,8 +229,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+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug= 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.8+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v20.10.10+incompatible h1:GKkP0T7U4ks6X3lmmHKC2QDprnpRJor2Z5a8m62R9ZM= +github.com/docker/docker v20.10.10+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/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= github.com/docker/go-events v0.0.0-20170721190031-9461782956ad/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= @@ -248,7 +251,7 @@ github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymF github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= +github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/fanliao/go-promise v0.0.0-20141029170127-1890db352a72/go.mod h1:PjfxuH4FZdUyfMdtBio2lsRr1AKEaVPwelzuHuh8Lqc= @@ -261,7 +264,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/ghodss/yaml v0.0.0-20150909031657-73d445a93680/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.5/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= 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-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= @@ -287,8 +290,8 @@ github.com/godbus/dbus v0.0.0-20180201030542-885f9cc04c9c/go.mod h1:/YcGZj5zSblf github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= 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/gofrs/uuid v4.0.0+incompatible h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPhW6m+TnJw= -github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/gofrs/uuid v4.1.0+incompatible h1:sIa2eCvUTwgjbqXrPLfNwUf9S3i3mpH1O1atV+iL/Wk= +github.com/gofrs/uuid v4.1.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/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/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= @@ -383,9 +386,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.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.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= 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-20210827173440-b95caade3eac/go.mod h1:h+MxyHxRg9NH3terB1nfRIUaQEcI0XOVkdR9LNBlp8E= +github.com/insomniacslk/dhcp v0.0.0-20211026125128-ad197bcd36fd h1:jupbuQFZtwOBg/3EmK91/rGaYFkqCb9bwHOnwn7Cav0= +github.com/insomniacslk/dhcp v0.0.0-20211026125128-ad197bcd36fd/go.mod h1:h+MxyHxRg9NH3terB1nfRIUaQEcI0XOVkdR9LNBlp8E= 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-20160803190731-bd40a432e4c7/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= @@ -492,7 +496,7 @@ github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59P 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-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 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= @@ -642,6 +646,7 @@ go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/automaxprocs v1.4.0/go.mod h1:/mTEdr7LvHhs0v7mjdxDreTz1OG5zdZGqgOnhWiR/+Q= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= golang.org/x/crypto v0.0.0-20171113213409-9f005a07e0d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -658,8 +663,8 @@ 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-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-20210817164053-32db794688a5 h1:HWj/xjIHfjYU5nVXpTM0s39J9CbLn7Cc5a7IC5rwsMQ= -golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 h1:7I4JAnoQBe7ZtJcBaYHi5UtiO8tQHbUSXxL+pnGRANg= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -728,8 +733,8 @@ 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-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-20210903162142-ad29c8ab022f h1:w6wWR0H+nyVpbSAQbzVEIACVyr/h8l/BEkY6Sokc7Eg= -golang.org/x/net v0.0.0-20210903162142-ad29c8ab022f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211105192438-b53810dc28af h1:SMeNJG/vclJ5wyBBd4xupMsSJIHTd1coW9g7q6KOjmY= +golang.org/x/net v0.0.0-20211105192438-b53810dc28af/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-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -819,8 +824,8 @@ golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7w 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-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34 h1:GkvMjFtXUmahfDtashnc1mnrCtuBVcwse5QV2lUk/tI= -golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211107104306-e0b2ad06fe42 h1:G2DDmludOQZoWbpCr7OKDxnl478ZBGMcOhrv+ooX/Q4= +golang.org/x/sys v0.0.0-20211107104306-e0b2ad06fe42/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -936,8 +941,8 @@ google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.40.0 h1:AGJ0Ih4mHjSeibYkFGh1dD9KJ/eOtZ93I6hoHhukQ5Q= -google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= +google.golang.org/grpc v1.42.0 h1:XT2/MFpuPFsEX2fWh3YQtHkZ+WYZFQRfaUgLZYj/p6A= +google.golang.org/grpc v1.42.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-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= From c9be614821d5c9b4cb3582c2eaebed89341c7f6e Mon Sep 17 00:00:00 2001 From: Dreamacro <8615343+Dreamacro@users.noreply.github.com> Date: Mon, 8 Nov 2021 21:24:39 +0800 Subject: [PATCH 96/96] Fix: windows arm7 build --- component/dialer/bind_others.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/component/dialer/bind_others.go b/component/dialer/bind_others.go index e94946739..a74995b58 100644 --- a/component/dialer/bind_others.go +++ b/component/dialer/bind_others.go @@ -58,7 +58,7 @@ func bindIfaceToDialer(ifaceName string, dialer *net.Dialer, network string, des return nil } - local := 0 + local := int64(0) if dialer.LocalAddr != nil { _, port, err := net.SplitHostPort(dialer.LocalAddr.String()) if err == nil { @@ -66,7 +66,7 @@ func bindIfaceToDialer(ifaceName string, dialer *net.Dialer, network string, des } } - addr, err := lookupLocalAddr(ifaceName, network, destination, local) + addr, err := lookupLocalAddr(ifaceName, network, destination, int(local)) if err != nil { return err } @@ -84,7 +84,7 @@ func bindIfaceToListenConfig(ifaceName string, _ *net.ListenConfig, network, add local, _ := strconv.ParseInt(port, 10, 16) - addr, err := lookupLocalAddr(ifaceName, network, nil, local) + addr, err := lookupLocalAddr(ifaceName, network, nil, int(local)) if err != nil { return "", err }