Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Nginx 获取客户端 IP 的几种方式 #36

Open
jinhailang opened this issue Sep 7, 2018 · 0 comments
Open

Nginx 获取客户端 IP 的几种方式 #36

jinhailang opened this issue Sep 7, 2018 · 0 comments

Comments

@jinhailang
Copy link
Owner

jinhailang commented Sep 7, 2018

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 开始支持的):

proxy_bind $remote_addr  transparent;

注意,需要开启 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 头?有时间可以试一试,理论上应该有些效果。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant