前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Nginx - 在Nginx中透传客户端真实IP的技巧

Nginx - 在Nginx中透传客户端真实IP的技巧

作者头像
小小工匠
发布2024-05-26 13:51:17
4750
发布2024-05-26 13:51:17
举报
文章被收录于专栏:小工匠聊架构小工匠聊架构

概述

1. 为什么需要获取客户端的真实 IP 地址?

在使用 Nginx 作为反向代理服务器时,默认情况下,后端服务器只能看到 Nginx 的 IP 地址。为了记录日志、限制访问或进行其他基于 IP 地址的操作,获取客户端的真实 IP 地址非常重要。

2. Nginx 中用于获取真实 IP 地址的模块

Nginx 提供了两个主要模块来处理这一需求:

  • HttpRealipModule: 用于从请求头中提取客户端的真实 IP 地址。
  • HttpGeoipModule: 用于根据 IP 地址定位地理位置(较少用于获取真实 IP)。

这里主要介绍 HttpRealipModule

3. 配置示例和步骤

3.1 安装和启用模块

大多数情况下,Nginx 已经包含了 HttpRealipModule。可以通过以下命令检查:

代码语言:javascript
复制
nginx -V 2>&1 | grep -o with-http_realip_module

如果没有启用该模块,则需要重新编译 Nginx 或安装包含该模块的 Nginx 版本。

3.2 配置 Nginx

编辑你的 Nginx 配置文件(通常位于 /etc/nginx/nginx.conf/etc/nginx/conf.d/ 中的某个文件),添加以下配置:

代码语言:javascript
复制
http {
    ...
    set_real_ip_from 0.0.0.0/0;  # 允许所有 IP 地址的代理
    real_ip_header X-Forwarded-For;
    real_ip_recursive on;
    ...
    
    server {
        ...
        location / {
            ...
            # 如果需要日志中记录真实 IP
            log_format custom '$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 custom;
            ...
        }
    }
}
3.3 配置说明
  • set_real_ip_from: 允许哪些 IP 地址可以作为可信代理。如果你的代理服务器在特定的 IP 范围内,只允许那些 IP。
  • real_ip_header: 指定哪个头部字段包含了真实 IP 地址。常用的是 X-Forwarded-For
  • real_ip_recursive: 递归地检查 X-Forwarded-For 头部中的所有 IP 地址,直到找到第一个非可信代理的 IP。

4. 潜在的陷阱和调试方法

4.1 潜在的陷阱
  • 代理链中的 IP 地址顺序X-Forwarded-For 头部可能包含多个 IP 地址,代表了一系列代理服务器。确保配置的 real_ip_recursive on 正确地获取到第一个客户端的 IP 地址。
  • 安全问题:配置 set_real_ip_from 时,要小心不要信任不受控制的 IP 地址,否则可能会导致 IP 欺骗。
4.2 调试方法
  • 检查日志:通过查看 Nginx 日志,确认是否成功获取到真实 IP 地址。
  • 测试请求:使用工具如 curl 模拟请求,带上 X-Forwarded-For 头部,观察服务器的响应和日志记录。
代码语言:javascript
复制
curl -H "X-Forwarded-For: 203.0.113.195" http://your-nginx-server

实操

http 节点 添加$http_x_forwarded_for日志格式

配置文件中需要添加$http_x_forwarded_for日志格式, 核心内容如下

