来自我的公众号 『 YongHao 写东西的 Cache 』 打个小广告,还是希望写的东西有人看🙊
分享一下见解,权当抛砖引玉
很多流量大的网站会限流,比如一秒 1000 次访问即视为非法,会阻止 10 分钟的访问。
通常简单的做法,就是通过 nginx 时,nginx 设置
proxy_set_header X-Real-IP $remote_addr;
nginx 的 $remote_addr
代表客户端的访问 ip,把它设到 http 请求的头部 X-Real-IP ;然后程序取出并存入数据库,统计访问次数。
remote_addr
基本上不能被伪造,因为是直接从 TCP 连接信息中获取的,也就是 netstat
的Foreign Address
那栏。
你想想, 客户端 A 与 B 服务器建立 TCP 连接,是不是 B 肯定知道 A 的公网地址是什么呢,除非客户端 A 是经过了一个代理服务器 Z, 那么就是 A -> Z -> B, 服务器 B 拿到的只能是 Z 的 ip 地址了,但这不意味就是伪造 ip,限流依然有效。
上述应对外网访问,没有任何问题。假如公司内部需要测试,不停的访问服务器上的程序时,并且经过负载均衡或者 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 呢?
这个情况下,限流一样可以生效,最多就是稍微误杀下无辜,影响不大。
那么,有办法伪造 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 检测是否在路由表中,不在就拒绝掉此请求。
1
hxsf 2019-03-11 14:07:30 +08:00
1. TCP 有握手
2. 不能放大的攻击有啥用? 第三方 D 对面的流量 === 你 D 第三方的流量。 |
2
tabris17 2019-03-11 14:09:12 +08:00 1
9012 年了,还有这种伪科学文章啊
|
3
rochek 2019-03-11 14:10:41 +08:00 via Android 1
过去,一般打机器的时候是做跳板的。
后来,跳板容易被反追,有人用伪造 ip,再中途拿包转发这个妖路。 可以了解一下。 |
4
ChristopherWu OP @tabris17 ???
|
6
ChristopherWu OP @rochek 已感谢。 自己中途拿包转发,是自己容许伪造 ip 的请求过来对吧?那么效果如何,可行吗?
|
7
ChristopherWu OP |
8
ChristopherWu OP @tabris17 还是很不爽你的说法,请您说出哪里伪科学了。。。
|
9
rochek 2019-03-11 14:25:55 +08:00 via Android
@ChristopherWu 特定环境下的小聪明
|
10
tabris17 2019-03-11 14:31:34 +08:00
@ChristopherWu
1. 伪造 IP 源的数据包会被 ISP 的路由器丢弃 2. 想要实现 TCP 的三次盲握手必须能猜解出对方的 IP 数据包的序列号,那你还不如直接猜出对方数据库密码呢 标题搞个噱头,通篇文章毫无意义 |
11
oott123 2019-03-11 14:54:16 +08:00
这种文章不提一下 nginx 的 set_real_ip_from 指令吗?
|
13
ChristopherWu OP @tabris17 你再看看我的标题? 注意是『谈到』 。。。不是做到,而且我文章也提及是做不到以及说明了原因。
所以你的『标题搞个噱头』从何而来?接下来的『通篇文章毫无意义』更是毫无根据了。 对你没什么用的,但是在我的角度来看,比起配置啥啥,如何安装,算法题解等重复的文章有用了一点。 |
14
www5070504 2019-03-11 15:10:15 +08:00
抛砖引玉 这个真的是砖 感觉真没啥用。。。这个连握手第一步都过不去的吧。。
|
15
0ZXYDDu796nVCFxq 2019-03-11 15:15:36 +08:00 via Android
楼主是真的抛砖
|
16
1134506391 2019-03-11 15:28:47 +08:00
<script>alert("aa")</script>
|
17
goodryb 2019-03-11 15:51:37 +08:00
估计楼主也就是顺手一抄,楼上不要太较真
|
18
VoidChen 2019-03-11 15:52:44 +08:00
对我我这种外行来说还是能受到一点启发的
|
19
ChristopherWu OP @www5070504
注意文中最后一句,『但是现在运营商的路由器都部署了 uRPF,可以根据你发过来的源 ip 检测是否在路由表中,不在就拒绝掉此请求。』。 回复前,尤其是负面性评论时,能否先认真看看呢?。。 |
20
ryd994 2019-03-11 16:07:50 +08:00 via Android
要是真听了你的就出事了,连猜 TCP 都不用,直接伪造 x-forwarded-for。
所以必须设置 set_real_ip_from,同时前端反代必须覆盖这个 header 而不是按照默认配置拼接。 然后你这个攻击思路一看就是拍脑袋。1.没有放大系数,其实完全没有必要反射。直接带宽上去打死就行了。没必要纠结协议。只要能路由到对方端口,都是一样的。 2. RST 怎么就能 DDoS 了?且不说人家前面套 CDN,CDN 都是硬件清洗。就算靠自己软防火墙抗,一条 conntrack 规则就可以把这些全部 drop 掉了,不会对 CPU 构成压力。要么你占满带宽打死,那还用什么 RST ?见 1,直接暴力打就是了。 |
21
ChristopherWu OP @ryd994
关于`proxy_add_x_forwarded_for`, 你怎么伪造都好啊,与我无关,我取的只是最后的 `$remote_addr`,你与前端建立连接时,`$remote_addr`就几乎不可能伪造。 > $proxy_add_x_forwarded_for > the “ X-Forwarded-For ” client request header field with the $remote_addr variable appended to it, separated by a comma. 请看 http://nginx.org/en/docs/http/ngx_http_proxy_module.html 关于攻击思路,请看 https://www.wikiwand.com/en/Denial-of-service_attack#/Backscatter,写的时候忘记放进去文章了 |
22
ChristopherWu OP |
23
ryd994 2019-03-11 17:31:03 +08:00 4
@ChristopherWu
“ the “ X-Forwarded-For ” client request header field with the $remote_addr variable appended to it, separated by a comma.“ 这就是我说的拼接。正确做法是在前端 proxy_set_header X-Forwarded-For $remote_addr; 在后端 set_real_ip_from。 按你的做法,到应用内再处理,不仅开销大,而且 nginx 的 access_log 就完全没意义了。Nginx 明明做好的你不用,还要自己造轮子。 "backscatter is a side-effect of a spoofed denial-of-service attack ” 你英文不及格。这是副作用而不是攻击手段和主要目的。用你的例子来讲,被攻击的是 Google 的服务器,只不过 Google 会以为是另一个 IP 在 syn flood 它。但是实际上都是有硬件清洗的。硬件先和你握手,三次握手成功之后再去和服务器握手。syn flood 很难完成三次握手。除非你破解了对方的 seq 生成随机算法。对于没有足够熵源的服务器来说,这种攻击从协议上来讲是有机会的。后来的 CPU 都有熵发生器了,这种攻击也就彻底不可行了。 写安全类文章前,不如自己搭个服务器,去 hostloc 挑衅一下,看看自己是怎么死的,再教别人。恕我直言,我认为你没有运维过一个公开服务的 nginx http 反代,很可能连服务器管理的经验也没有。 |
24
ChristopherWu OP @ryd994 谢谢你的回复,非常有帮助。
我确实之前不知道`set_real_ip_from`这个模块,我稍候再想想怎么改对目前的程序。 > 恕我直言,我认为你没有运维过一个公开服务的 nginx http 反代,很可能连服务器管理的经验也没有。 实不相瞒,我有。。而且就是这样子做的。。 另外,写文章就是总结下自己学到的东西啊,我不可能知道很多对的事情应该怎么做,身边说不定也没有人知道,所以像现在贴上来,不就收到了你的建议了吗 - = - |
25
zeraba 2019-03-11 19:04:20 +08:00 via Android 1
就和 ryd994 说的一样,多层其实设置好 header 后用 realip 模块可以搞定,另外,针对同一个出口的策略也需要调整了,可以自己生成 id 作为用户识别,毕竟移动网络下,这种情况很常见,还有可以深入写下 ng 多层代理后的 header 情况
|
26
ChristopherWu OP @zeraba
已感谢。 请问『针对同一个出口的策略也需要调整了,可以自己生成 id 作为用户识别』可以细讲一下吗? 『有可以深入写下 ng 多层代理后的 header 情况』这个是指啥意思呢?有哪些 header 需要关注? |
27
zeraba 2019-03-11 20:51:31 +08:00 via Android
@ChristopherWu 你现在限流是针对 ip 其实可以通过 cookie lua 可以 set cookie 如果项目不是基于 cookie 比如小程序之类的 可以在 url 设置某个参数标识用户 再限流,至于多层,举个例子,X-Forwarded-For 这个变量就可以展开,一层是什么情况,内网多层是什么情况,如何排除中间的 ip 其他变量当然也可以深入,可以拓宽一点理解整个 proxy 模块
|
28
msg7086 2019-03-12 01:04:56 +08:00
我刚打开的时候就觉得这写得都什么玩意儿,谈 nginx 不谈 real_ip 那还谈什么。9012 年了还谈 forwarded-for 伪造。
翻了下回复,看来我不是第一个这么觉得的。 > 实不相瞒,我有。。而且就是这样子做的。。 建议找个懂的来做运维。 抱歉,我说话比较冲。 如果自己不确定,那么就开贴直接问。把错误的知识写成科普性文章是很不好的行为。 |
29
freaking 2019-03-12 09:07:54 +08:00 via Android
好喷
|
30
Paradisiaercy 2019-03-12 09:38:03 +08:00 via iPhone
以网络安全角度来看,不知道说了什么。
|