Merge remote-tracking branch 'Meta/Alpha' into Alpha
# Conflicts: # go.mod # go.sum
This commit is contained in:
commit
2f339c2ef5
16 changed files with 210 additions and 74 deletions
|
@ -19,6 +19,7 @@ import (
|
|||
"github.com/sagernet/sing/common/buf"
|
||||
"github.com/sagernet/sing/common/bufio"
|
||||
M "github.com/sagernet/sing/common/metadata"
|
||||
"github.com/sagernet/sing/common/uot"
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
@ -29,6 +30,7 @@ type ShadowSocks struct {
|
|||
*Base
|
||||
method shadowsocks.Method
|
||||
|
||||
option *ShadowSocksOption
|
||||
// obfs
|
||||
obfsMode string
|
||||
obfsOption *simpleObfsOption
|
||||
|
@ -45,6 +47,7 @@ type ShadowSocksOption struct {
|
|||
UDP bool `proxy:"udp,omitempty"`
|
||||
Plugin string `proxy:"plugin,omitempty"`
|
||||
PluginOpts map[string]any `proxy:"plugin-opts,omitempty"`
|
||||
UDPOverTCP bool `proxy:"udp-over-tcp,omitempty"`
|
||||
}
|
||||
|
||||
type simpleObfsOption struct {
|
||||
|
@ -77,6 +80,10 @@ func (ss *ShadowSocks) StreamConn(c net.Conn, metadata *C.Metadata) (net.Conn, e
|
|||
return nil, fmt.Errorf("%s connect error: %w", ss.addr, err)
|
||||
}
|
||||
}
|
||||
if metadata.NetWork == C.UDP && ss.option.UDPOverTCP {
|
||||
metadata.Host = uot.UOTMagicAddress
|
||||
metadata.DstPort = "443"
|
||||
}
|
||||
return ss.method.DialConn(c, M.ParseSocksaddr(metadata.RemoteAddress()))
|
||||
}
|
||||
|
||||
|
@ -96,6 +103,13 @@ func (ss *ShadowSocks) DialContext(ctx context.Context, metadata *C.Metadata, op
|
|||
|
||||
// ListenPacketContext implements C.ProxyAdapter
|
||||
func (ss *ShadowSocks) ListenPacketContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (C.PacketConn, error) {
|
||||
if ss.option.UDPOverTCP {
|
||||
tcpConn, err := ss.DialContext(ctx, metadata, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return newPacketConn(uot.NewClientConn(tcpConn), ss), nil
|
||||
}
|
||||
pc, err := dialer.ListenPacket(ctx, "udp", "", ss.Base.DialOptions(opts...)...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -110,6 +124,19 @@ func (ss *ShadowSocks) ListenPacketContext(ctx context.Context, metadata *C.Meta
|
|||
return newPacketConn(pc, ss), nil
|
||||
}
|
||||
|
||||
// ListenPacketOnStreamConn implements C.ProxyAdapter
|
||||
func (ss *ShadowSocks) ListenPacketOnStreamConn(c net.Conn, metadata *C.Metadata) (_ C.PacketConn, err error) {
|
||||
if ss.option.UDPOverTCP {
|
||||
return newPacketConn(uot.NewClientConn(c), ss), nil
|
||||
}
|
||||
return nil, errors.New("no support")
|
||||
}
|
||||
|
||||
// SupportUOT implements C.ProxyAdapter
|
||||
func (ss *ShadowSocks) SupportUOT() bool {
|
||||
return ss.option.UDPOverTCP
|
||||
}
|
||||
|
||||
func NewShadowSocks(option ShadowSocksOption) (*ShadowSocks, error) {
|
||||
addr := net.JoinHostPort(option.Server, strconv.Itoa(option.Port))
|
||||
method, err := shadowimpl.FetchMethod(option.Cipher, option.Password)
|
||||
|
@ -167,6 +194,7 @@ func NewShadowSocks(option ShadowSocksOption) (*ShadowSocks, error) {
|
|||
},
|
||||
method: method,
|
||||
|
||||
option: &option,
|
||||
obfsMode: obfsMode,
|
||||
v2rayOption: v2rayOption,
|
||||
obfsOption: obfsOption,
|
||||
|
|
|
@ -40,9 +40,10 @@ func (f *fetcher[V]) VehicleType() types.VehicleType {
|
|||
|
||||
func (f *fetcher[V]) Initial() (V, error) {
|
||||
var (
|
||||
buf []byte
|
||||
err error
|
||||
isLocal bool
|
||||
buf []byte
|
||||
err error
|
||||
isLocal bool
|
||||
forceUpdate bool
|
||||
)
|
||||
|
||||
if stat, fErr := os.Stat(f.vehicle.Path()); fErr == nil {
|
||||
|
@ -51,10 +52,8 @@ func (f *fetcher[V]) Initial() (V, error) {
|
|||
f.updatedAt = &modTime
|
||||
isLocal = true
|
||||
if f.interval != 0 && modTime.Add(f.interval).Before(time.Now()) {
|
||||
defer func() {
|
||||
log.Infoln("[Provider] %s's proxies not updated for a long time, force refresh", f.Name())
|
||||
go f.Update()
|
||||
}()
|
||||
log.Infoln("[Provider] %s not updated for a long time, force refresh", f.Name())
|
||||
forceUpdate = true
|
||||
}
|
||||
} else {
|
||||
buf, err = f.vehicle.Read()
|
||||
|
@ -64,7 +63,21 @@ func (f *fetcher[V]) Initial() (V, error) {
|
|||
return getZero[V](), err
|
||||
}
|
||||
|
||||
proxies, err := f.parser(buf)
|
||||
var proxies V
|
||||
if forceUpdate {
|
||||
var forceBuf []byte
|
||||
if forceBuf, err = f.vehicle.Read(); err == nil {
|
||||
if proxies, err = f.parser(forceBuf); err == nil {
|
||||
isLocal = false
|
||||
buf = forceBuf
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if err != nil || !forceUpdate {
|
||||
proxies, err = f.parser(buf)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
if !isLocal {
|
||||
return getZero[V](), err
|
||||
|
|
|
@ -173,7 +173,7 @@ func ResolveAllIPv4WithResolver(host string, r Resolver) ([]netip.Addr, error) {
|
|||
|
||||
ip, err := netip.ParseAddr(host)
|
||||
if err == nil {
|
||||
if ip.Is4() {
|
||||
if ip.Is4() || ip.Is4In6() {
|
||||
return []netip.Addr{ip}, nil
|
||||
}
|
||||
return []netip.Addr{}, ErrIPVersion
|
||||
|
|
8
go.mod
8
go.mod
|
@ -13,9 +13,9 @@ require (
|
|||
github.com/lucas-clemente/quic-go v0.27.2
|
||||
github.com/miekg/dns v1.1.49
|
||||
github.com/oschwald/geoip2-golang v1.7.0
|
||||
github.com/sagernet/sing v0.0.0-20220615170357-aa30c4140ca9
|
||||
github.com/sagernet/sing-shadowsocks v0.0.0-20220615081955-91a0901d1c89
|
||||
github.com/sagernet/sing-vmess v0.0.0-20220614092239-0052a5a383f5
|
||||
github.com/sagernet/sing v0.0.0-20220619130320-8793fe5e067d
|
||||
github.com/sagernet/sing-shadowsocks v0.0.0-20220619134218-830a2f478eb1
|
||||
github.com/sagernet/sing-vmess v0.0.0-20220616051646-3d3fc5d01eec
|
||||
github.com/sirupsen/logrus v1.8.1
|
||||
github.com/stretchr/testify v1.7.2
|
||||
github.com/tobyxdd/hysteria v1.0.4
|
||||
|
@ -28,7 +28,7 @@ require (
|
|||
golang.org/x/exp v0.0.0-20220608143224-64259d1afd70
|
||||
golang.org/x/net v0.0.0-20220607020251-c690dde0001d
|
||||
golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f
|
||||
golang.org/x/sys v0.0.0-20220610221304-9f5ed59c137d
|
||||
golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c
|
||||
golang.org/x/time v0.0.0-20220411224347-583f2d630306
|
||||
golang.zx2c4.com/wireguard v0.0.0-20220601130007-6a08d81f6bc4
|
||||
golang.zx2c4.com/wireguard/windows v0.5.4-0.20220328111914-004c22c5647e
|
||||
|
|
16
go.sum
16
go.sum
|
@ -305,12 +305,12 @@ github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0
|
|||
github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
|
||||
github.com/sagernet/sing v0.0.0-20220615170357-aa30c4140ca9 h1:jsrgPBWIMRBk71zKtEpVLJ10AqSQO+K2psplU8Wrouo=
|
||||
github.com/sagernet/sing v0.0.0-20220615170357-aa30c4140ca9/go.mod h1:Bgwxr10oTxYlQ33MgsXW3GuS2w5St11qqk4DqzJOdU4=
|
||||
github.com/sagernet/sing-shadowsocks v0.0.0-20220615081955-91a0901d1c89 h1:l7TGNYSm4H2nZfvp2iOlCxvaGZO0tSts+o7+YJE8M2I=
|
||||
github.com/sagernet/sing-shadowsocks v0.0.0-20220615081955-91a0901d1c89/go.mod h1:r3xDib+IPJH/cT1DBzez3O3me4HpGLbzdsMzqwyGX6U=
|
||||
github.com/sagernet/sing-vmess v0.0.0-20220614092239-0052a5a383f5 h1:mTeGXZ/mNvUgiEPQ0hhMtqCdkPQlOjmgdl40TQNQnLQ=
|
||||
github.com/sagernet/sing-vmess v0.0.0-20220614092239-0052a5a383f5/go.mod h1:LHcJcRDCJnAeI7tlMmVqeJapURFJr7HQfDrBxkylu/g=
|
||||
github.com/sagernet/sing v0.0.0-20220619130320-8793fe5e067d h1:zr8y4wmNIxv6Kkvgqysx8Piy82ATAThEj1jaEf23YQs=
|
||||
github.com/sagernet/sing v0.0.0-20220619130320-8793fe5e067d/go.mod h1:I67R/q5f67xDExL2kL3RLIP7kGJBOPkYXkpRAykgC+E=
|
||||
github.com/sagernet/sing-shadowsocks v0.0.0-20220619134218-830a2f478eb1 h1:3GEdnWbuSX4XwSKnxLUB/1rMXUxSVKeyRhEeT7k7N1Q=
|
||||
github.com/sagernet/sing-shadowsocks v0.0.0-20220619134218-830a2f478eb1/go.mod h1:xk8Hh1hQiTeiY6jHCQjaxxN8M6B94JoGaNx5q61naE8=
|
||||
github.com/sagernet/sing-vmess v0.0.0-20220616051646-3d3fc5d01eec h1:jUSfKmyL6K9O2TvIvcVacZ4eNXHYbNSfdph+DRPyVlU=
|
||||
github.com/sagernet/sing-vmess v0.0.0-20220616051646-3d3fc5d01eec/go.mod h1:jDZ8fJgOea7Y7MMHWgfqwLBVLnhtW2zuxS5wjtDaB84=
|
||||
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
|
||||
github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY=
|
||||
github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48/go.mod h1:5u70Mqkb5O5cxEA8nxTsgrgLehJeAw6Oc4Ab1c/P1HM=
|
||||
|
@ -566,8 +566,8 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220610221304-9f5ed59c137d h1:Zu/JngovGLVi6t2J3nmAf3AoTDwuzw85YZ3b9o4yU7s=
|
||||
golang.org/x/sys v0.0.0-20220610221304-9f5ed59c137d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c h1:aFV+BgZ4svzjfabn8ERpuB4JI4N6/rdy1iusx77G3oU=
|
||||
golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c/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=
|
||||
|
|
|
@ -46,6 +46,7 @@ type configSchema struct {
|
|||
IPv6 *bool `json:"ipv6"`
|
||||
Sniffing *bool `json:"sniffing"`
|
||||
TcpConcurrent *bool `json:"tcp-concurrent"`
|
||||
InterfaceName *string `json:"interface-name"`
|
||||
}
|
||||
|
||||
func getConfigs(w http.ResponseWriter, r *http.Request) {
|
||||
|
@ -85,6 +86,10 @@ func patchConfigs(w http.ResponseWriter, r *http.Request) {
|
|||
dialer.SetDial(*general.TcpConcurrent)
|
||||
}
|
||||
|
||||
if general.InterfaceName != nil {
|
||||
dialer.DefaultInterface.Store(*general.InterfaceName)
|
||||
}
|
||||
|
||||
ports := P.GetPorts()
|
||||
|
||||
tcpIn := tunnel.TCPIn()
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package common
|
||||
|
||||
import (
|
||||
"golang.org/x/net/idna"
|
||||
"strings"
|
||||
|
||||
C "github.com/Dreamacro/clash/constant"
|
||||
|
@ -8,8 +9,9 @@ import (
|
|||
|
||||
type Domain struct {
|
||||
*Base
|
||||
domain string
|
||||
adapter string
|
||||
domain string
|
||||
rawDomain string
|
||||
adapter string
|
||||
}
|
||||
|
||||
func (d *Domain) RuleType() C.RuleType {
|
||||
|
@ -28,14 +30,16 @@ func (d *Domain) Adapter() string {
|
|||
}
|
||||
|
||||
func (d *Domain) Payload() string {
|
||||
return d.domain
|
||||
return d.rawDomain
|
||||
}
|
||||
|
||||
func NewDomain(domain string, adapter string) *Domain {
|
||||
actualDomain, _ := idna.ToASCII(domain)
|
||||
return &Domain{
|
||||
Base: &Base{},
|
||||
domain: strings.ToLower(domain),
|
||||
adapter: adapter,
|
||||
Base: &Base{},
|
||||
domain: strings.ToLower(actualDomain),
|
||||
adapter: adapter,
|
||||
rawDomain: domain,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package common
|
||||
|
||||
import (
|
||||
"golang.org/x/net/idna"
|
||||
"strings"
|
||||
|
||||
C "github.com/Dreamacro/clash/constant"
|
||||
|
@ -8,8 +9,9 @@ import (
|
|||
|
||||
type DomainKeyword struct {
|
||||
*Base
|
||||
keyword string
|
||||
adapter string
|
||||
keyword string
|
||||
adapter string
|
||||
rawKeyword string
|
||||
}
|
||||
|
||||
func (dk *DomainKeyword) RuleType() C.RuleType {
|
||||
|
@ -29,14 +31,16 @@ func (dk *DomainKeyword) Adapter() string {
|
|||
}
|
||||
|
||||
func (dk *DomainKeyword) Payload() string {
|
||||
return dk.keyword
|
||||
return dk.rawKeyword
|
||||
}
|
||||
|
||||
func NewDomainKeyword(keyword string, adapter string) *DomainKeyword {
|
||||
actualDomainKeyword, _ := idna.ToASCII(keyword)
|
||||
return &DomainKeyword{
|
||||
Base: &Base{},
|
||||
keyword: strings.ToLower(keyword),
|
||||
adapter: adapter,
|
||||
Base: &Base{},
|
||||
keyword: strings.ToLower(actualDomainKeyword),
|
||||
adapter: adapter,
|
||||
rawKeyword: keyword,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package common
|
||||
|
||||
import (
|
||||
"golang.org/x/net/idna"
|
||||
"strings"
|
||||
|
||||
C "github.com/Dreamacro/clash/constant"
|
||||
|
@ -8,8 +9,9 @@ import (
|
|||
|
||||
type DomainSuffix struct {
|
||||
*Base
|
||||
suffix string
|
||||
adapter string
|
||||
suffix string
|
||||
adapter string
|
||||
rawSuffix string
|
||||
}
|
||||
|
||||
func (ds *DomainSuffix) RuleType() C.RuleType {
|
||||
|
@ -29,14 +31,16 @@ func (ds *DomainSuffix) Adapter() string {
|
|||
}
|
||||
|
||||
func (ds *DomainSuffix) Payload() string {
|
||||
return ds.suffix
|
||||
return ds.rawSuffix
|
||||
}
|
||||
|
||||
func NewDomainSuffix(suffix string, adapter string) *DomainSuffix {
|
||||
actualDomainKeyword, _ := idna.ToASCII(suffix)
|
||||
return &DomainSuffix{
|
||||
Base: &Base{},
|
||||
suffix: strings.ToLower(suffix),
|
||||
adapter: adapter,
|
||||
Base: &Base{},
|
||||
suffix: strings.ToLower(actualDomainKeyword),
|
||||
adapter: adapter,
|
||||
rawSuffix: suffix,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"fmt"
|
||||
C "github.com/Dreamacro/clash/constant"
|
||||
"github.com/Dreamacro/clash/log"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type classicalStrategy struct {
|
||||
|
@ -52,6 +53,19 @@ func (c *classicalStrategy) OnUpdate(rules []string) {
|
|||
c.count = len(classicalRules)
|
||||
}
|
||||
|
||||
func ruleParse(ruleRaw string) (string, string, []string) {
|
||||
item := strings.Split(ruleRaw, ",")
|
||||
if len(item) == 1 {
|
||||
return "", item[0], nil
|
||||
} else if len(item) == 2 {
|
||||
return item[0], item[1], nil
|
||||
} else if len(item) > 2 {
|
||||
return item[0], item[1], item[2:]
|
||||
}
|
||||
|
||||
return "", "", nil
|
||||
}
|
||||
|
||||
func NewClassicalStrategy(parse func(tp, payload, target string, params []string) (parsed C.Rule, parseErr error)) *classicalStrategy {
|
||||
return &classicalStrategy{rules: []C.Rule{}, parse: func(tp, payload, target string, params []string) (parsed C.Rule, parseErr error) {
|
||||
switch tp {
|
||||
|
|
|
@ -4,7 +4,7 @@ import (
|
|||
"github.com/Dreamacro/clash/component/trie"
|
||||
C "github.com/Dreamacro/clash/constant"
|
||||
"github.com/Dreamacro/clash/log"
|
||||
"strings"
|
||||
"golang.org/x/net/idna"
|
||||
)
|
||||
|
||||
type domainStrategy struct {
|
||||
|
@ -28,7 +28,8 @@ func (d *domainStrategy) OnUpdate(rules []string) {
|
|||
domainTrie := trie.New[bool]()
|
||||
count := 0
|
||||
for _, rule := range rules {
|
||||
err := domainTrie.Insert(rule, true)
|
||||
actualDomain, _ := idna.ToASCII(rule)
|
||||
err := domainTrie.Insert(actualDomain, true)
|
||||
if err != nil {
|
||||
log.Warnln("invalid domain:[%s]", rule)
|
||||
} else {
|
||||
|
@ -40,19 +41,6 @@ func (d *domainStrategy) OnUpdate(rules []string) {
|
|||
d.count = count
|
||||
}
|
||||
|
||||
func ruleParse(ruleRaw string) (string, string, []string) {
|
||||
item := strings.Split(ruleRaw, ",")
|
||||
if len(item) == 1 {
|
||||
return "", item[0], nil
|
||||
} else if len(item) == 2 {
|
||||
return item[0], item[1], nil
|
||||
} else if len(item) > 2 {
|
||||
return item[0], item[1], item[2:]
|
||||
}
|
||||
|
||||
return "", "", nil
|
||||
}
|
||||
|
||||
func NewDomainStrategy() *domainStrategy {
|
||||
return &domainStrategy{}
|
||||
}
|
||||
|
|
|
@ -40,9 +40,10 @@ func (f *fetcher) VehicleType() P.VehicleType {
|
|||
|
||||
func (f *fetcher) Initial() (interface{}, error) {
|
||||
var (
|
||||
buf []byte
|
||||
hasLocal bool
|
||||
err error
|
||||
buf []byte
|
||||
hasLocal bool
|
||||
err error
|
||||
forceUpdate bool
|
||||
)
|
||||
|
||||
defer func() {
|
||||
|
@ -57,10 +58,8 @@ func (f *fetcher) Initial() (interface{}, error) {
|
|||
f.updatedAt = &modTime
|
||||
hasLocal = true
|
||||
if f.interval != 0 && modTime.Add(f.interval).Before(time.Now()) {
|
||||
defer func() {
|
||||
log.Infoln("[Provider] %s's rules not updated for a long time, force refresh", f.Name())
|
||||
go f.update()
|
||||
}()
|
||||
forceUpdate = true
|
||||
log.Infoln("[Provider] %s not updated for a long time, force refresh", f.Name())
|
||||
}
|
||||
} else {
|
||||
buf, err = f.vehicle.Read()
|
||||
|
@ -70,7 +69,21 @@ func (f *fetcher) Initial() (interface{}, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
rules, err := f.parser(buf)
|
||||
var rules interface{}
|
||||
if forceUpdate {
|
||||
var forceBuf []byte
|
||||
if forceBuf, err = f.vehicle.Read(); err == nil {
|
||||
if rules, err = f.parser(forceBuf); err == nil {
|
||||
hasLocal = false
|
||||
buf = forceBuf
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if err != nil || !forceUpdate {
|
||||
rules, err = f.parser(buf)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
if !hasLocal {
|
||||
return nil, err
|
||||
|
|
27
test/config/xray-shadowsocks.json
Normal file
27
test/config/xray-shadowsocks.json
Normal file
|
@ -0,0 +1,27 @@
|
|||
{
|
||||
"inbounds": [
|
||||
{
|
||||
"port": 10002,
|
||||
"listen": "0.0.0.0",
|
||||
"protocol": "shadowsocks",
|
||||
"settings": {
|
||||
"network": "tcp,udp",
|
||||
"clients": [
|
||||
{
|
||||
"method": "aes-128-gcm",
|
||||
"level": 0,
|
||||
"password": "FzcLbKs2dY9mhL"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"outbounds": [
|
||||
{
|
||||
"protocol": "freedom"
|
||||
}
|
||||
],
|
||||
"log": {
|
||||
"loglevel": "debug"
|
||||
}
|
||||
}
|
|
@ -61,9 +61,9 @@ require (
|
|||
github.com/prometheus/client_model v0.2.0 // indirect
|
||||
github.com/prometheus/common v0.32.1 // indirect
|
||||
github.com/prometheus/procfs v0.7.3 // indirect
|
||||
github.com/sagernet/sing v0.0.0-20220614034114-7caa1d0c0851 // indirect
|
||||
github.com/sagernet/sing-shadowsocks v0.0.0-20220610074818-432dcbdb1d7c // indirect
|
||||
github.com/sagernet/sing-vmess v0.0.0-20220614042419-6f7c1431421a // indirect
|
||||
github.com/sagernet/sing v0.0.0-20220619130320-8793fe5e067d // indirect
|
||||
github.com/sagernet/sing-shadowsocks v0.0.0-20220619134218-830a2f478eb1 // indirect
|
||||
github.com/sagernet/sing-vmess v0.0.0-20220616051646-3d3fc5d01eec // indirect
|
||||
github.com/sirupsen/logrus v1.8.1 // indirect
|
||||
github.com/tobyxdd/hysteria v1.0.4 // indirect
|
||||
github.com/txthinking/runnergroup v0.0.0-20210608031112-152c7c4432bf // indirect
|
||||
|
@ -79,7 +79,7 @@ require (
|
|||
golang.org/x/exp v0.0.0-20220608143224-64259d1afd70 // indirect
|
||||
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 // indirect
|
||||
golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f // indirect
|
||||
golang.org/x/sys v0.0.0-20220608164250-635b8c9b7f68 // indirect
|
||||
golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c // indirect
|
||||
golang.org/x/text v0.3.8-0.20220124021120-d1c84af989ab // indirect
|
||||
golang.org/x/time v0.0.0-20220411224347-583f2d630306 // indirect
|
||||
golang.org/x/tools v0.1.10 // indirect
|
||||
|
|
16
test/go.sum
16
test/go.sum
|
@ -323,12 +323,12 @@ github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0
|
|||
github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
|
||||
github.com/sagernet/sing v0.0.0-20220614034114-7caa1d0c0851 h1:Pp+9IPHtlwxrkiKMSrTOPS/eg+qJLdfZoeM89QX40BI=
|
||||
github.com/sagernet/sing v0.0.0-20220614034114-7caa1d0c0851/go.mod h1:ZEo7wZBfJmzm8uwnbCtWEHw9GsIfSThSylZYcR+H/Zw=
|
||||
github.com/sagernet/sing-shadowsocks v0.0.0-20220610074818-432dcbdb1d7c h1:dapkcUcFbOwqnBwut6Dct7L695PVS6GoEqJeSRMWe0k=
|
||||
github.com/sagernet/sing-shadowsocks v0.0.0-20220610074818-432dcbdb1d7c/go.mod h1:ty1OoG/SgB6IccsWUS5DZBkEGKUKM8nRSWxLlqYUPx0=
|
||||
github.com/sagernet/sing-vmess v0.0.0-20220614042419-6f7c1431421a h1:vEJtwy2Ysw9ftf+5TALig2ZiRFf1pDnWGxhwRqDs+Cs=
|
||||
github.com/sagernet/sing-vmess v0.0.0-20220614042419-6f7c1431421a/go.mod h1:KZxqBTXh1v6q7TnVm36y+oCzPQLQKgv0z/TeBuozb2s=
|
||||
github.com/sagernet/sing v0.0.0-20220619130320-8793fe5e067d h1:zr8y4wmNIxv6Kkvgqysx8Piy82ATAThEj1jaEf23YQs=
|
||||
github.com/sagernet/sing v0.0.0-20220619130320-8793fe5e067d/go.mod h1:I67R/q5f67xDExL2kL3RLIP7kGJBOPkYXkpRAykgC+E=
|
||||
github.com/sagernet/sing-shadowsocks v0.0.0-20220619134218-830a2f478eb1 h1:3GEdnWbuSX4XwSKnxLUB/1rMXUxSVKeyRhEeT7k7N1Q=
|
||||
github.com/sagernet/sing-shadowsocks v0.0.0-20220619134218-830a2f478eb1/go.mod h1:xk8Hh1hQiTeiY6jHCQjaxxN8M6B94JoGaNx5q61naE8=
|
||||
github.com/sagernet/sing-vmess v0.0.0-20220616051646-3d3fc5d01eec h1:jUSfKmyL6K9O2TvIvcVacZ4eNXHYbNSfdph+DRPyVlU=
|
||||
github.com/sagernet/sing-vmess v0.0.0-20220616051646-3d3fc5d01eec/go.mod h1:jDZ8fJgOea7Y7MMHWgfqwLBVLnhtW2zuxS5wjtDaB84=
|
||||
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
|
||||
github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY=
|
||||
github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48/go.mod h1:5u70Mqkb5O5cxEA8nxTsgrgLehJeAw6Oc4Ab1c/P1HM=
|
||||
|
@ -586,8 +586,8 @@ golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220608164250-635b8c9b7f68 h1:z8Hj/bl9cOV2grsOpEaQFUaly0JWN3i97mo3jXKJNp0=
|
||||
golang.org/x/sys v0.0.0-20220608164250-635b8c9b7f68/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c h1:aFV+BgZ4svzjfabn8ERpuB4JI4N6/rdy1iusx77G3oU=
|
||||
golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c/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=
|
||||
|
|
|
@ -3,11 +3,13 @@ package main
|
|||
import (
|
||||
"crypto/rand"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"net"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/Dreamacro/clash/adapter/outbound"
|
||||
C "github.com/Dreamacro/clash/constant"
|
||||
"github.com/docker/docker/api/types/container"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
@ -277,3 +279,37 @@ func Benchmark_Shadowsocks(b *testing.B) {
|
|||
require.True(b, TCPing(net.JoinHostPort(localIP.String(), "10002")))
|
||||
benchmarkProxy(b, proxy)
|
||||
}
|
||||
|
||||
func TestClash_ShadowsocksUoT(t *testing.T) {
|
||||
configPath := C.Path.Resolve("xray-shadowsocks.json")
|
||||
|
||||
cfg := &container.Config{
|
||||
Image: ImageVless,
|
||||
ExposedPorts: defaultExposedPorts,
|
||||
}
|
||||
hostCfg := &container.HostConfig{
|
||||
PortBindings: defaultPortBindings,
|
||||
Binds: []string{fmt.Sprintf("%s:/etc/xray/config.json", configPath)},
|
||||
}
|
||||
|
||||
id, err := startContainer(cfg, hostCfg, "xray-ss")
|
||||
require.NoError(t, err)
|
||||
|
||||
t.Cleanup(func() {
|
||||
cleanContainer(id)
|
||||
})
|
||||
|
||||
proxy, err := outbound.NewShadowSocks(outbound.ShadowSocksOption{
|
||||
Name: "ss",
|
||||
Server: localIP.String(),
|
||||
Port: 10002,
|
||||
Password: "FzcLbKs2dY9mhL",
|
||||
Cipher: "aes-128-gcm",
|
||||
UDP: true,
|
||||
UDPOverTCP: true,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
time.Sleep(waitTime)
|
||||
testSuit(t, proxy)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue