Node.js HTTPS后端安全获取客户端真实IP的方法
安全获取Node.js HTTPS后端用户真实IP的最佳实践
核心原则:只信任可控代理,拒绝客户端自定义头
客户端直接发送的X-Forwarded-For、X-Real-IP等请求头完全不可信,必须通过反向代理(如Nginx)或CDN层覆盖这些头,仅保留代理层直接获取的真实连接IP。
1. Nginx反向代理配置(关键步骤)
在Nginx的server块中,强制覆盖客户端提交的代理头,确保只有Nginx获取的$remote_addr(即直接连接Nginx的IP)被传递给Node.js:
server { listen 443 ssl; server_name your-domain.com; # 覆盖客户端提交的代理头,仅保留Nginx获取的真实连接IP proxy_set_header X-Forwarded-For $remote_addr; proxy_set_header X-Real-IP $remote_addr; proxy_set_header Host $host; # 转发请求到Node.js服务 location / { proxy_pass http://localhost:3000; } }
如果使用多层信任代理(如Cloudflare + Nginx),则需要保留上层代理传递的X-Forwarded-For,但必须验证连接Nginx的IP是否属于服务商官方IP段(防止伪造):
# 先验证连接IP是否在Cloudflare信任IP段内(需替换为官方最新IP段) set $trusted_proxy 0; if ($remote_addr ~* ^103\.21\.244\..*|^103\.22\.200\..*) { set $trusted_proxy 1; } # 仅当来自信任代理时,保留上层的X-Forwarded-For,否则强制覆盖 proxy_set_header X-Forwarded-For $remote_addr; if ($trusted_proxy = 1) { proxy_set_header X-Forwarded-For $http_x_forwarded_for; }
2. Node.js后端的安全IP提取
在Express框架中,通过配置trust proxy指定信任的代理IP,让框架自动从可信的代理头中提取真实IP,避免直接读取不可信的请求头:
const express = require('express'); const app = express(); // 指定信任的代理IP(Nginx服务器的IP或IP段) app.set('trust proxy', ['127.0.0.1', '192.168.1.0/24']); // 获取真实IP的方式 app.get('/', (req, res) => { // req.ip 返回经过验证的真实IP // req.ips 返回代理链中的所有IP(从客户端到最后一层代理) res.send(`真实IP: ${req.ip}`); }); app.listen(3000);
如果不使用Express,可手动编写中间件验证代理来源后提取IP:
// 信任的代理IP列表 const TRUSTED_PROXIES = ['127.0.0.1', '192.168.1.100']; function getRealIP(req) { const clientIP = req.connection.remoteAddress; // 验证当前连接是否来自信任代理 if (!TRUSTED_PROXIES.includes(clientIP)) { return clientIP; // 直接返回连接IP,无代理 } // 从可信代理头中提取首个非代理IP const forwardedFor = req.headers['x-forwarded-for']; if (forwardedFor) { return forwardedFor.split(',')[0].trim(); } return clientIP; }
3. 验证代理来源的合法性
如果使用CDN或第三方代理服务(如Cloudflare、AWS CloudFront),必须验证连接到反向代理的IP是否属于服务商官方公布的IP段,防止攻击者伪造代理头。可通过ip-range-check库快速验证:
const ipRangeCheck = require('ip-range-check'); // 替换为服务商官方最新IP段 const CLOUDFLARE_IPS = ['103.21.244.0/22', '103.22.200.0/22']; function isTrustedProxy(ip) { return ipRangeCheck(ip, CLOUDFLARE_IPS); }
4. 关于VPN/匿名代理的局限性
如果用户使用匿名VPN、Tor或第三方代理服务,你只能获取到代理服务器的IP,无法直接拿到用户真实物理IP。这种情况下,可通过以下方式辅助判断:
- 检查IP的ASN信息(如使用
maxmind库),判断是否属于数据中心或已知VPN服务商的IP段; - 结合用户行为特征(如地理位置、设备指纹)做补充验证,但无法100%准确还原真实IP。
内容的提问来源于stack exchange,提问作者GisCat
相关产品推荐
相关产品推荐

