feat: add socks support

This commit is contained in:
divocat
2025-10-20 21:24:08 +03:00
parent 49dd1d608f
commit f0290fcc9e
7 changed files with 221 additions and 5 deletions

View File

@@ -383,6 +383,72 @@ function validateTrojanUrl(url) {
return { valid: true, message: _("Valid") };
}
// src/validators/validateSocksUrl.ts
function validateSocksUrl(url) {
try {
if (!/^socks(4|4a|5):\/\//.test(url)) {
return {
valid: false,
message: _(
"Invalid SOCKS URL: must start with socks4://, socks4a://, or socks5://"
)
};
}
if (!url || /\s/.test(url)) {
return {
valid: false,
message: _("Invalid SOCKS URL: must not contain spaces")
};
}
const body = url.replace(/^socks(4|4a|5):\/\//, "");
const [authAndHost] = body.split("#");
const [credentials, hostPortPart] = authAndHost.includes("@") ? authAndHost.split("@") : [null, authAndHost];
if (credentials) {
const [username, _password] = credentials.split(":");
if (!username) {
return {
valid: false,
message: _("Invalid SOCKS URL: missing username")
};
}
}
if (!hostPortPart) {
return {
valid: false,
message: _("Invalid SOCKS URL: missing host and port")
};
}
const [host, port] = hostPortPart.split(":");
if (!host) {
return {
valid: false,
message: _("Invalid SOCKS URL: missing hostname or IP")
};
}
if (!port) {
return { valid: false, message: _("Invalid SOCKS URL: missing port") };
}
const portNum = Number(port);
if (!Number.isInteger(portNum) || portNum < 1 || portNum > 65535) {
return {
valid: false,
message: _("Invalid SOCKS URL: invalid port number")
};
}
const ipv4Result = validateIPV4(host);
const domainResult = validateDomain(host);
if (!ipv4Result.valid && !domainResult.valid) {
return {
valid: false,
message: _("Invalid SOCKS URL: invalid host format")
};
}
} catch (_e) {
return { valid: false, message: _("Invalid SOCKS URL: parsing failed") };
}
return { valid: true, message: _("Valid") };
}
// src/validators/validateProxyUrl.ts
function validateProxyUrl(url) {
if (url.startsWith("ss://")) {
@@ -394,9 +460,14 @@ function validateProxyUrl(url) {
if (url.startsWith("trojan://")) {
return validateTrojanUrl(url);
}
if (/^socks(4|4a|5):\/\//.test(url)) {
return validateSocksUrl(url);
}
return {
valid: false,
message: _("URL must start with vless:// or ss:// or trojan://")
message: _(
"URL must start with vless://, ss://, trojan://, or socks4/5://"
)
};
}
@@ -4490,6 +4561,7 @@ return baseclass.extend({
validatePath,
validateProxyUrl,
validateShadowsocksUrl,
validateSocksUrl,
validateSubnet,
validateTrojanUrl,
validateUrl,