Network Scanning
最近更新:2025-10-20   |   字数总计:7.1k   |   阅读估时:27分钟   |   阅读量:
  1. Network-Scanning
    1. ICMP-Protocol
    2. 主机扫描
      1. -sL,列表扫描
      2. -sP,端口扫描
      3. -P0,无ping
      4. -PS,TCP SYN Ping
      5. -PA,TCP ACK Ping
      6. 其他扫描方法
    3. 端口扫描
      1. 端口扫描技术
        1. -sS,TCP SYN扫描
        2. -sT,TCP connect()扫描
        3. -sU,UDP扫描
        4. -sN; -sF; -sX,TCP Null,FIN,Xmas扫描
        5. -sA,TCP ACK扫描
        6. -sW,TCP窗口扫描
        7. –scanflags 定制TCP扫描
        8. 其余的端口扫描技术
    4. Nmap其他功能
    5. 实验内容

Network-Scanning

网络扫描对于侵、维护都十分重要,是信息收集工作的一部分。

通过网络扫描我们可以知道主机的开放情况、主机端口的开放情况、是否采用防火墙等。

ICMP-Protocol

以下内容由Chat-GPT生成:

ICMP(Internet Control Message Protocol)是一种在计算机网络中广泛使用的网络层协议。它的主要目的是用于在IP网络中传输控制消息错误报告。以下是对ICMP协议的详细解释:

  1. 控制消息传递:ICMP主要用于向网络中的设备发送控制消息,以执行各种网络功能。这些控制消息可以用于检测目标设备是否可达、测量网络延迟、跟踪路由路径等。
  2. 错误报告:当发生网络错误时,ICMP还用于生成错误报告,这些报告将被发送回源设备,以通知其发生了问题。例如,如果目标主机不可达,ICMP会生成”目标不可达”消息并将其发送回源主机。
  3. Ping工具:ICMP的一个常见用途是用于Ping工具。Ping工具通过发送ICMP Echo请求消息到目标主机,然后等待目标主机返回Echo响应消息来测试目标主机是否可达和网络延迟情况。
  4. Traceroute工具:Traceroute工具使用ICMP协议来跟踪数据包在网络中的路径。它通过发送一系列的ICMP Echo请求消息,每个请求逐步增加TTL(Time to Live)值,以便在每一跃点收到目标不可达消息时返回网络路径信息。
  5. ICMP消息类型:ICMP定义了多种不同类型的消息,包括Echo请求和Echo响应(用于Ping)、目标不可达消息、超时消息、路由更改通知等。每种消息类型都有特定的目的和用途。
  6. 网络管理和故障排除:ICMP还在网络管理和故障排除中起着关键作用。网络管理员可以使用ICMP消息来监视网络设备的状态、诊断问题以及测量网络性能。
  7. 可控制性:ICMP消息可以根据网络需求进行控制和配置。管理员可以选择允许或禁止特定类型的ICMP消息,以增强网络安全或满足特定需求。

ICMP报文的格式如下:

1
2
3
4
5
6
7
8
9
10
11
+-----------------------+ 
| Type (8bits) | Code (8bits) |
+-----------------------+
| Checksum (16bits) |
+-----------------------+
| Idertifier (16bits) |
+-----------------------+
| Sequence Number (16bits) |
+-----------------------+
| Data (Optional) |
+-----------------------+

一般来说,ICMP报文的头部固定字段有:

  • 类型(Type):8位,用于表示消息的类型。
  • 代码(Code):8位,用于细化消息类型。
  • 校验和(Checksum):16位,校验。
  • 标识符(Identifier):16位
  • 序列号(Sequence Number):16位,与标识符一起用于匹配报文的。

这些字段总共64位,也就是8字节。

Type(类型)

  • Type 字段是 ICMP 消息的第一个字段,占用 8 位(1 字节)。
  • Type 字段用于指示 ICMP 消息的基本类型或类别,定义了消息的目的和操作。
  • 不同的 Type 值对应不同的 ICMP 消息类型,每个 Type 值都有其特定的用途和含义。
  • 一些常见的 ICMP 消息 Type 值及其含义包括:
    • Type 0: Echo Reply(回显应答),通常用于响应 Ping 请求。
    • Type 3: Destination Unreachable(目标不可达),用于指示数据包无法到达目标。
    • Type 8: Echo Request(回显请求),通常用于发送 Ping 请求。
    • Type 11: Time Exceeded(超时),用于指示数据包在路由时超过了最大生存时间。
  • 不同的 Type 值决定了消息的处理方式和如何解释 Code 字段。

