Skip to content

Commit

Permalink
Add udp over tcp support for shadowsocks-2022
Browse files Browse the repository at this point in the history
  • Loading branch information
nekohasekai committed Jun 1, 2022
1 parent 6f93ef7 commit c350563
Show file tree
Hide file tree
Showing 14 changed files with 119 additions and 33 deletions.
4 changes: 4 additions & 0 deletions app/proxyman/outbound/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,10 @@ func (h *Handler) Dial(ctx context.Context, dest net.Destination) (stat.Connecti
}
}

if conn, err := h.getUoTConnection(ctx, dest); err != os.ErrInvalid {
return conn, err
}

conn, err := internet.Dial(ctx, dest, h.streamSettings)
return h.getStatCouterConnection(conn), err
}
Expand Down
25 changes: 25 additions & 0 deletions app/proxyman/outbound/uot.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
//go:build go1.18

package outbound

import (
"context"
"os"

"github.com/sagernet/sing/common/uot"
"github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/transport/internet"
"github.com/xtls/xray-core/transport/internet/stat"
)

func (h *Handler) getUoTConnection(ctx context.Context, dest net.Destination) (stat.Connection, error) {
if !dest.Address.Family().IsDomain() || dest.Address.Domain() != uot.UOTMagicAddress {
return nil, os.ErrInvalid
}
packetConn, err := internet.ListenSystemPacket(ctx, &net.UDPAddr{IP: net.AnyIP.IP(), Port: 0}, h.streamSettings.SocketSettings)
if err != nil {
return nil, newError("unable to listen socket").Base(err)
}
conn := uot.NewServerConn(packetConn)
return h.getStatCouterConnection(conn), nil
}
15 changes: 15 additions & 0 deletions app/proxyman/outbound/uot_stub.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
//go:build !go1.18

package outbound

import (
"context"
"os"

"github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/transport/internet/stat"
)

