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-Forreal_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 已正确记录。

在这里插入图片描述



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。