mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-08-16 16:20:59 +00:00
fix(node): adopt a node inbound's host overrides into the master
Per-inbound Host overrides (Security/SNI/Fingerprint/ALPN and friends) are looked up by the local inbound id when subscriptions render, but nothing in the node sync ever fetched the node's hosts table: an inbound adopted from a managed node got zero Host rows on the master, so its subscription configs fell back to a bare TLS block without the fingerprint/SNI the node was configured with. When a traffic snapshot carries a tag with no central row yet - the only moment adoption can happen - the sync job now also pulls the node's existing hosts/list endpoint (best-effort, so old nodes just skip it) and the adoption branch materializes that inbound's groups against the new central id inside the same transaction, reusing the group-to-rows projection the hosts API already uses. Master stays authoritative afterwards: this is a one-time import, not a continuous sync, matching how the inbound's own settings are adopted. Closes #5890
This commit is contained in:
@@ -224,6 +224,41 @@ func liftActivatedClientRecordExpiries(tx *gorm.DB) error {
|
||||
).Error
|
||||
}
|
||||
|
||||
// SnapshotHasUnadoptedInbounds reports whether the snapshot carries a tag with
|
||||
// no central row yet, i.e. the next merge would adopt a new inbound.
|
||||
func (s *InboundService) SnapshotHasUnadoptedInbounds(nodeID int, snap *runtime.TrafficSnapshot) (bool, error) {
|
||||
if snap == nil || len(snap.Inbounds) == 0 {
|
||||
return false, nil
|
||||
}
|
||||
var tags []string
|
||||
if err := database.GetDB().Model(model.Inbound{}).
|
||||
Where("node_id = ?", nodeID).
|
||||
Pluck("tag", &tags).Error; err != nil {
|
||||
return false, err
|
||||
}
|
||||
prefix := nodeTagPrefix(&nodeID)
|
||||
known := make(map[string]struct{}, len(tags)*2)
|
||||
for _, tag := range tags {
|
||||
known[tag] = struct{}{}
|
||||
if prefix != "" {
|
||||
if stripped, found := strings.CutPrefix(tag, prefix); found {
|
||||
known[stripped] = struct{}{}
|
||||
} else {
|
||||
known[prefix+tag] = struct{}{}
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, ib := range snap.Inbounds {
|
||||
if ib == nil {
|
||||
continue
|
||||
}
|
||||
if _, ok := known[ib.Tag]; !ok {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func (s *InboundService) SetRemoteTraffic(nodeID int, snap *runtime.TrafficSnapshot, dirty bool) (bool, error) {
|
||||
var structuralChange bool
|
||||
err := submitTrafficWrite(func() error {
|
||||
@@ -537,6 +572,11 @@ func (s *InboundService) setRemoteTrafficLocked(nodeID int, snap *runtime.Traffi
|
||||
if newIb.Tag != snapIb.Tag {
|
||||
tagToCentral[newIb.Tag] = &newIb
|
||||
}
|
||||
if rows := adoptedHostRows(snap.HostGroups, snapIb.Id, newIb.Id); len(rows) > 0 {
|
||||
if err := tx.Create(&rows).Error; err != nil {
|
||||
logger.Warningf("setRemoteTraffic: adopt host rows for tag %q failed: %v", newIb.Tag, err)
|
||||
}
|
||||
}
|
||||
newInboundIDs[newIb.Id] = struct{}{}
|
||||
structuralChange = true
|
||||
continue
|
||||
|
||||
Reference in New Issue
Block a user