func (h *Handler) getUoTConnection(ctx context.Context, dest net.Destination) (stat.Connection, error) {
return nil, os.ErrInvalid
}
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ require (
github.com/pelletier/go-toml v1.9.5
github.com/pires/go-proxyproto v0.6.2
github.com/refraction-networking/utls v1.1.0
github.com/sagernet/sing v0.0.0-20220530041323-c82c144a8e00
github.com/sagernet/sing-shadowsocks v0.0.0-20220531032427-182b7837c827
github.com/sagernet/sing v0.0.0-20220601033944-4e04bbd3d84d
github.com/sagernet/sing-shadowsocks v0.0.0-20220601034426-ee9be8af94e4
github.com/seiflotfy/cuckoofilter v0.0.0-20220411075957-e3b120b3f5fb
github.com/stretchr/testify v1.7.1
github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e
Expand Down
8 changes: 4 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -172,10 +172,10 @@ github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 h1:f/FNXud6gA3MNr
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3/go.mod h1:HgjTstvQsPGkxUsCd2KWxErBblirPizecHcpD3ffK+s=
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/sagernet/sing v0.0.0-20220530041323-c82c144a8e00 h1:kQCITv1yBrSSL6RIBPWTe1+goyWLbS4DELWTeRKmoh8=
github.com/sagernet/sing v0.0.0-20220530041323-c82c144a8e00/go.mod h1:w2HnJzXKHpD6F5Z/9XlSD4qbcpHY2RSZuQnFzqgELMg=
github.com/sagernet/sing-shadowsocks v0.0.0-20220531032427-182b7837c827 h1:dy8/Ltn4TW8op9esqdXBCuOVuaUSEZW2gCVE609z2UY=
github.com/sagernet/sing-shadowsocks v0.0.0-20220531032427-182b7837c827/go.mod h1:24Hwpi7iyZ8KSUqV5GpG29xSc8jUfU//RlClJcOqph4=
github.com/sagernet/sing v0.0.0-20220601033944-4e04bbd3d84d h1:BNhKTknI2tBPUOPDV3lcgwOX6iZimL7K3TPdTdp5hiA=
github.com/sagernet/sing v0.0.0-20220601033944-4e04bbd3d84d/go.mod h1:w2HnJzXKHpD6F5Z/9XlSD4qbcpHY2RSZuQnFzqgELMg=
github.com/sagernet/sing-shadowsocks v0.0.0-20220601034426-ee9be8af94e4 h1:POJZphM4VaovhB/7GjJTG+pUTcI/Q9jaOHBqTL6jq1E=
github.com/sagernet/sing-shadowsocks v0.0.0-20220601034426-ee9be8af94e4/go.mod h1:8NNH8ACh+C0oZb4ielvRJHYA4kFmhDdSQxmwAa+N8PM=
github.com/seiflotfy/cuckoofilter v0.0.0-20220411075957-e3b120b3f5fb h1:XfLJSPIOUX+osiMraVgIrMR27uMXnRJWGm1+GL8/63U=
github.com/seiflotfy/cuckoofilter v0.0.0-20220411075957-e3b120b3f5fb/go.mod h1:bR6DqgcAl1zTcOX8/pE2Qkj9XO00eCNqmKb7lXP8EAg=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
Expand Down
2 changes: 2 additions & 0 deletions infra/conf/shadowsocks.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ type ShadowsocksServerTarget struct {
Email string `json:"email"`
Level byte `json:"level"`
IVCheck bool `json:"ivCheck"`
UoT bool `json:"uot"`
}

type ShadowsocksClientConfig struct {
Expand Down Expand Up @@ -165,6 +166,7 @@ func (v *ShadowsocksClientConfig) Build() (proto.Message, error) {
config.Port = uint32(server.Port)
config.Method = server.Cipher
config.Key = server.Password
config.UdpOverTcp = server.UoT
return config, nil
}
}
Expand Down
2 changes: 2 additions & 0 deletions infra/conf/shadowsocks_legacy.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
//go:build !go1.18

package conf

import (
Expand Down Expand Up @@ -98,6 +99,7 @@ type ShadowsocksServerTarget struct {
Email string `json:"email"`
Level byte `json:"level"`
IVCheck bool `json:"ivCheck"`
UoT bool `json:"uot"`
}

type ShadowsocksClientConfig struct {
Expand Down
38 changes: 24 additions & 14 deletions proxy/shadowsocks_2022/config.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions proxy/shadowsocks_2022/config.proto
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,5 @@ message ClientConfig {
uint32 port = 2;
string method = 3;
string key = 4;
bool udp_over_tcp = 5;
}
13 changes: 10 additions & 3 deletions proxy/shadowsocks_2022/inbound.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
C "github.com/sagernet/sing/common"
B "github.com/sagernet/sing/common/buf"
"github.com/sagernet/sing/common/bufio"
E "github.com/sagernet/sing/common/exceptions"
M "github.com/sagernet/sing/common/metadata"
N "github.com/sagernet/sing/common/network"
"github.com/xtls/xray-core/common"
Expand Down Expand Up @@ -74,20 +75,23 @@ func (i *Inbound) Process(ctx context.Context, network net.Network, connection s
ctx = session.ContextWithDispatcher(ctx, dispatcher)

if network == net.Network_TCP {
return i.service.NewConnection(ctx, connection, metadata)
return returnError(i.service.NewConnection(ctx, connection, metadata))
} else {
reader := buf.NewReader(connection)
pc := &natPacketConn{connection}
for {
mb, err := reader.ReadMultiBuffer()
if err != nil {
return err
buf.ReleaseMulti(mb)
return returnError(err)
}
for _, buffer := range mb {
err = i.service.NewPacket(ctx, pc, B.As(buffer.Bytes()), metadata)
err = i.service.NewPacket(ctx, pc, B.As(buffer.Bytes()).ToOwned(), metadata)
if err != nil {
buf.ReleaseMulti(mb)
return err
}
buffer.Release()
}
}
}
Expand Down Expand Up @@ -147,6 +151,9 @@ func (i *Inbound) NewPacketConnection(ctx context.Context, conn N.PacketConn, me
}

func (i *Inbound) HandleError(err error) {
if E.IsClosed(err) {
return
}
newError(err).AtWarning().WriteToLog()
}

Expand Down
13 changes: 10 additions & 3 deletions proxy/shadowsocks_2022/inbound_multi.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"github.com/sagernet/sing-shadowsocks/shadowaead_2022"
B "github.com/sagernet/sing/common/buf"
"github.com/sagernet/sing/common/bufio"
E "github.com/sagernet/sing/common/exceptions"
M "github.com/sagernet/sing/common/metadata"
N "github.com/sagernet/sing/common/network"
"github.com/xtls/xray-core/common"
Expand Down Expand Up @@ -93,20 +94,23 @@ func (i *MultiUserInbound) Process(ctx context.Context, network net.Network, con
ctx = session.ContextWithDispatcher(ctx, dispatcher)

if network == net.Network_TCP {
return i.service.NewConnection(ctx, connection, metadata)
return returnError(i.service.NewConnection(ctx, connection, metadata))
} else {
reader := buf.NewReader(connection)
pc := &natPacketConn{connection}
for {
mb, err := reader.ReadMultiBuffer()
if err != nil {
return err
buf.ReleaseMulti(mb)
return returnError(err)
}
for _, buffer := range mb {
err = i.service.NewPacket(ctx, pc, B.As(buffer.Bytes()), metadata)
err = i.service.NewPacket(ctx, pc, B.As(buffer.Bytes()).ToOwned(), metadata)
if err != nil {
buf.ReleaseMulti(mb)
return err
}
buffer.Release()
}
}
}
Expand Down Expand Up @@ -170,5 +174,8 @@ func (i *MultiUserInbound) NewPacketConnection(ctx context.Context, conn N.Packe
}

func (i *MultiUserInbound) HandleError(err error) {
if E.IsClosed(err) {
return
}
newError(err).AtWarning().WriteToLog()
}
19 changes: 16 additions & 3 deletions proxy/shadowsocks_2022/outbound.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ import (
C "github.com/sagernet/sing/common"
B "github.com/sagernet/sing/common/buf"
"github.com/sagernet/sing/common/bufio"
M "github.com/sagernet/sing/common/metadata"
N "github.com/sagernet/sing/common/network"
"github.com/sagernet/sing/common/uot"
"github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/buf"
"github.com/xtls/xray-core/common/net"
Expand All @@ -32,6 +34,7 @@ type Outbound struct {
ctx context.Context
server net.Destination
method shadowsocks.Method
uot bool
}

func NewClient(ctx context.Context, config *ClientConfig) (*Outbound, error) {
Expand All @@ -42,6 +45,7 @@ func NewClient(ctx context.Context, config *ClientConfig) (*Outbound, error) {
Port: net.Port(config.Port),
Network: net.Network_TCP,
},
uot: config.UdpOverTcp,
}
if C.Contains(shadowaead_2022.List, config.Method) {
if config.Key == "" {
Expand Down Expand Up @@ -75,7 +79,11 @@ func (o *Outbound) Process(ctx context.Context, link *transport.Link, dialer int
newError("tunneling request to ", destination, " via ", o.server.NetAddr()).WriteToLog(session.ExportIDToError(ctx))

serverDestination := o.server
serverDestination.Network = network
if o.uot {
serverDestination.Network = net.Network_TCP
} else {
serverDestination.Network = network
}
connection, err := dialer.Dial(ctx, serverDestination)
if err != nil {
return newError("failed to connect to server").Base(err)
Expand Down Expand Up @@ -143,7 +151,12 @@ func (o *Outbound) Process(ctx context.Context, link *transport.Link, dialer int
}
}

serverConn := o.method.DialPacketConn(connection)
return returnError(bufio.CopyPacketConn(ctx, packetConn, serverConn))
if o.uot {
serverConn := o.method.DialEarlyConn(connection, M.Socksaddr{Fqdn: uot.UOTMagicAddress})
return returnError(bufio.CopyPacketConn(ctx, packetConn, uot.NewClientConn(serverConn)))
} else {
serverConn := o.method.DialPacketConn(connection)
return returnError(bufio.CopyPacketConn(ctx, packetConn, serverConn))
}
}
}
4 changes: 2 additions & 2 deletions proxy/shadowsocks_2022/shadowsocks_2022.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
package shadowsocks_2022

import (
"errors"
"io"

B "github.com/sagernet/sing/common/buf"
E "github.com/sagernet/sing/common/exceptions"
M "github.com/sagernet/sing/common/metadata"
"github.com/xtls/xray-core/common/buf"
"github.com/xtls/xray-core/common/net"
Expand Down Expand Up @@ -140,7 +140,7 @@ func (w *packetConnWrapper) Close() error {
}

func returnError(err error) error {
if errors.Is(err, io.EOF) {
if E.IsClosed(err) {
return nil
}
return err
Expand Down
4 changes: 2 additions & 2 deletions testing/scenarios/shadowsocks_2022_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,10 @@ package scenarios
import (
"crypto/rand"
"encoding/base64"
"github.com/sagernet/sing-shadowsocks/shadowaead_2022"
"github.com/xtls/xray-core/proxy/shadowsocks_2022"
"testing"
"time"

"github.com/sagernet/sing-shadowsocks/shadowaead_2022"
"github.com/xtls/xray-core/app/log"
"github.com/xtls/xray-core/app/proxyman"
"github.com/xtls/xray-core/common"
Expand All @@ -17,6 +16,7 @@ import (
"github.com/xtls/xray-core/core"
"github.com/xtls/xray-core/proxy/dokodemo"
"github.com/xtls/xray-core/proxy/freedom"
"github.com/xtls/xray-core/proxy/shadowsocks_2022"
"github.com/xtls/xray-core/testing/servers/tcp"
"github.com/xtls/xray-core/testing/servers/udp"
"golang.org/x/sync/errgroup"
Expand Down

0 comments on commit c350563

Please sign in to comment.