跳转到主要内容

向 HTTP 后端传递访问者真实 IP

通过 X-Forwarded-For 向 HTTP 后端传递访问者地址,并正确配置可信代理

HTTP(S) 隧道默认由 NPC 连接内网服务,因此后端看到的 TCP 来源通常是 NPC 所在主机,而不是公网访问者。开启来源头后,NPS 会把访问者地址写入 HTTP 请求头,供后端应用或反向代理恢复真实 IP。

开启来源头

在服务端 nps.conf 中设置:

http_add_origin_header=true

重启 NPS 后生效。NPS 会在转发请求时设置:

  • X-Forwarded-For:保留已有链路并在末尾追加 NPS 实际看到的来源地址。
  • X-Real-IP:设置为 NPS 生成的来源地址内容。

该功能只适用于 NPS 能解析 HTTP 的流量。HTTPS 隧道必须在 NPS 上配置证书并由 NPS 终止 TLS;未配置证书时是 TLS 透传,NPS 无法插入请求头。原始 TCP 服务请使用 PROXY 协议 。

配置后端反向代理

不要无条件信任公网传入的 X-Forwarded-For。下面的 127.0.0.1 应替换为后端实际看到的直接上游地址:目标服务与 NPC 同机时通常是回环地址,目标在另一台内网主机时通常是 NPC 的内网地址。

Nginx

确保 Nginx 包含 http_realip_module,在 http、server 或对应 location 中配置:

set_real_ip_from 127.0.0.1; # 只信任 NPC 到后端的来源地址
real_ip_header X-Forwarded-For;
real_ip_recursive on;

log_format with_real_ip '$remote_addr proxy=$realip_remote_addr "$request"';
access_log /var/log/nginx/access.log with_real_ip;

应用读取 $remote_addr 即可得到解析后的访问者地址,$realip_remote_addr 保留直接上游地址。检查并重载配置:

nginx -t && nginx -s reload

Apache HTTP Server

启用 mod_remoteip,然后在虚拟主机中配置:

RemoteIPHeader X-Forwarded-For
RemoteIPTrustedProxy 127.0.0.1

LogFormat "%a proxy=%{c}a %l %u %t \"%r\" %>s %b" nps_real_ip
CustomLog logs/access_log nps_real_ip

Debian/Ubuntu 可先执行 a2enmod remoteip。检查并平滑重载:

apachectl configtest && apachectl graceful

%a 是处理后的访问者地址,%{c}a 是连接到 Apache 的直接上游地址。

Caddy

Caddy 需要把 NPC 的地址声明为可信代理,并严格从右向左解析转发链:

{
    servers {
        trusted_proxies static 127.0.0.1/32
        trusted_proxies_strict
    }
}

internal.example.com {
    reverse_proxy 127.0.0.1:8080
}

检查并平滑加载:

caddy validate --config /etc/caddy/Caddyfile
caddy reload --config /etc/caddy/Caddyfile

应用或日志可使用 Caddy 的 {client_ip} 占位符取得解析后的地址。

验证与排障

先让后端临时输出请求头,再从另一网络发起请求:

curl -H 'X-Forwarded-For: 198.51.100.123' https://your-domain.example/

正确配置时,后端识别出的地址应是实际访问端,而不是伪造的 198.51.100.123、NPC 地址或回环地址。若仍看到 NPC 地址,请依次检查:NPS 是否已重启、HTTPS 是否在 NPS 终止、可信代理地址是否填写为后端实际看到的直接上游,以及前方 CDN/负载均衡器是否另有可信代理链配置。