Code(代码)

  • Code 字段是 Type 字段之后的 8 位字段,占用 8 位(1 字节)。
  • Code 字段用于细化 ICMP 消息的类型,通常用于区分消息的子类型或更具体的操作。
  • 每个 Type 值可以有多个相关的 Code 值,以便更精确地描述消息的目的。
  • 以 Type 3(目标不可达)消息为例,不同的 Code 值表示不可达的原因,如:
    • Code 0: Network Unreachable(网络不可达)
    • Code 1: Host Unreachable(主机不可达)
    • Code 2: Protocol Unreachable(协议不可达)
    • Code 3: Port Unreachable(端口不可达)
  • Code 字段的含义和用途与特定 Type 值密切相关,不同的 Type/Code 组合定义了不同的 ICMP 操作和响应。

最简单的ping程序,发送一个ICMP type 8 (回声请求)报文到目标IP地址,如果目标主机回应一个type 0的报文,那么就表示主机是开放的。

但是很多主机为了保护资产安全,都会有防火墙拦截此类报文,所以仅仅ICMP扫描对于互联网上的目标通常是不够的。

主机扫描

以下内容基于Nmap工具以及Nmap官方文档。

-sL,列表扫描

1
nmap -sL 202.115.32.43/24

它仅仅列出指定网络上的每台主机, 不发送任何报文到目标主机。

也就是说,该命令的结果并不会表明主机是否开机,他只是对主机进行反向域名解析以获得它们的名字。因为这些名字也是会有有价值的信息,比如: fw.chi.playboy.com是花花公子芝加哥办公室的防火墙。

-sP,端口扫描

1
nmap -sP 202.115.32.43/24

让Nmap仅仅使用ping扫描,然后打印有反应的主机。

地毯式ping而非广播ping,许多主机都不会响应广播请求。

-sP选项在默认情况下, 发送一个ICMP回声请求和一个TCP报文到80端口。如果非特权用户执行,就发送一个SYN报文 (用connect()系统调用)到目标机的80端口。 当特权用户扫描局域网上的目标机时,会发送ARP请求(-PR), ,除非使用了--send-ip选项。 -sP选项可以和除-P0)之外的任何发现探测类型-P* 选项结合使用以达到更大的灵活性。 一旦使用了任何探测类型和端口选项,默认的探测(ACK和回应请求)就被覆盖了。 当防守严密的防火墙位于运行Nmap的源主机和目标网络之间时, 推荐使用那些高级选项。否则,当防火墙捕获并丢弃探测包或者响应包时,一些主机就不能被探测到。

附:ARP请求的基本工作方式:

  1. 设备A知道设备B的IP地址,但不知道它的MAC地址
  2. 设备A创建一个ARP请求数据包,其中包含它自己的IP地址、MAC地址、目标IP地址(设备B的IP地址)以及一个特殊的ARP请求操作码
  3. 设备A将ARP请求数据包发送到本地网络上的所有设备
  4. 其他设备(包括设备B)接收ARP请求数据包,但只有设备B会响应
  5. 设备B接收ARP请求后,知道设备A需要它的MAC地址,因此设备B创建一个ARP响应数据包,其中包含它的IP地址、MAC地址,以及目标IP地址(设备A的IP地址)
  6. 设备B将ARP响应数据包发送回设备A
  7. 设备A接收ARP响应后,知道了设备B的MAC地址,现在可以使用它来构建数据包并将数据包发送到设备B

-P0,无ping

1
nmap -P0 localhost/24

-Pn-P0,跳过主机发现。

该选项完全跳过Nmap发现阶段。 通常Nmap在进行高强度的扫描时用它确定正在运行的机器。 默认情况下,Nmap只对正在运行的主机进行高强度的探测如 端口扫描,版本探测,或者操作系统探测。

