参考资料:44-http协议
x-forward-for是http请求的一个字段,该字段表示客户端的IP地址,一般称为“XXF”头,服务端通过这个头可以知道客户端的真实或代理IP。x-forward-for字段虽然没有写入RFC标准,但已经应用到http协议中成为一个实施标准了。
x-forward-for字段的格式为:
x-forward-for:client1,proxy1,proxy2,proxy3
该字段的ip地址值以逗分隔,其中client1代表真实的客户端的ip地址,代理服务器每成功收到一个请求,就把请求来源IP地址添加到右边,最末端的服务器收到http请求得到这样一个ip地址列表:client1,proxy1,proxy2,proxy3,可以这个http请求经过了三个代理服务器,最左边的ip就是真实的客户端ip地址。
在进行入侵溯源的时候往往可以通过x-forward-for字段溯源到攻击者的真实ip地址。
但事实上攻击者并不会这么容易暴露自己的真实ip,攻击者会在一开始就修改x-forward-for字段在最前面伪造一个ip地址wzip。最终得到的ip是这样的:x-forward-for:wzip,clientip,proxy1,proxy2,proxy3。
由于x-forward-for字段最左边的ip就是真实的客户端ip地址,我们在进行溯源时得到的客户端“真实ip”是wzip,并不是真正的clientip,从而掉进攻击者的陷阱。
那如何溯源到攻击者真实的ip呢?
我们知道http的整个请求过程中需要经过客户端-->代理服务器1--->代理服务器2-->最终的服务器。从安全的角度来说,最不安全的因素就是人,在这个过程中:
客户端不可控的
代理服务器是可控的
最终的服务器可控
对应的解决方案就是对代理服务器和最终的服务器进行防御,我们可以通过nginx的http模块的X-Forwarded-For对最外层的代理服务器进行配置:
proxy_set_header X-Forwarded-For $remote_addr;
remote_addr表示对x-forward-for字段中的ip地址进行覆盖,就是最外层代理服务器不信任客户端的 X-Forwarded-For 输入,直接覆盖,而不是追加。
非最外层的 Nginx 服务器,配置:
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_add_x_forwarded_for表示对x-forward-for字段里的ip地址内容进行追加。
而在最终的服务器里我们可以根据代理服务器的数目来进行获取真实ip地址,例如上面这个例子中的代理有三层,假设得到的ip地址为:
x-forward-for:wzip,client1,proxy1,proxy2,proxy3
从右开始排除三个代理服务器的ip,最终确定client1就是攻击者真实的ip地址。