当端口扫描遇到防火墙
问题背景
在为什么masscan扫描快(1)? 里,我提到之前端口扫描时遇到过很严重的误报:"端口扫描结果中发现有的ip开放了5000+个端口,并且端口上似乎没有什么业务。"。
写完上篇文章后,后台收到一个读者留言说他也遇到过这样的ip。ip是国外的一个垃圾站点,下文中我以"x.x.x.x"代替这个ip。
"x.x.x.x"使用masscan x.x.x.x -p 1-65535 --rate 4000
时,结果中确实显示大量开放端口。
为了验证这些端口是否真的开放,我使用echo 111 | nc x.x.x.x 28328
命令验证(28328是masscan判定为开放的端口),并同时tcpdump抓包,如下:
[root@instance-fj5pftdp ~]# tcpdump "host x.x.x.x"
...
// 第一次执行 echo 111 | nc x.x.x.x 28328
23:59:20.635538 IP instance-fj5pftdp.34796 > x.x.x.x.11935: Flags [S], seq 1688099017, win 27200, options [mss 1360,sackOK,TS val 2944989102 ecr 0,nop,wscale 7], length 0
23:59:20.670753 IP x.x.x.x.11935 > instance-fj5pftdp.34796: Flags [S.], seq 3942687481, ack 1688099018, win 14600, options [mss 1460,nop,wscale 7,nop,nop,sackOK], length 0
23:59:20.670859 IP instance-fj5pftdp.34796 > x.x.x.x.11935: Flags [.], ack 1, win 213, length 0
23:59:20.671028 IP instance-fj5pftdp.34796 > x.x.x.x.11935: Flags [P.], seq 1:5, ack 1, win 213, length 4
23:59:20.671044 IP instance-fj5pftdp.34796 > x.x.x.x.11935: Flags [F.], seq 5, ack 1, win 213, length 0
23:59:20.709843 IP x.x.x.x > instance-fj5pftdp: ICMP host x.x.x.x unreachable - admin prohibited, length 60
23:59:20.742398 IP instance-fj5pftdp.34796 > x.x.x.x.11935: Flags [F.], seq 5, ack 1, win 213, length 0
23:59:20.978400 IP instance-fj5pftdp.34796 > x.x.x.x.11935: Flags [FP.], seq 1:5, ack 1, win 213, length 4
23:59:21.451408 IP instance-fj5pftdp.34796 > x.x.x.x.11935: Flags [FP.], seq 1:5, ack 1, win 213, length 4
23:59:22.397413 IP instance-fj5pftdp.34796 > x.x.x.x.11935: Flags [FP.], seq 1:5, ack 1, win 213, length 4
// 第二次执行 echo 111 | nc x.x.x.x 28328
00:05:02.133562 IP instance-fj5pftdp.36738 > x.x.x.x.11935: Flags [S], seq 3374266173, win 27200, options [mss 1360,sackOK,TS val 2945330600 ecr 0,nop,wscale 7], length 0
00:05:02.168661 IP x.x.x.x > instance-fj5pftdp: ICMP host x.x.x.x unreachable - admin prohibited, length 68
从数据包中可以看到一个奇怪的现象:
第一次执行命令时,服务端第一次返回syn-ack,第二次返回icmp不可达。 第二次执行命令时,服务端直接返回icmp不可达。 实际上第三次、第四次执行命令时,服务端也是直接返回icmp不可达。
另外多测试几次,有一个更奇怪的现象:
扫描结果不稳定:有时显示大量端口开放、有时显示一个不固定的端口开放(比如44736)
因此我想搞清楚以下问题:
为啥会出现两个上面奇怪的现象? 是否存在防火墙? 防火墙的防护策略是啥? 怎么规避这种防火墙获取正确的端口信息?
首先有三个非常肯定的前提:
目标机器28328、44736等端口肯定是没有tcp监听的,只有80、22、3306等端口开放 目标机器上用了firewalld,且是默认防护策略 因为返回了syn-ack,所以syn扫描才误判成端口开放
什么是防火墙?
按照防火墙的位置,防火墙可以划分成:
主机防火墙:运行在服务器上 硬件设备:串联或者旁路部署
系统自带的主机防火墙包括:
iptables firewalld tcp wrappers
这次目标主机上就运行着firewalld,当访问不存在的端口时,它会返回icmp包。
除了系统自带的防火墙,很多甲方会基于snort、bro、suricata、ossec等开源项目做入侵检测系统。
除了这些,各家乙方的ips、ddos等防护设备都有可能在存在。
按照是否支持状态跟踪,防火墙可以划分成:
有状态防火墙 无状态防火墙(也叫"包过滤防火墙")
按照在osi七层模型的位置,防火墙也可以划分成:
四层防火墙 七层防火墙(主要是waf产品)
先总结这次遇到的防火墙策略
小结:
整条链路存在两个防火墙:
一个是主机上的firewalld,默认策略 另一个应该是部署在机房中 主机的firewalld防火墙,有如下特征:
收到syn包,目的端口不存在时会返回icmp包 机房的防火墙可能是一台防ddos设备,有如下特征:
不是rst方式、首包丢弃等方式的防火墙;也不是基于"陷阱端口"
当频率到达阈值时,会开启"源认证"
通过"源认证"会暂时加白;如果频率再次触发阈值,就会再次开启"源认证"
有ip拉黑机制,被拉黑后,一段时间内客户端发出的syn、ack包不会收到任何回包
不拦截长度大于0的udp包
分析过程
判断是否存在防火墙?
现象一:
nc x.x.x.x 不存在的端口
时,响应icmp包。基于如下两个原因可以推断出存在防火墙
* 一般来说,向操作系统不存在的端口发送tcp syn包时,会收到操作系统的rst包
* 似乎只有防火墙喜欢返回icmp包现象二:
nmap工具扫描前:可以ping通,curl 80可以访问
nmap工具扫描后,ping和curl都无法访问
过一段时间后:又可以ping通,curl 80也可以访问说明防火墙有黑名单机制。
结论:确认存在防火墙,且有黑名单ip机制
判断防火墙是否有"握手时rst"、首包丢弃等行为
思路:连接提供tcp服务的端口并抓包,查看是否有rst,首包丢弃等行为
过程:
执行
echo | nc x.x.x.x 80
,并抓包[root@instance-fj5pftdp ~]# tcpdump -i eth0 'host x.x.x.x'
...
18:15:53.547200 IP instance-fj5pftdp.51400 > x.x.x.x.http: Flags [S], seq 468920486, win 27200, options [mss 1360,sackOK,TS val 2405982013 ecr 0,nop,wscale 7], length 0
18:15:53.579860 IP x.x.x.x.http > instance-fj5pftdp.51400: Flags [S.], seq 3601120884, ack 468920487, win 14480, options [mss 1460,sackOK,TS val 556123394 ecr 2405982013,nop,wscale 7], length 0
18:15:53.579943 IP instance-fj5pftdp.51400 > x.x.x.x.http: Flags [.], ack 1, win 213, options [nop,nop,TS val 2405982046 ecr 556123394], length 0
18:15:53.580084 IP instance-fj5pftdp.51400 > x.x.x.x.http: Flags [P.], seq 1:2, ack 1, win 213, options [nop,nop,TS val 2405982046 ecr 556123394], length 1: HTTP
18:15:53.580097 IP instance-fj5pftdp.51400 > x.x.x.x.http: Flags [F.], seq 2, ack 1, win 213, options [nop,nop,TS val 2405982046 ecr 556123394], length 0
18:15:53.611613 IP x.x.x.x.http > instance-fj5pftdp.51400: Flags [.], ack 2, win 114, options [nop,nop,TS val 556123427 ecr 2405982046], length 0
18:15:53.611895 IP x.x.x.x.http > instance-fj5pftdp.51400: Flags [F.], seq 1, ack 3, win 114, options [nop,nop,TS val 556123427 ecr 2405982046], length 0
18:15:53.611924 IP instance-fj5pftdp.51400 > x.x.x.x.http: Flags [.], ack 2, win 213, options [nop,nop,TS val 2405982078 ecr 556123427], length 0可以看到,总共八个包:前三个握手、后四个挥手、中间一个包传tcp数据。
中间并没有rst,首包syn也并没有被丢。
结论:
不是rst方式的防火墙 不是首包丢弃的防火墙 判断防火墙是否syn-ack代理
思路:在未被拉黑时,向x.x.x.x不存在tcp服务的端口发送syn包,如果能收到syn-ack,就说明防火墙做了syn-ack代理
结论:防火墙没有syn-ack代理功能
拉黑后客户端发包能收到什么?
经过测试,ip被拉黑后:
客户端发出去的syn包、ack包得不到任何响应 udp包可以正常通过(traceroute可以收到icmp回包) 什么时候会被防火墙拉黑?
简单来说,存在两种可能性:
* 频率超过一定限制 (主流的做法)
* 扫到"陷阱端口" (非主流的做法)"陷阱端口"的概念见anti-portscan[1]
向80端口高频发出syn包,过了一会就被拉黑了。
docker run -ti --rm docker.io/williamyeh/wrk -t4 -c40000 -d 10000 http://x.x.x.x
基于下面四点原因,可以排除"陷阱端口"这种防御检测方式。
* "陷阱端口"这种方式比较复杂、比较非主流
* 因为可能和业务端口冲突,所以部署在机房中的硬件防火墙不太可能基于"陷阱端口"检测
* 后面确认了目标Linux系统上用了firewalld防火墙,主机上并没有"陷阱端口"这种机制
* 测试结果表明 "频率超过一定限制" 后,ip就被拉黑了结论:基于频率封禁ip
为什么会出现问题背景中的奇怪现象
为什么防火墙会返回syn-ack?
如前面的分析,防火墙虽然没有syn-ack代理功能,但是在扫描端口时,目的端口不存在服务的syn包却收到了syn-ack响应。
换句话说,就是"syn包频率过快"时,就会收到大量的syn-ack响应。
虽然知道了这个现象,但是不清楚为啥会这样。问人和查资料后,在【华安解密之DDoS攻防】11 TCP原理篇之SYN Flood[2]找到一些线索。
如文中所说,ddos设备会做源认证来识别客户端是否合法,此时就会响应syn-ack包。
所以,当扫描端口时,"syn包频率过快",引起ddos设备做源认证。
因为一直没有回ack包,所以一直没有通过源认证。
因为没有通过源认证,同时又在不断的发syn包,所以ddos设备会接着做认证,不断地回syn-ack包。这个时候ddos设备也不会拉黑ip。
为什么防火墙会返回syn-ack和icmp呢?
有了上面的理解,这里也容易猜了。
估计是执行
echo 111 | nc x.x.x.x 28328
时,此时正处于源认证阶段,客户端执行命令刚好能完成正常的三次握手,被识别成正常客户端,因此ddos设备把客户端加白了。加白后,包转发到后端目标机器上。目标机器因为firewalld防火墙,所以返回icmp包
为什么"扫描结果不稳定:有时显示大量端口开放、有时显示一个不固定的端口开放(比如44736)"?
经过测试后,准确的说现象应该是:
1. masscan扫描,然后发现大量端口开放
2. nc完成一次正常连接
3. masscan再次扫描,然后发现ip被拉黑,并且结果中显示有一个开放端口(此端口号不固定)估摸着,ddos安全策略如下:
1. 客户端用masscan扫描,触发源认证
2. nc完成正常连接,通过源认证。此时设备将客户端加白
3. 客户端用masscan再次扫描,因为客户端已经加白了,同时syn包频率异常,所以设备需要再次验证客户端是否正常,不过这次只回一次syn-ack包
4. 客户端masscan 因为收到一次syn-ack包,所以显示有一个端口开放。同时masscan回rst包
5. 设备收到rst包后,认为客户端是恶意的,直接拉黑
怎么规避这种防火墙获取到正确的端口信息?
最简单的一种规避手段:如果目标ip足够多,masscan/nmap扫时随机化扫描地址,就应该到不了频率阈值。
照这个想法,按理说fofa、钟馗之眼 等空间绘测产品应该能准确识别开放端口。验证了一下:有两三个不该显示的端口、实际开放的端口也并没有获取完全(可能是数据更新的问题)。
总结
在这个案例中,主要整清楚了:
链路上有哪些防火墙? 主机防火墙firewalld,策略是默认策略,比较简单 机房中的防ddos设备 防ddos设备的防护策略有哪些? 源认证 首包丢弃 握手时rst 什么时候会触发防护策略? 频率达到阈值 触发防护策略后会发生啥? 要不拉黑;要不就暂时加白
另外可以在云厂商控制台上看看云上抗ddos产品的功能和文档,也能了解ddos产品防护策略有哪些,虽然可能不全。
如果发现内容结论有问题,请后台联系我。
参考资料
anti-portscan: https://github.com/EtherDream/anti-portscan
[2]【华安解密之DDoS攻防】11 TCP原理篇之SYN Flood: https://forum.huawei.com/enterprise/zh/thread-373115.html
[3]从nmap的issue看到有人遇到同样问题: https://github.com/nmap/nmap/issues/1904