aes128xor (all) -> xored (optimized)

https://github.com/XTLS/Xray-core/pull/4952#issuecomment-3182301703
This commit is contained in:
RPRX
2025-08-13 10:41:26 +00:00
committed by GitHub
parent 3c20bddfcf
commit 1720be168f
2 changed files with 35 additions and 12 deletions

View File

@@ -92,7 +92,7 @@ func (c *VLessInboundConfig) Build() (proto.Message, error) {
} }
switch s[1] { switch s[1] {
case "vless": case "vless":
case "aes128xor": case "xored":
config.Xor = 1 config.Xor = 1
default: default:
return false return false
@@ -240,7 +240,7 @@ func (c *VLessOutboundConfig) Build() (proto.Message, error) {
} }
switch s[1] { switch s[1] {
case "vless": case "vless":
case "aes128xor": case "xored":
account.Xor = 1 account.Xor = 1
default: default:
return false return false

View File

@@ -10,16 +10,19 @@ import (
type XorConn struct { type XorConn struct {
net.Conn net.Conn
key []byte key []byte
ctr cipher.Stream ctr cipher.Stream
peerCtr cipher.Stream peerCtr cipher.Stream
isHeader bool
skipNext bool
} }
func NewXorConn(conn net.Conn, key []byte) *XorConn { func NewXorConn(conn net.Conn, key []byte) *XorConn {
return &XorConn{Conn: conn, key: key[:16]} 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 { if len(b) == 0 {
return 0, nil return 0, nil
} }
@@ -30,7 +33,13 @@ func (c *XorConn) Write(b []byte) (int, error) {
rand.Read(iv) rand.Read(iv)
c.ctr = cipher.NewCTR(block, 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 { if iv != nil {
b = append(iv, b...) b = append(iv, b...)
} }
@@ -43,7 +52,7 @@ func (c *XorConn) Write(b []byte) (int, error) {
return len(b), nil 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 { if len(b) == 0 {
return 0, nil return 0, nil
} }
@@ -54,10 +63,24 @@ func (c *XorConn) Read(b []byte) (int, error) {
} }
block, _ := aes.NewCipher(c.key) block, _ := aes.NewCipher(c.key)
c.peerCtr = cipher.NewCTR(block, peerIv) c.peerCtr = cipher.NewCTR(block, peerIv)
c.isHeader = true
} }
n, err := c.Conn.Read(b) if _, err := io.ReadFull(c.Conn, b); err != nil {
if n > 0 { return 0, err
c.peerCtr.XORKeyStream(b[:n], b[:n])
} }
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
} }