* sub: isolate Incy subscription routing from Happ headers
The resolved Incy line is written to the body only when IsIncyClient
matches the subscription User-Agent, Incy routing is enabled, and the
resolved text is non-blank. ApplyCommonHeaders computes that same Incy
check once and, for a matching client, skips the Happ routing-header
block, leaving Routing-Enable, the Happ Routing value, and the JSON
routing header unset. ApplyIncyHeaders is called with that incyClient
flag. The new test requests the subscription as INCY/1.0.0/ios and as
Happ/1.2.0 and expects the Incy response to end with the incy:// line
and to have empty Routing headers, and the Happ response to keep the
happ:// Routing header with Routing-Enable true and no incy:// line in
the body.
Fixes#6062
* fix(sub): keep the shared JSON routing profile for INCY clients
The INCY isolation wrapped the whole Routing block, JSON fallback
included, in !incyClient. INCY therefore lost the subJsonRoutingRules
profile that #6402 sends as the Routing header so Happ and INCY fetch
the geo files the baked rules reference, on the raw, JSON and Clash
endpoints alike, while every other client kept it, incy:// deeplinks
included.
INCY accepts a routing link of any scheme in that header
(docs.incy.cc/en/routing), so only the Happ tab is Happ-only: an INCY
request now reads it as blank and falls back to the shared profile,
as the setting text promises. Where the raw body carries INCY's own
profile the header is dropped, because INCY ranks a Routing header
above a base64 body line (docs.incy.cc/en/app-management) and the
shared profile would override it, which is #6062 again.
---------
Co-authored-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com>
Co-authored-by: MHSanaei <ho3ein.sanaei@gmail.com>
The WireGuard branch now copies PublicKey from the matching inbound
settings client. When that entry's KeepAlive is nil the peer keepalive
is cleared, and when it is set the integer is copied into a new pointer.
The dual-tunnel test seeds different keys and keepalives, checks that
the shared row still has the AmneziaWG identity, and expects the emitted
WireGuard peer to use the WireGuard public key and keepalive, including
a case where the WireGuard settings entry has no keepalive and the peer
omits it.
Fixes#6731
matchingClients primed the per-request link cache with the shared clients rows, whose wg_* columns hold whichever WireGuard/AmneziaWG inbound synced last. A client on several such inbounds (one per node) therefore got the same tunnel address and keys in every subscription profile.
Membership, subId, enable, quota and expiry still come from the normalized tables. For WireGuard and AmneziaWG the tunnel identity (keys, AllowedIPs, keepalive) is now overlaid from this inbound's own settings, the source clientsForLinkExport already uses for direct links. A member with no settings entry, or malformed settings, yields no link for that inbound rather than another inbound's credentials.
Fixes#6641.
Clients are stored once per email in the client table, so when the same email
exists on more than one WireGuard inbound the shared record's AllowedIPs and
PreSharedKey win for every inbound. A client present on both a WG and an AWG
tunnel was emitted with one tunnel's address on both, so the second tunnel's
peer got the wrong allowedIPs.
Read the per-inbound client settings for WireGuard inbounds and, when the
inbound carries its own entry for that email, use its AllowedIPs and
PreSharedKey when building the peer.
Object-form DNS server entries always received port: 53, because
DnsServerObjectInnerSchema defaulted the port unconditionally and the
DnsServerModal wire adapter always wrote it. Per Xray-core, encrypted
schemes must not carry a port field; a non-standard port is embedded in
the URL instead.
Default the port to 53 only for non-encrypted addresses and omit it for
the encrypted DNS schemes Xray dispatches without a port - https,
https+local, h2c, h2c+local and quic+local - both in the Zod schema and
in the modal's valuesToWire adapter. Schemes are matched
case-insensitively to mirror Xray-core's EqualFold comparison. A shared
isEncryptedDnsAddress helper backs both paths.
Fixes#5920
Co-authored-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com>