这意味着,Nmap会对给出的所有的IP地址进行扫描,好像每个IP所对应的主机都是开启的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
PS D:\Program Files (x86)\Nmap> nmap -P0 192.168.1.105/31
Starting Nmap 7.93 ( https://nmap.org ) at 2023-10-01 20:00 中国标准时间
Nmap scan report for 192.168.1.104
Host is up (0.0085s latency).
All 1000 scanned ports on 192.168.1.104 are in ignored states.
Not shown: 1000 closed tcp ports (reset)
MAC Address: E2:96:FF:67:2B:C7 (Unknown)

Nmap scan report for 192.168.1.105
Host is up (0.000034s latency).
Not shown: 992 closed tcp ports (reset)
PORT STATE SERVICE
80/tcp open http
135/tcp open msrpc
139/tcp open netbios-ssn
445/tcp open microsoft-ds
902/tcp open iss-realsecure
912/tcp open apex-mesh
5357/tcp open wsdapi
5555/tcp open freeciv

-PS,TCP SYN Ping

1
nmap -PS localhost/24

该选项发送一个设置了SYN标志位的空TCP报文。 默认目的端口为80 (可以通过改变nmap.h) 文件中的DEFAULT-TCP-PROBE-PORT值进行配置,但不同的端口也可以作为选项指定。 甚至可以指定一个以逗号分隔的端口列表(如 -PS22,23,25,80,113,1050,35000), 在这种情况下,每个端口会被并发地扫描。

SYN标志位告诉对方您正试图建立一个连接。 通常目标端口是关闭的,一个RST (复位) 包会发回来。 如果碰巧端口是开放的,目标会进行TCP三步握手的第二步,回应 一个SYN/ACK TCP报文。然后运行Nmap的机器则会扼杀这个正在建立的连接, 发送一个RST而非ACK报文,否则,一个完全的连接将会建立。 RST报文是运行Nmap的机器而不是Nmap本身响应的,因为它对收到 的SYN/ACK感到很意外。

Nmap并不关心端口开放还是关闭。 无论RST还是SYN/ACK响应都告诉Nmap该主机正在运行。

在UNIX机器上,通常只有特权用户 root 能否发送和接收 原始的TCP报文。因此作为一个变通的方法,对于非特权用户, Nmap会为每个目标主机进行系统调用connect(),它也会发送一个SYN 报文来尝试建立连接。如果connect()迅速返回成功或者一个ECONNREFUSED 失败,下面的TCP堆栈一定已经收到了一个SYN/ACK或者RST,该主机将被 标志位为在运行。 如果连接超时了,该主机就标志位为down掉了。这种方法也用于IPv6 连接,因为Nmap目前还不支持原始的IPv6报文。

这类方法也用于端口扫描。

-PA,TCP ACK Ping

1
nmap -PA localhost

TCP ACK ping和刚才讨论的SYN ping相当类似。 也许您已经猜到了,区别就是设置TCP的ACK标志位而不是SYN标志位。 ACK报文表示确认一个建立连接的尝试,但该连接尚未完全建立。 所以远程主机应该总是回应一个RST报文, 因为它们并没有发出过连接请求到运行Nmap的机器,如果它们正在运行的话。

-PA选项使用和SYN探测相同的默认端口(80),也可以 用相同的格式指定目标端口列表。如果非特权用户尝试该功能, 或者指定的是IPv6目标,前面说过的connect()方法将被使用。 这个方法并不完美,因为它实际上发送的是SYN报文,而不是ACK报文。

提供SYN和ACK两种ping探测的原因是使通过防火墙的机会尽可能大。 许多管理员会配置他们的路由器或者其它简单的防火墙来封锁SYN报文,除非 连接目标是那些公开的服务器像公司网站或者邮件服务器。 这可以阻止其它进入组织的连接,同时也允许用户访问互联网。 这种无状态的方法几乎不占用防火墙/路由器的资源,因而被硬件和软件过滤器 广泛支持。Linux Netfilter/iptables 防火墙软件提供方便的 --syn选项来实现这种无状态的方法。 当这样的无状态防火墙规则存在时,发送到关闭目标端口的SYN ping探测 (-PS) 很可能被封锁。这种情况下,ACK探测格外有闪光点,因为它正好利用了 这样的规则。

另外一种常用的防火墙用有状态的规则来封锁非预期的报文。 这一特性已开始只存在于高端防火墙,但是这些年类它越来越普遍了。 Linux Netfilter/iptables 通过 --state选项支持这一特性,它根据连接状态把报文 进行分类。SYN探测更有可能用于这样的系统,由于没头没脑的ACK报文 通常会被识别成伪造的而丢弃。解决这个两难的方法是通过即指定 -PS又指定-PA来即发送SYN又发送ACK。

同样该方法也适用于端口扫描。

其他扫描方法

  • -PU,UDP Ping (可以穿越只过滤TCP的防火墙)
  • -PE; -PP ; -PM ,ICMP Ping Type (经典ping)
  • -PR ,ARP Ping(用于局域网)

详细内容见:主机发现 | Nmap参考指南(Man Page)

端口扫描

Nmap把端口分成六个状态: open(开放的), closed(关闭的),filtered(被过滤的), unfiltered(未被过滤的), open|filtered(开放或者被过滤的),或者 closed|filtered(关闭或者被过滤的)

详细内容见:端口扫描基础 | Nmap参考指南(Man Page)

端口扫描技术

端口扫描技术有很多种,对于一些特定的场景,默认的扫描方法可能不适用,这就需要找出最适合的端口扫描技术,但要做到这些,前提就要了解大量的端口扫描技术。

接下来的博客内容记录Nmap的常用的端口扫描的功能。

大部分扫描类型只对特权用户可用。 这是因为他们发送接收原始报文,这在Unix系统需要root权限。 在Windows上推荐使用administrator账户,但是当WinPcap已经被加载到操作系统时, 非特权用户也可以正常使用Nmap。当Nmap在1997年发布时,需要root权限是一个严重的 局限,因为很多用户只有共享的shell账户。现在,世界变了,计算机便宜了,更多人拥有互联网连接 ,桌面UNIX系统 (包括Linux和MAC OS X)很普遍了。Windows版本的Nmap现在也有了,这使它可以运行在更多的桌面上。 由于所有这些原因,用户不再需要用有限的共享shell账户运行Nmap。 这是很幸运的,因为特权选项让Nmap强大得多也灵活得多。

虽然Nmap努力产生正确的结果,但请记住所有结果都是基于目标机器(或者它们前面的防火墙)返回的报文的。 。这些主机也许是不值得信任的,它们可能响应以迷惑或误导Nmap的报文。 更普遍的是非RFC兼容的主机以不正确的方式响应Nmap探测。FIN,Null和Xmas扫描 特别容易遇到这个问题。

-sS,TCP SYN扫描
1
nmap -sS localhost -p portNum

TCP SYN是Nmap的默认扫描,执行的速度很快。

而且不易被察觉,因为没有完成完整的TCP连接,而且几乎所有的平台都遵守统一规则。可以明确地区分端口的状态。

TCP SYN被称为半开放扫描, 因为它不打开一个完全的TCP连接。它发送一个SYN报文, 就像您真的要打开一个连接,然后等待响应。 SYN/ACK表示端口在监听 (开放open),而 RST (复位)表示没有监听者closed。如果数次重发后仍没响应, 该端口就被标记为被过滤filtered。如果收到ICMP不可到达错误 (类型3,代码1,2,3,9,10,或者13),该端口也被标记为被过滤。

-sT,TCP connect()扫描
1
nmap -sT localhost -p portNum

创建系统调用connect(),直接与目标端口建立连接,所以并不会构造原始报文并发送。

系统中的网络应用程序一样会调用connect(),用于与其他主机通信。

Nmap会使用该API读取每个连接的信息,而不是分析原始报文。这导致,TCP connect()扫描耗费的时间比SYN扫描要长许多。

当SYN扫描可用时,它通常是更好的选择。因为Nmap对高层的 connect()调用比对原始报文控制更少, 所以TCP connect()的效率较低。 该系统调用完全连接到开放的目标端口而不是像SYN扫描进行 半开放的复位。这不仅花更长时间,需要更多报文得到同样信息,目标机也更可能 记录下连接。IDS(入侵检测系统)可以捕获两者,但大部分机器没有这样的警报系统。 当Nmap连接,然后不发送数据又关闭连接, 许多普通UNIX系统上的服务会在syslog留下记录,有时候是一条加密的错误消息。 此时,有些真正可怜的服务会崩溃,虽然这不常发生。如果管理员在日志里看到来自同一系统的 一堆连接尝试,她应该知道她的系统被扫描了。

-sU,UDP扫描
1
nmap -sU localhost -p portNum

由于大多数服务都是运行在TCP协议上的,但是也有运行在UDP协议上的服务,可以使用-sU命令进行扫描。

虽然互联网上很多流行的服务运行在TCP 协议上,UDP服务也不少。 DNS,SNMP,和DHCP (注册的端口是53,161/162,和67/68)是最常见的三个。 因为UDP扫描一般较慢,比TCP更困难,一些安全审核人员忽略这些端口。 这是一个错误,因为可探测的UDP服务相当普遍,攻击者当然不会忽略整个协议。 所幸,Nmap可以帮助记录并报告UDP端口。

UDP扫描用-sU选项激活。它可以和TCP扫描如 SYN扫描 (-sS)结合使用来同时检查两种协议。

UDP扫描发送空的(没有数据)UDP报头到每个目标端口。 如果返回ICMP端口不可到达错误(类型3,代码3), 该端口是closed(关闭的)。 其它ICMP不可到达错误(类型3, 代码1,2,9,10,或者13)表明该端口是filtered(被过滤的)。 偶尔地,某服务会响应一个UDP报文,证明该端口是open(开放的)。 如果几次重试后还没有响应,该端口就被认为是 open|filtered(开放|被过滤的)。 这意味着该端口可能是开放的,也可能包过滤器正在封锁通信。 可以用版本扫描(-sV)帮助区分真正的开放端口和被过滤的端口。

UDP扫描的问题:

UDP扫描的巨大挑战是怎样使它更快速。 开放的和被过滤的端口很少响应,让Nmap超时然后再探测,以防探测帧或者 响应丢失。关闭的端口常常是更大的问题。 它们一般发回一个ICMP端口无法到达错误。但是不像关闭的TCP端口响应SYN或者Connect 扫描所发送的RST报文,许多主机在默认情况下限制ICMP端口不可到达消息。 Linux和Solaris对此特别严格。例如, Linux 2.4.20内核限制一秒钟只发送一条目标不可到达消息

-sN; -sF; -sX,TCP Null,FIN,Xmas扫描
1
nmap -sN localhost -p portNum

这是根据TCP RFC中的规范发展出来的扫描方法。

如果扫描系统遵循该RFC,当端口关闭时,任何不包含SYN,RST,或者ACK位的报文会导致 一个RST返回,而当端口开放时,应该没有任何响应。只要不包含SYN,RST,或者ACK, 任何其它三种**(FIN,PSH,and URG)**的组合都行。Nmap有三种扫描类型利用这一点:

  • Null扫描 (-sN)

    不设置任何标志位(tcp标志头是0)

  • FIN扫描 (-sF)

    只设置TCP FIN标志位。

  • Xmas扫描 (-sX)

    设置FIN,PSH,和URG标志位,就像点亮圣诞树上所有的灯一样。

除了探测报文的标志位不同,这三种扫描在行为上完全一致。 如果收到一个RST报文,该端口被认为是 closed(关闭的),而没有响应则意味着 端口是open|filtered。 如果收到ICMP不可到达错误(类型 3,代号 1,2,3,9,10,或者13),该端口就被标记为 filtered

优势:可以躲过一些防火墙,没有建立连接比较神秘。

劣势:并非所有的系统平台都遵循了词条RFC规定。在这些平台(包含Windows)上,针对这样的不含SYN、RST、ACK的报文,端口无论开放或者关闭,都会返回RST,导致所有端口都被标记为closed。并且它不能辨别端口是open还是filtered

但是大多数的Unix操作系统都可以使用此类方法。

-sA,TCP ACK扫描
1
nmap -sA localhost -p portNum

上一种将ACK SYN RST置零的扫描模式无法确定端口是open还是filtered

-sA TCP ACK扫描方式与前面都不同,它无法确定端口处于open还是closed,它的作用是确定防火墙是否启用,即端口是否被过滤。

原理:

ACK扫描探测报文只设置ACK标志位(除非您使用 --scanflags)。当扫描未被过滤的系统时, open(开放的)和closed(关闭的) 端口 都会返回RST报文。Nmap把它们标记为 unfiltered(未被过滤的),意思是 ACK报文不能到达,但至于它们是open(开放的)或者 closed(关闭的) 无法确定。不响应的端口 或者发送特定的ICMP错误消息(类型3,代号1,2,3,9,10, 或者13)的端口,标记为 filtered(被过滤的)。

-sW,TCP窗口扫描
1
nmap -sW localhost -p portNum

窗口扫描其实与ACK扫描差不多,它会分析返回的RST报文。

它与ACK扫描一样,发送TCP ACK数据包,但是将TCP 窗口字段设为非零值,意在与对方服务器商讨窗口范围。如果服务器返回的RST报文中,窗口值的大小为正数,那么该端口的状态为open,如果为0,则closed,而ACK扫描仅会将其判定为unfiltered

该扫描依赖于互联网上少数系统的实现细节, 因此您不能永远相信它。不支持它的系统会通常返回所有端口closed。 当然,一台机器没有开放端口也是有可能的。 如果大部分被扫描的端口是 closed,而一些常见的端口 (如 22, 25,53) 是 filtered,该系统就非常可疑了。 偶尔地,系统甚至会显示恰恰相反的行为。 如果您的扫描显示1000个开放的端口和3个关闭的或者被过滤的端口, 那么那3个很可能也是开放的端口。

–scanflags 定制TCP扫描
1
nmap --scanflags SYNACK localhost -p 80

☆ 还需要指定响应类型,如果不指定,就会用SYN扫描的响应类型来分析返回的数据包。

除了设置需要的标志位,您也可以设置 TCP扫描类型(如-sA或者-sF)。 那个基本类型告诉Nmap怎样解释响应。例如, SYN扫描认为没有响应意味着 filtered端口,而FIN扫描则认为是 open|filtered。 除了使用您指定的TCP标记位,Nmap会和基本扫描类型一样工作。 如果您不指定基本类型,就使用SYN扫描。

自定义头部,自定义响应类型可以更加灵活地对端口进行扫描。

其余的端口扫描技术
  • -sI <zombie host[:probeport]> (Idlescan)
  • -sO (IP协议扫描)
  • -b <ftp relay host> (FTP弹跳扫描)

详细内容见:端口扫描技术 | Nmap参考指南(Man Page)

Nmap其他功能

  • -p portNum 扫描指定端口
  • -F 快速扫描
  • -r 随机扫描端口

待补充,可以参见:Nmap参考指南(Man Page)

实验内容

实验要求:

本次实验主要对主机扫描和端口扫描原理的理解。使用python(scapy库)编写端口扫描程序,对目标IP(包含IP地址段)进行扫描,完成以下功能:

1)使用icmp协议探测主机是否开启;

