mirror of
https://github.com/XTLS/Xray-core.git
synced 2025-08-22 01:26:49 +08:00
Rename reuse/index -> ticket
This commit is contained in:
@@ -65,7 +65,7 @@ func (c *VLessInboundConfig) Build() (proto.Message, error) {
|
|||||||
return nil, errors.New(`VLESS clients: "flow" doesn't support "` + account.Flow + `" in this version`)
|
return nil, errors.New(`VLESS clients: "flow" doesn't support "` + account.Flow + `" in this version`)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(account.Encryption) > 0 {
|
if account.Encryption != "" {
|
||||||
return nil, errors.New(`VLESS clients: "encryption" should not in inbound settings`)
|
return nil, errors.New(`VLESS clients: "encryption" should not in inbound settings`)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,8 +73,9 @@ func (c *VLessInboundConfig) Build() (proto.Message, error) {
|
|||||||
config.Clients[idx] = user
|
config.Clients[idx] = user
|
||||||
}
|
}
|
||||||
|
|
||||||
|
config.Decryption = c.Decryption
|
||||||
if !func() bool {
|
if !func() bool {
|
||||||
s := strings.Split(c.Decryption, "-mlkem768seed-")
|
s := strings.Split(config.Decryption, "-mlkem768seed-")
|
||||||
if len(s) != 2 {
|
if len(s) != 2 {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -95,11 +96,11 @@ func (c *VLessInboundConfig) Build() (proto.Message, error) {
|
|||||||
}
|
}
|
||||||
config.Decryption = s[1]
|
config.Decryption = s[1]
|
||||||
return true
|
return true
|
||||||
}() && c.Decryption != "none" {
|
}() && config.Decryption != "none" {
|
||||||
if c.Decryption == "" {
|
if config.Decryption == "" {
|
||||||
return nil, errors.New(`VLESS settings: please add/set "decryption":"none" to every settings`)
|
return nil, errors.New(`VLESS settings: please add/set "decryption":"none" to every settings`)
|
||||||
}
|
}
|
||||||
return nil, errors.New(`VLESS settings: unsupported "decryption": ` + c.Decryption)
|
return nil, errors.New(`VLESS settings: unsupported "decryption": ` + config.Decryption)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, fb := range c.Fallbacks {
|
for _, fb := range c.Fallbacks {
|
||||||
|
@@ -31,14 +31,14 @@ type ClientInstance struct {
|
|||||||
minutes time.Duration
|
minutes time.Duration
|
||||||
expire time.Time
|
expire time.Time
|
||||||
baseKey []byte
|
baseKey []byte
|
||||||
reuse []byte
|
ticket []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
type ClientConn struct {
|
type ClientConn struct {
|
||||||
net.Conn
|
net.Conn
|
||||||
instance *ClientInstance
|
instance *ClientInstance
|
||||||
baseKey []byte
|
baseKey []byte
|
||||||
reuse []byte
|
ticket []byte
|
||||||
random []byte
|
random []byte
|
||||||
aead cipher.AEAD
|
aead cipher.AEAD
|
||||||
nonce []byte
|
nonce []byte
|
||||||
@@ -64,7 +64,7 @@ func (i *ClientInstance) Handshake(conn net.Conn) (net.Conn, error) {
|
|||||||
if time.Now().Before(i.expire) {
|
if time.Now().Before(i.expire) {
|
||||||
c.instance = i
|
c.instance = i
|
||||||
c.baseKey = i.baseKey
|
c.baseKey = i.baseKey
|
||||||
c.reuse = i.reuse
|
c.ticket = i.ticket
|
||||||
i.RUnlock()
|
i.RUnlock()
|
||||||
return c, nil
|
return c, nil
|
||||||
}
|
}
|
||||||
@@ -94,7 +94,7 @@ func (i *ClientInstance) Handshake(conn net.Conn) (net.Conn, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
encapsulatedPfsKey := peerServerHello[:1088]
|
encapsulatedPfsKey := peerServerHello[:1088]
|
||||||
c.reuse = peerServerHello[1088:]
|
c.ticket = peerServerHello[1088:]
|
||||||
|
|
||||||
pfsKey, err := dKeyPfs.Decapsulate(encapsulatedPfsKey)
|
pfsKey, err := dKeyPfs.Decapsulate(encapsulatedPfsKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -105,7 +105,7 @@ func (i *ClientInstance) Handshake(conn net.Conn) (net.Conn, error) {
|
|||||||
authKey := make([]byte, 32)
|
authKey := make([]byte, 32)
|
||||||
hkdf.New(sha256.New, c.baseKey, encapsulatedNfsKey, eKeyPfs).Read(authKey)
|
hkdf.New(sha256.New, c.baseKey, encapsulatedNfsKey, eKeyPfs).Read(authKey)
|
||||||
nonce := make([]byte, 12)
|
nonce := make([]byte, 12)
|
||||||
VLESS, _ := newAead(ClientCipher, authKey).Open(nil, nonce, c.reuse, encapsulatedPfsKey)
|
VLESS, _ := newAead(ClientCipher, authKey).Open(nil, nonce, c.ticket, encapsulatedPfsKey)
|
||||||
if !bytes.Equal(VLESS, []byte("VLESS")) { // TODO: more message
|
if !bytes.Equal(VLESS, []byte("VLESS")) { // TODO: more message
|
||||||
return nil, errors.New("invalid server").AtError()
|
return nil, errors.New("invalid server").AtError()
|
||||||
}
|
}
|
||||||
@@ -114,7 +114,7 @@ func (i *ClientInstance) Handshake(conn net.Conn) (net.Conn, error) {
|
|||||||
i.Lock()
|
i.Lock()
|
||||||
i.expire = time.Now().Add(i.minutes)
|
i.expire = time.Now().Add(i.minutes)
|
||||||
i.baseKey = c.baseKey
|
i.baseKey = c.baseKey
|
||||||
i.reuse = c.reuse
|
i.ticket = c.ticket
|
||||||
i.Unlock()
|
i.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -130,12 +130,12 @@ func (c *ClientConn) Write(b []byte) (int, error) {
|
|||||||
c.random = make([]byte, 32)
|
c.random = make([]byte, 32)
|
||||||
rand.Read(c.random)
|
rand.Read(c.random)
|
||||||
key := make([]byte, 32)
|
key := make([]byte, 32)
|
||||||
hkdf.New(sha256.New, c.baseKey, c.random, c.reuse).Read(key)
|
hkdf.New(sha256.New, c.baseKey, c.random, c.ticket).Read(key)
|
||||||
c.aead = newAead(ClientCipher, key)
|
c.aead = newAead(ClientCipher, key)
|
||||||
c.nonce = make([]byte, 12)
|
c.nonce = make([]byte, 12)
|
||||||
|
|
||||||
data = make([]byte, 21+32+5+len(b)+16)
|
data = make([]byte, 21+32+5+len(b)+16)
|
||||||
copy(data, c.reuse)
|
copy(data, c.ticket)
|
||||||
copy(data[21:], c.random)
|
copy(data[21:], c.random)
|
||||||
encodeHeader(data[53:], len(b)+16)
|
encodeHeader(data[53:], len(b)+16)
|
||||||
c.aead.Seal(data[:58], c.nonce, b, data[53:58])
|
c.aead.Seal(data[:58], c.nonce, b, data[53:58])
|
||||||
@@ -200,7 +200,7 @@ func (c *ClientConn) Read(b []byte) (int, error) { // after first Write()
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
if c.instance != nil {
|
if c.instance != nil {
|
||||||
c.instance.Lock()
|
c.instance.Lock()
|
||||||
if bytes.Equal(c.reuse, c.instance.reuse) {
|
if bytes.Equal(c.ticket, c.instance.ticket) {
|
||||||
c.instance.expire = time.Now() // expired
|
c.instance.expire = time.Now() // expired
|
||||||
}
|
}
|
||||||
c.instance.Unlock()
|
c.instance.Unlock()
|
||||||
|
@@ -34,7 +34,7 @@ type ServerConn struct {
|
|||||||
net.Conn
|
net.Conn
|
||||||
cipher byte
|
cipher byte
|
||||||
baseKey []byte
|
baseKey []byte
|
||||||
reuse []byte
|
ticket []byte
|
||||||
peerRandom []byte
|
peerRandom []byte
|
||||||
peerAead cipher.AEAD
|
peerAead cipher.AEAD
|
||||||
peerNonce []byte
|
peerNonce []byte
|
||||||
@@ -71,20 +71,20 @@ func (i *ServerInstance) Handshake(conn net.Conn) (net.Conn, error) {
|
|||||||
}
|
}
|
||||||
c := &ServerConn{Conn: conn}
|
c := &ServerConn{Conn: conn}
|
||||||
|
|
||||||
peerReuseHello := make([]byte, 21+32)
|
peerTicketHello := make([]byte, 21+32)
|
||||||
if _, err := io.ReadFull(c.Conn, peerReuseHello); err != nil {
|
if _, err := io.ReadFull(c.Conn, peerTicketHello); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if i.minutes > 0 {
|
if i.minutes > 0 {
|
||||||
i.RLock()
|
i.RLock()
|
||||||
s := i.sessions[[21]byte(peerReuseHello)]
|
s := i.sessions[[21]byte(peerTicketHello)]
|
||||||
i.RUnlock()
|
i.RUnlock()
|
||||||
if s != nil {
|
if s != nil {
|
||||||
if _, replay := s.randoms.LoadOrStore([32]byte(peerReuseHello[21:]), true); !replay {
|
if _, replay := s.randoms.LoadOrStore([32]byte(peerTicketHello[21:]), true); !replay {
|
||||||
c.cipher = s.cipher
|
c.cipher = s.cipher
|
||||||
c.baseKey = s.baseKey
|
c.baseKey = s.baseKey
|
||||||
c.reuse = peerReuseHello[:21]
|
c.ticket = peerTicketHello[:21]
|
||||||
c.peerRandom = peerReuseHello[21:]
|
c.peerRandom = peerTicketHello[21:]
|
||||||
return c, nil
|
return c, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -96,11 +96,11 @@ func (i *ServerInstance) Handshake(conn net.Conn) (net.Conn, error) {
|
|||||||
}
|
}
|
||||||
if l, _ := decodeHeader(peerHeader); l != 0 {
|
if l, _ := decodeHeader(peerHeader); l != 0 {
|
||||||
c.Conn.Write(make([]byte, crypto.RandBetween(100, 1000))) // make client do new handshake
|
c.Conn.Write(make([]byte, crypto.RandBetween(100, 1000))) // make client do new handshake
|
||||||
return nil, errors.New("invalid reuse")
|
return nil, errors.New("invalid ticket")
|
||||||
}
|
}
|
||||||
|
|
||||||
peerClientHello := make([]byte, 1088+1184+1)
|
peerClientHello := make([]byte, 1088+1184+1)
|
||||||
copy(peerClientHello, peerReuseHello)
|
copy(peerClientHello, peerTicketHello)
|
||||||
copy(peerClientHello[53:], peerHeader)
|
copy(peerClientHello[53:], peerHeader)
|
||||||
if _, err := io.ReadFull(c.Conn, peerClientHello[58:]); err != nil {
|
if _, err := io.ReadFull(c.Conn, peerClientHello[58:]); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -126,13 +126,13 @@ func (i *ServerInstance) Handshake(conn net.Conn) (net.Conn, error) {
|
|||||||
authKey := make([]byte, 32)
|
authKey := make([]byte, 32)
|
||||||
hkdf.New(sha256.New, c.baseKey, encapsulatedNfsKey, eKeyPfsData).Read(authKey)
|
hkdf.New(sha256.New, c.baseKey, encapsulatedNfsKey, eKeyPfsData).Read(authKey)
|
||||||
nonce := make([]byte, 12)
|
nonce := make([]byte, 12)
|
||||||
c.reuse = newAead(c.cipher, authKey).Seal(nil, nonce, []byte("VLESS"), encapsulatedPfsKey)
|
c.ticket = newAead(c.cipher, authKey).Seal(nil, nonce, []byte("VLESS"), encapsulatedPfsKey)
|
||||||
|
|
||||||
padding := crypto.RandBetween(100, 1000)
|
padding := crypto.RandBetween(100, 1000)
|
||||||
|
|
||||||
serverHello := make([]byte, 1088+21+5+padding)
|
serverHello := make([]byte, 1088+21+5+padding)
|
||||||
copy(serverHello, encapsulatedPfsKey)
|
copy(serverHello, encapsulatedPfsKey)
|
||||||
copy(serverHello[1088:], c.reuse)
|
copy(serverHello[1088:], c.ticket)
|
||||||
encodeHeader(serverHello[1109:], int(padding))
|
encodeHeader(serverHello[1109:], int(padding))
|
||||||
|
|
||||||
if _, err := c.Conn.Write(serverHello); err != nil {
|
if _, err := c.Conn.Write(serverHello); err != nil {
|
||||||
@@ -141,7 +141,7 @@ func (i *ServerInstance) Handshake(conn net.Conn) (net.Conn, error) {
|
|||||||
|
|
||||||
if i.minutes > 0 {
|
if i.minutes > 0 {
|
||||||
i.Lock()
|
i.Lock()
|
||||||
i.sessions[[21]byte(c.reuse)] = &ServerSession{
|
i.sessions[[21]byte(c.ticket)] = &ServerSession{
|
||||||
expire: time.Now().Add(i.minutes),
|
expire: time.Now().Add(i.minutes),
|
||||||
cipher: c.cipher,
|
cipher: c.cipher,
|
||||||
baseKey: c.baseKey,
|
baseKey: c.baseKey,
|
||||||
@@ -171,12 +171,12 @@ func (c *ServerConn) Read(b []byte) (int, error) {
|
|||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
peerIndex := make([]byte, 21)
|
peerTicket := make([]byte, 21)
|
||||||
copy(peerIndex, peerHeader)
|
copy(peerTicket, peerHeader)
|
||||||
if _, err := io.ReadFull(c.Conn, peerIndex[5:]); err != nil {
|
if _, err := io.ReadFull(c.Conn, peerTicket[5:]); err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
if !bytes.Equal(peerIndex, c.reuse) {
|
if !bytes.Equal(peerTicket, c.ticket) {
|
||||||
return 0, errors.New("naughty boy")
|
return 0, errors.New("naughty boy")
|
||||||
}
|
}
|
||||||
c.peerRandom = make([]byte, 32)
|
c.peerRandom = make([]byte, 32)
|
||||||
@@ -185,7 +185,7 @@ func (c *ServerConn) Read(b []byte) (int, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
peerKey := make([]byte, 32)
|
peerKey := make([]byte, 32)
|
||||||
hkdf.New(sha256.New, c.baseKey, c.peerRandom, c.reuse).Read(peerKey)
|
hkdf.New(sha256.New, c.baseKey, c.peerRandom, c.ticket).Read(peerKey)
|
||||||
c.peerAead = newAead(c.cipher, peerKey)
|
c.peerAead = newAead(c.cipher, peerKey)
|
||||||
c.peerNonce = make([]byte, 12)
|
c.peerNonce = make([]byte, 12)
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user