diff --git a/listener/sing_vless/server.go b/listener/sing_vless/server.go index 764f687f..3a5943b5 100644 --- a/listener/sing_vless/server.go +++ b/listener/sing_vless/server.go @@ -100,7 +100,7 @@ func New(config LC.VlessServer, tunnel C.Tunnel, additions ...inbound.Addition) if sl.decryption != nil { defer func() { // decryption must be closed to avoid the goroutine leak if err != nil { - //_ = sl.decryption.Close() + _ = sl.decryption.Close() sl.decryption = nil } }() @@ -210,7 +210,7 @@ func (l *Listener) Close() error { } } if l.decryption != nil { - //_ = l.decryption.Close() + _ = l.decryption.Close() } return retErr } diff --git a/transport/vless/encryption/doc.go b/transport/vless/encryption/doc.go index 0486b594..32a0023f 100644 --- a/transport/vless/encryption/doc.go +++ b/transport/vless/encryption/doc.go @@ -26,4 +26,5 @@ // https://github.com/XTLS/Xray-core/commit/6768a22f676c9121cfc9dc4f51181a8a07837c8d // https://github.com/XTLS/Xray-core/commit/4c6fd94d97159f5a3e740ba6dd2d9b65e3ed320c // https://github.com/XTLS/Xray-core/commit/19f890729656bc923ae3dee8426168c93b8ee9c2 +// https://github.com/XTLS/Xray-core/commit/cbade89ab11af26ba1e480a3688a6c205fa3c3f8 package encryption diff --git a/transport/vless/encryption/factory.go b/transport/vless/encryption/factory.go index 179e79cb..951bf3b1 100644 --- a/transport/vless/encryption/factory.go +++ b/transport/vless/encryption/factory.go @@ -82,14 +82,14 @@ func NewServer(decryption string) (*ServerInstance, error) { if err != nil { return nil, fmt.Errorf("invaild vless decryption value: %s", decryption) } - secondsFrom := uint32(i) - var secondsTo uint32 - if len(t) > 1 { + secondsFrom := int64(i) + secondsTo := int64(0) + if len(t) == 2 { i, err = strconv.Atoi(t[1]) if err != nil { return nil, fmt.Errorf("invaild vless decryption value: %s", decryption) } - secondsTo = uint32(i) + secondsTo = int64(i) } var nfsSKeysBytes [][]byte var paddings []string diff --git a/transport/vless/encryption/server.go b/transport/vless/encryption/server.go index 3a85bc9a..71185698 100644 --- a/transport/vless/encryption/server.go +++ b/transport/vless/encryption/server.go @@ -27,16 +27,19 @@ type ServerInstance struct { Hash32s [][32]byte RelaysLength int XorMode uint32 - SecondsFrom uint32 - SecondsTo uint32 + SecondsFrom int64 + SecondsTo int64 PaddingLens [][3]int PaddingGaps [][3]int RWLock sync.RWMutex + Closed bool + Lasts map[int64][16]byte + Tickets [][16]byte Sessions map[[16]byte]*ServerSession } -func (i *ServerInstance) Init(nfsSKeysBytes [][]byte, xorMode, secondsFrom, secondsTo uint32, padding string) (err error) { +func (i *ServerInstance) Init(nfsSKeysBytes [][]byte, xorMode uint32, secondsFrom, secondsTo int64, padding string) (err error) { if i.NfsSKeys != nil { return errors.New("already initialized") } @@ -67,8 +70,47 @@ func (i *ServerInstance) Init(nfsSKeysBytes [][]byte, xorMode, secondsFrom, seco i.XorMode = xorMode i.SecondsFrom = secondsFrom i.SecondsTo = secondsTo - i.Sessions = make(map[[16]byte]*ServerSession) - return ParsePadding(padding, &i.PaddingLens, &i.PaddingGaps) + err = ParsePadding(padding, &i.PaddingLens, &i.PaddingGaps) + if err != nil { + return + } + if i.SecondsFrom > 0 || i.SecondsTo > 0 { + i.Lasts = make(map[int64][16]byte) + i.Tickets = make([][16]byte, 0, 1024) + i.Sessions = make(map[[16]byte]*ServerSession) + go func() { + for { + time.Sleep(time.Minute) + i.RWLock.Lock() + if i.Closed { + i.RWLock.Unlock() + return + } + minute := time.Now().Unix() / 60 + last := i.Lasts[minute] + delete(i.Lasts, minute) + delete(i.Lasts, minute-1) // for insurance + if last != [16]byte{} { + for j, ticket := range i.Tickets { + delete(i.Sessions, ticket) + if ticket == last { + i.Tickets = i.Tickets[j+1:] + break + } + } + } + i.RWLock.Unlock() + } + }() + } + return +} + +func (i *ServerInstance) Close() (err error) { + i.RWLock.Lock() + i.Closed = true + i.RWLock.Unlock() + return } func (i *ServerInstance) Handshake(conn net.Conn, fallback *[]byte) (*CommonConn, error) { @@ -223,25 +265,21 @@ func (i *ServerInstance) Handshake(conn net.Conn, fallback *[]byte) (*CommonConn c.AEAD = NewAEAD(pfsPublicKey, c.UnitedKey, c.UseAES) c.PeerAEAD = NewAEAD(encryptedPfsPublicKey[:1184+32], c.UnitedKey, c.UseAES) - ticket := make([]byte, 16) - rand.Read(ticket) - seconds := 0 + ticket := [16]byte{} + rand.Read(ticket[:]) + var seconds int64 if i.SecondsTo == 0 { - seconds = int(i.SecondsFrom) * int(randBetween(50, 100)) / 100 + seconds = i.SecondsFrom * randBetween(50, 100) / 100 } else { - seconds = int(randBetween(int64(i.SecondsFrom), int64(i.SecondsTo))) + seconds = randBetween(i.SecondsFrom, i.SecondsTo) } - copy(ticket, EncodeLength(int(seconds))) + copy(ticket[:], EncodeLength(int(seconds))) if seconds > 0 { i.RWLock.Lock() - i.Sessions[[16]byte(ticket)] = &ServerSession{PfsKey: pfsKey} + i.Lasts[(time.Now().Unix()+max(i.SecondsFrom, i.SecondsTo))/60+2] = ticket + i.Tickets = append(i.Tickets, ticket) + i.Sessions[ticket] = &ServerSession{PfsKey: pfsKey} i.RWLock.Unlock() - go func() { - time.Sleep(time.Duration(seconds)*time.Second + time.Minute) - i.RWLock.Lock() - delete(i.Sessions, [16]byte(ticket)) - i.RWLock.Unlock() - }() } pfsKeyExchangeLength := 1088 + 32 + 16 @@ -249,7 +287,7 @@ func (i *ServerInstance) Handshake(conn net.Conn, fallback *[]byte) (*CommonConn paddingLength, paddingLens, paddingGaps := CreatPadding(i.PaddingLens, i.PaddingGaps) serverHello := make([]byte, pfsKeyExchangeLength+encryptedTicketLength+paddingLength) nfsAEAD.Seal(serverHello[:0], MaxNonce, pfsPublicKey, nil) - c.AEAD.Seal(serverHello[:pfsKeyExchangeLength], nil, ticket, nil) + c.AEAD.Seal(serverHello[:pfsKeyExchangeLength], nil, ticket[:], nil) padding := serverHello[pfsKeyExchangeLength+encryptedTicketLength:] c.AEAD.Seal(padding[:0], nil, EncodeLength(paddingLength-18), nil) c.AEAD.Seal(padding[:18], nil, padding[18:paddingLength-16], nil) @@ -283,7 +321,7 @@ func (i *ServerInstance) Handshake(conn net.Conn, fallback *[]byte) (*CommonConn } if i.XorMode == 2 { - c.Conn = NewXorConn(conn, NewCTR(c.UnitedKey, ticket), NewCTR(c.UnitedKey, iv), 0, 0) + c.Conn = NewXorConn(conn, NewCTR(c.UnitedKey, ticket[:]), NewCTR(c.UnitedKey, iv), 0, 0) } return c, nil }