一、概述
X-Forwarded-For
, X-Real-IP
, remote_addr
是http协议中用来表示客户端地址的请求头。
X-Forwarded-For
和X-Real-IP
只有请求存在代理时才有值,而remote_addr
一直存在。
X-Forwarded-For
:记录代理服务器的地址,每经过一个代理,该字段会加上一个记录。格式形如:1.1.1.1, 2.2.2.2
X-Real-IP
:也是用来记录服务器的地址,但是和上面的不同,它不把记录添加到结尾,而是直接替换remote_addr
:上一个客户端连接的地址,不存在代理就表示客户端的地址,存在代理就表示最后一个代理服务器的地址
以下使用三个nginx服务器来测试以上三个请求头在不同条件组合下的值:
本机地址:
192.168.234.1
。server1: http://192.168.234.13
server2: http://192.168.234.128
server3: http://test.intely.xyz
server1的代理配置
server {
listen 80;
server_name _;
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://192.168.234.131;
}
}
server2的代理配置
server {
listen 80;
server_name _;
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://test.intely.xyz;
}
}
server3为web服务端
server{
listen 80;
server_name test.intely.xyz;
location / {
root /data/html;
index index.html;
}
access_log /data/wwwlogs/test.intely.xyz/access.log test;
}
日志格式test分别打印出三个请求头的内容:
log_format test ''$http_x_forwarded_for | $http_x_real_ip | $remote_addr'';
在不使用代理直接访问http://test.intely.xyz
的情况下日志信息为:
- | - | 223.73.59.254
因为不存在代理,所以前面两个值是不存在的。而server3
是公网地址,记录的remote_addr
是本机公网地址223.73.59.254
。
二、请求说明
X-Forwarded-For
就像是vector
中的push_back
,每经过一个代理服务器就把该请求的来源地址
加在记录的后面(由于是记录来源地址,所以该字段不会保存最后一个代理服务器的地址)。
在本机访问server1
,请求会被转发到server3
,此时server3
的日志为:
192.168.234.1, 192.168.234.128 | 192.168.234.128 | 223.73.59.254
X-Forwarded-For
为192.168.234.1, 192.168.234.128
,说明经过了两次转发,但并没有记录server2
的地址。
X-Real-IP
会替换代理服务器的地址,请求头会在经过server2
时被设置位server1
的地址。
三、不记录转发请求
如果把server2
的proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
注释掉,即server2
在转发时不添加该请求头,X-Forwarded-For
就不会加上server1
的地址:
192.168.234.1 | 192.168.234.128 | 223.73.59.254
如果再把server2
的proxy_set_header X-Real-IP $remote_addr;
也注释掉,请求在server2
时也不会替换X-Real-IP
的值。
192.168.234.1 | 192.168.234.1 | 223.73.59.254
但是不管怎样,remote_addr
是永远不会变的,它永远都是上一个请求客户端的地址,也就是server2
的地址。
四、伪造请求头
请求头是可以伪造的,如果客户端伪造了请求头地址,X-Forwarded-For
和X-Real-IP
将会收到影响。
# server2上请求服务,并手动构造请求头
> curl 127.0.0.1 -H ''X-Forwarded-For: 1.1.1.1'' -H ''X-Real-IP: 2.2.2.2''
收到的日志信息:
1.1.1.1 | 2.2.2.2 | 223.73.59.254
tips:对于X-Real-IP来说,如果存在一级以上的代理,它也不会收到影响,因为每经过一次代理,它就会被覆盖
而remote_addr
这个地址不管怎样伪造都是无用的:
# 在server2上直接请求server3
> curl http://test.intely.xyz -H "remote_addr:1.1.1.1"
# 得到的日志信息
- | - | 223.73.59.254
因为remote_addr
字段不是通过请求头来决定的,而是服务端在建立tcp连接时获取的的客户端地址。
此处评论已关闭