mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-07-24 21:46:07 +00:00
fix(sub): SS2022 share links must not base64-encode userinfo (#5432)
Per SIP022, ss:// links for 2022-blake3-* methods must NOT base64-encode the userinfo; method and password are percent-encoded instead. Clients like Hiddify reject the base64 form. Fix both the server-side subscription path and the client-side panel link, plus the matching parsers for round-trip import.
This commit is contained in:
@@ -617,6 +617,19 @@ export function genShadowsocksLink(input: GenShadowsocksLinkInput): string {
|
||||
if (isSS2022) passwords.push(settings.password);
|
||||
if (isSSMultiUser) passwords.push(clientPassword);
|
||||
|
||||
if (isSS2022) {
|
||||
// SIP022 (2022-blake3-*) forbids base64 userinfo: method and each key are
|
||||
// percent-encoded, joined by literal ':' separators. Built by hand because
|
||||
// `new URL` would re-encode the inner key separator to %3A.
|
||||
const userinfo = [settings.method, ...passwords].map(encodeURIComponent).join(':');
|
||||
let link = `ss://${userinfo}@${formatUrlHost(address)}:${port}`;
|
||||
const query = params.toString();
|
||||
if (query) link += `?${query}`;
|
||||
link += `#${encodeURIComponent(remark)}`;
|
||||
return link;
|
||||
}
|
||||
|
||||
// SIP002 userinfo is base64(method:pw).
|
||||
const userinfo = Base64.encode(`${settings.method}:${passwords.join(':')}`, true);
|
||||
const url = new URL(`ss://${userinfo}@${formatUrlHost(address)}:${port}`);
|
||||
for (const [key, value] of params) url.searchParams.set(key, value);
|
||||
|
||||
@@ -372,8 +372,15 @@ export function parseShadowsocksLink(link: string): Raw | null {
|
||||
const core = queryIndex >= 0 ? linkNoHash.slice(0, queryIndex) : linkNoHash;
|
||||
const atIndex = core.indexOf('@');
|
||||
if (atIndex >= 0) {
|
||||
try { userInfo = Base64.decode(core.slice('ss://'.length, atIndex)); }
|
||||
catch { userInfo = core.slice('ss://'.length, atIndex); }
|
||||
const rawUserInfo = core.slice('ss://'.length, atIndex);
|
||||
if (rawUserInfo.includes(':')) {
|
||||
// SIP022 (2022-blake3-*) userinfo is percent-encoded, never base64
|
||||
// (a literal ':' can't appear in a base64/base64url string).
|
||||
try { userInfo = decodeURIComponent(rawUserInfo); } catch { userInfo = rawUserInfo; }
|
||||
} else {
|
||||
try { userInfo = Base64.decode(rawUserInfo); }
|
||||
catch { userInfo = rawUserInfo; }
|
||||
}
|
||||
const hostPort = core.slice(atIndex + 1);
|
||||
const colon = hostPort.lastIndexOf(':');
|
||||
if (colon < 0) return null;
|
||||
|
||||
Reference in New Issue
Block a user