Add shadowsocks uot and test

This commit is contained in:
世界 2022-06-18 10:50:18 +08:00
parent 5af17f70b4
commit a562b249a2
No known key found for this signature in database
GPG key ID: CD109927C34A63C4
3 changed files with 76 additions and 0 deletions

View file

@ -19,6 +19,7 @@ import (
"github.com/sagernet/sing/common/buf" "github.com/sagernet/sing/common/buf"
"github.com/sagernet/sing/common/bufio" "github.com/sagernet/sing/common/bufio"
M "github.com/sagernet/sing/common/metadata" M "github.com/sagernet/sing/common/metadata"
"github.com/sagernet/sing/common/uot"
) )
func init() { func init() {
@ -29,6 +30,7 @@ type ShadowSocks struct {
*Base *Base
method shadowsocks.Method method shadowsocks.Method
option *ShadowSocksOption
// obfs // obfs
obfsMode string obfsMode string
obfsOption *simpleObfsOption obfsOption *simpleObfsOption
@ -45,6 +47,7 @@ type ShadowSocksOption struct {
UDP bool `proxy:"udp,omitempty"` UDP bool `proxy:"udp,omitempty"`
Plugin string `proxy:"plugin,omitempty"` Plugin string `proxy:"plugin,omitempty"`
PluginOpts map[string]any `proxy:"plugin-opts,omitempty"` PluginOpts map[string]any `proxy:"plugin-opts,omitempty"`
UDPOverTCP bool `proxy:"udp-over-tcp,omitempty"`
} }
type simpleObfsOption struct { type simpleObfsOption struct {
@ -96,6 +99,15 @@ func (ss *ShadowSocks) DialContext(ctx context.Context, metadata *C.Metadata, op
// ListenPacketContext implements C.ProxyAdapter // ListenPacketContext implements C.ProxyAdapter
func (ss *ShadowSocks) ListenPacketContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (C.PacketConn, error) { func (ss *ShadowSocks) ListenPacketContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (C.PacketConn, error) {
if ss.option.UDPOverTCP {
metadata.Host = uot.UOTMagicAddress
metadata.DstPort = "443"
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...)...) pc, err := dialer.ListenPacket(ctx, "udp", "", ss.Base.DialOptions(opts...)...)
if err != nil { if err != nil {
return nil, err return nil, err
@ -167,6 +179,7 @@ func NewShadowSocks(option ShadowSocksOption) (*ShadowSocks, error) {
}, },
method: method, method: method,
option: &option,
obfsMode: obfsMode, obfsMode: obfsMode,
v2rayOption: v2rayOption, v2rayOption: v2rayOption,
obfsOption: obfsOption, obfsOption: obfsOption,

View 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"
}
}

View file

@ -3,11 +3,13 @@ package main
import ( import (
"crypto/rand" "crypto/rand"
"encoding/base64" "encoding/base64"
"fmt"
"net" "net"
"testing" "testing"
"time" "time"
"github.com/Dreamacro/clash/adapter/outbound" "github.com/Dreamacro/clash/adapter/outbound"
C "github.com/Dreamacro/clash/constant"
"github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/container"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
@ -277,3 +279,37 @@ func Benchmark_Shadowsocks(b *testing.B) {
require.True(b, TCPing(net.JoinHostPort(localIP.String(), "10002"))) require.True(b, TCPing(net.JoinHostPort(localIP.String(), "10002")))
benchmarkProxy(b, proxy) 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)
}