mirror of
https://github.com/MetaCubeX/mihomo.git
synced 2026-03-09 17:49:56 +00:00
75 lines
1.5 KiB
Go
75 lines
1.5 KiB
Go
package sudoku
|
|
|
|
import (
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
var handshakeReplayTTL = 60 * time.Second
|
|
|
|
type nonceSet struct {
|
|
mu sync.Mutex
|
|
m map[[kipHelloNonceSize]byte]time.Time
|
|
maxEntries int
|
|
lastPrune time.Time
|
|
}
|
|
|
|
func newNonceSet(maxEntries int) *nonceSet {
|
|
if maxEntries <= 0 {
|
|
maxEntries = 4096
|
|
}
|
|
return &nonceSet{
|
|
m: make(map[[kipHelloNonceSize]byte]time.Time),
|
|
maxEntries: maxEntries,
|
|
}
|
|
}
|
|
|
|
func (s *nonceSet) allow(nonce [kipHelloNonceSize]byte, now time.Time, ttl time.Duration) bool {
|
|
s.mu.Lock()
|
|
defer s.mu.Unlock()
|
|
|
|
if ttl <= 0 {
|
|
ttl = 60 * time.Second
|
|
}
|
|
|
|
if now.Sub(s.lastPrune) > ttl/2 || len(s.m) > s.maxEntries {
|
|
for k, exp := range s.m {
|
|
if !now.Before(exp) {
|
|
delete(s.m, k)
|
|
}
|
|
}
|
|
s.lastPrune = now
|
|
for len(s.m) > s.maxEntries {
|
|
for k := range s.m {
|
|
delete(s.m, k)
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
if exp, ok := s.m[nonce]; ok && now.Before(exp) {
|
|
return false
|
|
}
|
|
s.m[nonce] = now.Add(ttl)
|
|
return true
|
|
}
|
|
|
|
type handshakeReplayProtector struct {
|
|
users sync.Map // map[userHash string]*nonceSet
|
|
}
|
|
|
|
func (p *handshakeReplayProtector) allow(userHash string, nonce [kipHelloNonceSize]byte, now time.Time) bool {
|
|
if userHash == "" {
|
|
userHash = "_"
|
|
}
|
|
val, _ := p.users.LoadOrStore(userHash, newNonceSet(4096))
|
|
set, ok := val.(*nonceSet)
|
|
if !ok || set == nil {
|
|
set = newNonceSet(4096)
|
|
p.users.Store(userHash, set)
|
|
}
|
|
return set.allow(nonce, now, handshakeReplayTTL)
|
|
}
|
|
|
|
var globalHandshakeReplay = &handshakeReplayProtector{}
|