目录
主机发现技术详解
碎碎念
最近在开发资产扫描器,决定梳理和深挖一下几款经典工具的实现方式,开源代码看了几套原理大同小异,于是决定从最基础的协议层开始深挖。用了好多年 Nmap,似乎一直没有深究过这款时代产物的运行原理,正好整理一番。因为目的是开发自己的扫描器,所以分类【安全开发】
本章只关注探活
讨论主机发现的时候 nmap 命令补充参数 -sn,用来禁用 nmap 端口扫描,我们只关注探活。
Nmap 基于协议实现主机发现,根据协议分类,依次有:
一、ARP 协议发现
- 原理:构造一个arp 请求数据包,并广播出去,有回应包(arp-reply)则是活跃主机,迟迟收不到回应包则不是活跃主机
- 优点:准确度高
- 缺点:不能对不同网段的目标进行扫描
- 适用场景:目标主机与扫描器(nmap)处在同一个广播域
- 命令 :
nmap -PR [Target]
二、ICMP 协议发现

- 背景知识 :icmp 报文有两种:
差错和查询报文,其中查询报文是用一对请求和应答定义的,可以通过发送特定的 icmp 请求报文,看对方在收到后回应什么类型的应答报文来判断主机是否存活。 - 原理 :4种类型的查询报文,但是适合做探测的只有3种报文
- i. 响应请求或应答
- ping 命令,对方应答回复则是活跃主机,否则不活跃
- ii. 时间戳请求或应答
- 发送时间戳请求,有应答是活跃主机,否则不活跃
- iii. 地址掩码请求或应答
- 源主机发送,用于无盘(网吧等)系统在引导过程中获取自己子网掩码,发送地址掩码请求,有应答是活跃主机,否则不是
- i. 响应请求或应答
- 命令 1 :
nmap -PE [target]- (ping 发送 icmp type 8 等待 icmp type 0)
- 命令 2 :
nmap -PP [target]- (时间戳请求 发送 icmp type 13 等待 icmp type 14)
- 命令 3 :
nmap -PM [target]- (地址掩码请求 发送 icmp type 17 等待 icmp type 18)
三、TCP 协议发现

- 背景知识:到 tcp 层有端口概念,tcp 三次握手过程。
- 原理:利用 tcp 三次握手机制实现主机探活
- 具体方式:TCP syn 扫描 和 TCP ack 扫描
- syn 扫描 :nmap 发送一个设置了 SYN 标志位的数据包,默认发送给对方 80 端口,数据包内容为空,也可以通过参数修改默认端口,如果目标主机这个端口是开放的,会返回一个 syn/ack 数据包,端口不开放,会返回 rst 数据包,不论哪种数据包,返回了就说明主机活跃。nmap 探测完后会主动发送 rst。
- 命令 :
nmap -PS[port1,port2] [target] - 命令样例 :
nmap -PS 8998 12.12.12.12
- 命令 :
- ack 扫描 :nmap 给目标发送 ack 包,主机搞不清情况,只能回复 rst 包,表示无法建立连接。(ack 扫描成功率很低,因为不少主机或安全机制会把这种莫名其妙的 ack 请求直接过滤掉)
- 命令 :
nmap -PA [target]
- 命令 :
四、UDP 协议发现
- 原理:发送 udp 数据包,如果端口返回 icmp 不可达数据包(icmp type 3),说明端口是关闭的,如果端口不返回,说明端口是开放的。
- 缺点:端口不返回情况较复杂,可能是网络问题导致不回包,会被误判为端口开放,所以发现率低。而且速度慢,因为 icmp 错误报文生成速度有限制,每 4s 产生 80 个,超出会暂停 1/4s。
- 命令 :
nmap -PU [target] - 备注:基于 UDP 探测的特性,所以 tcp 扫描适合发现主机开放端口,udp 扫描适合发现主机关闭端口
五、SCTP 协议发现
SCTP(Stream Control Transmission Protocol,流控制传输协议)是一种可靠的、面向连接的、面向消息的传输层协议,位于 TCP/IP 协议栈中,与 TCP 和 UDP 处于同一层级。
- 补充 :与 tcp 协议一样都是传输层协议,但是有很大区别:
- 1.tcp 是单地址链接,sctp 可用于多地址链接
- 2.tcp 是基于字节流传输,sctp 是基于消息流(stream),tcp 只能支持一个流,sctp 链接(association)同时可以支持多个流。
- 3.tcp 三次握手,sctp 四次握手机制(互相问好并确认)
- 在 SCTP中,客户端使用一个INIT报文发起一个连接,服务器端使用一个INIT-ACK报文进行应答,其中就包括了cookie(标识这个连接的唯一上下文)。然后客户端使用一个COOKIE-ECHO报文进行响应,其中包含了服务器端所发送的cookie。服务器端要为这个连接分配资源,并通过向客户端发送一个COOKIE-ACK报文对其进行响应。
- 命令 :
nmap -PY[port1,port2] [target] - 缺点:对方主机很有可能不支持 sctp 协议,所以命中率很低
六、IP 协议发现

