mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-11-15 01:25:00 +03:00
fix(wireguard): step over wide address claims when allocating
allocateWireguardAddress walked the scope one address at a time and tested each against every wide claim, so a claim covering an IPv6 /64 (a node can report such allowedIPs) turned the next address-less client add into a 2^64-step loop that also held every later client change on that inbound. The scan now jumps past a wide claim in one step, so it is bounded by the number of claims.
This commit is contained in:
@@ -117,16 +117,15 @@ func allocateWireguardAddress(used []string, base string, allowWidening bool) (s
|
||||
wide = append(wide, p)
|
||||
}
|
||||
}
|
||||
isTaken := func(a netip.Addr) bool {
|
||||
if _, ok := taken[a]; ok {
|
||||
return true
|
||||
}
|
||||
// wideClaimOf returns a wide claim holding a, so the scan can step over the whole claim:
|
||||
// a node may report one spanning the scope, and walking it is 2^64 steps in IPv6.
|
||||
wideClaimOf := func(a netip.Addr) (netip.Prefix, bool) {
|
||||
for _, p := range wide {
|
||||
if p.Contains(a) {
|
||||
return true
|
||||
return p, true
|
||||
}
|
||||
}
|
||||
return false
|
||||
return netip.Prefix{}, false
|
||||
}
|
||||
scopes := []netip.Prefix{prefix}
|
||||
if allowWidening && prefix.Addr().Is4() && prefix.Bits() > wireguardPoolFloorBits {
|
||||
@@ -136,16 +135,31 @@ func allocateWireguardAddress(used []string, base string, allowWidening bool) (s
|
||||
}
|
||||
for _, scope := range scopes {
|
||||
addr := scope.Masked().Addr().Next().Next()
|
||||
for scope.Contains(addr) {
|
||||
if !isTaken(addr) {
|
||||
return addr.String() + "/" + hostBits, nil
|
||||
for addr.IsValid() && scope.Contains(addr) {
|
||||
if _, ok := taken[addr]; ok {
|
||||
addr = addr.Next()
|
||||
continue
|
||||
}
|
||||
addr = addr.Next()
|
||||
if claim, ok := wideClaimOf(addr); ok {
|
||||
addr = lastPrefixAddr(claim).Next()
|
||||
continue
|
||||
}
|
||||
return addr.String() + "/" + hostBits, nil
|
||||
}
|
||||
}
|
||||
return "", common.NewError("wireguard: no free address available in", scopes[len(scopes)-1].String())
|
||||
}
|
||||
|
||||
// lastPrefixAddr is the highest address of p.
|
||||
func lastPrefixAddr(p netip.Prefix) netip.Addr {
|
||||
bytes := p.Masked().Addr().AsSlice()
|
||||
for bit := p.Bits(); bit < len(bytes)*8; bit++ {
|
||||
bytes[bit/8] |= 0x80 >> (bit % 8)
|
||||
}
|
||||
addr, _ := netip.AddrFromSlice(bytes)
|
||||
return addr
|
||||
}
|
||||
|
||||
// normalizeWireguardAllowedIPs validates user-supplied allowedIPs entries and
|
||||
// canonicalizes them: bare addresses become single-host prefixes, duplicates drop.
|
||||
func normalizeWireguardAllowedIPs(values []string) ([]string, error) {
|
||||
|
||||
Reference in New Issue
Block a user