diff --git a/docs/config.yaml b/docs/config.yaml index 245b38e8..e4c5e753 100644 --- a/docs/config.yaml +++ b/docs/config.yaml @@ -639,7 +639,7 @@ proxies: # socks5 uuid: uuid network: tcp encryption: "8min-vless-mlkem768client-bas64RawURLEncoding" # 复用八分钟后协商新的 sharedKey,需小于服务端的值 - # encryption: "8min-aes128xor-mlkem768client-bas64RawURLEncoding" + # encryption: "8min-xored-mlkem768client-bas64RawURLEncoding" tls: false #可以不开启tls udp: true @@ -1348,7 +1348,7 @@ listeners: # ws-path: "/" # 如果不为空则开启 websocket 传输层 # grpc-service-name: "GunService" # 如果不为空则开启 grpc 传输层 # decryption: "10min-vless-mlkem768seed-bas64RawURLEncoding" # 同时允许 1-RTT 模式与十分钟复用的 0-RTT 模式, 后面base64字符串可由可由 mihomo generate vless-mlkem768 命令生成 - # decryption: "10min-aes128xor-mlkem768seed-bas64RawURLEncoding" + # decryption: "10min-xored-mlkem768seed-bas64RawURLEncoding" # 下面两项如果填写则开启 tls(需要同时填写) # certificate: ./server.crt # private-key: ./server.key diff --git a/listener/inbound/vless_test.go b/listener/inbound/vless_test.go index 2ef12126..e344aa2e 100644 --- a/listener/inbound/vless_test.go +++ b/listener/inbound/vless_test.go @@ -103,12 +103,12 @@ func TestInboundVless_Encryption(t *testing.T) { } testInboundVless(t, inboundOptions, outboundOptions) }) - t.Run("-aes128xor-", func(t *testing.T) { + t.Run("-xored-", func(t *testing.T) { inboundOptions := inbound.VlessOption{ - Decryption: "10min-aes128xor-mlkem768seed-" + seedBase64, + Decryption: "10min-xored-mlkem768seed-" + seedBase64, } outboundOptions := outbound.VlessOption{ - Encryption: "8min-aes128xor-mlkem768client-" + clientBase64, + Encryption: "8min-xored-mlkem768client-" + clientBase64, } testInboundVless(t, inboundOptions, outboundOptions) }) diff --git a/transport/vless/encryption/doc.go b/transport/vless/encryption/doc.go index deb410ee..6c73732b 100644 --- a/transport/vless/encryption/doc.go +++ b/transport/vless/encryption/doc.go @@ -6,4 +6,5 @@ // https://github.com/XTLS/Xray-core/commit/5c611420487a92f931faefc01d4bf03869f477f6 // https://github.com/XTLS/Xray-core/commit/23d7aad461d232bc5bed52dd6aaa731ecd88ad35 // https://github.com/XTLS/Xray-core/commit/3c20bddfcfd8999be5f9a2ac180dc959950e4c61 +// https://github.com/XTLS/Xray-core/commit/1720be168fa069332c418503d30341fc6e01df7f package encryption diff --git a/transport/vless/encryption/factory.go b/transport/vless/encryption/factory.go index 18b88c2e..4988dbbf 100644 --- a/transport/vless/encryption/factory.go +++ b/transport/vless/encryption/factory.go @@ -31,7 +31,7 @@ func NewClient(encryption string) (*ClientInstance, error) { var xor uint32 switch s[1] { case "vless": - case "aes128xor": + case "xored": xor = 1 default: return nil, fmt.Errorf("invaild vless encryption value: %s", encryption) @@ -76,7 +76,7 @@ func NewServer(decryption string) (*ServerInstance, error) { var xor uint32 switch s[1] { case "vless": - case "aes128xor": + case "xored": xor = 1 default: return nil, fmt.Errorf("invaild vless decryption value: %s", decryption) diff --git a/transport/vless/encryption/xor.go b/transport/vless/encryption/xor.go index 296fdd63..696702bc 100644 --- a/transport/vless/encryption/xor.go +++ b/transport/vless/encryption/xor.go @@ -10,16 +10,19 @@ import ( type XorConn struct { net.Conn - key []byte - ctr cipher.Stream - peerCtr cipher.Stream + key []byte + ctr cipher.Stream + peerCtr cipher.Stream + isHeader bool + skipNext bool } func NewXorConn(conn net.Conn, key []byte) *XorConn { return &XorConn{Conn: conn, key: key[:16]} + //chacha20.NewUnauthenticatedCipher() } -func (c *XorConn) Write(b []byte) (int, error) { +func (c *XorConn) Write(b []byte) (int, error) { // two records at most if len(b) == 0 { return 0, nil } @@ -30,7 +33,13 @@ func (c *XorConn) Write(b []byte) (int, error) { rand.Read(iv) c.ctr = cipher.NewCTR(block, iv) } - c.ctr.XORKeyStream(b, b) // caller MUST discard b + t, l, _ := DecodeHeader(b) + if t != 23 { + l += 10 // 5+l+5 + } else { + l = 5 + } + c.ctr.XORKeyStream(b[:l], b[:l]) // caller MUST discard b if iv != nil { b = append(iv, b...) } @@ -43,7 +52,7 @@ func (c *XorConn) Write(b []byte) (int, error) { return len(b), nil } -func (c *XorConn) Read(b []byte) (int, error) { +func (c *XorConn) Read(b []byte) (int, error) { // 5-bytes, data, 5-bytes... if len(b) == 0 { return 0, nil } @@ -54,10 +63,24 @@ func (c *XorConn) Read(b []byte) (int, error) { } block, _ := aes.NewCipher(c.key) c.peerCtr = cipher.NewCTR(block, peerIv) + c.isHeader = true } - n, err := c.Conn.Read(b) - if n > 0 { - c.peerCtr.XORKeyStream(b[:n], b[:n]) + if _, err := io.ReadFull(c.Conn, b); err != nil { + return 0, err } - return n, err + if c.skipNext { + c.skipNext = false + return len(b), nil + } + c.peerCtr.XORKeyStream(b, b) + if c.isHeader { + if t, _, _ := DecodeHeader(b); t == 23 { // always 5-bytes + c.skipNext = true + } else { + c.isHeader = false + } + } else { + c.isHeader = true + } + return len(b), nil }