mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-09-17 07:37:15 +00:00
fix(amneziawg): refuse a WireGuard port that is the row's own relay port
All three relay checks filter themselves out of the candidates with id != ignoreId, so nothing ever compared an AmneziaWG row's own WireGuard listen port with the relay port its own id derives. Saving a row on that exact port left the embedded device (UDP on the inbound's listen address, amneziawgnet/device.go:137) and its injected relay (TCP and UDP on 127.0.0.1, amneziawgnet/relay.go:47-61) bound to the same UDP port, so whichever loses the race dies -- and when the relay loses it, Xray refuses the whole config and takes every other protocol on the host with it. The first AmneziaWG inbound on port 65101 was enough to reach it: id 1 derives exactly that port. The row now states the rule its three siblings do: it owns the slot its id derives. A node-hosted row still keeps its own port, since it binds no relay on this host. TestAddInbound_AmneziawgRefusesItsOwnRelayPort and TestUpdateInbound_AmneziawgRefusesItsOwnRelayPort fail without this -- both were watched red first -- and pin the two separate call sites, AddInbound's post-Save block and checkPortConflictTx's ignoreId > 0 block.
This commit is contained in:
@@ -223,6 +223,9 @@ func checkPortConflictTx(db *gorm.DB, inbound *model.Inbound, ignoreId int) (*po
|
||||
// The reverse direction, only meaningful once the id is known -- AddInbound
|
||||
// runs it after Save. Only a local row owns a relay slot (#6537 review).
|
||||
if inbound.NodeID == nil && inbound.Protocol == model.AmneziaWG && ignoreId > 0 {
|
||||
if self := amneziawgnetSocksSelfConflict(inbound, ignoreId); self != "" {
|
||||
return nil, common.NewError(self)
|
||||
}
|
||||
conflict, err := checkAmneziawgnetSocksRelayCollision(db, ignoreId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -330,6 +333,20 @@ func checkAmneziawgnetSocksRelayCollision(db *gorm.DB, id int) (*portConflictDet
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// amneziawgnetSocksSelfConflict: a row's own WireGuard port vs the relay port its
|
||||
// own id derives -- all three checks below exclude that id, so nothing else does.
|
||||
func amneziawgnetSocksSelfConflict(inbound *model.Inbound, id int) string {
|
||||
if id <= 0 || inbound.NodeID != nil || !listenOverlaps("127.0.0.1", inbound.Listen) {
|
||||
return ""
|
||||
}
|
||||
relayPort := amneziawgnet.SOCKSPortForInbound(id)
|
||||
if inbound.Port != relayPort {
|
||||
return ""
|
||||
}
|
||||
return fmt.Sprintf("WireGuard port %d is inbound #%d's own SOCKS5 relay port on 127.0.0.1; choose a different WireGuard port",
|
||||
relayPort, id)
|
||||
}
|
||||
|
||||
// checkAmneziawgnetSocksReverseConflict mirrors checkAmneziawgnetSocksConflict:
|
||||
// does id's own derived relay port collide with some other inbound's port.
|
||||
func checkAmneziawgnetSocksReverseConflict(db *gorm.DB, id int) (*portConflictDetail, error) {
|
||||
|
||||
Reference in New Issue
Block a user