Update UoT protocol
This commit is contained in:
parent
3001df622f
commit
4b6bbef697
4 changed files with 48 additions and 14 deletions
|
@ -50,6 +50,7 @@ type ShadowSocksOption struct {
|
||||||
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"`
|
UDPOverTCP bool `proxy:"udp-over-tcp,omitempty"`
|
||||||
|
UDPOverTCPVersion int `proxy:"udp-over-tcp-version,omitempty"`
|
||||||
ClientFingerprint string `proxy:"client-fingerprint,omitempty"`
|
ClientFingerprint string `proxy:"client-fingerprint,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -123,10 +124,16 @@ func (ss *ShadowSocks) StreamConnContext(ctx context.Context, c net.Conn, metada
|
||||||
}
|
}
|
||||||
useEarly = useEarly || N.NeedHandshake(c)
|
useEarly = useEarly || N.NeedHandshake(c)
|
||||||
if metadata.NetWork == C.UDP && ss.option.UDPOverTCP {
|
if metadata.NetWork == C.UDP && ss.option.UDPOverTCP {
|
||||||
if useEarly {
|
var uotDestination M.Socksaddr
|
||||||
return ss.method.DialEarlyConn(c, M.ParseSocksaddr(uot.UOTMagicAddress+":443")), nil
|
if ss.option.UDPOverTCPVersion == 1 {
|
||||||
|
uotDestination.Fqdn = uot.LegacyMagicAddress
|
||||||
} else {
|
} else {
|
||||||
return ss.method.DialConn(c, M.ParseSocksaddr(uot.UOTMagicAddress+":443"))
|
uotDestination.Fqdn = uot.MagicAddress
|
||||||
|
}
|
||||||
|
if useEarly {
|
||||||
|
return ss.method.DialEarlyConn(c, uotDestination), nil
|
||||||
|
} else {
|
||||||
|
return ss.method.DialConn(c, uotDestination)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if useEarly {
|
if useEarly {
|
||||||
|
@ -169,7 +176,12 @@ func (ss *ShadowSocks) ListenPacketWithDialer(ctx context.Context, dialer C.Dial
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return newPacketConn(uot.NewClientConn(tcpConn), ss), nil
|
destination := M.ParseSocksaddr(metadata.RemoteAddress())
|
||||||
|
if ss.option.UDPOverTCPVersion == 1 {
|
||||||
|
return newPacketConn(uot.NewConn(tcpConn, false, destination), ss), nil
|
||||||
|
} else {
|
||||||
|
return newPacketConn(uot.NewLazyConn(tcpConn, uot.Request{Destination: destination}), ss), nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
addr, err := resolveUDPAddrWithPrefer(ctx, "udp", ss.addr, ss.prefer)
|
addr, err := resolveUDPAddrWithPrefer(ctx, "udp", ss.addr, ss.prefer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -192,7 +204,12 @@ func (ss *ShadowSocks) SupportWithDialer() bool {
|
||||||
// ListenPacketOnStreamConn implements C.ProxyAdapter
|
// ListenPacketOnStreamConn implements C.ProxyAdapter
|
||||||
func (ss *ShadowSocks) ListenPacketOnStreamConn(c net.Conn, metadata *C.Metadata) (_ C.PacketConn, err error) {
|
func (ss *ShadowSocks) ListenPacketOnStreamConn(c net.Conn, metadata *C.Metadata) (_ C.PacketConn, err error) {
|
||||||
if ss.option.UDPOverTCP {
|
if ss.option.UDPOverTCP {
|
||||||
return newPacketConn(uot.NewClientConn(c), ss), nil
|
destination := M.ParseSocksaddr(metadata.RemoteAddress())
|
||||||
|
if ss.option.UDPOverTCPVersion == 1 {
|
||||||
|
return newPacketConn(uot.NewConn(c, false, destination), ss), nil
|
||||||
|
} else {
|
||||||
|
return newPacketConn(uot.NewLazyConn(c, uot.Request{Destination: destination}), ss), nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return nil, errors.New("no support")
|
return nil, errors.New("no support")
|
||||||
}
|
}
|
||||||
|
@ -279,6 +296,13 @@ func NewShadowSocks(option ShadowSocksOption) (*ShadowSocks, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
switch option.UDPOverTCPVersion {
|
||||||
|
case uot.Version, uot.LegacyVersion:
|
||||||
|
case 0:
|
||||||
|
option.UDPOverTCPVersion = uot.Version
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("ss %s unknown udp over tcp protocol version: %d", addr, option.UDPOverTCPVersion)
|
||||||
|
}
|
||||||
|
|
||||||
return &ShadowSocks{
|
return &ShadowSocks{
|
||||||
Base: &Base{
|
Base: &Base{
|
||||||
|
|
4
go.mod
4
go.mod
|
@ -26,7 +26,7 @@ require (
|
||||||
github.com/mroth/weightedrand/v2 v2.0.0
|
github.com/mroth/weightedrand/v2 v2.0.0
|
||||||
github.com/oschwald/geoip2-golang v1.8.0
|
github.com/oschwald/geoip2-golang v1.8.0
|
||||||
github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97
|
github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97
|
||||||
github.com/sagernet/sing v0.1.8
|
github.com/sagernet/sing v0.1.9-0.20230315063014-2731df16725b
|
||||||
github.com/sagernet/sing-shadowtls v0.1.0
|
github.com/sagernet/sing-shadowtls v0.1.0
|
||||||
github.com/sagernet/sing-vmess v0.1.3-0.20230307060529-d110e81a50bc
|
github.com/sagernet/sing-vmess v0.1.3-0.20230307060529-d110e81a50bc
|
||||||
github.com/sagernet/tfo-go v0.0.0-20230207095944-549363a7327d
|
github.com/sagernet/tfo-go v0.0.0-20230207095944-549363a7327d
|
||||||
|
@ -44,7 +44,7 @@ require (
|
||||||
golang.org/x/exp v0.0.0-20221205204356-47842c84f3db
|
golang.org/x/exp v0.0.0-20221205204356-47842c84f3db
|
||||||
golang.org/x/net v0.7.0
|
golang.org/x/net v0.7.0
|
||||||
golang.org/x/sync v0.1.0
|
golang.org/x/sync v0.1.0
|
||||||
golang.org/x/sys v0.5.0
|
golang.org/x/sys v0.6.0
|
||||||
google.golang.org/protobuf v1.28.2-0.20230118093459-a9481185b34d
|
google.golang.org/protobuf v1.28.2-0.20230118093459-a9481185b34d
|
||||||
gopkg.in/yaml.v3 v3.0.1
|
gopkg.in/yaml.v3 v3.0.1
|
||||||
lukechampine.com/blake3 v1.1.7
|
lukechampine.com/blake3 v1.1.7
|
||||||
|
|
10
go.sum
10
go.sum
|
@ -127,8 +127,10 @@ github.com/sagernet/go-tun2socks v1.16.12-0.20220818015926-16cb67876a61/go.mod h
|
||||||
github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97 h1:iL5gZI3uFp0X6EslacyapiRz7LLSJyr4RajF/BhMVyE=
|
github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97 h1:iL5gZI3uFp0X6EslacyapiRz7LLSJyr4RajF/BhMVyE=
|
||||||
github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97/go.mod h1:xLnfdiJbSp8rNqYEdIW/6eDO4mVoogml14Bh2hSiFpM=
|
github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97/go.mod h1:xLnfdiJbSp8rNqYEdIW/6eDO4mVoogml14Bh2hSiFpM=
|
||||||
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.1.8 h1:6DKo2FkSHn0nUcjO7bAext/ai7y7pCusK/+fScBJ5Jk=
|
github.com/sagernet/sing v0.1.9-0.20230315055814-2f422b53b06f h1:bCx4+svKuZyw8CxxFXmrmhAERFf5BAAiNb1aYXj4hwk=
|
||||||
github.com/sagernet/sing v0.1.8/go.mod h1:jt1w2u7lJQFFSGLiRrRIs5YWmx4kAPfWuOejuDW9qMk=
|
github.com/sagernet/sing v0.1.9-0.20230315055814-2f422b53b06f/go.mod h1:9uHswk2hITw8leDbiLS/xn0t9nzBcbePxzm9PJhwdlw=
|
||||||
|
github.com/sagernet/sing v0.1.9-0.20230315063014-2731df16725b h1:1iKGftQ59+shDSx2RaLaxXJcMK/B+IU9WqUPwyBW+E0=
|
||||||
|
github.com/sagernet/sing v0.1.9-0.20230315063014-2731df16725b/go.mod h1:9uHswk2hITw8leDbiLS/xn0t9nzBcbePxzm9PJhwdlw=
|
||||||
github.com/sagernet/sing-shadowtls v0.1.0 h1:05MYce8aR5xfKIn+y7xRFsdKhKt44QZTSEQW+lG5IWQ=
|
github.com/sagernet/sing-shadowtls v0.1.0 h1:05MYce8aR5xfKIn+y7xRFsdKhKt44QZTSEQW+lG5IWQ=
|
||||||
github.com/sagernet/sing-shadowtls v0.1.0/go.mod h1:Kn1VUIprdkwCgkS6SXYaLmIpKzQbqBIKJBMY+RvBhYc=
|
github.com/sagernet/sing-shadowtls v0.1.0/go.mod h1:Kn1VUIprdkwCgkS6SXYaLmIpKzQbqBIKJBMY+RvBhYc=
|
||||||
github.com/sagernet/sing-vmess v0.1.3-0.20230307060529-d110e81a50bc h1:vqlYWupvVDRpvv2F+RtECJN+VbuKjLtmQculQvOecls=
|
github.com/sagernet/sing-vmess v0.1.3-0.20230307060529-d110e81a50bc h1:vqlYWupvVDRpvv2F+RtECJN+VbuKjLtmQculQvOecls=
|
||||||
|
@ -222,8 +224,8 @@ golang.org/x/sys v0.0.0-20220622161953-175b2fd9d664/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/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/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU=
|
golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ=
|
||||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.6.0/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/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
|
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"golang.org/x/exp/slices"
|
"golang.org/x/exp/slices"
|
||||||
"net"
|
"net"
|
||||||
|
"net/netip"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -61,9 +62,16 @@ func (h *ListenerHandler) NewConnection(ctx context.Context, conn net.Conn, meta
|
||||||
switch metadata.Destination.Fqdn {
|
switch metadata.Destination.Fqdn {
|
||||||
case vmess.MuxDestination.Fqdn:
|
case vmess.MuxDestination.Fqdn:
|
||||||
return vmess.HandleMuxConnection(ctx, conn, h)
|
return vmess.HandleMuxConnection(ctx, conn, h)
|
||||||
case uot.UOTMagicAddress:
|
case uot.MagicAddress:
|
||||||
metadata.Destination = M.Socksaddr{}
|
request, err := uot.ReadRequest(conn)
|
||||||
return h.NewPacketConnection(ctx, uot.NewClientConn(conn), metadata)
|
if err != nil {
|
||||||
|
return E.Cause(err, "read UoT request")
|
||||||
|
}
|
||||||
|
metadata.Destination = request.Destination
|
||||||
|
return h.NewPacketConnection(ctx, uot.NewConn(conn, request.IsConnect, metadata.Destination), metadata)
|
||||||
|
case uot.LegacyMagicAddress:
|
||||||
|
metadata.Destination = M.Socksaddr{Addr: netip.IPv4Unspecified()}
|
||||||
|
return h.NewPacketConnection(ctx, uot.NewConn(conn, false, metadata.Destination), metadata)
|
||||||
}
|
}
|
||||||
target := socks5.ParseAddr(metadata.Destination.String())
|
target := socks5.ParseAddr(metadata.Destination.String())
|
||||||
wg := &sync.WaitGroup{}
|
wg := &sync.WaitGroup{}
|
||||||
|
|
Loading…
Reference in a new issue