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

举报
wljslmz 发表于 2025/12/26 11:04:08 2025/12/26
【摘要】 Nginx 是一个高性能的反向代理服务器,也是一个非常流行的负载均衡器和 HTTP 缓存。其轻量级的设计和高并发处理能力使得它广泛应用于各种 Web 服务中。在使用 Nginx 作为反向代理服务器时,一个常见的问题是如何在代理转发过程中传递客户端的真实 IP 地址。默认情况下,Nginx 会将客户端的 IP 地址替换为代理服务器的 IP 地址,这可能会在某些情况下引发问题,比如日志记录、访问...

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_type  application/octet-stream;

    log_format  main  '$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.log  main;

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;

    gzip  on;

    server {
        listen       80;
        server_name  localhost;

        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_type  application/octet-stream;

    log_format  main  '$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.log  main;

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;

    gzip  on;

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

    server {
        listen       80;
        server_name  localhost;

        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_headerset_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 地址,从而提升系统的可靠性和准确性。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。