Refactor: vmess

Add support for vmess length masking/packetaddr/authenticated length

Add support for zero/aes-128-cfb protcol
This commit is contained in:
世界 2022-06-14 13:21:22 +08:00
parent c968104a19
commit d8dc44e786
No known key found for this signature in database
GPG Key ID: CD109927C34A63C4
7 changed files with 152 additions and 86 deletions

View File

@ -5,17 +5,20 @@ import (
"crypto/tls" "crypto/tls"
"errors" "errors"
"fmt" "fmt"
"github.com/Dreamacro/clash/common/convert"
"net" "net"
"net/http" "net/http"
"strconv" "strconv"
"strings" "strings"
"github.com/Dreamacro/clash/common/convert"
"github.com/Dreamacro/clash/component/dialer" "github.com/Dreamacro/clash/component/dialer"
"github.com/Dreamacro/clash/component/resolver" "github.com/Dreamacro/clash/component/resolver"
C "github.com/Dreamacro/clash/constant" C "github.com/Dreamacro/clash/constant"
"github.com/Dreamacro/clash/transport/gun" "github.com/Dreamacro/clash/transport/gun"
"github.com/Dreamacro/clash/transport/vmess" clashVMess "github.com/Dreamacro/clash/transport/vmess"
"github.com/sagernet/sing-vmess"
"github.com/sagernet/sing-vmess/packetaddr"
M "github.com/sagernet/sing/common/metadata"
) )
type Vmess struct { type Vmess struct {
@ -31,21 +34,23 @@ type Vmess struct {
type VmessOption struct { type VmessOption struct {
BasicOption BasicOption
Name string `proxy:"name"` Name string `proxy:"name"`
Server string `proxy:"server"` Server string `proxy:"server"`
Port int `proxy:"port"` Port int `proxy:"port"`
UUID string `proxy:"uuid"` UUID string `proxy:"uuid"`
AlterID int `proxy:"alterId"` AlterID int `proxy:"alterId"`
Cipher string `proxy:"cipher"` Cipher string `proxy:"cipher"`
UDP bool `proxy:"udp,omitempty"` UDP bool `proxy:"udp,omitempty"`
Network string `proxy:"network,omitempty"` Network string `proxy:"network,omitempty"`
TLS bool `proxy:"tls,omitempty"` TLS bool `proxy:"tls,omitempty"`
SkipCertVerify bool `proxy:"skip-cert-verify,omitempty"` SkipCertVerify bool `proxy:"skip-cert-verify,omitempty"`
ServerName string `proxy:"servername,omitempty"` ServerName string `proxy:"servername,omitempty"`
HTTPOpts HTTPOptions `proxy:"http-opts,omitempty"` HTTPOpts HTTPOptions `proxy:"http-opts,omitempty"`
HTTP2Opts HTTP2Options `proxy:"h2-opts,omitempty"` HTTP2Opts HTTP2Options `proxy:"h2-opts,omitempty"`
GrpcOpts GrpcOptions `proxy:"grpc-opts,omitempty"` GrpcOpts GrpcOptions `proxy:"grpc-opts,omitempty"`
WSOpts WSOptions `proxy:"ws-opts,omitempty"` WSOpts WSOptions `proxy:"ws-opts,omitempty"`
PacketAddr bool `proxy:"packet-addr,omitempty"`
AuthenticatedLength bool `proxy:"authenticated-length,omitempty"`
// TODO: compatible with VMESS WS older version configurations // TODO: compatible with VMESS WS older version configurations
WSHeaders map[string]string `proxy:"ws-headers,omitempty"` WSHeaders map[string]string `proxy:"ws-headers,omitempty"`
@ -81,7 +86,7 @@ func (v *Vmess) StreamConn(c net.Conn, metadata *C.Metadata) (net.Conn, error) {
case "ws": case "ws":
host, port, _ := net.SplitHostPort(v.addr) host, port, _ := net.SplitHostPort(v.addr)
wsOpts := &vmess.WebsocketConfig{ wsOpts := &clashVMess.WebsocketConfig{
Host: host, Host: host,
Port: port, Port: port,
Path: v.option.WSOpts.Path, Path: v.option.WSOpts.Path,
@ -114,12 +119,12 @@ func (v *Vmess) StreamConn(c net.Conn, metadata *C.Metadata) (net.Conn, error) {
convert.SetUserAgent(wsOpts.Headers) convert.SetUserAgent(wsOpts.Headers)
} }
} }
c, err = vmess.StreamWebsocketConn(c, wsOpts) c, err = clashVMess.StreamWebsocketConn(c, wsOpts)
case "http": case "http":
// readability first, so just copy default TLS logic // readability first, so just copy default TLS logic
if v.option.TLS { if v.option.TLS {
host, _, _ := net.SplitHostPort(v.addr) host, _, _ := net.SplitHostPort(v.addr)
tlsOpts := &vmess.TLSConfig{ tlsOpts := &clashVMess.TLSConfig{
Host: host, Host: host,
SkipCertVerify: v.option.SkipCertVerify, SkipCertVerify: v.option.SkipCertVerify,
} }
@ -128,24 +133,24 @@ func (v *Vmess) StreamConn(c net.Conn, metadata *C.Metadata) (net.Conn, error) {
tlsOpts.Host = v.option.ServerName tlsOpts.Host = v.option.ServerName
} }
c, err = vmess.StreamTLSConn(c, tlsOpts) c, err = clashVMess.StreamTLSConn(c, tlsOpts)
if err != nil { if err != nil {
return nil, err return nil, err
} }
} }
host, _, _ := net.SplitHostPort(v.addr) host, _, _ := net.SplitHostPort(v.addr)
httpOpts := &vmess.HTTPConfig{ httpOpts := &clashVMess.HTTPConfig{
Host: host, Host: host,
Method: v.option.HTTPOpts.Method, Method: v.option.HTTPOpts.Method,
Path: v.option.HTTPOpts.Path, Path: v.option.HTTPOpts.Path,
Headers: v.option.HTTPOpts.Headers, Headers: v.option.HTTPOpts.Headers,
} }
c = vmess.StreamHTTPConn(c, httpOpts) c = clashVMess.StreamHTTPConn(c, httpOpts)
case "h2": case "h2":
host, _, _ := net.SplitHostPort(v.addr) host, _, _ := net.SplitHostPort(v.addr)
tlsOpts := vmess.TLSConfig{ tlsOpts := clashVMess.TLSConfig{
Host: host, Host: host,
SkipCertVerify: v.option.SkipCertVerify, SkipCertVerify: v.option.SkipCertVerify,
NextProtos: []string{"h2"}, NextProtos: []string{"h2"},
@ -155,24 +160,24 @@ func (v *Vmess) StreamConn(c net.Conn, metadata *C.Metadata) (net.Conn, error) {
tlsOpts.Host = v.option.ServerName tlsOpts.Host = v.option.ServerName
} }
c, err = vmess.StreamTLSConn(c, &tlsOpts) c, err = clashVMess.StreamTLSConn(c, &tlsOpts)
if err != nil { if err != nil {
return nil, err return nil, err
} }
h2Opts := &vmess.H2Config{ h2Opts := &clashVMess.H2Config{
Hosts: v.option.HTTP2Opts.Host, Hosts: v.option.HTTP2Opts.Host,
Path: v.option.HTTP2Opts.Path, Path: v.option.HTTP2Opts.Path,
} }
c, err = vmess.StreamH2Conn(c, h2Opts) c, err = clashVMess.StreamH2Conn(c, h2Opts)
case "grpc": case "grpc":
c, err = gun.StreamGunWithConn(c, v.gunTLSConfig, v.gunConfig) c, err = gun.StreamGunWithConn(c, v.gunTLSConfig, v.gunConfig)
default: default:
// handle TLS // handle TLS
if v.option.TLS { if v.option.TLS {
host, _, _ := net.SplitHostPort(v.addr) host, _, _ := net.SplitHostPort(v.addr)
tlsOpts := &vmess.TLSConfig{ tlsOpts := &clashVMess.TLSConfig{
Host: host, Host: host,
SkipCertVerify: v.option.SkipCertVerify, SkipCertVerify: v.option.SkipCertVerify,
} }
@ -181,15 +186,18 @@ func (v *Vmess) StreamConn(c net.Conn, metadata *C.Metadata) (net.Conn, error) {
tlsOpts.Host = v.option.ServerName tlsOpts.Host = v.option.ServerName
} }
c, err = vmess.StreamTLSConn(c, tlsOpts) c, err = clashVMess.StreamTLSConn(c, tlsOpts)
} }
} }
if err != nil { if err != nil {
return nil, err return nil, err
} }
if metadata.NetWork == C.UDP {
return v.client.StreamConn(c, parseVmessAddr(metadata)) return v.client.DialPacketConn(c, M.ParseSocksaddr(metadata.RemoteAddress()))
} else {
return v.client.DialConn(c, M.ParseSocksaddr(metadata.RemoteAddress()))
}
} }
// DialContext implements C.ProxyAdapter // DialContext implements C.ProxyAdapter
@ -202,7 +210,7 @@ func (v *Vmess) DialContext(ctx context.Context, metadata *C.Metadata, opts ...d
} }
defer safeConnClose(c, err) defer safeConnClose(c, err)
c, err = v.client.StreamConn(c, parseVmessAddr(metadata)) c, err = v.client.DialConn(c, M.ParseSocksaddr(metadata.RemoteAddress()))
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -232,6 +240,11 @@ func (v *Vmess) ListenPacketContext(ctx context.Context, metadata *C.Metadata, o
metadata.DstIP = ip metadata.DstIP = ip
} }
if v.option.PacketAddr {
metadata.Host = packetaddr.SeqPacketMagicAddress
metadata.DstPort = "443"
}
var c net.Conn var c net.Conn
// gun transport // gun transport
if v.transport != nil && len(opts) == 0 { if v.transport != nil && len(opts) == 0 {
@ -241,7 +254,7 @@ func (v *Vmess) ListenPacketContext(ctx context.Context, metadata *C.Metadata, o
} }
defer safeConnClose(c, err) defer safeConnClose(c, err)
c, err = v.client.StreamConn(c, parseVmessAddr(metadata)) c, err = v.client.DialPacketConn(c, M.ParseSocksaddr(metadata.RemoteAddress()))
} else { } else {
c, err = dialer.DialContext(ctx, "tcp", v.addr, v.Base.DialOptions(opts...)...) c, err = dialer.DialContext(ctx, "tcp", v.addr, v.Base.DialOptions(opts...)...)
if err != nil { if err != nil {
@ -257,11 +270,21 @@ func (v *Vmess) ListenPacketContext(ctx context.Context, metadata *C.Metadata, o
return nil, fmt.Errorf("new vmess client error: %v", err) return nil, fmt.Errorf("new vmess client error: %v", err)
} }
return v.ListenPacketOnStreamConn(c, metadata) if v.option.PacketAddr {
return newPacketConn(packetaddr.NewBindClient(c), v), nil
} else if pc, ok := c.(net.PacketConn); ok {
return newPacketConn(pc, v), nil
}
return newPacketConn(&vmessPacketConn{Conn: c, rAddr: metadata.UDPAddr()}, v), nil
} }
// ListenPacketOnStreamConn implements C.ProxyAdapter // ListenPacketOnStreamConn implements C.ProxyAdapter
func (v *Vmess) ListenPacketOnStreamConn(c net.Conn, metadata *C.Metadata) (_ C.PacketConn, err error) { func (v *Vmess) ListenPacketOnStreamConn(c net.Conn, metadata *C.Metadata) (_ C.PacketConn, err error) {
if v.option.PacketAddr {
return newPacketConn(packetaddr.NewBindClient(c), v), nil
} else if pc, ok := c.(net.PacketConn); ok {
return newPacketConn(pc, v), nil
}
return newPacketConn(&vmessPacketConn{Conn: c, rAddr: metadata.UDPAddr()}, v), nil return newPacketConn(&vmessPacketConn{Conn: c, rAddr: metadata.UDPAddr()}, v), nil
} }
@ -272,14 +295,11 @@ func (v *Vmess) SupportUOT() bool {
func NewVmess(option VmessOption) (*Vmess, error) { func NewVmess(option VmessOption) (*Vmess, error) {
security := strings.ToLower(option.Cipher) security := strings.ToLower(option.Cipher)
client, err := vmess.NewClient(vmess.Config{ var options []vmess.ClientOption
UUID: option.UUID, if option.AuthenticatedLength {
AlterID: uint16(option.AlterID), options = append(options, vmess.ClientWithAuthenticatedLength())
Security: security, }
HostName: option.Server, client, err := vmess.NewClient(option.UUID, security, option.AlterID, options...)
Port: strconv.Itoa(option.Port),
IsAead: option.AlterID == 0,
})
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -338,38 +358,9 @@ func NewVmess(option VmessOption) (*Vmess, error) {
v.gunConfig = gunConfig v.gunConfig = gunConfig
v.transport = gun.NewHTTP2Client(dialFn, tlsConfig) v.transport = gun.NewHTTP2Client(dialFn, tlsConfig)
} }
return v, nil return v, nil
} }
func parseVmessAddr(metadata *C.Metadata) *vmess.DstAddr {
var addrType byte
var addr []byte
switch metadata.AddrType {
case C.AtypIPv4:
addrType = byte(vmess.AtypIPv4)
addr = make([]byte, net.IPv4len)
copy(addr[:], metadata.DstIP.AsSlice())
case C.AtypIPv6:
addrType = byte(vmess.AtypIPv6)
addr = make([]byte, net.IPv6len)
copy(addr[:], metadata.DstIP.AsSlice())
case C.AtypDomainName:
addrType = byte(vmess.AtypDomainName)
addr = make([]byte, len(metadata.Host)+1)
addr[0] = byte(len(metadata.Host))
copy(addr[1:], []byte(metadata.Host))
}
port, _ := strconv.ParseUint(metadata.DstPort, 10, 16)
return &vmess.DstAddr{
UDP: metadata.NetWork == C.UDP,
AddrType: addrType,
Addr: addr,
Port: uint(port),
}
}
type vmessPacketConn struct { type vmessPacketConn struct {
net.Conn net.Conn
rAddr net.Addr rAddr net.Addr

3
go.mod
View File

@ -13,8 +13,9 @@ require (
github.com/lucas-clemente/quic-go v0.27.2 github.com/lucas-clemente/quic-go v0.27.2
github.com/miekg/dns v1.1.49 github.com/miekg/dns v1.1.49
github.com/oschwald/geoip2-golang v1.7.0 github.com/oschwald/geoip2-golang v1.7.0
github.com/sagernet/sing v0.0.0-20220610074707-a30d5506be41 github.com/sagernet/sing v0.0.0-20220614034114-7caa1d0c0851
github.com/sagernet/sing-shadowsocks v0.0.0-20220610074818-432dcbdb1d7c github.com/sagernet/sing-shadowsocks v0.0.0-20220610074818-432dcbdb1d7c
github.com/sagernet/sing-vmess v0.0.0-20220614042419-6f7c1431421a
github.com/sirupsen/logrus v1.8.1 github.com/sirupsen/logrus v1.8.1
github.com/stretchr/testify v1.7.2 github.com/stretchr/testify v1.7.2
github.com/tobyxdd/hysteria v1.0.4 github.com/tobyxdd/hysteria v1.0.4

6
go.sum
View File

@ -305,10 +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/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/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/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/sagernet/sing v0.0.0-20220610074707-a30d5506be41 h1:vquZangXPhZJJz5PMCn/6qOYk+c4dtk/fb7HpDlof2I= github.com/sagernet/sing v0.0.0-20220614034114-7caa1d0c0851 h1:Pp+9IPHtlwxrkiKMSrTOPS/eg+qJLdfZoeM89QX40BI=
github.com/sagernet/sing v0.0.0-20220610074707-a30d5506be41/go.mod h1:ZEo7wZBfJmzm8uwnbCtWEHw9GsIfSThSylZYcR+H/Zw= 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 h1:dapkcUcFbOwqnBwut6Dct7L695PVS6GoEqJeSRMWe0k=
github.com/sagernet/sing-shadowsocks v0.0.0-20220610074818-432dcbdb1d7c/go.mod h1:ty1OoG/SgB6IccsWUS5DZBkEGKUKM8nRSWxLlqYUPx0= 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/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= 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/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= github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48/go.mod h1:5u70Mqkb5O5cxEA8nxTsgrgLehJeAw6Oc4Ab1c/P1HM=

View File

@ -31,6 +31,7 @@ const (
ImageShadowsocks = "mritd/shadowsocks:latest" ImageShadowsocks = "mritd/shadowsocks:latest"
ImageShadowsocksRust = "ghcr.io/shadowsocks/ssserver-rust:latest" ImageShadowsocksRust = "ghcr.io/shadowsocks/ssserver-rust:latest"
ImageVmess = "v2fly/v2fly-core:latest" ImageVmess = "v2fly/v2fly-core:latest"
ImageVmessLatest = "sagernet/v2fly-core:latest"
ImageVless = "teddysun/xray:latest" ImageVless = "teddysun/xray:latest"
ImageTrojan = "trojangfw/trojan:latest" ImageTrojan = "trojangfw/trojan:latest"
ImageTrojanGo = "p4gefau1t/trojan-go:latest" ImageTrojanGo = "p4gefau1t/trojan-go:latest"
@ -450,26 +451,26 @@ func testLargeDataWithPacketConn(t *testing.T, pc net.PacketConn) error {
writeRandData := func(pc net.PacketConn, addr net.Addr) (map[int][]byte, error) { writeRandData := func(pc net.PacketConn, addr net.Addr) (map[int][]byte, error) {
hashMap := map[int][]byte{} hashMap := map[int][]byte{}
mux := sync.Mutex{} mux := sync.Mutex{}
for i := 0; i < times; i++ { go func() {
go func(idx int) { for i := 0; i < times; i++ {
buf := make([]byte, chunkSize) buf := make([]byte, chunkSize)
if _, err := rand.Read(buf[1:]); err != nil { if _, err := rand.Read(buf[1:]); err != nil {
t.Log(err.Error()) t.Log(err.Error())
return return
} }
buf[0] = byte(idx) buf[0] = byte(i)
hash := md5.Sum(buf) hash := md5.Sum(buf)
mux.Lock() mux.Lock()
hashMap[idx] = hash[:] hashMap[i] = hash[:]
mux.Unlock() mux.Unlock()
if _, err := pc.WriteTo(buf, addr); err != nil { if _, err := pc.WriteTo(buf, addr); err != nil {
t.Log(err.Error()) t.Log(err.Error())
return return
} }
}(i) }
} }()
return hashMap, nil return hashMap, nil
} }

View File

@ -61,8 +61,9 @@ require (
github.com/prometheus/client_model v0.2.0 // indirect github.com/prometheus/client_model v0.2.0 // indirect
github.com/prometheus/common v0.32.1 // indirect github.com/prometheus/common v0.32.1 // indirect
github.com/prometheus/procfs v0.7.3 // indirect github.com/prometheus/procfs v0.7.3 // indirect
github.com/sagernet/sing v0.0.0-20220609091055-86d0144940e7 // indirect github.com/sagernet/sing v0.0.0-20220614034114-7caa1d0c0851 // indirect
github.com/sagernet/sing-shadowsocks v0.0.0-20220609092835-699292971c13 // 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/sirupsen/logrus v1.8.1 // indirect github.com/sirupsen/logrus v1.8.1 // indirect
github.com/tobyxdd/hysteria v1.0.4 // indirect github.com/tobyxdd/hysteria v1.0.4 // indirect
github.com/txthinking/runnergroup v0.0.0-20210608031112-152c7c4432bf // indirect github.com/txthinking/runnergroup v0.0.0-20210608031112-152c7c4432bf // indirect

View File

@ -323,10 +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/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/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/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/sagernet/sing v0.0.0-20220609091055-86d0144940e7 h1:Q+uNKLNSKqpx+p96qcBTVFh8RUKiQFr4IrNVi5Q5yl0= github.com/sagernet/sing v0.0.0-20220614034114-7caa1d0c0851 h1:Pp+9IPHtlwxrkiKMSrTOPS/eg+qJLdfZoeM89QX40BI=
github.com/sagernet/sing v0.0.0-20220609091055-86d0144940e7/go.mod h1:w2HnJzXKHpD6F5Z/9XlSD4qbcpHY2RSZuQnFzqgELMg= github.com/sagernet/sing v0.0.0-20220614034114-7caa1d0c0851/go.mod h1:ZEo7wZBfJmzm8uwnbCtWEHw9GsIfSThSylZYcR+H/Zw=
github.com/sagernet/sing-shadowsocks v0.0.0-20220609092835-699292971c13 h1:bQN0hjTHdB7SyaD9yjEYAl+bDl/kXW9zC0xNa+LMTrA= github.com/sagernet/sing-shadowsocks v0.0.0-20220610074818-432dcbdb1d7c h1:dapkcUcFbOwqnBwut6Dct7L695PVS6GoEqJeSRMWe0k=
github.com/sagernet/sing-shadowsocks v0.0.0-20220609092835-699292971c13/go.mod h1:Fp/9+odJhtgDmiHbZClMLnxaVvmDRJxwA7u/+uXWDiQ= 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/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= 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/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= github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48/go.mod h1:5u70Mqkb5O5cxEA8nxTsgrgLehJeAw6Oc4Ab1c/P1HM=

View File

@ -44,6 +44,74 @@ func TestClash_Vmess(t *testing.T) {
testSuit(t, proxy) testSuit(t, proxy)
} }
func TestClash_VmessAuthenticatedLength(t *testing.T) {
configPath := C.Path.Resolve("vmess.json")
cfg := &container.Config{
Image: ImageVmess,
ExposedPorts: defaultExposedPorts,
}
hostCfg := &container.HostConfig{
PortBindings: defaultPortBindings,
Binds: []string{fmt.Sprintf("%s:/etc/v2ray/config.json", configPath)},
}
id, err := startContainer(cfg, hostCfg, "vmess")
require.NoError(t, err)
t.Cleanup(func() {
cleanContainer(id)
})
proxy, err := outbound.NewVmess(outbound.VmessOption{
Name: "vmess",
Server: localIP.String(),
Port: 10002,
UUID: "b831381d-6324-4d53-ad4f-8cda48b30811",
Cipher: "auto",
UDP: true,
AuthenticatedLength: true,
})
require.NoError(t, err)
time.Sleep(waitTime)
testSuit(t, proxy)
}
func TestClash_VmessPacketAddr(t *testing.T) {
configPath := C.Path.Resolve("vmess.json")
cfg := &container.Config{
Image: ImageVmessLatest,
ExposedPorts: defaultExposedPorts,
}
hostCfg := &container.HostConfig{
PortBindings: defaultPortBindings,
Binds: []string{fmt.Sprintf("%s:/etc/v2ray/config.json", configPath)},
}
id, err := startContainer(cfg, hostCfg, "vmess")
require.NoError(t, err)
t.Cleanup(func() {
cleanContainer(id)
})
proxy, err := outbound.NewVmess(outbound.VmessOption{
Name: "vmess",
Server: localIP.String(),
Port: 10002,
UUID: "b831381d-6324-4d53-ad4f-8cda48b30811",
Cipher: "auto",
UDP: true,
PacketAddr: true,
})
require.NoError(t, err)
time.Sleep(waitTime)
testSuit(t, proxy)
}
func TestClash_VmessTLS(t *testing.T) { func TestClash_VmessTLS(t *testing.T) {
cfg := &container.Config{ cfg := &container.Config{
Image: ImageVmess, Image: ImageVmess,