|
|
@@ -210,6 +210,43 @@ async function selectValueByMode() {
|
|
|
throw new Error(`invalid VALUE_SOURCE_MODE=${VALUE_SOURCE_MODE}, expected: default | server_only | router_only`);
|
|
|
}
|
|
|
|
|
|
+function normalizeIPv4(raw) {
|
|
|
+ const parts = raw.split(".");
|
|
|
+ if (parts.length !== 4) return null;
|
|
|
+ for (const part of parts) {
|
|
|
+ if (!/^\d{1,3}$/.test(part)) return null;
|
|
|
+ const n = Number(part);
|
|
|
+ if (!Number.isInteger(n) || n < 0 || n > 255) return null;
|
|
|
+ }
|
|
|
+ return parts.map((part) => String(Number(part))).join(".");
|
|
|
+}
|
|
|
+
|
|
|
+function normalizeIPv6(raw) {
|
|
|
+ let value = raw;
|
|
|
+ if (value.startsWith("[") || value.endsWith("]")) {
|
|
|
+ if (!(value.startsWith("[") && value.endsWith("]"))) return null;
|
|
|
+ value = value.slice(1, -1);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!value || !/^[0-9a-f:]+$/.test(value)) return null;
|
|
|
+ if ((value.match(/::/g) || []).length > 1) return null;
|
|
|
+
|
|
|
+ const hasCompression = value.includes("::");
|
|
|
+ const sides = value.split("::");
|
|
|
+ const left = sides[0] ? sides[0].split(":") : [];
|
|
|
+ const right = sides.length > 1 && sides[1] ? sides[1].split(":") : [];
|
|
|
+ const groups = left.concat(right);
|
|
|
+
|
|
|
+ if (groups.some((part) => !/^[0-9a-f]{1,4}$/.test(part))) return null;
|
|
|
+ if (hasCompression) {
|
|
|
+ if (groups.length >= 8) return null;
|
|
|
+ } else if (groups.length !== 8) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ return value;
|
|
|
+}
|
|
|
+
|
|
|
function extractOverrideDomain() {
|
|
|
const args = typeof $arguments !== "undefined" ? $arguments : {};
|
|
|
|
|
|
@@ -225,16 +262,17 @@ function extractOverrideDomain() {
|
|
|
if (!raw) return null;
|
|
|
|
|
|
// 基本格式校验:域名或 IPv4/IPv6
|
|
|
- const domainRe = /^([a-z0-9]([a-z0-9-]*[a-z0-9])?\.)+[a-z]{2,}$/;
|
|
|
- const ipv4Re = /^(\d{1,3}\.){3}\d{1,3}$/;
|
|
|
- const ipv6Re = /^\[?[0-9a-f:]+\]?$/;
|
|
|
+ const domainRe = /^([a-z0-9]([a-z0-9-]*[a-z0-9])?\.)+(?=[a-z0-9-]{2,}$)(?=[a-z0-9-]*[a-z])[a-z0-9]([a-z0-9-]*[a-z0-9])?$/;
|
|
|
+ const ipv4 = normalizeIPv4(raw);
|
|
|
+ if (ipv4) return ipv4;
|
|
|
|
|
|
- if (!domainRe.test(raw) && !ipv4Re.test(raw) && !ipv6Re.test(raw)) {
|
|
|
- logWithTime(`[vmess-domain-rotator] invalid override domain format: "${raw}", ignoring`);
|
|
|
- return null;
|
|
|
- }
|
|
|
+ const ipv6 = normalizeIPv6(raw);
|
|
|
+ if (ipv6) return ipv6;
|
|
|
|
|
|
- return raw;
|
|
|
+ if (domainRe.test(raw)) return raw;
|
|
|
+
|
|
|
+ logWithTime(`[vmess-domain-rotator] invalid override domain format: "${raw}", ignoring`);
|
|
|
+ return null;
|
|
|
}
|
|
|
|
|
|
async function operator(proxies = [], targetPlatform, context) {
|
|
|
@@ -283,4 +321,3 @@ async function operator(proxies = [], targetPlatform, context) {
|
|
|
|
|
|
return proxies;
|
|
|
}
|
|
|
-
|