从限流谈到伪造 IP

818 阅读2分钟
原文链接: xiaozhuanlan.com

从限流谈到伪造 IP(nginx remote_addr)

remote_addr

很多流量大的网站会限流,比如一秒 1000 次访问即视为非法,会阻止 10 分钟的访问。

通常简单的做法,就是通过 nginx 时,nginx 设置

    proxy_set_header X-Real-IP $remote_addr;

nginx的 $remote_addr代表客户端的访问 ip,把它设到 http 请求的头部X-Real-IP;然后程序取出并存入数据库,统计访问次数。

remote_addr 基本上不能被伪造,因为是直接从 TCP 连接信息中获取的,也就是 netstatForeign Address那栏。

你想想, 客户端A 与 B服务器建立 TCP 连接,是不是 B 肯定知道 A的公网地址是什么呢,除非客户端 A 是经过了一个代理服务器 Z, 那么就是 A -> Z -> B, 服务器 B 拿到的只能是 Z 的 ip 地址了,但这不意味就是伪造 ip,限流依然有效。

nginx 转发

上述应对外网访问,没有任何问题。假如公司内部需要测试,不停的访问服务器上的程序时,并且经过负载均衡或者 nginx 转发时,也就是 client -> nginx1 -> nginx2 -> server, remote_addr 就变成了nginx2 的内网地址了。

因此,需要在 nginx1处, e client 的 remote_addr, 再传给 nginx2,server 再取出。

示例:

   proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

$proxy_add_x_forwarded_for$remote_addr 加到 X-Forwarded-For 头部后面;最后设在 my_ips

如果是需要做 ip 统计,地理信息获取,天气定位等,需要常用的另一个 http 头部, X-Forwarded-For 来做处理。通过名字就知道,X-Forwarded-For 是一个 HTTP 扩展头部。HTTP/1.1(RFC 2616)协议并没有对它的定义,它最开始是由 Squid 这个缓存代理软件引入,用来表示 HTTP 请求端真实 IP。如今它已经成为事实上的标准,被各大 HTTP 代理、负载均衡等转发服务广泛使用,并被写入 RFC 7239(Forwarded HTTP Extension)标准之中。[1]

然后my_ips 就代表了请求从 client 到 server 的完整ip路径, 只要由后往前推,直到 找到 外网的 ip,就证明这就是 client 的真正 ip。

```python
bb_real_ip = request.environ.get('my_ips')
bb_real_ip = bb_real_ip.replace(" ", "").split(',')
for ip in reversed(bb_real_ip):
if not is_private(ip):
return ip