Nginx 如何代理转发传递真实 ip 地址

2024-08-01 10:19:00 Jinyu

Nginx 是一个高性能的反向代理服务器,也是一个非常流行的负载均衡器和 HTTP 缓存。其轻量级的设计和高并发处理能力使得它广泛应用于各种 Web 服务中。在使用 Nginx 作为反向代理服务器时,一个常见的问题是如何在代理转发过程中传递客户端的真实 IP 地址。默认情况下,Nginx 会将客户端的 IP 地址替换为代理服务器的 IP 地址,这可能会在某些情况下引发问题,比如日志记录、访问控制和地理位置追踪等。

图片

为什么需要传递真实 IP 地址

传递真实 IP 地址的需求主要有以下几个原因:

  1. 「日志记录和分析」:真实 IP 地址对于日志分析和用户行为追踪至关重要。如果使用代理服务器的 IP 地址,所有请求看起来都来自同一来源,这会导致分析结果不准确。

  2. 「安全和访问控制」:基于 IP 地址的访问控制策略需要识别真实的客户端 IP 地址。如果只看到代理服务器的 IP 地址,访问控制策略将无法正确应用。

  3. 「地理位置追踪」:很多服务依赖于客户端的地理位置信息,而这些信息通常是基于 IP 地址进行的。如果无法获取到真实的客户端 IP 地址,地理位置服务将无法正常工作。

使用 X-Forwarded-For 头传递真实 IP 地址

最常用的方法是通过 X-Forwarded-For HTTP 头传递客户端的真实 IP 地址。Nginx 可以在代理转发请求时添加这个头,以便后端服务器能够获取到真实的客户端 IP 地址。

在 Nginx 配置文件中,可以使用以下指令来设置 X-Forwarded-For 头:

http {
include mime.types;
default_typeapplication/octet-stream;

log_formatmain'$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"'

access_log/var/log/nginx/access.logmain;

sendfileon;
#tcp_nopush on;

keepalive_timeout65;

gzipon;

server {
listen 80;
server_namelocalhost;

location / {
proxy_pass http://backend_server;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
}

在上述配置中:

  • proxy_pass:指定后端服务器的地址。
  • proxy_set_header:用于设置请求头。X-Real-IP 头传递客户端的真实 IP 地址,而 X-Forwarded-For 头包含客户端的真实 IP 地址以及代理服务器的 IP 地址。

后端服务器的配置

后端服务器需要正确解析 X-Forwarded-For 头以获取客户端的真实 IP 地址。例如,在 Apache 中,可以使用 mod_remoteip 模块:

<IfModule mod_remoteip.c>
RemoteIPHeader X-Forwarded-For
RemoteIPInternalProxy 10.0.0.0/8
</IfModule>

在以上配置中:

  • RemoteIPHeader:指定用于传递真实 IP 地址的请求头。
  • RemoteIPInternalProxy:指定可信任的代理服务器的 IP 地址范围。

使用 real_ip 模块

Nginx 提供了一个 ngx_http_realip_module 模块,用于处理 X-Forwarded-For 头并将其作为客户端的真实 IP 地址。

启用 real_ip 模块

首先,确保 Nginx 已经编译并启用了 ngx_http_realip_module 模块。可以通过以下命令检查:

nginx -V 2>&1 | grep -o with-http_realip_module

如果输出结果中包含 with-http_realip_module,则表示该模块已启用。

配置 real_ip 模块

在 Nginx 配置文件中,可以使用以下配置来启用 real_ip 模块:

http {
include mime.types;
default_typeapplication/octet-stream;

log_formatmain'$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"'

access_log/var/log/nginx/access.logmain;

sendfileon;
#tcp_nopush on;

keepalive_timeout65;

gzipon;

real_ip_header X-Forwarded-For;
set_real_ip_from 10.0.0.0/8;

server {
listen 80;
server_namelocalhost;

location / {
proxy_pass http://backend_server;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
}

在以上配置中:

  • real_ip_header:指定用于传递真实 IP 地址的请求头。
  • set_real_ip_from:指定可信任的代理服务器的 IP 地址范围。

假设有一个前端 Nginx 服务器和一个后端应用服务器,前端服务器的 IP 地址为 192.168.1.1,后端服务器的 IP 地址为 192.168.1.2

在前端 Nginx 服务器上,可以使用以下配置:

server {
listen 80;
server_name frontend.example.com;

location / {
proxy_pass http://192.168.1.2;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}

在后端应用服务器上,可以使用以下配置:

server {
listen 80;
server_name backend.example.com;

real_ip_header X-Forwarded-For;
set_real_ip_from 192.168.1.1;

location / {
root /var/www/html;
index index.html index.htm;
}
}

配置完成后,可以通过以下步骤验证真实 IP 地址的传递是否正确:

  1. 「发送请求」:从客户端发送一个 HTTP 请求到前端 Nginx 服务器。
  2. 「检查日志」:在后端应用服务器的日志中检查请求的 IP 地址,确保显示的是客户端的真实 IP 地址而不是前端 Nginx 服务器的 IP 地址。

例如,可以使用 curl 命令发送请求:

curl -I http://frontend.example.com

然后,在后端应用服务器的日志中检查请求的 IP 地址:

tail -f /var/log/nginx/access.log

日志中应显示客户端的真实 IP 地址,而不是前端 Nginx 服务器的 IP 地址。

常见问题和解决方法

问题一:后端服务器仍然显示代理服务器的 IP 地址

解决方法:确保在后端服务器的 Nginx 配置中正确设置了 real_ip_header 和 set_real_ip_from 指令,并且前端服务器已正确设置 X-Forwarded-For 头。

问题二:多个代理服务器导致 X-Forwarded-For 头中包含多个 IP 地址

解决方法:在后端服务器的配置中,确保 real_ip_recursive 指令已启用,以处理包含多个 IP 地址的 X-Forwarded-For 头。

http {
real_ip_header X-Forwarded-For;
set_real_ip_from 192.168.1.1;
real_ip_recursive on;
}

总结

在使用 Nginx 作为反向代理服务器时,传递客户端的真实 IP 地址对于日志记录、访问控制和地理位置追踪等应用至关重要。通过使用 X-Forwarded-For 头和 ngx_http_realip_module 模块,可以有效地实现这一需求。正确配置后端服务器以解析这些头信息,将确保能够正确获取到客户端的真实 IP 地址,从而提升系统的可靠性和准确性。


我要咨询