You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Nginx 服务端很多时候需要知道请求客户端的真实 IP,但是实际请求客户端可能经过了很多层代理才到的服务端,而误将代理 IP 当作请求客户端的 IP 可能导致很严重的问题,比如在 IP 维度做请求限速或者请求统计时。
这种情况下,要怎样获取请求端真实 IP 呢?
获取 IP 的三种方式
设置 X-Forwarded-For 请求头
设置 X-Real-IP 请求头
这两种方式的原理其实是一样的,都是跟上下游代理之间约定某个特定字段,将请求 IP 放进去,然后层层传递下去。 X-Forwarded-For 一般包含了整个请求经过的所有对端IP,以逗号+空格分割,最前(左)端的 IP 就是第一个请求客户端的 IP,因为这种方式被广泛的使用,可以作为业界共识。
但是,很明显的是,这种约定是脆弱的,也不安全,客户端甚至可以在请求的时候自己指定 X-Forwarded-For 头,这样就相当于可以随意篡改自己的 IP 地址了。当然,一般我们真正关心的是请求进入公司内网时的 IP,所以,可以在内网最前面的代理上做过滤。
Nginx 获取客户端 IP 的几种方式
Nginx 服务端很多时候需要知道请求客户端的真实 IP,但是实际请求客户端可能经过了很多层代理才到的服务端,而误将代理 IP 当作请求客户端的 IP 可能导致很严重的问题,比如在 IP 维度做请求限速或者请求统计时。
这种情况下,要怎样获取请求端真实 IP 呢?
获取 IP 的三种方式
X-Forwarded-For
请求头X-Real-IP
请求头这两种方式的原理其实是一样的,都是跟上下游代理之间约定某个特定字段,将请求 IP 放进去,然后层层传递下去。
X-Forwarded-For
一般包含了整个请求经过的所有对端IP,以逗号+空格分割,最前(左)端的 IP 就是第一个请求客户端的 IP,因为这种方式被广泛的使用,可以作为业界共识。但是,很明显的是,这种约定是脆弱的,也不安全,客户端甚至可以在请求的时候自己指定
X-Forwarded-For
头,这样就相当于可以随意篡改自己的 IP 地址了。当然,一般我们真正关心的是请求进入公司内网时的 IP,所以,可以在内网最前面的代理上做过滤。proxy_bind
允许代理指定发起请求的 IP,因此我们可以如下设置(Nginx 1.11.0 开始支持的):注意,需要开启
root
权限user root;
。这样设置后,Nginx 后面的服务器看到的 IP($remote_addr
) 不再是 Nginx 反向代理服务器主机的 IP,而是真正发起请求的主机 IP。这就是所谓的“透明代理”。实现原理是在Linux 2.6.24以后,socket 增加了一个选项IP_TRANSPARENT可以接受目的地址没有配置的数据包,也可以发送原地址不是本地地址的数据包。可以通过该特性实现4层以上的透明代理。,详细分析可以看这里。相对上面两种,这种方式相对更简便,也更安全(初看以为也能篡改 IP,其实是不行的,必须是发起请求的 IP 才行,原因自行思考一分钟吧)。
小结
因此,最好都设置透明代理,这样后端就不需要特别去关注怎么获取真实的请求 IP 地址,直接取
ngx.var.remote_addr
值就是了。关键这也是最安全的方式,没有被篡改的风险。想起以前做爬虫的时候,最大的难题就是爬取次数太多,IP 被限制了,只能花钱去买代理,然后代理又被封了,让人很头大。现在看来,也许可以在请求的时候加上
X-Forwarded-For
头?有时间可以试一试,理论上应该有些效果。The text was updated successfully, but these errors were encountered: