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

2019-03-11 14:01:30 +08:00
 ChristopherWu

来自我的公众号 『 YongHao 写东西的 Cache 』 打个小广告,还是希望写的东西有人看🙊

分享一下见解,权当抛砖引玉


从限流谈到伪造 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。

     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

     # 不可能出现这种情况, 除非 LBS/nginx 没有设$proxy_add_x_forwarded_for
     return request.environ.get('REMOTE_ADDR')

这样取到的也是真实的 ip 地址,但有一个问题,假如 client 跟其他很多 client 通过同一个出口出来,共享一个外网 ip,那么如何获取它的 ip 呢?

这个情况下,限流一样可以生效,最多就是稍微误杀下无辜,影响不大。

伪造 ip (也就是 remote_addr )

那么,有办法伪造 remote_addr吗? 其实本质就是,TCP 连接中,有办法伪造 ip 信息吗?

请看如何用 hping3 工具发出伪装 ip 的包到 google.com

$ sudo apt-get install hping3
$ sudo hping3 --icmp --spoof 6.6.6.6 baidu.com
HPING baidu.com (eth0 220.181.57.216): icmp mode set, 28 headers + 0 data bytes

另一个控制台抓 icmp 包:

$ sudo tcpdump -i eth0 'icmp'
21:24:58.562844 IP 6.6.6.6 > 220.181.57.216: ICMP echo request, id 11035, seq 5120, length 8

可以看到, 我们成功的伪装成 6.6.6.6 并向 baidu.com 发出了 ping (也就是 ICMP 包),不过由于我们的 IP 实质上并不是6.6.6.6,所以收不到 baidu.com 发往 它的 ICMP 包。

模拟的原理是,自己重新实现系统的 tcp ( ICMP )协议栈,然后 自己改变自己的 ip。

值得一提的八卦是,hping 的作者是 Salvatore Sanfilippo,同时他也是 redis 的作者。

试想一下,可以通过这个办法来做借刀杀人——伪造一个 ip (如4.4.4.4),大量发包给第三方(如 Google ),然后第三方返回 TCP reset 或者 ICMP unreachable 给 你伪造的 ip(4.4.4.4), 这样就可以借 Google 来 ddos 4.4.4.4了。2

但是现在运营商的路由器都部署了 uRPF,可以根据你发过来的源 ip 检测是否在路由表中,不在就拒绝掉此请求。

7832 次点击
所在节点    推广
30 条回复
hxsf
2019-03-11 14:07:30 +08:00
1. TCP 有握手
2. 不能放大的攻击有啥用? 第三方 D 对面的流量 === 你 D 第三方的流量。
tabris17
2019-03-11 14:09:12 +08:00
9012 年了,还有这种伪科学文章啊
rochek
2019-03-11 14:10:41 +08:00
过去,一般打机器的时候是做跳板的。
后来,跳板容易被反追,有人用伪造 ip,再中途拿包转发这个妖路。

可以了解一下。
ChristopherWu
2019-03-11 14:14:40 +08:00
yexm0
2019-03-11 14:16:59 +08:00
@Livid 公众号推广
ChristopherWu
2019-03-11 14:22:10 +08:00
@rochek 已感谢。 自己中途拿包转发,是自己容许伪造 ip 的请求过来对吧?那么效果如何,可行吗?
ChristopherWu
2019-03-11 14:23:31 +08:00
@yexm0 v 站里不允许宣传公众号吗,还是不允许宣传推广?

我还见过每个帖子都带上自己博客的。。还有一堆嗮博客的帖子,那些属于博客推广吗?
ChristopherWu
2019-03-11 14:24:32 +08:00
@tabris17 还是很不爽你的说法,请您说出哪里伪科学了。。。
rochek
2019-03-11 14:25:55 +08:00
@ChristopherWu 特定环境下的小聪明
tabris17
2019-03-11 14:31:34 +08:00
@ChristopherWu

1. 伪造 IP 源的数据包会被 ISP 的路由器丢弃
2. 想要实现 TCP 的三次盲握手必须能猜解出对方的 IP 数据包的序列号,那你还不如直接猜出对方数据库密码呢

标题搞个噱头,通篇文章毫无意义
oott123
2019-03-11 14:54:16 +08:00
这种文章不提一下 nginx 的 set_real_ip_from 指令吗?
j0hnj
2019-03-11 15:03:20 +08:00
@tabris17 #2 我也想知道怎么就伪科学了
ChristopherWu
2019-03-11 15:03:36 +08:00
@tabris17 你再看看我的标题? 注意是『谈到』 。。。不是做到,而且我文章也提及是做不到以及说明了原因。

所以你的『标题搞个噱头』从何而来?接下来的『通篇文章毫无意义』更是毫无根据了。

对你没什么用的,但是在我的角度来看,比起配置啥啥,如何安装,算法题解等重复的文章有用了一点。
www5070504
2019-03-11 15:10:15 +08:00
抛砖引玉 这个真的是砖 感觉真没啥用。。。这个连握手第一步都过不去的吧。。
0ZXYDDu796nVCFxq
2019-03-11 15:15:36 +08:00
楼主是真的抛砖
1134506391
2019-03-11 15:28:47 +08:00
<script>alert("aa")</script>
goodryb
2019-03-11 15:51:37 +08:00
估计楼主也就是顺手一抄,楼上不要太较真
VoidChen
2019-03-11 15:52:44 +08:00
对我我这种外行来说还是能受到一点启发的
ChristopherWu
2019-03-11 16:00:40 +08:00
@www5070504

注意文中最后一句,『但是现在运营商的路由器都部署了 uRPF,可以根据你发过来的源 ip 检测是否在路由表中,不在就拒绝掉此请求。』。

回复前,尤其是负面性评论时,能否先认真看看呢?。。
ryd994
2019-03-11 16:07:50 +08:00
要是真听了你的就出事了,连猜 TCP 都不用,直接伪造 x-forwarded-for。
所以必须设置 set_real_ip_from,同时前端反代必须覆盖这个 header 而不是按照默认配置拼接。

然后你这个攻击思路一看就是拍脑袋。1.没有放大系数,其实完全没有必要反射。直接带宽上去打死就行了。没必要纠结协议。只要能路由到对方端口,都是一样的。
2. RST 怎么就能 DDoS 了?且不说人家前面套 CDN,CDN 都是硬件清洗。就算靠自己软防火墙抗,一条 conntrack 规则就可以把这些全部 drop 掉了,不会对 CPU 构成压力。要么你占满带宽打死,那还用什么 RST ?见 1,直接暴力打就是了。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/543304

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX