diff --git a/backend/server.js b/backend/server.js index fad85ad..6589201 100644 --- a/backend/server.js +++ b/backend/server.js @@ -814,29 +814,51 @@ function cleanupOldTempFiles() { function isPrivateIp(ip) { if (!net.isIP(ip)) return false; - return ip.startsWith('10.') || - ip.startsWith('192.168.') || - ip.startsWith('172.16.') || - ip.startsWith('172.17.') || - ip.startsWith('172.18.') || - ip.startsWith('172.19.') || - ip.startsWith('172.20.') || - ip.startsWith('172.21.') || - ip.startsWith('172.22.') || - ip.startsWith('172.23.') || - ip.startsWith('172.24.') || - ip.startsWith('172.25.') || - ip.startsWith('172.26.') || - ip.startsWith('172.27.') || - ip.startsWith('172.28.') || - ip.startsWith('172.29.') || - ip.startsWith('172.30.') || - ip.startsWith('172.31.') || - ip.startsWith('127.') || - ip === '0.0.0.0' || - ip === '::1' || - ip.startsWith('fe80:') || - ip.startsWith('fd'); + + // IPv4 私有地址和特殊地址 + if (net.isIPv4(ip)) { + // 10.0.0.0/8 - 私有网络 + if (ip.startsWith('10.')) return true; + // 192.168.0.0/16 - 私有网络 + if (ip.startsWith('192.168.')) return true; + // 172.16.0.0/12 - 私有网络 (172.16.0.0 - 172.31.255.255) + if (/^172\.(1[6-9]|2[0-9]|3[01])\./.test(ip)) return true; + // 127.0.0.0/8 - 回环地址 + if (ip.startsWith('127.')) return true; + // 0.0.0.0 - 无效地址 + if (ip === '0.0.0.0') return true; + // 169.254.0.0/16 - 链路本地地址(包括云服务元数据 169.254.169.254) + if (ip.startsWith('169.254.')) return true; + // 100.64.0.0/10 - 运营商级NAT + if (/^100\.(6[4-9]|[7-9][0-9]|1[01][0-9]|12[0-7])\./.test(ip)) return true; + + return false; + } + + // IPv6 私有地址和特殊地址 + if (net.isIPv6(ip)) { + const lowerIp = ip.toLowerCase(); + + // ::1 - 回环地址 + if (lowerIp === '::1') return true; + // :: - 未指定地址 + if (lowerIp === '::') return true; + // fe80::/10 - 链路本地地址 + if (/^fe[89ab][0-9a-f]:/i.test(lowerIp)) return true; + // fc00::/7 - 唯一本地地址 (fc 和 fd 开头) + if (/^f[cd][0-9a-f]{2}:/i.test(lowerIp)) return true; + // ff00::/8 - 多播地址 + if (lowerIp.startsWith('ff')) return true; + // ::ffff:x.x.x.x - IPv4映射地址,需要检查内部的IPv4 + const ipv4Mapped = lowerIp.match(/^::ffff:(\d+\.\d+\.\d+\.\d+)$/); + if (ipv4Mapped) { + return isPrivateIp(ipv4Mapped[1]); + } + + return false; + } + + return false; } async function validateSftpDestination(host, port) {