Skip to content

Commit 2a2e76a

Browse files
committed
feat: 完善 WireGuard IP/IPv6 解析转换
1 parent 820c191 commit 2a2e76a

15 files changed

Lines changed: 479 additions & 42 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.21.99",
3+
"version": "2.22.1",
44
"description": "Advanced Subscription Manager for QX, Loon, Surge, Stash and Shadowrocket.",
55
"main": "src/main.js",
66
"scripts": {

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

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,11 @@ import { findByName } from '@/utils/database';
2323
import { produceArtifact } from '@/restful/sync';
2424
import { getFlag, removeFlag, getISO, MMDB } from '@/utils/geo';
2525
import Gist from '@/utils/gist';
26-
import { isPresent, isShadowsocksOverTls } from './producers/utils';
26+
import {
27+
isPresent,
28+
isShadowsocksOverTls,
29+
normalizeWireGuardInterface,
30+
} from './producers/utils';
2731
import { doh } from '@/utils/dns';
2832
import JSON5 from 'json5';
2933
import { hex_md5 } from '@/vendor/md5';
@@ -313,6 +317,9 @@ function produce(proxies, targetPlatform, type, opts = {}) {
313317
proxy.port = getRandomPort(proxy.ports);
314318
}
315319
}
320+
if (proxy.type === 'wireguard') {
321+
normalizeWireGuardInterface(proxy);
322+
}
316323

317324
return proxy;
318325
});
@@ -745,18 +752,7 @@ function lastParse(proxy) {
745752
}
746753
}
747754
}
748-
if (proxy.ip?.includes('/')) {
749-
const [ip] = proxy.ip.split('/');
750-
if (isIPv4(ip)) {
751-
proxy.ip = ip;
752-
}
753-
}
754-
if (proxy.ipv6?.includes('/')) {
755-
const [ip] = proxy.ipv6.split('/');
756-
if (isIPv6(ip)) {
757-
proxy.ipv6 = ip;
758-
}
759-
}
755+
normalizeWireGuardInterface(proxy);
760756
}
761757
return proxy;
762758
}

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

Lines changed: 48 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,32 @@ function splitURIFragment(raw) {
4242
};
4343
}
4444

