mirror of
https://github.com/SagerNet/sing-box.git
synced 2024-11-25 18:11:28 +00:00
Add custom tls client support for v2ray h2/grpclite transports
This commit is contained in:
parent
7e09beb0c3
commit
a2d1f89922
|
@ -30,7 +30,7 @@ func NewClient(router adapter.Router, serverAddress string, options option.Outbo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func ClientHandshake(ctx context.Context, conn net.Conn, config Config) (net.Conn, error) {
|
func ClientHandshake(ctx context.Context, conn net.Conn, config Config) (Conn, error) {
|
||||||
tlsConn := config.Client(conn)
|
tlsConn := config.Client(conn)
|
||||||
ctx, cancel := context.WithTimeout(ctx, C.TCPTimeout)
|
ctx, cancel := context.WithTimeout(ctx, C.TCPTimeout)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
|
@ -15,6 +15,8 @@ type (
|
||||||
)
|
)
|
||||||
|
|
||||||
type Config interface {
|
type Config interface {
|
||||||
|
NextProtos() []string
|
||||||
|
SetNextProtos(nextProto []string)
|
||||||
Config() (*STDConfig, error)
|
Config() (*STDConfig, error)
|
||||||
Client(conn net.Conn) Conn
|
Client(conn net.Conn) Conn
|
||||||
}
|
}
|
||||||
|
@ -28,6 +30,7 @@ type ServerConfig interface {
|
||||||
type Conn interface {
|
type Conn interface {
|
||||||
net.Conn
|
net.Conn
|
||||||
HandshakeContext(ctx context.Context) error
|
HandshakeContext(ctx context.Context) error
|
||||||
|
ConnectionState() tls.ConnectionState
|
||||||
}
|
}
|
||||||
|
|
||||||
func ParseTLSVersion(version string) (uint16, error) {
|
func ParseTLSVersion(version string) (uint16, error) {
|
||||||
|
|
|
@ -4,6 +4,7 @@ package tls
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"crypto/tls"
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"net"
|
"net"
|
||||||
|
@ -12,7 +13,7 @@ import (
|
||||||
|
|
||||||
"github.com/sagernet/sing-box/adapter"
|
"github.com/sagernet/sing-box/adapter"
|
||||||
"github.com/sagernet/sing-box/option"
|
"github.com/sagernet/sing-box/option"
|
||||||
"github.com/sagernet/sing-box/transport/cloudflaretls"
|
cftls "github.com/sagernet/sing-box/transport/cloudflaretls"
|
||||||
"github.com/sagernet/sing-dns"
|
"github.com/sagernet/sing-dns"
|
||||||
E "github.com/sagernet/sing/common/exceptions"
|
E "github.com/sagernet/sing/common/exceptions"
|
||||||
|
|
||||||
|
@ -21,7 +22,15 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type echClientConfig struct {
|
type echClientConfig struct {
|
||||||
config *tls.Config
|
config *cftls.Config
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *echClientConfig) NextProtos() []string {
|
||||||
|
return e.config.NextProtos
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *echClientConfig) SetNextProtos(nextProto []string) {
|
||||||
|
e.config.NextProtos = nextProto
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *echClientConfig) Config() (*STDConfig, error) {
|
func (e *echClientConfig) Config() (*STDConfig, error) {
|
||||||
|
@ -29,7 +38,29 @@ func (e *echClientConfig) Config() (*STDConfig, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *echClientConfig) Client(conn net.Conn) Conn {
|
func (e *echClientConfig) Client(conn net.Conn) Conn {
|
||||||
return tls.Client(conn, e.config)
|
return &echConnWrapper{cftls.Client(conn, e.config)}
|
||||||
|
}
|
||||||
|
|
||||||
|
type echConnWrapper struct {
|
||||||
|
*cftls.Conn
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *echConnWrapper) ConnectionState() tls.ConnectionState {
|
||||||
|
state := c.Conn.ConnectionState()
|
||||||
|
return tls.ConnectionState{
|
||||||
|
Version: state.Version,
|
||||||
|
HandshakeComplete: state.HandshakeComplete,
|
||||||
|
DidResume: state.DidResume,
|
||||||
|
CipherSuite: state.CipherSuite,
|
||||||
|
NegotiatedProtocol: state.NegotiatedProtocol,
|
||||||
|
NegotiatedProtocolIsMutual: state.NegotiatedProtocolIsMutual,
|
||||||
|
ServerName: state.ServerName,
|
||||||
|
PeerCertificates: state.PeerCertificates,
|
||||||
|
VerifiedChains: state.VerifiedChains,
|
||||||
|
SignedCertificateTimestamps: state.SignedCertificateTimestamps,
|
||||||
|
OCSPResponse: state.OCSPResponse,
|
||||||
|
TLSUnique: state.TLSUnique,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func newECHClient(router adapter.Router, serverAddress string, options option.OutboundTLSOptions) (Config, error) {
|
func newECHClient(router adapter.Router, serverAddress string, options option.OutboundTLSOptions) (Config, error) {
|
||||||
|
@ -45,7 +76,7 @@ func newECHClient(router adapter.Router, serverAddress string, options option.Ou
|
||||||
return nil, E.New("missing server_name or insecure=true")
|
return nil, E.New("missing server_name or insecure=true")
|
||||||
}
|
}
|
||||||
|
|
||||||
var tlsConfig tls.Config
|
var tlsConfig cftls.Config
|
||||||
if options.DisableSNI {
|
if options.DisableSNI {
|
||||||
tlsConfig.ServerName = "127.0.0.1"
|
tlsConfig.ServerName = "127.0.0.1"
|
||||||
} else {
|
} else {
|
||||||
|
@ -55,7 +86,7 @@ func newECHClient(router adapter.Router, serverAddress string, options option.Ou
|
||||||
tlsConfig.InsecureSkipVerify = options.Insecure
|
tlsConfig.InsecureSkipVerify = options.Insecure
|
||||||
} else if options.DisableSNI {
|
} else if options.DisableSNI {
|
||||||
tlsConfig.InsecureSkipVerify = true
|
tlsConfig.InsecureSkipVerify = true
|
||||||
tlsConfig.VerifyConnection = func(state tls.ConnectionState) error {
|
tlsConfig.VerifyConnection = func(state cftls.ConnectionState) error {
|
||||||
verifyOptions := x509.VerifyOptions{
|
verifyOptions := x509.VerifyOptions{
|
||||||
DNSName: serverName,
|
DNSName: serverName,
|
||||||
Intermediates: x509.NewCertPool(),
|
Intermediates: x509.NewCertPool(),
|
||||||
|
@ -87,7 +118,7 @@ func newECHClient(router adapter.Router, serverAddress string, options option.Ou
|
||||||
if options.CipherSuites != nil {
|
if options.CipherSuites != nil {
|
||||||
find:
|
find:
|
||||||
for _, cipherSuite := range options.CipherSuites {
|
for _, cipherSuite := range options.CipherSuites {
|
||||||
for _, tlsCipherSuite := range tls.CipherSuites() {
|
for _, tlsCipherSuite := range cftls.CipherSuites() {
|
||||||
if cipherSuite == tlsCipherSuite.Name {
|
if cipherSuite == tlsCipherSuite.Name {
|
||||||
tlsConfig.CipherSuites = append(tlsConfig.CipherSuites, tlsCipherSuite.ID)
|
tlsConfig.CipherSuites = append(tlsConfig.CipherSuites, tlsCipherSuite.ID)
|
||||||
continue find
|
continue find
|
||||||
|
@ -124,7 +155,7 @@ func newECHClient(router adapter.Router, serverAddress string, options option.Ou
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
clientConfig, err := tls.UnmarshalECHConfigs(clientConfigContent)
|
clientConfig, err := cftls.UnmarshalECHConfigs(clientConfigContent)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -137,8 +168,8 @@ func newECHClient(router adapter.Router, serverAddress string, options option.Ou
|
||||||
|
|
||||||
const typeHTTPS = 65
|
const typeHTTPS = 65
|
||||||
|
|
||||||
func fetchECHClientConfig(router adapter.Router) func(ctx context.Context, serverName string) ([]tls.ECHConfig, error) {
|
func fetchECHClientConfig(router adapter.Router) func(ctx context.Context, serverName string) ([]cftls.ECHConfig, error) {
|
||||||
return func(ctx context.Context, serverName string) ([]tls.ECHConfig, error) {
|
return func(ctx context.Context, serverName string) ([]cftls.ECHConfig, error) {
|
||||||
message := &dnsmessage.Message{
|
message := &dnsmessage.Message{
|
||||||
Header: dnsmessage.Header{
|
Header: dnsmessage.Header{
|
||||||
RecursionDesired: true,
|
RecursionDesired: true,
|
||||||
|
@ -176,7 +207,7 @@ func fetchECHClientConfig(router adapter.Router) func(ctx context.Context, serve
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, E.Cause(err, "decode ECH config")
|
return nil, E.Cause(err, "decode ECH config")
|
||||||
}
|
}
|
||||||
return tls.UnmarshalECHConfigs(echConfig)
|
return cftls.UnmarshalECHConfigs(echConfig)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -99,6 +99,14 @@ func newStdClient(serverAddress string, options option.OutboundTLSOptions) (Conf
|
||||||
return &stdClientConfig{&tlsConfig}, nil
|
return &stdClientConfig{&tlsConfig}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *stdClientConfig) NextProtos() []string {
|
||||||
|
return s.config.NextProtos
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *stdClientConfig) SetNextProtos(nextProto []string) {
|
||||||
|
s.config.NextProtos = nextProto
|
||||||
|
}
|
||||||
|
|
||||||
func (s *stdClientConfig) Config() (*STDConfig, error) {
|
func (s *stdClientConfig) Config() (*STDConfig, error) {
|
||||||
return s.config, nil
|
return s.config, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,14 @@ type STDServerConfig struct {
|
||||||
watcher *fsnotify.Watcher
|
watcher *fsnotify.Watcher
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *STDServerConfig) NextProtos() []string {
|
||||||
|
return c.config.NextProtos
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *STDServerConfig) SetNextProtos(nextProto []string) {
|
||||||
|
c.config.NextProtos = nextProto
|
||||||
|
}
|
||||||
|
|
||||||
func newSTDServer(ctx context.Context, logger log.Logger, options option.InboundTLSOptions) (ServerConfig, error) {
|
func newSTDServer(ctx context.Context, logger log.Logger, options option.InboundTLSOptions) (ServerConfig, error) {
|
||||||
if !options.Enabled {
|
if !options.Enabled {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
|
|
|
@ -22,6 +22,14 @@ type utlsClientConfig struct {
|
||||||
id utls.ClientHelloID
|
id utls.ClientHelloID
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (e *utlsClientConfig) NextProtos() []string {
|
||||||
|
return e.config.NextProtos
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *utlsClientConfig) SetNextProtos(nextProto []string) {
|
||||||
|
e.config.NextProtos = nextProto
|
||||||
|
}
|
||||||
|
|
||||||
func (e *utlsClientConfig) Config() (*STDConfig, error) {
|
func (e *utlsClientConfig) Config() (*STDConfig, error) {
|
||||||
return nil, E.New("unsupported usage for uTLS")
|
return nil, E.New("unsupported usage for uTLS")
|
||||||
}
|
}
|
||||||
|
@ -38,6 +46,24 @@ func (c *utlsConnWrapper) HandshakeContext(ctx context.Context) error {
|
||||||
return c.Conn.Handshake()
|
return c.Conn.Handshake()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *utlsConnWrapper) ConnectionState() tls.ConnectionState {
|
||||||
|
state := c.Conn.ConnectionState()
|
||||||
|
return tls.ConnectionState{
|
||||||
|
Version: state.Version,
|
||||||
|
HandshakeComplete: state.HandshakeComplete,
|
||||||
|
DidResume: state.DidResume,
|
||||||
|
CipherSuite: state.CipherSuite,
|
||||||
|
NegotiatedProtocol: state.NegotiatedProtocol,
|
||||||
|
NegotiatedProtocolIsMutual: state.NegotiatedProtocolIsMutual,
|
||||||
|
ServerName: state.ServerName,
|
||||||
|
PeerCertificates: state.PeerCertificates,
|
||||||
|
VerifiedChains: state.VerifiedChains,
|
||||||
|
SignedCertificateTimestamps: state.SignedCertificateTimestamps,
|
||||||
|
OCSPResponse: state.OCSPResponse,
|
||||||
|
TLSUnique: state.TLSUnique,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func newUTLSClient(router adapter.Router, serverAddress string, options option.OutboundTLSOptions) (Config, error) {
|
func newUTLSClient(router adapter.Router, serverAddress string, options option.OutboundTLSOptions) (Config, error) {
|
||||||
var serverName string
|
var serverName string
|
||||||
if options.ServerName != "" {
|
if options.ServerName != "" {
|
||||||
|
|
16
test/go.mod
16
test/go.mod
|
@ -7,14 +7,14 @@ require github.com/sagernet/sing-box v0.0.0
|
||||||
replace github.com/sagernet/sing-box => ../
|
replace github.com/sagernet/sing-box => ../
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/docker/docker v20.10.17+incompatible
|
github.com/docker/docker v20.10.18+incompatible
|
||||||
github.com/docker/go-connections v0.4.0
|
github.com/docker/go-connections v0.4.0
|
||||||
github.com/gofrs/uuid v4.2.0+incompatible
|
github.com/gofrs/uuid v4.3.0+incompatible
|
||||||
github.com/sagernet/sing v0.0.0-20220905164441-f3d346256d4a
|
github.com/sagernet/sing v0.0.0-20220910144724-62c4ebdbcb3f
|
||||||
github.com/sagernet/sing-shadowsocks v0.0.0-20220819002358-7461bb09a8f6
|
github.com/sagernet/sing-shadowsocks v0.0.0-20220819002358-7461bb09a8f6
|
||||||
github.com/spyzhov/ajson v0.7.1
|
github.com/spyzhov/ajson v0.7.1
|
||||||
github.com/stretchr/testify v1.8.0
|
github.com/stretchr/testify v1.8.0
|
||||||
golang.org/x/net v0.0.0-20220907135653-1e95f45603a7
|
golang.org/x/net v0.0.0-20220909164309-bea034e7d591
|
||||||
)
|
)
|
||||||
|
|
||||||
//replace github.com/sagernet/sing => ../../sing
|
//replace github.com/sagernet/sing => ../../sing
|
||||||
|
@ -66,12 +66,13 @@ require (
|
||||||
github.com/sagernet/go-tun2socks v1.16.12-0.20220818015926-16cb67876a61 // indirect
|
github.com/sagernet/go-tun2socks v1.16.12-0.20220818015926-16cb67876a61 // indirect
|
||||||
github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97 // indirect
|
github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97 // indirect
|
||||||
github.com/sagernet/quic-go v0.0.0-20220818150011-de611ab3e2bb // indirect
|
github.com/sagernet/quic-go v0.0.0-20220818150011-de611ab3e2bb // indirect
|
||||||
github.com/sagernet/sing-dns v0.0.0-20220903082137-b1102b8fc961 // indirect
|
github.com/sagernet/sing-dns v0.0.0-20220822023312-3e086b06d666 // indirect
|
||||||
github.com/sagernet/sing-tun v0.0.0-20220909114108-a6b5a9289ecb // indirect
|
github.com/sagernet/sing-tun v0.0.0-20220909114108-a6b5a9289ecb // indirect
|
||||||
github.com/sagernet/sing-vmess v0.0.0-20220907073918-72d7fdf6825f // indirect
|
github.com/sagernet/sing-vmess v0.0.0-20220907073918-72d7fdf6825f // indirect
|
||||||
github.com/sagernet/smux v0.0.0-20220907034654-1acb8471c15a // indirect
|
github.com/sagernet/smux v0.0.0-20220831015742-e0f1988e3195 // indirect
|
||||||
github.com/sirupsen/logrus v1.8.1 // indirect
|
github.com/sirupsen/logrus v1.8.1 // indirect
|
||||||
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 // indirect
|
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 // indirect
|
||||||
|
go.etcd.io/bbolt v1.3.6 // indirect
|
||||||
go.uber.org/atomic v1.10.0 // indirect
|
go.uber.org/atomic v1.10.0 // indirect
|
||||||
go.uber.org/multierr v1.6.0 // indirect
|
go.uber.org/multierr v1.6.0 // indirect
|
||||||
go.uber.org/zap v1.22.0 // indirect
|
go.uber.org/zap v1.22.0 // indirect
|
||||||
|
@ -79,7 +80,7 @@ require (
|
||||||
golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90 // indirect
|
golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90 // indirect
|
||||||
golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e // indirect
|
golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e // indirect
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
|
||||||
golang.org/x/sys v0.0.0-20220908164124-27713097b956 // indirect
|
golang.org/x/sys v0.0.0-20220909162455-aba9fc2a8ff2 // indirect
|
||||||
golang.org/x/text v0.3.7 // indirect
|
golang.org/x/text v0.3.7 // indirect
|
||||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0 // indirect
|
golang.org/x/time v0.0.0-20191024005414-555d28b269f0 // indirect
|
||||||
golang.org/x/tools v0.1.11-0.20220513221640-090b14e8501f // indirect
|
golang.org/x/tools v0.1.11-0.20220513221640-090b14e8501f // indirect
|
||||||
|
@ -89,7 +90,6 @@ require (
|
||||||
google.golang.org/grpc v1.49.0 // indirect
|
google.golang.org/grpc v1.49.0 // indirect
|
||||||
google.golang.org/protobuf v1.28.1 // indirect
|
google.golang.org/protobuf v1.28.1 // indirect
|
||||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
|
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
|
||||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
gotest.tools/v3 v3.3.0 // indirect
|
gotest.tools/v3 v3.3.0 // indirect
|
||||||
gvisor.dev/gvisor v0.0.0-20220901235040-6ca97ef2ce1c // indirect
|
gvisor.dev/gvisor v0.0.0-20220901235040-6ca97ef2ce1c // indirect
|
||||||
|
|
34
test/go.sum
34
test/go.sum
|
@ -32,8 +32,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/docker/distribution v2.8.1+incompatible h1:Q50tZOPR6T/hjNsyc9g8/syEs6bk8XXApsHjKukMl68=
|
github.com/docker/distribution v2.8.1+incompatible h1:Q50tZOPR6T/hjNsyc9g8/syEs6bk8XXApsHjKukMl68=
|
||||||
github.com/docker/distribution v2.8.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
github.com/docker/distribution v2.8.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||||
github.com/docker/docker v20.10.17+incompatible h1:JYCuMrWaVNophQTOrMMoSwudOVEfcegoZZrleKc1xwE=
|
github.com/docker/docker v20.10.18+incompatible h1:SN84VYXTBNGn92T/QwIRPlum9zfemfitN7pbsp26WSc=
|
||||||
github.com/docker/docker v20.10.17+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
github.com/docker/docker v20.10.18+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||||
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
|
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
|
||||||
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
|
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
|
||||||
github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw=
|
github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw=
|
||||||
|
@ -57,8 +57,8 @@ github.com/go-chi/render v1.0.2 h1:4ER/udB0+fMWB2Jlf15RV3F4A2FDuYi/9f+lFttR/Lg=
|
||||||
github.com/go-chi/render v1.0.2/go.mod h1:/gr3hVkmYR0YlEy3LxCuVRFzEu9Ruok+gFqbIofjao0=
|
github.com/go-chi/render v1.0.2/go.mod h1:/gr3hVkmYR0YlEy3LxCuVRFzEu9Ruok+gFqbIofjao0=
|
||||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I=
|
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I=
|
||||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
|
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
|
||||||
github.com/gofrs/uuid v4.2.0+incompatible h1:yyYWMnhkhrKwwr8gAOcOCYxOOscHgDS9yZgBrnJfGa0=
|
github.com/gofrs/uuid v4.3.0+incompatible h1:CaSVZxm5B+7o45rtab4jC2G37WGYX1zQfuU2i6DSvnc=
|
||||||
github.com/gofrs/uuid v4.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
github.com/gofrs/uuid v4.3.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 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||||
|
@ -165,18 +165,18 @@ github.com/sagernet/quic-go v0.0.0-20220818150011-de611ab3e2bb h1:wc0yQ+SBn4TaTY
|
||||||
github.com/sagernet/quic-go v0.0.0-20220818150011-de611ab3e2bb/go.mod h1:MIccjRKnPTjWwAOpl+AUGWOkzyTd9tERytudxu+1ra4=
|
github.com/sagernet/quic-go v0.0.0-20220818150011-de611ab3e2bb/go.mod h1:MIccjRKnPTjWwAOpl+AUGWOkzyTd9tERytudxu+1ra4=
|
||||||
github.com/sagernet/sing v0.0.0-20220812082120-05f9836bff8f/go.mod h1:QVsS5L/ZA2Q5UhQwLrn0Trw+msNd/NPGEhBKR/ioWiY=
|
github.com/sagernet/sing v0.0.0-20220812082120-05f9836bff8f/go.mod h1:QVsS5L/ZA2Q5UhQwLrn0Trw+msNd/NPGEhBKR/ioWiY=
|
||||||
github.com/sagernet/sing v0.0.0-20220817130738-ce854cda8522/go.mod h1:QVsS5L/ZA2Q5UhQwLrn0Trw+msNd/NPGEhBKR/ioWiY=
|
github.com/sagernet/sing v0.0.0-20220817130738-ce854cda8522/go.mod h1:QVsS5L/ZA2Q5UhQwLrn0Trw+msNd/NPGEhBKR/ioWiY=
|
||||||
github.com/sagernet/sing v0.0.0-20220905164441-f3d346256d4a h1:Bqt+eYP7vJocAgAVAXC0B0ZN0uMr6g6exAoF3Ado2pg=
|
github.com/sagernet/sing v0.0.0-20220910144724-62c4ebdbcb3f h1:w1TJq7Lw3It35tDyMsZLtYz4T2msf1UK9JxC85L5+sk=
|
||||||
github.com/sagernet/sing v0.0.0-20220905164441-f3d346256d4a/go.mod h1:kZvzh1VDa/Dg/Bt5WaYKU0jl5ept8KKDpl3Ay4gRtRQ=
|
github.com/sagernet/sing v0.0.0-20220910144724-62c4ebdbcb3f/go.mod h1:kZvzh1VDa/Dg/Bt5WaYKU0jl5ept8KKDpl3Ay4gRtRQ=
|
||||||
github.com/sagernet/sing-dns v0.0.0-20220903082137-b1102b8fc961 h1:5JeqhvCGV6AQQiAO0V67Loh2eyO3JNjIQnvRF8NnTE0=
|
github.com/sagernet/sing-dns v0.0.0-20220822023312-3e086b06d666 h1:XUTocA/Ek0dFxUX+xJCWMPPFZCn2GC/uLrBjTSr1vHY=
|
||||||
github.com/sagernet/sing-dns v0.0.0-20220903082137-b1102b8fc961/go.mod h1:vKBBy4mNJRaFuJ8H6kYIOPofsZ1JT5mgdwIlebtvnZ4=
|
github.com/sagernet/sing-dns v0.0.0-20220822023312-3e086b06d666/go.mod h1:eDyH7AJmqBGjZQdQmpZIzlbTREudZuWDExMuGKgjRVM=
|
||||||
github.com/sagernet/sing-shadowsocks v0.0.0-20220819002358-7461bb09a8f6 h1:JJfDeYYhWunvtxsU/mOVNTmFQmnzGx9dY034qG6G3g4=
|
github.com/sagernet/sing-shadowsocks v0.0.0-20220819002358-7461bb09a8f6 h1:JJfDeYYhWunvtxsU/mOVNTmFQmnzGx9dY034qG6G3g4=
|
||||||
github.com/sagernet/sing-shadowsocks v0.0.0-20220819002358-7461bb09a8f6/go.mod h1:EX3RbZvrwAkPI2nuGa78T2iQXmrkT+/VQtskjou42xM=
|
github.com/sagernet/sing-shadowsocks v0.0.0-20220819002358-7461bb09a8f6/go.mod h1:EX3RbZvrwAkPI2nuGa78T2iQXmrkT+/VQtskjou42xM=
|
||||||
github.com/sagernet/sing-tun v0.0.0-20220909114108-a6b5a9289ecb h1:/swVU2mgwDwZ9l67v1Sim1ias/ZmriGTxQLnMakPhtQ=
|
github.com/sagernet/sing-tun v0.0.0-20220909114108-a6b5a9289ecb h1:/swVU2mgwDwZ9l67v1Sim1ias/ZmriGTxQLnMakPhtQ=
|
||||||
github.com/sagernet/sing-tun v0.0.0-20220909114108-a6b5a9289ecb/go.mod h1:5AhPUv9jWDQ3pv3Mj78SL/1TSjhoaj6WNASxRKLqXqM=
|
github.com/sagernet/sing-tun v0.0.0-20220909114108-a6b5a9289ecb/go.mod h1:5AhPUv9jWDQ3pv3Mj78SL/1TSjhoaj6WNASxRKLqXqM=
|
||||||
github.com/sagernet/sing-vmess v0.0.0-20220907073918-72d7fdf6825f h1:6l9aXZqAl1JqXJWi89KHpWnM/moQUPGG+XiwMc+yD0A=
|
github.com/sagernet/sing-vmess v0.0.0-20220907073918-72d7fdf6825f h1:6l9aXZqAl1JqXJWi89KHpWnM/moQUPGG+XiwMc+yD0A=
|
||||||
github.com/sagernet/sing-vmess v0.0.0-20220907073918-72d7fdf6825f/go.mod h1:u66Vv7NHXJWfeAmhh7JuJp/cwxmuQlM56QoZ7B7Mmd0=
|
github.com/sagernet/sing-vmess v0.0.0-20220907073918-72d7fdf6825f/go.mod h1:u66Vv7NHXJWfeAmhh7JuJp/cwxmuQlM56QoZ7B7Mmd0=
|
||||||
github.com/sagernet/smux v0.0.0-20220907034654-1acb8471c15a h1:GCNwsN8MEckpjGJjK3qjQBQ9qHsoXB9B/KHUWBvE1V4=
|
github.com/sagernet/smux v0.0.0-20220831015742-e0f1988e3195 h1:5VBIbVw9q7aKbrFdT83mjkyvQ+VaRsQ6yflTepfln38=
|
||||||
github.com/sagernet/smux v0.0.0-20220907034654-1acb8471c15a/go.mod h1:yedWtra8nyGJ+SyI+ziwuaGMzBatbB10P1IOOZbbSK8=
|
github.com/sagernet/smux v0.0.0-20220831015742-e0f1988e3195/go.mod h1:yedWtra8nyGJ+SyI+ziwuaGMzBatbB10P1IOOZbbSK8=
|
||||||
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
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 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
|
||||||
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||||
|
@ -197,6 +197,8 @@ github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74/go.mod h1:DD4vA1
|
||||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||||
|
go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU=
|
||||||
|
go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4=
|
||||||
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
|
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
|
||||||
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||||
go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ=
|
go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ=
|
||||||
|
@ -251,8 +253,8 @@ golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qx
|
||||||
golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.0.0-20211111160137-58aab5ef257a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20211111160137-58aab5ef257a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.0.0-20220630215102-69896b714898/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
golang.org/x/net v0.0.0-20220630215102-69896b714898/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||||
golang.org/x/net v0.0.0-20220907135653-1e95f45603a7 h1:1WGATo9HAhkWMbfyuVU0tEFP88OIkUvwaHFveQPvzCQ=
|
golang.org/x/net v0.0.0-20220909164309-bea034e7d591 h1:D0B/7al0LLrVC8aWF4+oxpv/m8bc7ViFfVS8/gXGdqI=
|
||||||
golang.org/x/net v0.0.0-20220907135653-1e95f45603a7/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
|
golang.org/x/net v0.0.0-20220909164309-bea034e7d591/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/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-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
@ -275,6 +277,7 @@ golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||||
golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
@ -290,8 +293,8 @@ golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220731174439-a90be440212d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220731174439-a90be440212d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220908164124-27713097b956 h1:XeJjHH1KiLpKGb6lvMiksZ9l0fVUh+AmGcm0nOMEBOY=
|
golang.org/x/sys v0.0.0-20220909162455-aba9fc2a8ff2 h1:wM1k/lXfpc5HdkJJyW9GELpd8ERGdnh8sMGL6Gzq3Ho=
|
||||||
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220909162455-aba9fc2a8ff2/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
|
@ -370,9 +373,8 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.4/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.8/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 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
|
||||||
gopkg.in/yaml.v2 v2.3.0/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/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
|
|
|
@ -2,7 +2,6 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net/netip"
|
"net/netip"
|
||||||
"os"
|
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -50,49 +49,3 @@ func TestWireGuard(t *testing.T) {
|
||||||
})
|
})
|
||||||
testSuitWg(t, clientPort, testPort)
|
testSuitWg(t, clientPort, testPort)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestWireGuardSystem(t *testing.T) {
|
|
||||||
if os.Getuid() != 0 {
|
|
||||||
t.Skip("requires root")
|
|
||||||
}
|
|
||||||
startDockerContainer(t, DockerOptions{
|
|
||||||
Image: ImageBoringTun,
|
|
||||||
Cap: []string{"MKNOD", "NET_ADMIN", "NET_RAW"},
|
|
||||||
Ports: []uint16{serverPort, testPort},
|
|
||||||
Bind: map[string]string{
|
|
||||||
"wireguard.conf": "/etc/wireguard/wg0.conf",
|
|
||||||
},
|
|
||||||
Cmd: []string{"wg0"},
|
|
||||||
})
|
|
||||||
time.Sleep(5 * time.Second)
|
|
||||||
startInstance(t, option.Options{
|
|
||||||
Inbounds: []option.Inbound{
|
|
||||||
{
|
|
||||||
Type: C.TypeMixed,
|
|
||||||
MixedOptions: option.HTTPMixedInboundOptions{
|
|
||||||
ListenOptions: option.ListenOptions{
|
|
||||||
Listen: option.ListenAddress(netip.IPv4Unspecified()),
|
|
||||||
ListenPort: clientPort,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Outbounds: []option.Outbound{
|
|
||||||
{
|
|
||||||
Type: C.TypeWireGuard,
|
|
||||||
WireGuardOptions: option.WireGuardOutboundOptions{
|
|
||||||
InterfaceName: "wg",
|
|
||||||
ServerOptions: option.ServerOptions{
|
|
||||||
Server: "127.0.0.1",
|
|
||||||
ServerPort: serverPort,
|
|
||||||
},
|
|
||||||
LocalAddress: []option.ListenPrefix{option.ListenPrefix(netip.MustParsePrefix("10.0.0.2/32"))},
|
|
||||||
PrivateKey: "qGnwlkZljMxeECW8fbwAWdvgntnbK7B8UmMFl3zM0mk=",
|
|
||||||
PeerPublicKey: "QsdcBm+oJw2oNv0cIFXLIq1E850lgTBonup4qnKEQBg=",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
time.Sleep(10 * time.Second)
|
|
||||||
testSuitWg(t, clientPort, testPort)
|
|
||||||
}
|
|
||||||
|
|
|
@ -13,6 +13,8 @@ import (
|
||||||
"github.com/sagernet/sing-box/option"
|
"github.com/sagernet/sing-box/option"
|
||||||
M "github.com/sagernet/sing/common/metadata"
|
M "github.com/sagernet/sing/common/metadata"
|
||||||
N "github.com/sagernet/sing/common/network"
|
N "github.com/sagernet/sing/common/network"
|
||||||
|
|
||||||
|
"golang.org/x/net/http2"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ adapter.V2RayClientTransport = (*Client)(nil)
|
var _ adapter.V2RayClientTransport = (*Client)(nil)
|
||||||
|
@ -27,27 +29,37 @@ type Client struct {
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
dialer N.Dialer
|
dialer N.Dialer
|
||||||
serverAddr M.Socksaddr
|
serverAddr M.Socksaddr
|
||||||
transport *http.Transport
|
transport http.RoundTripper
|
||||||
options option.V2RayGRPCOptions
|
options option.V2RayGRPCOptions
|
||||||
url *url.URL
|
url *url.URL
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewClient(ctx context.Context, dialer N.Dialer, serverAddr M.Socksaddr, options option.V2RayGRPCOptions, tlsConfig tls.Config) adapter.V2RayClientTransport {
|
func NewClient(ctx context.Context, dialer N.Dialer, serverAddr M.Socksaddr, options option.V2RayGRPCOptions, tlsConfig tls.Config) adapter.V2RayClientTransport {
|
||||||
return &Client{
|
var transport http.RoundTripper
|
||||||
ctx: ctx,
|
if tlsConfig == nil {
|
||||||
dialer: dialer,
|
transport = &http.Transport{
|
||||||
serverAddr: serverAddr,
|
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
|
||||||
options: options,
|
return dialer.DialContext(ctx, network, M.ParseSocksaddr(addr))
|
||||||
transport: &http.Transport{
|
},
|
||||||
DialTLSContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
|
}
|
||||||
|
} else {
|
||||||
|
tlsConfig.SetNextProtos([]string{http2.NextProtoTLS})
|
||||||
|
transport = &http2.Transport{
|
||||||
|
DialTLSContext: func(ctx context.Context, network, addr string, cfg *tls.STDConfig) (net.Conn, error) {
|
||||||
conn, err := dialer.DialContext(ctx, network, M.ParseSocksaddr(addr))
|
conn, err := dialer.DialContext(ctx, network, M.ParseSocksaddr(addr))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return tls.ClientHandshake(ctx, conn, tlsConfig)
|
return tls.ClientHandshake(ctx, conn, tlsConfig)
|
||||||
},
|
},
|
||||||
ForceAttemptHTTP2: true,
|
}
|
||||||
},
|
}
|
||||||
|
return &Client{
|
||||||
|
ctx: ctx,
|
||||||
|
dialer: dialer,
|
||||||
|
serverAddr: serverAddr,
|
||||||
|
options: options,
|
||||||
|
transport: transport,
|
||||||
url: &url.URL{
|
url: &url.URL{
|
||||||
Scheme: "https",
|
Scheme: "https",
|
||||||
Host: serverAddr.String(),
|
Host: serverAddr.String(),
|
||||||
|
|
|
@ -17,6 +17,8 @@ import (
|
||||||
M "github.com/sagernet/sing/common/metadata"
|
M "github.com/sagernet/sing/common/metadata"
|
||||||
N "github.com/sagernet/sing/common/network"
|
N "github.com/sagernet/sing/common/network"
|
||||||
sHttp "github.com/sagernet/sing/protocol/http"
|
sHttp "github.com/sagernet/sing/protocol/http"
|
||||||
|
|
||||||
|
"golang.org/x/net/http2"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ adapter.V2RayServerTransport = (*Server)(nil)
|
var _ adapter.V2RayServerTransport = (*Server)(nil)
|
||||||
|
@ -87,6 +89,10 @@ func (s *Server) Serve(listener net.Listener) error {
|
||||||
if s.httpServer.TLSConfig == nil {
|
if s.httpServer.TLSConfig == nil {
|
||||||
return s.httpServer.Serve(listener)
|
return s.httpServer.Serve(listener)
|
||||||
} else {
|
} else {
|
||||||
|
err := http2.ConfigureServer(s.httpServer, &http2.Server{})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
return s.httpServer.ServeTLS(listener, "", "")
|
return s.httpServer.ServeTLS(listener, "", "")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,8 @@ import (
|
||||||
E "github.com/sagernet/sing/common/exceptions"
|
E "github.com/sagernet/sing/common/exceptions"
|
||||||
M "github.com/sagernet/sing/common/metadata"
|
M "github.com/sagernet/sing/common/metadata"
|
||||||
N "github.com/sagernet/sing/common/network"
|
N "github.com/sagernet/sing/common/network"
|
||||||
|
|
||||||
|
"golang.org/x/net/http2"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ adapter.V2RayClientTransport = (*Client)(nil)
|
var _ adapter.V2RayClientTransport = (*Client)(nil)
|
||||||
|
@ -24,7 +26,7 @@ type Client struct {
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
dialer N.Dialer
|
dialer N.Dialer
|
||||||
serverAddr M.Socksaddr
|
serverAddr M.Socksaddr
|
||||||
client *http.Client
|
transport http.RoundTripper
|
||||||
http2 bool
|
http2 bool
|
||||||
url *url.URL
|
url *url.URL
|
||||||
host []string
|
host []string
|
||||||
|
@ -33,6 +35,25 @@ type Client struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewClient(ctx context.Context, dialer N.Dialer, serverAddr M.Socksaddr, options option.V2RayHTTPOptions, tlsConfig tls.Config) adapter.V2RayClientTransport {
|
func NewClient(ctx context.Context, dialer N.Dialer, serverAddr M.Socksaddr, options option.V2RayHTTPOptions, tlsConfig tls.Config) adapter.V2RayClientTransport {
|
||||||
|
var transport http.RoundTripper
|
||||||
|
if tlsConfig == nil {
|
||||||
|
transport = &http.Transport{
|
||||||
|
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
|
||||||
|
return dialer.DialContext(ctx, network, M.ParseSocksaddr(addr))
|
||||||
|
},
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
tlsConfig.SetNextProtos([]string{http2.NextProtoTLS})
|
||||||
|
transport = &http2.Transport{
|
||||||
|
DialTLSContext: func(ctx context.Context, network, addr string, cfg *tls.STDConfig) (net.Conn, error) {
|
||||||
|
conn, err := dialer.DialContext(ctx, network, M.ParseSocksaddr(addr))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return tls.ClientHandshake(ctx, conn, tlsConfig)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
client := &Client{
|
client := &Client{
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
dialer: dialer,
|
dialer: dialer,
|
||||||
|
@ -40,27 +61,9 @@ func NewClient(ctx context.Context, dialer N.Dialer, serverAddr M.Socksaddr, opt
|
||||||
host: options.Host,
|
host: options.Host,
|
||||||
method: options.Method,
|
method: options.Method,
|
||||||
headers: make(http.Header),
|
headers: make(http.Header),
|
||||||
client: &http.Client{},
|
transport: transport,
|
||||||
http2: tlsConfig != nil,
|
http2: tlsConfig != nil,
|
||||||
}
|
}
|
||||||
if client.http2 {
|
|
||||||
client.client.Transport = &http.Transport{
|
|
||||||
DialTLSContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
|
|
||||||
conn, err := dialer.DialContext(ctx, network, M.ParseSocksaddr(addr))
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return tls.ClientHandshake(ctx, conn, tlsConfig)
|
|
||||||
},
|
|
||||||
ForceAttemptHTTP2: true,
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
client.client.Transport = &http.Transport{
|
|
||||||
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
|
|
||||||
return dialer.DialContext(ctx, network, M.ParseSocksaddr(addr))
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if client.method == "" {
|
if client.method == "" {
|
||||||
client.method = "PUT"
|
client.method = "PUT"
|
||||||
}
|
}
|
||||||
|
@ -145,17 +148,16 @@ func (c *Client) dialHTTP2(ctx context.Context) (net.Conn, error) {
|
||||||
}
|
}
|
||||||
// Disable any compression method from server.
|
// Disable any compression method from server.
|
||||||
request.Header.Set("Accept-Encoding", "identity")
|
request.Header.Set("Accept-Encoding", "identity")
|
||||||
response, err := c.client.Do(request) // nolint: bodyclose
|
conn := newLateHTTPConn(pipeInWriter)
|
||||||
|
go func() {
|
||||||
|
response, err := c.transport.RoundTrip(request)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
pipeInWriter.Close()
|
conn.setup(nil, err)
|
||||||
return nil, err
|
} else if response.StatusCode != 200 {
|
||||||
|
conn.setup(nil, E.New("unexpected status: ", response.StatusCode, " ", response.Status))
|
||||||
|
} else {
|
||||||
|
conn.setup(response.Body, nil)
|
||||||
}
|
}
|
||||||
if response.StatusCode != 200 {
|
}()
|
||||||
pipeInWriter.Close()
|
return conn, nil
|
||||||
return nil, E.New("unexpected status: ", response.StatusCode, " ", response.Status)
|
|
||||||
}
|
|
||||||
return &HTTPConn{
|
|
||||||
response.Body,
|
|
||||||
pipeInWriter,
|
|
||||||
}, nil
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,9 +14,37 @@ import (
|
||||||
type HTTPConn struct {
|
type HTTPConn struct {
|
||||||
reader io.Reader
|
reader io.Reader
|
||||||
writer io.Writer
|
writer io.Writer
|
||||||
|
create chan struct{}
|
||||||
|
err error
|
||||||
|
}
|
||||||
|
|
||||||
|
func newHTTPConn(reader io.Reader, writer io.Writer) HTTPConn {
|
||||||
|
return HTTPConn{
|
||||||
|
reader: reader,
|
||||||
|
writer: writer,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func newLateHTTPConn(writer io.Writer) *HTTPConn {
|
||||||
|
return &HTTPConn{
|
||||||
|
create: make(chan struct{}),
|
||||||
|
writer: writer,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *HTTPConn) setup(reader io.Reader, err error) {
|
||||||
|
c.reader = reader
|
||||||
|
c.err = err
|
||||||
|
close(c.create)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *HTTPConn) Read(b []byte) (n int, err error) {
|
func (c *HTTPConn) Read(b []byte) (n int, err error) {
|
||||||
|
if c.reader == nil {
|
||||||
|
<-c.create
|
||||||
|
if c.err != nil {
|
||||||
|
return 0, c.err
|
||||||
|
}
|
||||||
|
}
|
||||||
n, err = c.reader.Read(b)
|
n, err = c.reader.Read(b)
|
||||||
return n, baderror.WrapH2(err)
|
return n, baderror.WrapH2(err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,8 @@ import (
|
||||||
M "github.com/sagernet/sing/common/metadata"
|
M "github.com/sagernet/sing/common/metadata"
|
||||||
N "github.com/sagernet/sing/common/network"
|
N "github.com/sagernet/sing/common/network"
|
||||||
sHttp "github.com/sagernet/sing/protocol/http"
|
sHttp "github.com/sagernet/sing/protocol/http"
|
||||||
|
|
||||||
|
"golang.org/x/net/http2"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ adapter.V2RayServerTransport = (*Server)(nil)
|
var _ adapter.V2RayServerTransport = (*Server)(nil)
|
||||||
|
@ -110,10 +112,7 @@ func (s *Server) ServeHTTP(writer http.ResponseWriter, request *http.Request) {
|
||||||
s.handler.NewConnection(request.Context(), conn, metadata)
|
s.handler.NewConnection(request.Context(), conn, metadata)
|
||||||
} else {
|
} else {
|
||||||
conn := &ServerHTTPConn{
|
conn := &ServerHTTPConn{
|
||||||
HTTPConn{
|
newHTTPConn(request.Body, writer),
|
||||||
request.Body,
|
|
||||||
writer,
|
|
||||||
},
|
|
||||||
writer.(http.Flusher),
|
writer.(http.Flusher),
|
||||||
}
|
}
|
||||||
s.handler.NewConnection(request.Context(), conn, metadata)
|
s.handler.NewConnection(request.Context(), conn, metadata)
|
||||||
|
@ -128,6 +127,10 @@ func (s *Server) Serve(listener net.Listener) error {
|
||||||
if s.httpServer.TLSConfig == nil {
|
if s.httpServer.TLSConfig == nil {
|
||||||
return s.httpServer.Serve(listener)
|
return s.httpServer.Serve(listener)
|
||||||
} else {
|
} else {
|
||||||
|
err := http2.ConfigureServer(s.httpServer, &http2.Server{})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
return s.httpServer.ServeTLS(listener, "", "")
|
return s.httpServer.ServeTLS(listener, "", "")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue