当端口扫描遇到防火墙

问题背景

为什么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抓包,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[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包。

    基于如下两个原因可以推断出存在防火墙

    1
    2
    * 一般来说,向操作系统不存在的端口发送tcp syn包时,会收到操作系统的rst包
    * 似乎只有防火墙喜欢返回icmp包

    现象二:

    1
    2
    3
    4
    5
    nmap工具扫描前:可以ping通,curl 80可以访问

    nmap工具扫描后,ping和curl都无法访问

    过一段时间后:又可以ping通,curl 80也可以访问

    说明防火墙有黑名单机制。

    结论:确认存在防火墙,且有黑名单ip机制

  • 判断防火墙是否有”握手时rst”、首包丢弃等行为

    思路:
    连接提供tcp服务的端口并抓包,查看是否有rst,首包丢弃等行为

    过程:

    执行echo | nc x.x.x.x 80,并抓包

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    [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回包)
  • 什么时候会被防火墙拉黑?

    简单来说,存在两种可能性:

    1
    2
    * 频率超过一定限制 (主流的做法)
    * 扫到"陷阱端口" (非主流的做法)

    “陷阱端口”的概念见anti-portscan

    向80端口高频发出syn包,过了一会就被拉黑了。

    1
    docker run -ti --rm docker.io/williamyeh/wrk -t4  -c40000 -d 10000 http://x.x.x.x

    基于下面四点原因,可以排除”陷阱端口”这种防御检测方式。

    1
    2
    3
    4
    * "陷阱端口"这种方式比较复杂、比较非主流
    * 因为可能和业务端口冲突,所以部署在机房中的硬件防火墙不太可能基于"陷阱端口"检测
    * 后面确认了目标Linux系统上用了firewalld防火墙,主机上并没有"陷阱端口"这种机制
    * 测试结果表明 "频率超过一定限制" 后,ip就被拉黑了

    结论:基于频率封禁ip

为什么会出现问题背景中的奇怪现象

  • 为什么防火墙会返回syn-ack?

    如前面的分析,防火墙虽然没有syn-ack代理功能,但是在扫描端口时,目的端口不存在服务的syn包却收到了syn-ack响应。

    换句话说,就是”syn包频率过快”时,就会收到大量的syn-ack响应。

    虽然知道了这个现象,但是不清楚为啥会这样。问人和查资料后,在【华安解密之DDoS攻防】11 TCP原理篇之SYN Flood找到一些线索。

    如文中所说,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
    2
    3
    1. masscan扫描,然后发现大量端口开放
    2. nc完成一次正常连接
    3. masscan再次扫描,然后发现ip被拉黑,并且结果中显示有一个开放端口(此端口号不固定)

    估摸着,ddos安全策略如下:

    1
    2
    3
    4
    5
    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产品防护策略有哪些,虽然可能不全。

如果发现内容结论有问题,请后台联系我。

参考

从nmap的issue看到有人遇到同样问题