Skip to content

Commit a2a6989

Browse files
committed
fix: 修复 SS URI 解析
1 parent 4c3da54 commit a2a6989

3 files changed

Lines changed: 73 additions & 8 deletions

File tree

backend/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "sub-store",
3-
"version": "2.22.10",
3+
"version": "2.22.11",
44
"description": "Advanced Subscription Manager for QX, Loon, Surge, Stash and Shadowrocket.",
55
"main": "src/main.js",
66
"scripts": {

backend/src/core/proxy-utils/parsers/index.js

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,23 @@ function splitURIFragment(raw) {
4646
};
4747
}
4848

49+
function decodeShadowsocksUserInfo(rawUserInfoStr) {
50+
const separatorIndex = rawUserInfoStr.indexOf(':');
51+
if (separatorIndex !== -1) {
52+
return [
53+
decodeURIComponent(rawUserInfoStr.slice(0, separatorIndex)),
54+
decodeURIComponent(rawUserInfoStr.slice(separatorIndex + 1)),
55+
].join(':');
56+
}
57+
58+
const decodedUserInfoStr = decodeURIComponent(rawUserInfoStr);
59+
if (decodedUserInfoStr.includes(':')) {
60+
return decodedUserInfoStr;
61+
}
62+
63+
return Base64.decode(decodedUserInfoStr);
64+
}
65+
4966
function parseWireGuardURIAddressValue(value) {
5067
if (value == null) return null;
5168
const raw = `${value}`.trim();
@@ -182,13 +199,7 @@ function URI_SS() {
182199
// handle IPV4 and IPV6
183200
let serverAndPortArray = content.match(/@([^/?]*)(\/|\?|$)/);
184201

185-
let rawUserInfoStr = decodeURIComponent(content.split('@')[0]); // 其实应该分隔之后, 用户名和密码再 decodeURIComponent. 但是问题不大
186-
let userInfoStr;
187-
if (rawUserInfoStr?.startsWith('2022-blake3-')) {
188-
userInfoStr = rawUserInfoStr;
189-
} else {
190-
userInfoStr = Base64.decode(rawUserInfoStr);
191-
}
202+
let userInfoStr = decodeShadowsocksUserInfo(content.split('@')[0]);
192203

193204
let query = '';
194205
if (!serverAndPortArray) {

backend/src/test/proxy-parsers/uri.spec.js

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,60 @@ describe('Proxy URI parser coverage', function () {
102102
});
103103
});
104104

105+
it('parses SIP002 Base64URL shadowsocks userinfo', function () {
106+
const proxy = parseOne(
107+
`ss://${Base64.encodeURI(
108+
'aes-128-gcm:aa>',
109+
)}@ss.example.com:8388#SS%20Base64URL`,
110+
);
111+
112+
expectSubset(proxy, {
113+
type: 'ss',
114+
name: 'SS Base64URL',
115+
server: 'ss.example.com',
116+
port: 8388,
117+
cipher: 'aes-128-gcm',
118+
password: 'aa>',
119+
});
120+
});
121+
122+
it('parses SIP002 plain shadowsocks userinfo with percent-encoded credentials', function () {
123+
const password = 'sec:ret@/plus+';
124+
const proxy = parseOne(
125+
`ss://aes-128-gcm:${encodeURIComponent(
126+
password,
127+
)}@ss.example.com:8388#SS%20Plain`,
128+
);
129+
130+
expectSubset(proxy, {
131+
type: 'ss',
132+
name: 'SS Plain',
133+
server: 'ss.example.com',
134+
port: 8388,
135+
cipher: 'aes-128-gcm',
136+
password,
137+
});
138+
});
139+
140+
it('parses SIP002 AEAD-2022 plain userinfo without Base64URL decoding', function () {
141+
const password =
142+
'YctPZ6U7xPPcU+gp3u+0tx/tRizJN9K8y+uKlW2qjlI=';
143+
const proxy = parseOne(
144+
`ss://2022-blake3-aes-256-gcm:${encodeURIComponent(
145+
password,
146+
)}@192.168.100.1:8888#SS%202022`,
147+
);
148+
149+
expectSubset(proxy, {
150+
type: 'ss',
151+
name: 'SS 2022',
152+
server: '192.168.100.1',
153+
port: 8888,
154+
cipher: '2022-blake3-aes-256-gcm',
155+
password,
156+
});
157+
});
158+
105159
it('parses legacy shadowsocks URIs with v2ray-plugin options', function () {
106160
const legacy = Base64.encode(
107161
'chacha20-ietf-poly1305:legacy-pass@legacy.example.com:443',

0 commit comments

Comments
 (0)