feat: Add XUDP migration support

This commit is contained in:
H1JK 2023-06-07 23:03:36 +08:00
parent 093453582f
commit c3ef05b257
6 changed files with 55 additions and 25 deletions

View file

@ -14,6 +14,7 @@ import (
"github.com/Dreamacro/clash/common/convert" "github.com/Dreamacro/clash/common/convert"
N "github.com/Dreamacro/clash/common/net" N "github.com/Dreamacro/clash/common/net"
"github.com/Dreamacro/clash/common/utils"
"github.com/Dreamacro/clash/component/dialer" "github.com/Dreamacro/clash/component/dialer"
"github.com/Dreamacro/clash/component/proxydialer" "github.com/Dreamacro/clash/component/proxydialer"
"github.com/Dreamacro/clash/component/resolver" "github.com/Dreamacro/clash/component/resolver"
@ -374,7 +375,9 @@ func (v *Vless) ListenPacketOnStreamConn(ctx context.Context, c net.Conn, metada
if v.option.XUDP { if v.option.XUDP {
return newPacketConn(N.NewThreadSafePacketConn( return newPacketConn(N.NewThreadSafePacketConn(
vmessSing.NewXUDPConn(c, M.SocksaddrFromNet(metadata.UDPAddr())), vmessSing.NewXUDPConn(c,
utils.GlobalID(metadata.SourceAddress()),
M.SocksaddrFromNet(metadata.UDPAddr())),
), v), nil ), v), nil
} else if v.option.PacketAddr { } else if v.option.PacketAddr {
return newPacketConn(N.NewThreadSafePacketConn( return newPacketConn(N.NewThreadSafePacketConn(

View file

@ -12,6 +12,7 @@ import (
"sync" "sync"
N "github.com/Dreamacro/clash/common/net" N "github.com/Dreamacro/clash/common/net"
"github.com/Dreamacro/clash/common/utils"
"github.com/Dreamacro/clash/component/dialer" "github.com/Dreamacro/clash/component/dialer"
"github.com/Dreamacro/clash/component/proxydialer" "github.com/Dreamacro/clash/component/proxydialer"
"github.com/Dreamacro/clash/component/resolver" "github.com/Dreamacro/clash/component/resolver"
@ -224,29 +225,39 @@ func (v *Vmess) streamConn(c net.Conn, metadata *C.Metadata) (conn net.Conn, err
if metadata.NetWork == C.UDP { if metadata.NetWork == C.UDP {
if v.option.XUDP { if v.option.XUDP {
if N.NeedHandshake(c) { if N.NeedHandshake(c) {
conn = v.client.DialEarlyXUDPPacketConn(c, M.SocksaddrFromNet(metadata.UDPAddr())) conn = v.client.DialEarlyXUDPPacketConn(c,
utils.GlobalID(metadata.SourceAddress()),
M.SocksaddrFromNet(metadata.UDPAddr()))
} else { } else {
conn, err = v.client.DialXUDPPacketConn(c, M.SocksaddrFromNet(metadata.UDPAddr())) conn, err = v.client.DialXUDPPacketConn(c,
utils.GlobalID(metadata.SourceAddress()),
M.SocksaddrFromNet(metadata.UDPAddr()))
} }
} else if v.option.PacketAddr { } else if v.option.PacketAddr {
if N.NeedHandshake(c) { if N.NeedHandshake(c) {
conn = v.client.DialEarlyPacketConn(c, M.ParseSocksaddrHostPort(packetaddr.SeqPacketMagicAddress, 443)) conn = v.client.DialEarlyPacketConn(c,
M.ParseSocksaddrHostPort(packetaddr.SeqPacketMagicAddress, 443))
} else { } else {
conn, err = v.client.DialPacketConn(c, M.ParseSocksaddrHostPort(packetaddr.SeqPacketMagicAddress, 443)) conn, err = v.client.DialPacketConn(c,
M.ParseSocksaddrHostPort(packetaddr.SeqPacketMagicAddress, 443))
} }
conn = packetaddr.NewBindConn(conn) conn = packetaddr.NewBindConn(conn)
} else { } else {
if N.NeedHandshake(c) { if N.NeedHandshake(c) {
conn = v.client.DialEarlyPacketConn(c, M.SocksaddrFromNet(metadata.UDPAddr())) conn = v.client.DialEarlyPacketConn(c,
M.SocksaddrFromNet(metadata.UDPAddr()))
} else { } else {
conn, err = v.client.DialPacketConn(c, M.SocksaddrFromNet(metadata.UDPAddr())) conn, err = v.client.DialPacketConn(c,
M.SocksaddrFromNet(metadata.UDPAddr()))
} }
} }
} else { } else {
if N.NeedHandshake(c) { if N.NeedHandshake(c) {
conn = v.client.DialEarlyConn(c, M.ParseSocksaddr(metadata.RemoteAddress())) conn = v.client.DialEarlyConn(c,
M.ParseSocksaddr(metadata.RemoteAddress()))
} else { } else {
conn, err = v.client.DialConn(c, M.ParseSocksaddr(metadata.RemoteAddress())) conn, err = v.client.DialConn(c,
M.ParseSocksaddr(metadata.RemoteAddress()))
} }
} }
if err != nil { if err != nil {

13
common/utils/global_id.go Normal file
View file

@ -0,0 +1,13 @@
package utils
import (
"hash/maphash"
"unsafe"
)
var globalSeed = maphash.MakeSeed()
func GlobalID(material string) (id [8]byte) {
*(*uint64)(unsafe.Pointer(&id[0])) = maphash.String(globalSeed, material)
return
}

2
go.mod
View file

@ -108,4 +108,4 @@ require (
replace github.com/sagernet/sing => github.com/metacubex/sing v0.0.0-20230530121223-b768faae5c6b replace github.com/sagernet/sing => github.com/metacubex/sing v0.0.0-20230530121223-b768faae5c6b
replace github.com/sagernet/sing-vmess => github.com/metacubex/sing-vmess v0.1.5-0.20230520082358-78b126617899 replace github.com/sagernet/sing-vmess => github.com/metacubex/sing-vmess v0.1.5-0.20230607134851-17f84aec22a1

4
go.sum
View file

@ -103,8 +103,8 @@ github.com/metacubex/sing-shadowsocks2 v0.0.0-20230529235701-a238874242ca h1:10q
github.com/metacubex/sing-shadowsocks2 v0.0.0-20230529235701-a238874242ca/go.mod h1:jVDD4N22bDPPKA73NvB7aqdlLWiAwv8D+jx7HwhcWak= github.com/metacubex/sing-shadowsocks2 v0.0.0-20230529235701-a238874242ca/go.mod h1:jVDD4N22bDPPKA73NvB7aqdlLWiAwv8D+jx7HwhcWak=
github.com/metacubex/sing-tun v0.1.5-0.20230530125750-171afb2dfd8e h1:7QlJQl4S3F3YXn48fYxjymMw8HkXg9bl++hLi4ZRyCY= github.com/metacubex/sing-tun v0.1.5-0.20230530125750-171afb2dfd8e h1:7QlJQl4S3F3YXn48fYxjymMw8HkXg9bl++hLi4ZRyCY=
github.com/metacubex/sing-tun v0.1.5-0.20230530125750-171afb2dfd8e/go.mod h1:u9onX49LZPYuIPQ7SdM64Gnins8y5wg4Cn6ZYRSxWHU= github.com/metacubex/sing-tun v0.1.5-0.20230530125750-171afb2dfd8e/go.mod h1:u9onX49LZPYuIPQ7SdM64Gnins8y5wg4Cn6ZYRSxWHU=
github.com/metacubex/sing-vmess v0.1.5-0.20230520082358-78b126617899 h1:iRfcuztp7REfmOyasSlCL/pqNWfUDMTJ2CwbGpxpeks= github.com/metacubex/sing-vmess v0.1.5-0.20230607134851-17f84aec22a1 h1:ARhfmDKWzOsDEX5oUiC8bnz7FxQFukLV6fBiNM73r/M=
github.com/metacubex/sing-vmess v0.1.5-0.20230520082358-78b126617899/go.mod h1:RSt9rxGHllLdc5JUebkQwaqyWLx09Lqya37DlBe8CP8= github.com/metacubex/sing-vmess v0.1.5-0.20230607134851-17f84aec22a1/go.mod h1:RSt9rxGHllLdc5JUebkQwaqyWLx09Lqya37DlBe8CP8=
github.com/metacubex/sing-wireguard v0.0.0-20230426030325-41db09ae771a h1:cWKym33Qvl6HA3hj4/YuYD8hHyqQPb47wT5cJRAPgco= github.com/metacubex/sing-wireguard v0.0.0-20230426030325-41db09ae771a h1:cWKym33Qvl6HA3hj4/YuYD8hHyqQPb47wT5cJRAPgco=
github.com/metacubex/sing-wireguard v0.0.0-20230426030325-41db09ae771a/go.mod h1:Bsw2BvKMMMY0FhZPseDI50ZOalvoUPMKYyGpyqvIIqY= github.com/metacubex/sing-wireguard v0.0.0-20230426030325-41db09ae771a/go.mod h1:Bsw2BvKMMMY0FhZPseDI50ZOalvoUPMKYyGpyqvIIqY=
github.com/miekg/dns v1.1.54 h1:5jon9mWcb0sFJGpnI99tOMhCPyJ+RPVz5b63MQG0VWI= github.com/miekg/dns v1.1.54 h1:5jon9mWcb0sFJGpnI99tOMhCPyJ+RPVz5b63MQG0VWI=

View file

@ -203,9 +203,10 @@ func newConn(conn net.Conn, client *Client, dst *DstAddr) (net.Conn, error) {
needHandshake: true, needHandshake: true,
} }
if !dst.UDP && client.Addons != nil { if client.Addons != nil {
switch client.Addons.Flow { switch client.Addons.Flow {
case XRO, XRD, XRS: case XRO, XRD, XRS:
if !dst.UDP {
if xtlsConn, ok := conn.(*xtls.Conn); ok { if xtlsConn, ok := conn.(*xtls.Conn); ok {
xtlsConn.RPRX = true xtlsConn.RPRX = true
xtlsConn.SHOW = client.XTLSShow xtlsConn.SHOW = client.XTLSShow
@ -221,6 +222,8 @@ func newConn(conn net.Conn, client *Client, dst *DstAddr) (net.Conn, error) {
} else { } else {
return nil, fmt.Errorf("failed to use %s, maybe \"security\" is not \"xtls\"", client.Addons.Flow) return nil, fmt.Errorf("failed to use %s, maybe \"security\" is not \"xtls\"", client.Addons.Flow)
} }
}
case XRV: case XRV:
visionConn, err := vision.NewConn(c, c.id) visionConn, err := vision.NewConn(c, c.id)
if err != nil { if err != nil {