Refactor: vmess
Add support for vmess length masking/packetaddr/authenticated length Add support for zero/aes-128-cfb protcol
This commit is contained in:
parent
c968104a19
commit
d8dc44e786
7 changed files with 152 additions and 86 deletions
|
@ -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 {
|
||||||
|
@ -46,6 +49,8 @@ type VmessOption struct {
|
||||||
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
3
go.mod
|
@ -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
6
go.sum
|
@ -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=
|
||||||
|
|
|
@ -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{}
|
||||||
|
go func() {
|
||||||
for i := 0; i < times; i++ {
|
for i := 0; i < times; i++ {
|
||||||
go func(idx int) {
|
|
||||||
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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
10
test/go.sum
10
test/go.sum
|
@ -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=
|
||||||
|
|
|
@ -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,
|
||||||
|
|
Loading…
Reference in a new issue