fix(amneziawg): stop losing an inbound and its server keys on the API path

Two saves that the panel UI never makes, but the documented REST API does.

A client whose allowedIPs normalized to empty passed validation, then
InstanceFromInbound skipped the peer and dropped the whole instance when it was
the only one. Nothing logged it, so an enabled inbound simply never opened its
socket. Refuse an enabled peer with no address, naming the client, the way the
injection and collision checks already do.

The server keypair was regenerated whenever a payload omitted privateKey, which
invalidates every client config already distributed, and a payload carrying only
privateKey left publicKey empty so rendered configs got a blank "PublicKey =".
An omitted key now means unchanged: the stored pair is carried forward, a
half-supplied pair has its public half derived, and generation is reserved for
an inbound that has no stored keys at all. UpdateInbound loads the stored row
before normalizing so those keys are available.

Closes #6407
This commit is contained in:
Sanaei
2026-09-09 00:42:52 +02:00
parent 4e423fa452
commit 705b291d34
3 changed files with 125 additions and 18 deletions
+7 -7
View File
@@ -1044,7 +1044,7 @@ func (s *InboundService) AddInbound(inbound *model.Inbound) (*model.Inbound, boo
if err := s.normalizeMtprotoXrayPort(inbound, ""); err != nil {
return inbound, false, err
}
if err := s.normalizeAmneziaWGSettings(inbound); err != nil {
if err := s.normalizeAmneziaWGSettings(inbound, ""); err != nil {
return inbound, false, err
}
if inbound.NodeID != nil && !isNodeEligibleProtocol(inbound.Protocol) {
@@ -1565,7 +1565,12 @@ func (s *InboundService) UpdateInbound(inbound *model.Inbound) (*model.Inbound,
return inbound, false, err
}
s.normalizeMtprotoSecret(inbound)
if err := s.normalizeAmneziaWGSettings(inbound); err != nil {
oldInbound, err := s.GetInbound(inbound.Id)
if err != nil {
return inbound, false, err
}
if err := s.normalizeAmneziaWGSettings(inbound, oldInbound.Settings); err != nil {
return inbound, false, err
}
inbound.SubSortIndex = normalizeSubSortIndex(inbound.SubSortIndex)
@@ -1581,11 +1586,6 @@ func (s *InboundService) UpdateInbound(inbound *model.Inbound) (*model.Inbound,
}
}
}
oldInbound, err := s.GetInbound(inbound.Id)
if err != nil {
return inbound, false, err
}
// Grandfather a row that was already stored incomplete so it stays editable;
// only a save that breaks a previously valid TLS block is refused.
if !s.FromNodeSync {