代码语言:javascript
复制
http {
    include       mime.types;
    default_type  application/octet-stream;
    log_format  main  ' $remote_addr |  $http_x_forwarded_for |  $remote_user | $time_local | $request | $http_host |'
                      ' $status | $upstream_status | $body_bytes_sent | $http_referer '
                      ' $http_user_agent | $upstream_addr | $request_time | $upstream_response_time';

http节点 日志格式中需要添加$http_x_forwarded_for

log_format 指令用于定义 Nginx 的日志格式。它指定了在日志文件中记录哪些信息以及如何格式化这些信息。每个字段使用一个变量表示,变量之间可以用分隔符分开,如空格、竖线(|)等。定义的日志格式可以应用于 access_log 指令,以便记录客户端请求的详细信息。

以下是 log_format 指令中各个变量的含义:

代码语言:javascript
复制
log_format  main  ' $remote_addr |  $http_x_forwarded_for |  $remote_user | $time_local | $request | $http_host |'
                  ' $status | $upstream_status | $body_bytes_sent | $http_referer '
                  ' $http_user_agent | $upstream_addr | $request_time | $upstream_response_time';
  • $remote_addr: 客户端的 IP 地址。这是直接连接到 Nginx 的客户端的 IP 地址。
  • $http_x_forwarded_for: 客户端的真实 IP 地址。通常用于记录经过代理服务器或负载均衡器的客户端 IP 地址,X-Forwarded-For 头部中包含了这些 IP。
  • $remote_user: 客户端的用户名,如果请求需要 HTTP 基本认证时会记录用户名。如果没有认证信息则为 -
  • $time_local: 本地时间和日期,格式为 day/month/year:hour:minute:second
  • $request: 请求的完整 URI,包括参数。格式为 METHOD URI PROTOCOL,例如 GET /index.html HTTP/1.1
  • $http_host: 请求中的 Host 头部内容,即访问的主机名。
  • $status: 响应的 HTTP 状态码,例如 200 表示成功,404 表示未找到,500 表示服务器内部错误等。
  • $upstream_status: 上游服务器返回的状态码。当 Nginx 作为反向代理时,此变量记录上游服务器的响应状态码。
  • $body_bytes_sent: 传送给客户端的响应主体内容的字节数,不包括响应头的大小。
  • $http_referer: 请求的引用页面,即从哪个页面链接过来的(Referer 头部内容)。如果没有引用页面则为 -
  • $http_user_agent: 客户端使用的浏览器或其他客户端的信息(User-Agent 头部内容)。
  • $upstream_addr: 上游服务器的地址。当 Nginx 作为反向代理时,此变量记录上游服务器的 IP 地址和端口。
  • $request_time: 处理请求的总时间,从接收到客户端请求到完整发送响应的时间,单位为秒。
  • $upstream_response_time: 从上游服务器读取响应的时间,单位为秒。

server节点 配置

代码语言:javascript
复制
server {
  listen       80;
  server_name  localhost;
  access_log  logs/access.log  main;       #需要添加日志引用
  proxy_set_header X-Real-IP $remote_addr;    #添加透传配置
  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for
  location / {
  root html;
   }
}

https://www.cnblogs.com/shouke/p/15511149.html

使用 proxy_set_header 指令设置透传头部。确保代理服务器(如 Nginx)在转发请求时保留原始客户端的 IP 地址


验证

方式一

访问Nginx页面

访问日志

代码语言:javascript
复制
192.168.0.6 |  168.138.171.206 |  - | 19/May/2024:10:57:24 +0800 | GET / HTTP/1.1 | nginx.frps.fun | 200 | - | 615 | -  Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 | - | 0.000 | -
  1. 192.168.0.6:
    • 含义:直接连接到 Nginx 服务器的客户端的 IP 地址。在这个例子中,这可能是一个内网的 IP 地址。
  2. 168.138.171.206:
    • 含义:通过 X-Forwarded-For 头部获取的客户端的真实 IP 地址。在经过代理或负载均衡器时,这个头部会记录原始客户端的 IP 地址。
  3. -:
    • 含义:客户端的用户名。在请求需要 HTTP 基本认证时记录用户名。这里没有进行认证,所以显示为 -
  4. 19/May/2024:10:57:24 +0800:
    • 含义:请求到达服务器的本地时间,格式为 day/month/year:hour:minute:second timezone。这个例子中表示 2024 年 5 月 19 日上午 10:57:24,时区为 +0800。
  5. GET / HTTP/1.1:
    • 含义:客户端的请求行,包含请求的方法(GET)、请求的资源路径(/),以及使用的 HTTP 协议版本(HTTP/1.1)。
  6. nginx.frps.fun:
    • 含义:请求中的 Host 头部,表示客户端请求访问的主机名。
  7. 200:
    • 含义:HTTP 响应状态码,表示请求成功。200 代表成功。
  8. -:
    • 含义:上游服务器的响应状态码。在没有上游服务器时,这里显示为 -
  9. 615:
    • 含义:传送给客户端的响应主体内容的字节数,不包括响应头的大小。
  10. -:
    • 含义:请求的引用页面(Referer)。如果没有引用页面则显示为 -
  11. Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36:
    • 含义:客户端使用的浏览器或其他客户端的信息(User-Agent)。在这个例子中,表示客户端使用的是 Chrome 浏览器,运行在 macOS 上。
  12. -:
    • 含义:上游服务器的地址。在没有上游服务器时,这里显示为 -
  13. 0.000:
    • 含义:处理请求的总时间,从接收到客户端请求到完整发送响应的时间,单位为秒。
  14. -:
    • 含义:从上游服务器读取响应的时间。在没有上游服务器时,这里显示为 -

方式二

如果我们前面没有apisix或者其它lb,也可以使用curl命令来模拟X-Forwarded-For日志

代码语言:javascript
复制
curl http://127.0.0.1/ -H 'X-Forwarded-For: 1.1.1.1' -v
* About to connect() to 127.0.0.1 port 80 (#0)
*   Trying 127.0.0.1...
* Connected to 127.0.0.1 (127.0.0.1) port 80 (#0)
> GET / HTTP/1.1
> User-Agent: curl/7.29.0
> Host: 127.0.0.1
> Accept: */*
> X-Forwarded-For: 1.1.1.1       #-v参数可以看到这里参数已经传入
>
< HTTP/1.1 200 OK
< Server: nginx
< Date: Sun, 19 May 2024 03:09:05 GMT
< Content-Type: text/html; charset=utf-8
< Content-Length: 615
< Last-Modified: Mon, 09 Oct 2023 06:03:57 GMT
< Connection: keep-alive
< ETag: "652397cd-267"
< Accept-Ranges: bytes
<
<!DOCTYPE html>
#http:127.0.0.1 就是Nginx服务器
  • http://127.0.0.1/: 请求的 URL,127.0.0.1 表示本地服务器。
  • -H ‘X-Forwarded-For: 1.1.1.1’: 添加 HTTP 请求头 X-Forwarded-For,其值为 1.1.1.1。这个头部通常用于表示客户端的真实 IP 地址。
  • -v: 显示详细的请求和响应过程,包括头部信息

日志

代码语言:javascript
复制
127.0.0.1 | 1.1.1.1 | - | 19/May/2024:10:57:24 +0800 | GET / HTTP/1.1 | 127.0.0.1 | 200 | - | 615 | - | curl/7.29.0 | - | 0.000 | -

从日志文件 logs/access.log 中,可以验证 X-Forwarded-For 头部信息是否正确记录, 此日志记录显示,X-Forwarded-For 头部中传递的 1.1.1.1 已正确记录。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-05-20,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 概述
    • 1. 为什么需要获取客户端的真实 IP 地址?
      • 2. Nginx 中用于获取真实 IP 地址的模块
        • 3. 配置示例和步骤
          • 3.1 安装和启用模块
          • 3.2 配置 Nginx
          • 3.3 配置说明
        • 4. 潜在的陷阱和调试方法
          • 4.1 潜在的陷阱
          • 4.2 调试方法
      • 实操
        • http 节点 添加$http_x_forwarded_for日志格式
          • server节点 配置
            • 验证
              • 方式一
              • 方式二
          相关产品与服务
          负载均衡
          负载均衡(Cloud Load Balancer,CLB)提供安全快捷的流量分发服务,访问流量经由 CLB 可以自动分配到云中的多台后端服务器上,扩展系统的服务能力并消除单点故障。负载均衡支持亿级连接和千万级并发,可轻松应对大流量访问,满足业务需求。
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档