Nginx的Http请求11个阶段之postread阶段_获取真实客户端地址的

今天我们来详细介绍一下POSTREAD阶段中的realip模块。它可以帮助我们发现用户的真实ip地址,这为我们后续的模块 如:限速 限流 提供了可能性。

这里其实会存在一个问题,就是如何才能拿到真实的用户IP地址?

我们可以看到 tcp连接四元组 中包含了源ip和目标ip,但是网络中存在了很多反向代理。

反向代理后,会导致反向代理与上游的机器又新建了一个tcp连接,所以上游的服务器想拿到原始的ip就变成了问题。

举例说明:

1.用户的在家里的路由器分配的内网IP是 192.168.0.x

2.在经过运营商的时候分配的公网ip是 115.204.33.1

3.这个用户在请求一个网站的时候经过cdn加速,这个cdn如果没有缓存请求的内容,那么他就会回源。cdn的ip地址是1.1.1.1

4. 回源的时候经过某云厂商的slb IP是2.2.2.2

5. slb 再访问我们的Nginx 。

此时 我们直接获取remote_addr实际上拿到的是slb的地址 2.2.2.2 ,

如果我们要做限速,或者做并发连接控制的时候,我们是实际上 是基于115.204.33.1 来做控制的。

那么怎么做到呢?

实际上http有这2个头部:

X-Forwarded-For:用于传递IP的。

X-Real-IP:用户传递用户IP的。

当CDN请求 SLB反向代理的时候 可以把用户的IP放到 X-Real-IP 里,把请求CDN的IP加入到X-Forwarded-For里。此时X-Forwarded-For 和 X-Real-IP里都是115.204.33.1。

当SLB去请求Nginx的时候,可以把用户的IP放到 X-Real-IP里 ,把CDN的IP加入到X-Forwarded-For里。此时X-Forwarded-For 里的值:115.204.33.1 , 1.1.1.1 , X-Real-IP的值是115.204.33.1。

到这里 我们发现 X-Real-IP 只有一个地址,而X-Forwarded-For是可以存多个地址的。

那么拿到真实用户IP后如何使用呢?

Nginx中会基于变量 来使用,根据我们在Nginx中的配置,会覆盖 binary_remote_addr, remote_addr 的值,这2个变量原来是直接和Nginx产生连接的地址,经过realip模块后,会被覆盖。 这时候也就理解了为什么 limit_conn模块为什么要在POSTREAD阶段之后了。

这里要提醒一下的是 realip模块默认是不会被编译到Nginx里的,我们必须手动添加来启动realip模块。

--with-http_realip_module

明天我们继续学习rewrite阶段。