mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-11-04 20:25:16 +03:00
fix(clients): reject AllowedIPs already used on another WireGuard/AmneziaWG inbound
defaultWireguardClients/defaultAmneziaWGClients only ever checked uniqueness against their own inbound's client list, so two inbounds sharing a subnet (same protocol or not) could silently hand out or accept the same address -- the exact scenario behind a real duplicate-IP incident where a WireGuard and an AmneziaWG client both ended up on the same address. otherTunnelAllowedIPs now collects every address already claimed on every other tunnel inbound and folds it into both the auto-allocation pool and the manual-entry collision check, naming the other inbound in the error when it fires.
This commit is contained in:
@@ -145,12 +145,23 @@ func wireguardAllowedIPsCollision(entries, used []string) string {
|
||||
// inbound's subnet. It mutates both the typed clients and the parallel raw client
|
||||
// maps that get persisted into the inbound settings. Existing values are never
|
||||
// overwritten, so editing a client never rotates its keys.
|
||||
func defaultWireguardClients(existing, clients []model.Client, interfaceClients []any) error {
|
||||
//
|
||||
// crossInboundUsed maps AllowedIPs already claimed by clients on every OTHER
|
||||
// WireGuard/AmneziaWG inbound on this panel to a human-readable description
|
||||
// of which inbound holds it (see otherTunnelAllowedIPs). It is folded into
|
||||
// used only AFTER wireguardAllocationBase runs, so an unrelated inbound's
|
||||
// subnet can never skew this inbound's own base-subnet inference — it only
|
||||
// ever narrows which addresses are free to hand out or accept, and lets a
|
||||
// manual-entry collision name the other inbound instead of just the address.
|
||||
func defaultWireguardClients(existing, clients []model.Client, interfaceClients []any, crossInboundUsed map[string]string) error {
|
||||
used := make([]string, 0)
|
||||
for i := range existing {
|
||||
used = append(used, existing[i].AllowedIPs...)
|
||||
}
|
||||
base := wireguardAllocationBase(used, defaultWireguardBase)
|
||||
for addr := range crossInboundUsed {
|
||||
used = append(used, addr)
|
||||
}
|
||||
for i := range clients {
|
||||
c := &clients[i]
|
||||
if c.PrivateKey == "" && c.PublicKey == "" {
|
||||
@@ -182,6 +193,9 @@ func defaultWireguardClients(existing, clients []model.Client, interfaceClients
|
||||
return common.NewError("wireguard: allowedIPs has no usable entry")
|
||||
}
|
||||
if hit := wireguardAllowedIPsCollision(normalized, used); hit != "" {
|
||||
if where := crossInboundUsed[hit]; where != "" {
|
||||
return common.NewError("wireguard: allowedIPs entry", hit, "is already used by a client on", where)
|
||||
}
|
||||
return common.NewError("wireguard: allowedIPs entry already used by another client:", hit)
|
||||
}
|
||||
c.AllowedIPs = normalized
|
||||
|
||||
Reference in New Issue
Block a user