Nginx - 在Nginx中透传客户端真实IP的技巧
小小工匠 2024-08-14 17:37:01 阅读 84
文章目录
概述1. 为什么需要获取客户端的真实 IP 地址?2. Nginx 中用于获取真实 IP 地址的模块3. 配置示例和步骤3.1 安装和启用模块3.2 配置 Nginx3.3 配置说明
4. 潜在的陷阱和调试方法4.1 潜在的陷阱4.2 调试方法
实操http 节点 添加$http_x_forwarded_for日志格式server节点 配置验证方式一方式二
概述
1. 为什么需要获取客户端的真实 IP 地址?
在使用 Nginx 作为反向代理服务器时,默认情况下,后端服务器只能看到 Nginx 的 IP 地址。为了记录日志、限制访问或进行其他基于 IP 地址的操作,获取客户端的真实 IP 地址非常重要。
2. Nginx 中用于获取真实 IP 地址的模块
Nginx 提供了两个主要模块来处理这一需求:
HttpRealipModule: 用于从请求头中提取客户端的真实 IP 地址。HttpGeoipModule: 用于根据 IP 地址定位地理位置(较少用于获取真实 IP)。
这里主要介绍 <code>HttpRealipModule。
3. 配置示例和步骤
3.1 安装和启用模块
大多数情况下,Nginx 已经包含了 HttpRealipModule
。可以通过以下命令检查:
nginx -V 2>&1 | grep -o with-http_realip_module
如果没有启用该模块,则需要重新编译 Nginx 或安装包含该模块的 Nginx 版本。
3.2 配置 Nginx
编辑你的 Nginx 配置文件(通常位于 /etc/nginx/nginx.conf
或 /etc/nginx/conf.d/
中的某个文件),添加以下配置:
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
头部,观察服务器的响应和日志记录。
curl -H "X-Forwarded-For: 203.0.113.195" http://your-nginx-server
实操
http 节点 添加$http_x_forwarded_for日志格式
配置文件中需要添加$http_x_forwarded_for日志格式, 核心内容如下
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
指令中各个变量的含义:
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节点 配置
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页面
访问日志
<code>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 | -
192.168.0.6
:
含义:直接连接到 Nginx 服务器的客户端的 IP 地址。在这个例子中,这可能是一个内网的 IP 地址。
168.138.171.206
:
含义:通过 X-Forwarded-For
头部获取的客户端的真实 IP 地址。在经过代理或负载均衡器时,这个头部会记录原始客户端的 IP 地址。
-
:
含义:客户端的用户名。在请求需要 HTTP 基本认证时记录用户名。这里没有进行认证,所以显示为 -
。
19/May/2024:10:57:24 +0800
:
含义:请求到达服务器的本地时间,格式为 day/month/year:hour:minute:second timezone
。这个例子中表示 2024 年 5 月 19 日上午 10:57:24,时区为 +0800。
GET / HTTP/1.1
:
含义:客户端的请求行,包含请求的方法(GET)、请求的资源路径(/),以及使用的 HTTP 协议版本(HTTP/1.1)。
nginx.frps.fun
:
含义:请求中的 Host
头部,表示客户端请求访问的主机名。
200
:
含义:HTTP 响应状态码,表示请求成功。200
代表成功。
-
:
含义:上游服务器的响应状态码。在没有上游服务器时,这里显示为 -
。
615
:
含义:传送给客户端的响应主体内容的字节数,不包括响应头的大小。
-
:
含义:请求的引用页面(Referer)。如果没有引用页面则显示为 -
。
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 上。
-
:
含义:上游服务器的地址。在没有上游服务器时,这里显示为 -
。
0.000
:
含义:处理请求的总时间,从接收到客户端请求到完整发送响应的时间,单位为秒。
-
:
含义:从上游服务器读取响应的时间。在没有上游服务器时,这里显示为 -
。
方式二
如果我们前面没有apisix或者其它lb,也可以使用curl命令来模拟X-Forwarded-For日志
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: 显示详细的请求和响应过程,包括头部信息
日志
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 已正确记录。
声明
本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。