Nginx 与 X-Forwarded-For


HTTP扩展头部 X-Forwarded-For,以及在nginx中使用http_x_forwarded_for变量来完成一些"特殊"功能,例如网站后台面向内部工作人员,希望只允许办公室网络IP访问。

 X-Forwarded-For,它用来记录代理服务器的地址,每经过一个代理该字段会追加上一个记录。例如:6.6.6.6, 8.8.8.8。


拿出生产环境的一个例子,客户端浏览网站发出一个请求,请求先经过阿里云SLB负载均衡器,然后进入Rancher内部的LB负载均衡器,经过两次负载均衡器转发后请求到达nginx服务器。


X-Forwarded-For HTTP扩展头部

日志中的记录表示 client: 101.251.xxx.192 、proxy1: 100.97.xxx.187,不是说 X-Forwarded-For用来记录代理服务器的地址,每经过一个代理该字段会追加上一个记录,为什么client IP 会出现在这个字段中呢?

带着疑惑这里有必要专门讲一讲 X-Forwarded-For HTTP头部。X-Forwarded-For 是一个 HTTP扩展头部,HTTP/1.1(RFC 2616)协议并没有对它的定义,它最开始是由 Squid缓存代理软件引入,用来表示 HTTP请求端真实IP。最终成为事实上的标准被写入 RFC 7239(Forwarded HTTP Extension)标准之中。

X-Forwarded-For 标准格式

X-Forwarded-For: client, proxy1, proxy2
 

从标准格式可以看出,X-Forwarded-For头部信息可以有多个,中间使用逗号分隔,第一项为真实的客户端IP剩下的就是经过的代理或负载均衡的IP地址,经过几个就会出现几个。

回到上面的示例,HTTP请求到达nginx服务器之前,经过了两个代理Proxy1、Proxy2,IP 分别为IP1、IP2,用户真实IP为 IP0,那么按照 XFF标准格式,nginx服务器最终的XFF变量如下:

X-Forwarded-For: IP0, IP1

 

Proxy2是直连服务器的,它会给 XFF追加IP1,表示它是在帮 Proxy1转发请求,IP2是在服务端通过 Remote Address 获得。Remote Address 也无法伪造,因为建立TCP连接需要三次握手,如果伪造了源IP,无法建立TCP连接,更不会有后面的 HTTP请求。


nginx 中的 http_x_forwarded_for 变量用来表示 X-Forwarded-For ,下面用一个例子说明 nginx 如何使用 http_x_forwarded_for,例如借用这个变量限制网站后台访问。

1. 环境

browser -> haproxy -> nginx

 

目标判断 haproxy负载均衡传递的 http_x_forwarded_for变量,确定是否为办公室IP?是否允许访问网站后台?

2. 方法

a. 修改 nginx 虚拟主机配置文件,添加以下语句。

cat default.conf

server  
{    
  #... 其它配置项省略

    location ^~ /admin/ {

      if ($http_x_forwarded_for !~ 'your_office_ip') {
         return 403;
      }
      
      #... 其它配置项省略    
    }

}

 

b. 重新加载

nginx -t && nginx -s reload

 

c. 伪造XFF

需要特别说明的是XFF是可以伪造的,例如使用curl 发送一个带有"X-Forwarded-For:8.8.8.8"的头部信息。

curl -IL -H "X-Forwarded-For:8.8.8.8" https://www.test.com/static/09.png

 

假设你采用XFF对比IP方式来限制网站后台访问,如果对方知道你的网站在用这个策略限制后台访问,并且通过一些方法知道了你办公室的IP地址,那么这个策略也就失效了。如果你的网站"前后台"可以分离,那么可以为分离后的后台服务器添加防火墙规则,通过网络层限制来源IP地址达到同样目的。

posted @ 2021-11-03 10:41  augusite  阅读(5113)  评论(0编辑  收藏  举报