feat: Support ShadowTLS v2 as Shadowsocks plugin (#330)

This commit is contained in:
3andero
2023-01-10 08:10:39 -08:00
committed by metacubex
parent 337be9124f
commit 51f9b34a7c
7 changed files with 206 additions and 20 deletions

View File

@ -10,11 +10,13 @@ import (
"github.com/Dreamacro/clash/common/structure"
"github.com/Dreamacro/clash/component/dialer"
C "github.com/Dreamacro/clash/constant"
"github.com/Dreamacro/clash/transport/shadowtls"
obfs "github.com/Dreamacro/clash/transport/simple-obfs"
"github.com/Dreamacro/clash/transport/socks5"
"github.com/Dreamacro/clash/transport/trojan"
v2rayObfs "github.com/Dreamacro/clash/transport/v2ray-plugin"
"github.com/metacubex/sing-shadowsocks"
shadowsocks "github.com/metacubex/sing-shadowsocks"
"github.com/metacubex/sing-shadowsocks/shadowimpl"
"github.com/sagernet/sing/common/bufio"
M "github.com/sagernet/sing/common/metadata"
@ -27,9 +29,11 @@ type ShadowSocks struct {
option *ShadowSocksOption
// obfs
obfsMode string
obfsOption *simpleObfsOption
v2rayOption *v2rayObfs.Option
obfsMode string
obfsOption *simpleObfsOption
v2rayOption *v2rayObfs.Option
shadowTLSOption *shadowTLSOption
tlsConnector *trojan.Trojan
}
type ShadowSocksOption struct {
@ -61,6 +65,11 @@ type v2rayObfsOption struct {
Mux bool `obfs:"mux,omitempty"`
}
type shadowTLSOption struct {
Password string `obfs:"password"`
Host string `obfs:"host"`
}
// StreamConn implements C.ProxyAdapter
func (ss *ShadowSocks) StreamConn(c net.Conn, metadata *C.Metadata) (net.Conn, error) {
switch ss.obfsMode {
@ -75,6 +84,11 @@ func (ss *ShadowSocks) StreamConn(c net.Conn, metadata *C.Metadata) (net.Conn, e
if err != nil {
return nil, fmt.Errorf("%s connect error: %w", ss.addr, err)
}
case shadowtls.Mode:
if ss.tlsConnector == nil {
ss.tlsConnector = trojan.New(&trojan.Option{ServerName: ss.shadowTLSOption.Host, SkipCertVerify: false})
}
c = shadowtls.NewShadowTls(c, ss.shadowTLSOption.Password, ss.tlsConnector)
}
if metadata.NetWork == C.UDP && ss.option.UDPOverTCP {
return ss.method.DialConn(c, M.ParseSocksaddr(uot.UOTMagicAddress+":443"))
@ -157,6 +171,7 @@ func NewShadowSocks(option ShadowSocksOption) (*ShadowSocks, error) {
var v2rayOption *v2rayObfs.Option
var obfsOption *simpleObfsOption
var shadowTLSOpt *shadowTLSOption
obfsMode := ""
decoder := structure.NewDecoder(structure.Option{TagName: "obfs", WeaklyTypedInput: true})
@ -192,6 +207,12 @@ func NewShadowSocks(option ShadowSocksOption) (*ShadowSocks, error) {
v2rayOption.TLS = true
v2rayOption.SkipCertVerify = opts.SkipCertVerify
}
} else if option.Plugin == shadowtls.Mode {
obfsMode = shadowtls.Mode
shadowTLSOpt = &shadowTLSOption{}
if err := decoder.Decode(option.PluginOpts, shadowTLSOpt); err != nil {
return nil, fmt.Errorf("ss %s initialize shadow-tls-plugin error: %w", addr, err)
}
}
return &ShadowSocks{
@ -206,10 +227,11 @@ func NewShadowSocks(option ShadowSocksOption) (*ShadowSocks, error) {
},
method: method,
option: &option,
obfsMode: obfsMode,
v2rayOption: v2rayOption,
obfsOption: obfsOption,
option: &option,
obfsMode: obfsMode,
v2rayOption: v2rayOption,
obfsOption: obfsOption,
shadowTLSOption: shadowTLSOpt,
}, nil
}