Repository navigation
fix(outbounds): enforce tagPrefix on refresh and deduplicate outbound tags (#7110) - #7111
Gaoshou101 wants to merge 2 commits into
Conversation
… tags (MHSanaei#7110) - Check expectedPrefix in assignStableTags so modified tagPrefix regenerates tags instead of indefinitely reusing stale tags - Disambiguate colliding tags in mergeSubscriptionOutbounds to prevent Xray startup crashes - Add unit tests for tagPrefix updates and outbound tag deduplication Fixes MHSanaei#7110 Co-authored-by: yzykov <37885628+yzykov@users.noreply.github.com>
|
An operator who gave several outbound subscriptions overlapping tag prefixes, or who later changed a prefix, was left with Xray refusing to start ("existing tag found"), and on every automatic refresh the old tags came back. With this change, a prefix edit now renames that subscription's outbounds under the new prefix at the next refresh. Any outbound tag that still collides is renamed with a numeric suffix while the config is built, so the core starts again. Two things are new for operators. Routing rules or balancers that named an old tag exactly stop matching once the prefix changes; the issue asked for this, but it is a user-visible behaviour change for the maintainer to accept. And the suffix renaming happens only inside the generated config, which the panel never shows. Verdict: Real, partly fixed. The startup failure is gone, but making a prefix shorter (for example No blocking issues — 0 HIGH / 2 MEDIUM / 1 LOW open (3 new), 0 pre-existing Reviewed head: 93a7aeb Evidence. Problem is real (read on base): Findings MEDIUM — the merge-time rename produces tags that no panel surface knows about (pr-head/internal/web/service/xray.go:1167-1175). This PR added the in-place MEDIUM — editing a legacy blank-prefix subscription now silently renames all its tags (pr-head/internal/web/service/outbound_subscription.go:632). This PR added the LOW — shortening a prefix still keeps the old tags (pr-head/internal/web/service/outbound_subscription.go:632, :638). This PR introduced the plain Coverage
|
… persist cross-sub deduped tags (MHSanaei#7110) - Shortened TagPrefix ('eu-de-' -> 'eu-'): detect extra prefix segments in matchesActiveTagPrefix during assignStableTags, and rewrite stored LinkIdentities / LastFetchedOutbounds in Update() when the normalized prefix changes. - Legacy blank TagPrefix: preserve blank tag_prefix ('sub<id>-' fallback) in Update() when the stored TagPrefix is already empty and the user saves without entering a new prefix, avoiding silent renames to an unrelated 'subN-'. - Cross-subscription & template tag collisions: pass reservedExternalTags into fetchOutbounds / rewriteStoredPrefix so collision suffixes ('-N') are persisted in LastFetchedOutbounds & LinkIdentities (preventing priority moves or disables from swapping tags), and apply dedupeSubscriptionOutboundList (with warning logs) in activeOutboundsSplit so AllActiveOutbounds / AllActiveOutboundTags always match the generated Xray config.
|
Addressed all three findings from the review in commit 1. MEDIUM — Merge-time rename vs. panel surfaces (
|
Fixes #7110
Root Cause
assignStableTags, existing identity tags fromsub.LinkIdentities(prev[id]) and positional fallbacks (prevTagByIndex[i]) were reused unconditionally without checking if they match the subscription's activetagPrefix. Additionally,Update()wrotetag_prefixwithout updating persistedlink_identities/last_fetched_outbounds.mergeSubscriptionOutboundsandactiveOutboundsSplit, subscription outbounds (prependandappendList) were not checked against template outbound tags or other subscriptions' tags. When subscriptions contained overlapping tags, duplicate tags reached the generated Xray configuration, causing Xray-core to fail on startup withapp/proxyman/outbound: existing tag found: <tag>.Key Changes
eu-de-->eu-) and rewrite onUpdate():assignStableTags(matchesActiveTagPrefix), verify that cached tags start with the normalizedexpectedPrefixand do not retain an extra prefix segment ahead of the link's base slug when a prefix is shortened (e.g.,eu-de-frankfurt->eu-frankfurt).Update(), when the normalized prefix changes (oldEffective != newEffective),rewriteStoredPrefiximmediately updates persistedlast_fetched_outboundsandlink_identitiesto the new prefix.sub<id>-) onUpdate():sub.TagPrefix == ""(legacy row usingsub<id>-fallback) and the user saves the edit form withtagPrefix == "", keeptag_prefixblank instead of allocating an unrelatedsubN-vianextDefaultSubPrefix(sub.Id).AllActiveOutbounds/AllActiveOutboundTags):fetchOutboundsandrewriteStoredPrefix, collectreservedExternalTags(sub.Id)(tags from template outbounds and other subscriptions'LastFetchedOutbounds) and pass them toassignStableTagsWithExternalso-Ndisambiguation suffixes are persisted directly inLastFetchedOutboundsandLinkIdentities(preventing priority reordering or subscription disabling from silently swapping tags).dedupeSubscriptionOutboundList(withlogger.Warningflogging) in bothactiveOutboundsSplitandmergeSubscriptionOutboundssoAllActiveOutbounds,AllActiveOutboundTags,OutboundTraffics, and the generated Xray config always expose identical tags.Verification
go test ./internal/web/service -run 'TestAssignStableTags|TestDefaultPrefixNumber|TestOutboundSubscription|TestActiveOutbounds|TestMergeSubscriptionOutbounds' -count=1 -v(20/20 PASS)go vet ./internal/web/service,gofmt -l,git diff --check(all clean)