头部中协议长度是 8 位,用来标识使用哪种协议进行数据传输。ICMP 是 1,IGMP(互联网组管理协议) 是 2,TCP 是 6,UDP 是 17,GRE 是 47 等。理论上 nmap 使用的协议可以包含上百个,如果不指定的话 nmap 默认使用 ICMP,IGMP 和 IP-in-IP (IP隧道协议,ip over ip)协议,对应的 IP 协议号分别为:1,2,4。也可以使用 -PO 指定使用的协议号
nmap -sP -PO [target]使用默认的协议扫描 (等同于:nmap -sP -PO 1,2,4 [target])nmap -sP -PO 6,17 [target](编号 6 TCP 协议,编号 17 UDP 协议)
但是这种的形式发动的数据包都是空,非正常数据包,很容易被检测出来,可以使用 --data-length 参数添加随机数据填充
nmap --data-length 25 [target]
七、DNS 协议发现
Nmap 对目标主机进行扫描的时候如果发现目标主机是一台 web 服务器,那么他除了 IP 之外还会有一个域名,nmap 发现 ip 存在域名后,会向域名服务器(DNS server)提出请求来显示 IP 对应的域名,但这种行为仅会对活跃主机进行探测,同网段非活跃主机不会默认进行。如果希望 nmap 对所有探测出来的活跃 IP 都显示其对应的域名的话,可以使用 -R 参数
nmap -R [target]强制对 IP 进行域名转换,显示 ip 对应的域名,这比较耗时nmap -n [target]强制不对 IP 进行域名装换,这样可以节省时间
如果不想 nmap 在扫描的时候查询 dns server 上留下查询记录,可以使用 --dns-servers 参数
nmap --dns-servers [server1,server2] [target]
补充
Nmap中提供了--packet-trace选项,通过它就可以观察Nmap发出了哪些数据包,收到了哪些数据包,有了这个研究方法,可以更深入地理解Nmap的运行原理。
发送数据包 - SENT
SENT (0.0253s) TCP 192.168.1.10:54321 > 192.168.1.1:80 S ttl=56 id=45678 iplen=44 seq=123456789 win=1024
字段含义:
- SENT (0.0253s):在扫描开始后 0.0253 秒发送了该包。
- TCP:协议类型(也可能是 UDP、ICMP 等)。
- 192.168.1.10:54321:本机 IP 和源端口。
- 192.168.1.1:80:目标 IP 和目标端口。
- S:TCP 标志位(这里是 SYN)。其他可能包括:
- S = SYN
- A = ACK
- SA = SYN+ACK
- R = RST
- F = FIN
- PA = PUSH+ACK 等
- ttl=56:IP 生存时间(Time To Live)。
- id=45678:IP 数据包标识符。
- iplen=44:IP 包总长度(字节)。
- seq=123456789:TCP 序列号。
- win=1024:TCP 窗口大小。
接收数据包 - RCVD
RCVD (0.0451s) TCP 192.168.1.1:80 > 192.168.1.10:54321 SA ttl=64 id=0 iplen=44 seq=987654321 ack=123456790 win=65535
字段含义
- SA 表示目标返回了 SYN+ACK,说明该端口是开放的。
- ack=123456790 是对之前发送的 SYN 包的确认(seq+1)【seq =123456789】
实操测试
nmap 扫描一个目标会先判断目标和自己是否在同一个网段,如果在同一个网段,会优先使用 arp 扫描,不在会默认进行其他扫描
目标 :流量层研究 nmap 的扫描具体做了哪些事
命令 :nmap 10.95.58.94