2)对本机(关闭防火墙)的开放端口和非开放端口完成半连接、ACK、FIN、Null、Xmas、windows扫描,并与nmap扫描结果进行比较。

3)对远程(有防火墙)主机的开放端口和非开放端口完成半连接、ACK、FIN、Null、Xmas、windows扫描,并与2)进行比较,分析结果。

4)回答问题:样例程序中“conf.L3socket=L3RawSocket”的作用是什么?

实验代码部分:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# 导入所需的库
from scapy.all import *
from IPy import IP as IPY


# made by jay1an 2023/9/19

scan_types = ['SYN','ACK','FIN','Null','Xmas','Window']


# conf.L3socket=L3RawSocket
# 定义一个函数,用于执行TCP端口扫描
def port_scan(ip, port, scan_type):
if scan_type == "SYN": # 半连接扫描
p = IP(dst=ip) / TCP(dport=int(port), flags="S")
ans = sr1(p, timeout=5, verbose=1)
print(ans)
print("---------------------------------------")
if ans:
ans.display()
if ans[TCP].flags == "SA":
print(ip, "port", port, "is open.")
elif ans[TCP].flags == "RA":
print(ip, "port", port, "is closed")
else:
print(ip, "port", port, "has a unknown response")
else:
print(ip, "port", port, "is filtered.")
elif scan_type == "ACK": # ACK扫描 (只能判定是否存在防火墙)
p = IP(dst=ip) / TCP(dport=int(port), flags="A")
ans = sr1(p, timeout=5, verbose=1)
print(ans)
print("---------------------------------------")
if ans:
ans.display()
if ans[TCP].flags == "R":
print(ip, "port", port, "is unfiltered")
else:
print(ip, "port", port, "is filtered")
else:
print(ip, "port", port, "is filtered")
elif scan_type == "FIN": # FIN扫描
p = IP(dst=ip) / TCP(dport=int(port), flags="F")
ans = sr1(p, timeout=5, verbose=1)
print(ans)
print("---------------------------------------")
if ans:
ans.display()
if ans[TCP].flags == "RA":
print(ip, "port", port, "is closed.")
else:
print(ip, "port", port, "has an unknown response.")
else:
print(ip, "port", port, "is open or filtered")
elif scan_type == "Null": # Null扫描
# 创建NULL数据包
p = IP(dst=ip) / TCP(dport=port, flags="")
ans = sr1(p, timeout=5, verbose=1)
print(ans)
print("---------------------------------------")
if ans:
ans.display()
if ans[TCP].flags == "RA":
print(ip, "port", port, "is closed.")
else:
print(ip, "port", port, "has an unknown response.")
else:
print(ip, "port", port, "is open or filtered")
elif scan_type == "Xmas": # Xmas扫描
# 创建Xmas Tree数据包
p = IP(dst=ip) / TCP(dport=port, flags="FPU")
ans = sr1(p, timeout=5, verbose=1)
print(ans)
print("---------------------------------------")
if ans:
ans.display()
if ans[TCP].flags == "RA":
print(ip, "port", port, "is closed.")
else:
print(ip, "port", port, "has an unknown response.")
else:
print(ip, "port", port, "is open or filtered")
elif scan_type == "Window": # window扫描(窗口扫描)
# 创建一个TCP SYN数据包,同时设置TCP窗口大小为0
p = IP(dst=ip) / TCP(dport=port, flags="S", window=0)
ans = sr1(p, timeout=5, verbose=1)
print(ans)
print("---------------------------------------")
if ans:
ans.display()
# 检查响应中的TCP标志位
if ans[TCP].flags == "SA":
print(ip, "port", port, f"is open (TCP window size: {ans[TCP].window}).")
else:
print(ip, "port", port, " is closed.")
else:
print(ip, "port", port, " is closed or filtered.")


