diff --git a/src/components/proxy/ProxyPanel.tsx b/src/components/proxy/ProxyPanel.tsx index 1052f2ece..fd6b9cb02 100644 --- a/src/components/proxy/ProxyPanel.tsx +++ b/src/components/proxy/ProxyPanel.tsx @@ -119,22 +119,36 @@ export function ProxyPanel({ const handleSaveBasicConfig = async () => { if (!globalConfig) return; - // 校验地址格式(简单的 IP 地址或 localhost 校验) + // 校验地址格式(IPv4 / IPv6 字面量 / localhost) const addressTrimmed = listenAddress.trim(); const ipv4Regex = /^(\d{1,3}\.){3}\d{1,3}$/; + const isValidIpv4 = (addr: string): boolean => + ipv4Regex.test(addr) && + addr.split(".").every((n) => { + const num = parseInt(n, 10); + return num >= 0 && num <= 255; + }); + // IPv6 字面量校验:必须含 `:` 且能在 [..] 包装后被 URL 解析器接受。 + // 后端 (services/proxy.rs) 会把 `::` 改写成 `::1`,所以这里也接受 `::`。 + const isValidIpv6 = (addr: string): boolean => { + if (!addr.includes(":")) return false; + try { + new URL(`http://[${addr}]/`); + return true; + } catch { + return false; + } + }; const isValidAddress = addressTrimmed === "localhost" || addressTrimmed === "0.0.0.0" || - (ipv4Regex.test(addressTrimmed) && - addressTrimmed.split(".").every((n) => { - const num = parseInt(n); - return num >= 0 && num <= 255; - })); + isValidIpv4(addressTrimmed) || + isValidIpv6(addressTrimmed); if (!isValidAddress) { toast.error( t("proxy.settings.invalidAddress", { defaultValue: - "地址无效,请输入有效的 IP 地址(如 127.0.0.1)或 localhost", + "地址无效,请输入 IPv4(如 127.0.0.1)、IPv6(如 ::1)或 localhost", }), ); return; diff --git a/src/i18n/locales/en.json b/src/i18n/locales/en.json index b4f54bc3c..eb2de6db5 100644 --- a/src/i18n/locales/en.json +++ b/src/i18n/locales/en.json @@ -2196,7 +2196,7 @@ "saveFailed": "Save failed: {{error}}" }, "invalidPort": "Invalid port, please enter a number between 1024-65535", - "invalidAddress": "Invalid address, please enter a valid IP address (e.g. 127.0.0.1) or localhost", + "invalidAddress": "Invalid address. Enter an IPv4 (e.g. 127.0.0.1), IPv6 (e.g. ::1), or localhost", "configSaved": "Routing configuration saved", "configSaveFailed": "Failed to save configuration", "restartRequired": "Restart routing service for address or port changes to take effect" diff --git a/src/i18n/locales/ja.json b/src/i18n/locales/ja.json index 94a7c5557..953c17672 100644 --- a/src/i18n/locales/ja.json +++ b/src/i18n/locales/ja.json @@ -2196,7 +2196,7 @@ "saveFailed": "保存に失敗しました: {{error}}" }, "invalidPort": "無効なポートです。1024〜65535 の数値を入力してください", - "invalidAddress": "無効なアドレスです。有効な IP アドレス(例: 127.0.0.1)または localhost を入力してください", + "invalidAddress": "無効なアドレスです。IPv4(例: 127.0.0.1)、IPv6(例: ::1)、または localhost を入力してください", "configSaved": "ルーティング設定を保存しました", "configSaveFailed": "設定の保存に失敗しました", "restartRequired": "アドレスまたはポートの変更を反映するにはルーティングサービスの再起動が必要です" diff --git a/src/i18n/locales/zh.json b/src/i18n/locales/zh.json index f82dc25cc..414bca5dd 100644 --- a/src/i18n/locales/zh.json +++ b/src/i18n/locales/zh.json @@ -2196,7 +2196,7 @@ "saveFailed": "保存失败: {{error}}" }, "invalidPort": "端口无效,请输入 1024-65535 之间的数字", - "invalidAddress": "地址无效,请输入有效的 IP 地址(如 127.0.0.1)或 localhost", + "invalidAddress": "地址无效,请输入 IPv4(如 127.0.0.1)、IPv6(如 ::1)或 localhost", "configSaved": "路由配置已保存", "configSaveFailed": "保存配置失败", "restartRequired": "修改地址或端口后需要重启路由服务才能生效"