前言
上面突然说,需要检查Nginx反向代理的安全问题并给出了修改方法,小白的我一脸懵逼,明明都是中文,连在一起咋就看不明白了。于是乎,对着修改内容简单学习了一下,在此做个记录,如有问题请大佬们指点指点。
1、proxy_set_header的参数
在Nginx中的location里,我们通常会配置proxy_set_header,如下代码:
# 定义转发分配规则
upstream kwtest {
server ip1:port;
server ip2:port;
}
server {
listen 8080; # Nginx监听端口
location /testApi {
# 反向代理
proxy_pass http://kwtest;
# 在原本的nginx中,这个是默认的
proxy_set_header Host $http_host;
}
}
1.1 具体参数
这里来解释一下这个参数$http_host
,以及后面会讲到的参数。
proxy_set_header参数 | 含义 |
---|---|
$http_host | 请求头中的完整的主机名或IP地址(包括端口号) |
$host | 请求头中的Host字段,主机名或IP地址(不包括端口号) |
$remote_addr | 是客户端的IP地址 |
$proxy_add_x_forwarded_for | 获取客户端真实的 IP 地址 |
1.2 客户端请求过来的 HTTP 请求头中的主机名或IP地址,与客户端的 IP 地址有什么不同
- 客户端请求过来的 HTTP 请求头中的主机名或IP地址:这里的IP不是客户端的IP,是服务器端的IP【eg.系统部署的地方】
- 客户端的 IP 地址:用户的IP地址【eg.浏览器打开的页面】
1.3 客户端的IP地址 与 获取客户端真实的 IP 地址有什么不同
$remote_addr
是 Nginx 服务器记录的发起连接的客户端 IP 地址,是从网络层获取的客户端 IP,也就是请求到达 Nginx 服务器的 IP 地址。这个变量通常在直接与客户端通信的情况下使用,例如,客户端直接请求 Nginx 服务器时,可以通过$remote_addr
获取客户端的真实 IP 地址。
$proxy_add_x_forwarded_for
是 Nginx 在作为反向代理服务器时,从 HTTP 请求头中提取客户端的真实 IP 地址。当 Nginx 作为反向代理服务器时,客户端请求会经过反向代理服务器,再由反向代理服务器转发给后端的真实服务器处理。在这个过程中,Nginx 在请求头中添加了X-Forwarded-For
字段,并将客户端的真实 IP 地址追加到该字段的末尾。$proxy_add_x_forwarded_for
可以从这个字段中提取出客户端的真实 IP 地址,从而获取客户端的真实 IP 地址。
因此,$remote_addr
和$proxy_add_x_forwarded_for
都是用于获取客户端 IP 地址的,但是 $remote_addr
适用于直接与客户端通信的场景,而 $proxy_add_x_forwarded_for
适用于 Nginx 作为反向代理服务器时获取客户端真实 IP 地址的场景,二者的使用场景不同。
2、X-Forwarded-For伪造客户端IP漏洞
这部分主要看利用X-Forwarded-For伪造客户端IP漏洞成因及防范这篇文章。虽然很详细,但理解完后,过一段时间忘了又得再理解。因此,以下内容主要对这篇文章的总结,快速回忆。
- 注意:
$proxy_add_x_forwarded_for
会将和Nginx直接连接的客户端IP追加在请求原有X-Forwarded-For值的右边。
$remote_addr
这个是无法伪造的,即使客户端伪造也会被覆盖掉,而不是追加。
- 存在多层Nginx情况下:
# 外层
server {
listen 8080; # Nginx监听端口
location /testApi1 {
# 反向代理
proxy_pass http://kwtest1;
proxy_set_header X-Forwarded-For $remote_addr;
}
}
# 内层
server {
listen 8080; # Nginx监听端口
location /testApi2 {
# 反向代理
proxy_pass http://kwtest2;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
如果有多层代理,那么只要在直接对外访问的Nginx上配置X-Forwarded-For为$remote_addr
,内部层的Nginx还是要配置为$proxy_add_x_forwarded_for
,不然内部层的Nginx又会覆盖掉客户端的真实IP。
- 单层Nginx,即对内又对外的情况:
# 内外层
server {
listen 8080; # Nginx监听端口
location /testApi3 {
# 反向代理
proxy_pass http://kwtest3;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
X-Real-IP
头部会包含真实的客户端 IP 地址,X-Forwarded-For
头部会包含一个逗号分隔的 IP 地址列表,其中第一个 IP 地址应该是真实的客户端 IP 地址