# 定义一个函数,用于执行ICMP ping扫描
def Ping(dest):
# 使用IPy库将目标参数dest解析为一个IP地址对象
ip_addr = IPY(dest)

# 遍历解析后的IP地址列表
for ip in ip_addr:
# 为每个IP地址构建一个ICMP ping数据包
packet = IP(dst=str(ip)) / ICMP() / b'rootkit'

# 使用Scapy的sr1函数发送ping数据包,timeout参数设置为1秒,verbose参数设置为False以禁用详细信息输出
ping = sr1(packet, timeout=3, verbose=False)

# 如果成功收到响应,打印 "ip is up!" 并使用彩色输出来突出显示
if ping:
print("\033[0;32;47m\t" + str(ip) + " is up!" + "\033[0m")
# 如果没有收到响应,打印 "ip is down!"
else:
print(str(ip) + " is down!")


def main():

#输入ip 端口 和扫描类型
dest = '127.0.0.1'
port = 22
scan_type = 'Window'

print("== Network Scanner ==")
print(dest,port,scan_type)

# 调用Ping函数执行ICMP ping扫描
Ping(dest)

# 调用port_scan函数执行TCP端口扫描
port_scan(dest, port, scan_type)

if __name__ == '__main__':
main()

本次实验主要是通过python代码实现网络数据包的构造、发送、接收、分析。

再通过计算机网络知识结合RFC规则,判断主机和端口状态。