nmap返回结果

流量上看出nmap 做了如下动作:
-
- 向目标IP发送一个ICMP Echo Request (type 8); → 目标回包:ICMP Echo replay (type 0) → 存活(这一步已经能判断主机存活)
-
- 向目标IP的443端口发送一个TCP SYN请求 (seq=0); → 目标回包:TCP RST-ACK ,seq=1
-
- 向目标IP的80端口发送一个TCP ACK请求; → 目标回包:图未回复,正常会回一个 RST 包
-
- 向目标IP发送一个ICMP Timestamp Request(type 13); → 目标回包:Timestamp replay
-
- 查找目标IP反向DNS解析的地址(图中未体现出来) → (目标 IP 是 web 服务器有域名,会触发反查 DNS)
-
- 当目标IP回应了任何一个探测包,则nmap认为目标IP存活,则进行下一步(图中 4 个请求包回复了 3个);
-
- 向目标发送1000个常用端口发送SYN请求,判断存活端口;
注:
-
前 4 个请求并不需要每个都有回应,任意 1个回应即可判定主机存活 (如下图可以看到目标回应ACK 1 个RST)

-
IP 反查是对 web 服务主机的默认行为,非 web 主机默认不会触发
-
以上测试 nmap 和目标主机均不在同一个广播域
其他情况
根据运行 nmap 的用户权限不同,nmap 功能会有一定的区别
| 特性 | 特权用户 | 非特权用户 |
|---|---|---|
| 用户身份 | root / 管理员 | 普通用户 |
| 能否发 ICMP | 能 | 不能 |
| 能否发自定义 TCP 包 | 如 SYN、ACK | 只能完整 connect() |
| 主机发现方式 | ICMP + TCP + ARP(跨网段用ICMP) | 仅对 80/443 做 TCP connect() |
| 端口扫描类型 | SYN 扫描(半开)→ 然后断开 | Connect 扫描(全连接)→ 然后断开 |
| 隐蔽性 | 更高 | 较低(会建立完整连接) |
-
非特权用户扫描

-
特权用户扫描

Masscan 扫描工具不区分运行用户权限,均为半链接
经验之谈
内网主机存活探测最佳实践:
nmap -n -sn -PE -PS80,443,22,445,3389,12345 -PU40125
-n禁止 IP 反向解析域名,优化项,加快探测速度-sn禁止端口扫描,仅用于存活探测,优化项,加快探测速度-PEICMP echo request 请求包 (type 8)-PS [port1,port2]SYN 半链接指定端口探测-PU允许发送 UDP 探测包(为什么是 40125 端口?因为这个高端口没有标准服务,随机选的,UDP 探测期待端口关闭并返回 ICMP Timestamp replay,这个端口大概率是关闭的)
凡事都有特殊情况及注意的点:
-
- 不要启用强制ARP请求,跨网段ARP请求有可能会出现代理ARP应答的情况;
-
- 扫描结果一般只供参考,不能100%可信,如,当遇到蜜罐的时候,所有蜜罐网络中的IP都是存活的;
by 久违 2026.1.18