45+
function parseWireGuardURIAddressValue(value) {
46+
if (value == null) return null;
47+
const raw = `${value}`.trim();
48+
if (!raw) return null;
49+
const [, hostRaw = raw, cidrRaw] = /^(.*?)(?:\/(\d+))?$/.exec(raw) || [];
50+
const host = `${hostRaw}`.trim().replace(/^\[/, '').replace(/\]$/, '');
51+
const normalizeCIDR = (cidr, max) => {
52+
if (cidr == null) return undefined;
53+
if (!/^\d+$/.test(cidr)) return undefined;
54+
const parsed = parseInt(cidr, 10);
55+
if (parsed < 0 || parsed > max) return undefined;
56+
return parsed;
57+
};
58+
if (isIPv4(host)) {
59+
return { family: 'ipv4', address: host, cidr: normalizeCIDR(cidrRaw, 32) };
60+
}
61+
if (isIPv6(host)) {
62+
return {
63+
family: 'ipv6',
64+
address: host,
65+
cidr: normalizeCIDR(cidrRaw, 128),
66+
};
67+
}
68+
return null;
69+
}
70+
4571
function URI_PROXY() {
4672
// socks5+tls
4773
// socks5
@@ -1420,7 +1446,16 @@ function URI_WireGuard() {
14201446
};
14211447
for (const addon of addons.split('&')) {
14221448
if (addon) {
1423-
let [key, value] = addon.split('=');
1449+
const equalIndex = addon.indexOf('=');
1450+
let key;
1451+
let value;
1452+
if (equalIndex === -1) {
1453+
key = addon;
1454+
value = '';
1455+
} else {
1456+
key = addon.slice(0, equalIndex);
1457+
value = addon.slice(equalIndex + 1);
1458+
}
14241459
key = key.replace(/_/, '-');
14251460
value = decodeURIComponent(value);
14261461
if (['reserved'].includes(key)) {
@@ -1433,15 +1468,18 @@ function URI_WireGuard() {
14331468
}
14341469
} else if (['address', 'ip'].includes(key)) {
14351470
value.split(',').map((i) => {
1436-
const ip = i
1437-
.trim()
1438-
.replace(/\/\d+$/, '')
1439-
.replace(/^\[/, '')
1440-
.replace(/\]$/, '');
1441-
if (isIPv4(ip)) {
1442-
proxy.ip = ip;
1443-
} else if (isIPv6(ip)) {
1444-
proxy.ipv6 = ip;
1471+
const parsed = parseWireGuardURIAddressValue(i);
1472+
if (!parsed) return;
1473+
if (parsed.family === 'ipv4') {
1474+
proxy.ip = parsed.address;
1475+
if (typeof parsed.cidr !== 'undefined') {
1476+
proxy['ip-cidr'] = parsed.cidr;
1477+
}
1478+
} else if (parsed.family === 'ipv6') {
1479+
proxy.ipv6 = parsed.address;
1480+
if (typeof parsed.cidr !== 'undefined') {
1481+
proxy['ipv6-cidr'] = parsed.cidr;
1482+
}
14451483
}
14461484
});
14471485
} else if (['mtu'].includes(key)) {

backend/src/core/proxy-utils/producers/clash.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,8 @@ export default function Clash_Producer() {
200200
delete proxy.id;
201201
delete proxy.resolved;
202202
delete proxy['no-resolve'];
203+
delete proxy['ip-cidr'];
204+
delete proxy['ipv6-cidr'];
203205
if (type !== 'internal') {
204206
for (const key in proxy) {
205207
if (proxy[key] == null || /^_/i.test(key)) {

backend/src/core/proxy-utils/producers/clashmeta.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import {
2+
getWireGuardAddressWithCIDR,
23
isPresent,
34
produceProxyListOutput,
45
supportsShadowsocksV2rayPluginMode,
@@ -163,6 +164,8 @@ export default function ClashMeta_Producer() {
163164
proxy['preshared-key'] =
164165
proxy['preshared-key'] ?? proxy['pre-shared-key'];
165166
proxy['pre-shared-key'] = proxy['preshared-key'];
167+
proxy.ip = getWireGuardAddressWithCIDR(proxy, 'ipv4');
168+
proxy.ipv6 = getWireGuardAddressWithCIDR(proxy, 'ipv6');
166169
} else if (proxy.type === 'snell' && proxy.version < 3) {
167170
delete proxy.udp;
168171
} else if (proxy.type === 'vless') {
@@ -287,6 +290,8 @@ export default function ClashMeta_Producer() {
287290
delete proxy.id;
288291
delete proxy.resolved;
289292
delete proxy['no-resolve'];
293+
delete proxy['ip-cidr'];
294+
delete proxy['ipv6-cidr'];
290295
if (type !== 'internal' || opts['delete-underscore-fields']) {
291296
for (const key in proxy) {
292297
if (proxy[key] == null || /^_/i.test(key)) {

backend/src/core/proxy-utils/producers/egern.js

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
import $ from '@/core/app';
2-
import { isPresent, produceProxyListOutput } from './utils';
2+
import {
3+
getWireGuardAddressWithCIDR,
4+
isPresent,
5+
produceProxyListOutput,
6+
} from './utils';
37

48
export default function Egern_Producer() {
59
const type = 'ALL';
@@ -433,8 +437,14 @@ export default function Egern_Producer() {
433437
proxy = {
434438
type: 'wireguard',
435439
name: proxy.name,
436-
local_ipv4: proxy.ip,
437-
local_ipv6: proxy.ipv6,
440+
local_ipv4: getWireGuardAddressWithCIDR(
441+
proxy,
442+
'ipv4',
443+
),
444+
local_ipv6: getWireGuardAddressWithCIDR(
445+
proxy,
446+
'ipv6',
447+
),
438448
server: proxy.server,
439449
port: proxy.port,
440450
private_key: proxy['private-key'],

backend/src/core/proxy-utils/producers/shadowrocket.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import {
2+
getWireGuardAddressWithCIDR,
23
isPresent,
34
isShadowsocksOverTls,
45
produceProxyListOutput,
@@ -146,6 +147,8 @@ export default function Shadowrocket_Producer() {
146147
proxy['preshared-key'] =
147148
proxy['preshared-key'] ?? proxy['pre-shared-key'];
148149
proxy['pre-shared-key'] = proxy['preshared-key'];
150+
proxy.ip = getWireGuardAddressWithCIDR(proxy, 'ipv4');
151+
proxy.ipv6 = getWireGuardAddressWithCIDR(proxy, 'ipv6');
149152
} else if (proxy.type === 'snell' && proxy.version < 3) {
150153
delete proxy.udp;
151154
} else if (proxy.type === 'vless') {
@@ -277,6 +280,8 @@ export default function Shadowrocket_Producer() {
277280
delete proxy.id;
278281
delete proxy.resolved;
279282
delete proxy['no-resolve'];
283+
delete proxy['ip-cidr'];
284+
delete proxy['ipv6-cidr'];
280285
if (type !== 'internal') {
281286
for (const key in proxy) {
282287
if (proxy[key] == null || /^_/i.test(key)) {

backend/src/core/proxy-utils/producers/sing-box.js

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import ClashMeta_Producer from './clashmeta';
22
import $ from '@/core/app';
3-
import { isIPv4, isIPv6, isPlainObject } from '@/utils';
4-
import { normalizePluginMuxValue } from './utils';
3+
import { isPlainObject } from '@/utils';
4+
import { getWireGuardAddressWithCIDR, normalizePluginMuxValue } from './utils';
55

66
const ipVersions = {
77
ipv4: 'ipv4_only',
@@ -951,12 +951,8 @@ const tailscaleParser = (proxy = {}) => {
951951
};
952952

953953
const wireguardParser = (proxy = {}) => {
954-
const address = ['ip', 'ipv6']
955-
.map((i) => proxy[i])
956-
.map((i) => {
957-
if (isIPv4(i)) return `${i}/32`;
958-
if (isIPv6(i)) return `${i}/128`;
959-
})
954+
const address = ['ipv4', 'ipv6']
955+
.map((family) => getWireGuardAddressWithCIDR(proxy, family))
960956
.filter((i) => i);
961957
const parsedProxy = {
962958
system: !!proxy.system,

backend/src/core/proxy-utils/producers/stash.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,8 @@ export default function Stash_Producer() {
340340
delete proxy.id;
341341
delete proxy.resolved;
342342
delete proxy['no-resolve'];
343+
delete proxy['ip-cidr'];
344+
delete proxy['ipv6-cidr'];
343345
if (type !== 'internal') {
344346
for (const key in proxy) {
345347
if (proxy[key] == null || /^_/i.test(key)) {

backend/src/core/proxy-utils/producers/uri.js

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/* eslint-disable no-case-declarations */
22
import { Base64 } from 'js-base64';
33
import { isIPv6 } from '@/utils';
4-
import { normalizePluginMuxValue } from './utils';
4+
import { getWireGuardAddressWithCIDR, normalizePluginMuxValue } from './utils';
55
import { normalizeXhttpScalarUpperBound } from '../xhttp-utils';
66

77
function isObject(value) {
@@ -1168,6 +1168,8 @@ export default function URI_Producer() {
11681168
'port',
11691169
'ip',
11701170
'ipv6',
1171+
'ip-cidr',
1172+
'ipv6-cidr',
11711173
'private-key',
11721174
].includes(key)
11731175
) {
@@ -1186,19 +1188,27 @@ export default function URI_Producer() {
11861188
}
11871189
}
11881190
});
1189-
if (proxy.ip && proxy.ipv6) {
1191+
const wireguardIPv4 = getWireGuardAddressWithCIDR(
1192+
proxy,
1193+
'ipv4',
1194+
);
1195+
const wireguardIPv6 = getWireGuardAddressWithCIDR(
1196+
proxy,
1197+
'ipv6',
1198+
);
1199+
if (wireguardIPv4 && wireguardIPv6) {
11901200
wireguardParams.push(
11911201
`address=${encodeURIComponent(
1192-
`${proxy.ip}/32,${proxy.ipv6}/128`,
1202+
`${wireguardIPv4},${wireguardIPv6}`,
11931203
)}`,
11941204
);
1195-
} else if (proxy.ip) {
1205+
} else if (wireguardIPv4) {
11961206
wireguardParams.push(
1197-
`address=${encodeURIComponent(`${proxy.ip}/32`)}`,
1207+
`address=${encodeURIComponent(wireguardIPv4)}`,
11981208
);
1199-
} else if (proxy.ipv6) {
1209+
} else if (wireguardIPv6) {
12001210
wireguardParams.push(
1201-
`address=${encodeURIComponent(`${proxy.ipv6}/128`)}`,
1211+
`address=${encodeURIComponent(wireguardIPv6)}`,
12021212
);
12031213
}
12041214
result = `wireguard://${encodeURIComponent(

0 commit comments

Comments
 (0)