Feature: support vmess 'zero' security (#2513)

This commit is contained in:
bobo liu 2023-01-30 14:14:42 +08:00 committed by GitHub
parent 58732ee8b1
commit 81b1e9f931
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 110 additions and 9 deletions

View File

@ -0,0 +1,35 @@
{
"inbounds": [
{
"port": 10002,
"listen": "0.0.0.0",
"protocol": "vmess",
"settings": {
"clients": [
{
"id": "b831381d-6324-4d53-ad4f-8cda48b30811",
"alterId": 0,
"security": "zero"
}
]
},
"streamSettings": {
"network": "ws",
"security": "tls",
"tlsSettings": {
"certificates": [
{
"certificateFile": "/etc/ssl/v2ray/fullchain.pem",
"keyFile": "/etc/ssl/v2ray/privkey.pem"
}
]
}
}
}
],
"outbounds": [
{
"protocol": "freedom"
}
]
}

View File

@ -18,6 +18,8 @@ func TestClash_Vmess(t *testing.T) {
cfg := &container.Config{
Image: ImageVmess,
ExposedPorts: defaultExposedPorts,
Entrypoint: []string{"/usr/bin/v2ray"},
Cmd: []string{"run", "-c", "/etc/v2ray/config.json"},
}
hostCfg := &container.HostConfig{
PortBindings: defaultPortBindings,
@ -49,6 +51,8 @@ func TestClash_VmessTLS(t *testing.T) {
cfg := &container.Config{
Image: ImageVmess,
ExposedPorts: defaultExposedPorts,
Entrypoint: []string{"/usr/bin/v2ray"},
Cmd: []string{"run", "-c", "/etc/v2ray/config.json"},
}
hostCfg := &container.HostConfig{
PortBindings: defaultPortBindings,
@ -86,6 +90,8 @@ func TestClash_VmessHTTP2(t *testing.T) {
cfg := &container.Config{
Image: ImageVmess,
ExposedPorts: defaultExposedPorts,
Entrypoint: []string{"/usr/bin/v2ray"},
Cmd: []string{"run", "-c", "/etc/v2ray/config.json"},
}
hostCfg := &container.HostConfig{
PortBindings: defaultPortBindings,
@ -128,6 +134,8 @@ func TestClash_VmessHTTP(t *testing.T) {
cfg := &container.Config{
Image: ImageVmess,
ExposedPorts: defaultExposedPorts,
Entrypoint: []string{"/usr/bin/v2ray"},
Cmd: []string{"run", "-c", "/etc/v2ray/config.json"},
}
hostCfg := &container.HostConfig{
PortBindings: defaultPortBindings,
@ -178,6 +186,8 @@ func TestClash_VmessWebsocket(t *testing.T) {
cfg := &container.Config{
Image: ImageVmess,
ExposedPorts: defaultExposedPorts,
Entrypoint: []string{"/usr/bin/v2ray"},
Cmd: []string{"run", "-c", "/etc/v2ray/config.json"},
}
hostCfg := &container.HostConfig{
PortBindings: defaultPortBindings,
@ -211,6 +221,8 @@ func TestClash_VmessWebsocketTLS(t *testing.T) {
cfg := &container.Config{
Image: ImageVmess,
ExposedPorts: defaultExposedPorts,
Entrypoint: []string{"/usr/bin/v2ray"},
Cmd: []string{"run", "-c", "/etc/v2ray/config.json"},
}
hostCfg := &container.HostConfig{
PortBindings: defaultPortBindings,
@ -221,7 +233,7 @@ func TestClash_VmessWebsocketTLS(t *testing.T) {
},
}
id, err := startContainer(cfg, hostCfg, "vmess-ws")
id, err := startContainer(cfg, hostCfg, "vmess-ws-tls")
require.NoError(t, err)
t.Cleanup(func() {
cleanContainer(id)
@ -244,10 +256,51 @@ func TestClash_VmessWebsocketTLS(t *testing.T) {
testSuit(t, proxy)
}
func TestClash_VmessWebsocketTLSZero(t *testing.T) {
cfg := &container.Config{
Image: ImageVmess,
ExposedPorts: defaultExposedPorts,
Entrypoint: []string{"/usr/bin/v2ray"},
Cmd: []string{"run", "-c", "/etc/v2ray/config.json"},
}
hostCfg := &container.HostConfig{
PortBindings: defaultPortBindings,
Binds: []string{
fmt.Sprintf("%s:/etc/v2ray/config.json", C.Path.Resolve("vmess-ws-tls-zero.json")),
fmt.Sprintf("%s:/etc/ssl/v2ray/fullchain.pem", C.Path.Resolve("example.org.pem")),
fmt.Sprintf("%s:/etc/ssl/v2ray/privkey.pem", C.Path.Resolve("example.org-key.pem")),
},
}
id, err := startContainer(cfg, hostCfg, "vmess-ws-tls-zero")
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: "zero",
Network: "ws",
TLS: true,
SkipCertVerify: true,
UDP: true,
})
require.NoError(t, err)
time.Sleep(waitTime)
testSuit(t, proxy)
}
func TestClash_VmessGrpc(t *testing.T) {
cfg := &container.Config{
Image: ImageVmess,
ExposedPorts: defaultExposedPorts,
Entrypoint: []string{"/usr/bin/v2ray"},
Cmd: []string{"run", "-c", "/etc/v2ray/config.json"},
}
hostCfg := &container.HostConfig{
PortBindings: defaultPortBindings,
@ -289,6 +342,8 @@ func TestClash_VmessWebsocket0RTT(t *testing.T) {
cfg := &container.Config{
Image: ImageVmess,
ExposedPorts: defaultExposedPorts,
Entrypoint: []string{"/usr/bin/v2ray"},
Cmd: []string{"run", "-c", "/etc/v2ray/config.json"},
}
hostCfg := &container.HostConfig{
PortBindings: defaultPortBindings,
@ -366,6 +421,8 @@ func Benchmark_Vmess(b *testing.B) {
cfg := &container.Config{
Image: ImageVmess,
ExposedPorts: defaultExposedPorts,
Entrypoint: []string{"/usr/bin/v2ray"},
Cmd: []string{"run", "-c", "/etc/v2ray/config.json"},
}
hostCfg := &container.HostConfig{
PortBindings: defaultPortBindings,

View File

@ -35,6 +35,7 @@ type Conn struct {
respBodyKey []byte
respV byte
security byte
option byte
isAead bool
received bool
@ -74,7 +75,7 @@ func (vc *Conn) sendRequest() error {
buf.Write(vc.reqBodyIV[:])
buf.Write(vc.reqBodyKey[:])
buf.WriteByte(vc.respV)
buf.WriteByte(OptionChunkStream)
buf.WriteByte(vc.option)
p := rand.Intn(16)
// P Sec Reserve Cmd
@ -206,6 +207,7 @@ func newConn(conn net.Conn, id *ID, dst *DstAddr, security Security, isAead bool
copy(reqBodyIV[:], randBytes[:16])
copy(reqBodyKey[:], randBytes[16:32])
respV := randBytes[32]
option := OptionChunkStream
var (
respBodyKey []byte
@ -227,6 +229,16 @@ func newConn(conn net.Conn, id *ID, dst *DstAddr, security Security, isAead bool
var writer io.Writer
var reader io.Reader
switch security {
case SecurityZero:
security = SecurityNone
if !dst.UDP {
reader = conn
writer = conn
option = 0
} else {
reader = newChunkReader(conn)
writer = newChunkWriter(conn)
}
case SecurityNone:
reader = newChunkReader(conn)
writer = newChunkWriter(conn)
@ -267,6 +279,7 @@ func newConn(conn net.Conn, id *ID, dst *DstAddr, security Security, isAead bool
reader: reader,
writer: writer,
security: security,
option: option,
isAead: isAead,
}
if err := c.sendRequest(); err != nil {

View File

@ -26,15 +26,9 @@ const (
SecurityAES128GCM Security = 3
SecurityCHACHA20POLY1305 Security = 4
SecurityNone Security = 5
SecurityZero Security = 6
)
// CipherMapping return
var CipherMapping = map[string]byte{
"none": SecurityNone,
"aes-128-gcm": SecurityAES128GCM,
"chacha20-poly1305": SecurityCHACHA20POLY1305,
}
// Command types
const (
CommandTCP byte = 1
@ -95,6 +89,8 @@ func NewClient(config Config) (*Client, error) {
security = SecurityCHACHA20POLY1305
case "none":
security = SecurityNone
case "zero":
security = SecurityZero
case "auto":
security = SecurityCHACHA20POLY1305
if runtime.GOARCH == "amd64" || runtime.GOARCH == "s390x" || runtime.GOARCH == "arm64" {