一、网络分层基础(OSI 与 TCP/IP)
| OSI 层 | TCP/IP 层 | 核心设备 | 关键协议 | 地址类型 | 广播域 |
|---|---|---|---|---|---|
| 7 应用层 | 应用层 | 终端软件 | HTTP/SSH/DNS | --- | --- |
| 4 传输层 | 传输层 | 防火墙 | TCP/UDP | 端口号 | --- |
| 3 网络层 | 网际层 | 路由器 | IP/ICMP/OSPF/BGP | IP 地址 | ❌ 不广播 |
| 2 数据链路层 | 网络接口层 | 交换机 | ARP/Ethernet/VLAN | MAC 地址 | ✅ 广播域 |
| 1 物理层 | 网络接口层 | 网线/光纤 | 电信号/光信号 | --- | --- |
关键结论:
- 二层(交换机):同一 VLAN 内,MAC 地址通信,ARP 广播可达;
- 三层(路由器):跨网段,IP 地址通信,ARP 广播被阻断,需路由表转发;
- 广播域边界:交换机转发广播,路由器隔离广播。
二、ARP 协议深度解析(二层探测)
2.1 ARP 工作流程
主机 A (192.168.1.10) 想访问 192.168.1.20
↓
查 ARP 缓存:无记录
↓
构造 ARP Request 广播帧:
发送方 MAC: AA:AA:AA:AA:AA:AA
发送方 IP: 192.168.1.10
目标 MAC: 00:00:00:00:00:00 (未知)
目标 IP: 192.168.1.20
以太网目标: FF:FF:FF:FF:FF:FF (广播)
↓
交换机泛洪到同一 VLAN 所有端口
↓
192.168.1.20 收到 → 单播 ARP Reply:
目标 MAC: AA:AA:AA:AA:AA:AA
发送方 MAC: BB:BB:BB:BB:BB:BB
发送方 IP: 192.168.1.20
↓
主机 A 缓存 MAC,开始二层通信
2.2 ARP 帧结构(Ethernet II)
| 字段 | 长度 | 说明 |
|---|---|---|
| 目标 MAC | 6 bytes | FF:FF:FF:FF:FF:FF = 广播 |
| 源 MAC | 6 bytes | 请求者 MAC |
| 类型 | 2 bytes | 0x0806 = ARP |
| 硬件类型 | 2 bytes | 0x0001 = Ethernet |
| 协议类型 | 2 bytes | 0x0800 = IPv4 |
| 操作码 | 2 bytes | 0x0001 = Request, 0x0002 = Reply |
| 发送方 MAC | 6 bytes | |
| 发送方 IP | 4 bytes | |
| 目标 MAC | 6 bytes | 请求时全 0 |
| 目标 IP | 4 bytes | 被查询的 IP |
2.3 ARP 探测的边界
| 场景 | 结果 | 原因 |
|---|---|---|
同网段 192.168.1.0/24 |
✅ 能扫到 | 二层广播可达 |
跨网段 192.168.2.0/24 |
❌ 扫不到 | 路由器阻断广播 |
| 目标关机但 IP 在交换机 MAC 表 | ⚠️ 可能误报 | 交换机缓存未过期 |
| 目标开防火墙禁 ping | ✅ ARP 仍能通 | ARP 在防火墙之前 |
三、ICMP/IP 协议深度解析(三层探测)
3.1 ICMP Echo (Ping) 流程
主机 A (192.168.1.10) ping 192.168.2.20
↓
判断:目标 IP 不在同一子网
↓
查路由表:走默认网关 192.168.1.1
↓
ARP 解析网关 MAC → 封装 ICMP 包:
IP 头:源 192.168.1.10,目标 192.168.2.20
以太网:目标 MAC = 网关 MAC
↓
路由器 R1 收到 → 查路由表 → 转发到 R2 → ... → 目标网络
↓
192.168.2.20 收到 ICMP Echo Request
↓
回复 ICMP Echo Reply(逆向路径)
↓
主机 A 收到 → 显示存活
3.2 ICMP 与 ARP 的关键差异
| 特性 | ARP | ICMP (Ping) |
|---|---|---|
| OSI 层 | 二层 (Data Link) | 三层 (Network) |
| 依赖地址 | MAC 地址 | IP 地址 |
| 能否跨网段 | ❌ 不能 | ✅ 能 |
| 经过路由 | ❌ 不经过 | ✅ 经过 |
| 防火墙拦截 | 很难拦截 | 容易被禁 |
| 响应速度 | 极快 (<1ms) | 较慢 (几 ms~几百 ms) |
| 准确性 | 高(直连) | 中(可能被过滤) |
四、查找空闲 IP 的实战方案
4.1 工具对比
| 工具 | 技术 | 层 | 跨网段 | 速度 | 隐蔽性 | 准确度 |
|---|---|---|---|---|---|---|
arp-scan |
ARP 广播 | 二层 | ❌ | 极快 (秒级/256IP) | 高(无日志) | 极高 |
arping |
ARP 单播 | 二层 | ❌ | 慢 (逐 IP) | 高 | 极高 |
nmap -sn |
ICMP/ARP/TCP | 智能 | ✅ | 快 | 中 | 高 |
nmap -PS |
TCP SYN | 三层 | ✅ | 快 | 低(有日志) | 中 |
masscan |
自定义 TCP | 三层 | ✅ | 极快 (万级/秒) | 低 | 中 |
fping |
ICMP 并行 | 三层 | ✅ | 极快 | 中 | 高 |
4.2 二层探测:ARP 方案(同网段)
arp-scan(推荐,批量最快)
# 安装
sudo apt install arp-scan
# 自动识别本地网卡并扫描
sudo arp-scan -l
# 指定网卡和网段
sudo arp-scan -I eth0 192.168.1.0/24
# 输出格式控制(只显示 IP+MAC)
sudo arp-scan 192.168.1.0/24 | grep -E '^[0-9]' | awk '{print $1}'
输出解析:
Interface: eth0, type: EN10MB, MAC: xx:xx:xx:xx:xx:xx, IPv4: 192.168.1.10
Starting arp-scan 1.9.7 with 256 hosts
192.168.1.1 aa:bb:cc:dd:ee:ff Huawei Technologies
192.168.1.10 11:22:33:44:55:66 (Unknown: locally administered)
192.168.1.20 77:88:99:aa:bb:cc Apple, Inc.
3 packets received by filter, 0 packets dropped by kernel
Ending arp-scan 1.9.7: 256 hosts scanned in 2.456 seconds. 3 responded
已用 IP :3 个(.1, .10, .20)
空闲 IP:256 - 3 = 253 个
Python + Scapy(自定义,无依赖)
#!/usr/bin/env python3
"""
arp_free_ip.py - 查找同网段空闲 IP
需要 root 权限
"""
from scapy.all import ARP, Ether, srp, conf
import sys
import ipaddress
from concurrent.futures import ThreadPoolExecutor
conf.verb = 0 # 关闭 Scapy 冗余输出
def arp_ping(ip):
"""单 IP ARP 探测"""
pkt = Ether(dst="ff:ff:ff:ff:ff:ff") / ARP(pdst=str(ip))
ans, _ = srp(pkt, timeout=1, retry=0)
return str(ip), len(ans) > 0
def scan_network(network, max_workers=50):
"""批量扫描网段"""
net = ipaddress.ip_network(network, strict=False)
hosts = list(net.hosts()) # 排除网络地址和广播地址
used = []
free = []
print(f"[*] 开始扫描 {network},共 {len(hosts)} 个主机...")
with ThreadPoolExecutor(max_workers=max_workers) as executor:
results = executor.map(arp_ping, hosts)
for ip, is_alive in results:
if is_alive:
used.append(ip)
print(f"[+] 存活: {ip}")
else:
free.append(ip)
return used, free
def main():
if len(sys.argv) != 2:
print(f"用法: sudo python3 {sys.argv[0]} 192.168.1.0/24")
sys.exit(1)
network = sys.argv[1]
used, free = scan_network(network)
print(f"\n{'='*50}")
print(f"扫描完成: {network}")
print(f"已用 IP: {len(used)} 个")
print(f"空闲 IP: {len(free)} 个")
print(f"\n前 10 个空闲 IP:")
for ip in free[:10]:
print(f" - {ip}")
# 保存到文件
with open("free_ips.txt", "w") as f:
f.write(f"# 空闲 IP 列表 - {network}\n")
f.write(f"# 生成时间: {__import__('datetime').datetime.now()}\n")
for ip in free:
f.write(f"{ip}\n")
print(f"\n[+] 空闲 IP 已保存到 free_ips.txt")
if __name__ == "__main__":
main()
运行:
sudo pip3 install scapy
sudo python3 arp_free_ip.py 192.168.1.0/24
4.3 三层探测:ICMP/TCP 方案(跨网段)
nmap 智能扫描(推荐,自动选最优协议)
# 默认:同网段用 ARP,跨网段用 ICMP
sudo nmap -sn 192.168.1.0/24 # 本地网段(实际走 ARP)
sudo nmap -sn 192.168.2.0/24 # 跨网段(走 ICMP)
# 强制只用 ICMP(防火墙可能禁 ping)
sudo nmap -sn -PE 192.168.2.0/24
# 强制 TCP SYN(防火墙禁 ping 时用)
sudo nmap -sn -PS22,80,443 192.168.2.0/24
# 强制 UDP(某些 Windows 主机只回 UDP)
sudo nmap -sn -PU53,161 192.168.2.0/24
输出解析:
Starting Nmap 7.94 ( https://nmap.org )
Nmap scan report for 192.168.2.1 [host down]
Nmap scan report for 192.168.2.10
Host is up (0.0023s latency).
MAC Address: AA:BB:CC:DD:EE:FF (Huawei Technologies)
...
Nmap done: 256 IP addresses (3 hosts up) scanned in 3.45 seconds
fping 高速并行 ping
# 安装
sudo apt install fping
# 扫描并分类输出
fping -a -g 192.168.2.0/24 2>/dev/null | tee alive_ips.txt
fping -u -g 192.168.2.0/24 2>/dev/null | tee dead_ips.txt
# -a = alive, -u = unreachable, -g = 生成网段
masscan 极速端口扫描(万级/秒)
# 安装
sudo apt install masscan
# 扫描存活(0 端口 = 只 ping)
sudo masscan 192.168.2.0/24 -p0 --rate 10000
# 扫描常用端口(更快判断存活)
sudo masscan 192.168.2.0/24 -p22,80,443,3389 --rate 10000
五、拓展技术
5.1 DHCP 租约表查询(比扫描更快)
# 如果网络有 DHCP 服务器,直接查租约
cat /var/lib/dhcp/dhcpd.leases | grep "lease\|hardware\|client-hostname"
# 或路由器 Web 界面导出
5.2 SNMP 交换机 MAC 表查询(企业网)
# 查交换机 MAC 地址表,反推已用 IP
snmpwalk -v 2c -c public 192.168.1.1 1.3.6.1.2.1.17.4.3.1.1
# OID: dot1dTpFdbAddress (MAC 表)
5.3 网络流量监听(被动发现)
# tcpdump 抓 ARP 请求,被动记录存活主机
sudo tcpdump -i eth0 arp -w arp_traffic.pcap
# 分析:tshark -r arp_traffic.pcap -T fields -e arp.src.proto_ipv4 | sort -u
5.4 IPv6 邻居发现(NDP)
# IPv6 没有 ARP,用 NDP (Neighbor Discovery Protocol)
sudo ip -6 neigh show # 查看邻居表
sudo ndisc6 -r 5 2001:db8::1 eth0 # 主动探测
六、技术选型总结
| 场景 | 推荐工具 | 理由 |
|---|---|---|
| 同网段找空闲 IP | arp-scan / Python Scapy |
二层最快,防火墙挡不住 |
| 跨网段找空闲 IP | nmap -sn -PS |
智能 fallback,TCP 穿透防火墙 |
| 极速扫描(10万+ IP) | masscan |
自定义协议栈,万级/秒 |
| 企业内网(有交换机权限) | SNMP + MAC 表 | 不发包,零影响 |
| 隐蔽探测(红队) | tcpdump 被动监听 |
不主动发包,无日志 |
| 自动化集成 | Python Scapy / Nmap XML | 结构化输出,易解析 |
七、一句话速记
同网段用 ARP(arp-scan),跨网段用 ICMP/TCP(nmap),极速用 masscan,隐蔽用被动监听,企业用 SNMP 。
二层广播不路由,三层路由不广播------选错层,扫空网。
八、 附录
8.1 Windows 通过 ping 查找存活的IP
150..161 | ForEach-Object {
ip = "10.73.2._"
ok = Test-Connection -Count 1 -Delay 1 -Quiet -ComputerName ip
if ($ok) { Write-Output "UP $ip" }
else { Write-Output "DOWN $ip" }
}
8.2 Linux 通过 ping 查找存活的IP
#!/bin/bash
# 探测 192.168.88.150-220 存活主机
MAX_JOB=30
LOG_T=$(date +%F_%H-%M)
up_log="up_ip_${LOG_T}.log"
down_log="down_ip_${LOG_T}.log"
> "$up_log" > "$down_log" # 清空旧日志
for i in {150..220};do
ip="192.168.88.$i"
{
if ping -c 2 -i 0.2 -w 1 "$ip" &>/dev/null;then
echo "$ip 运行中~~~~~"
else
echo "$ip 挂了" >&2
fi
} >> "$up_log" 2>>"$down_log" &
# 控制并发
while [ $(jobs -r | wc -l) -ge $MAX_JOB ];do sleep 0.5;done
done
wait
echo "扫描完成,结果已写入 $up_log $down_log"
本文为同步搬运内容,原创首发于个人独立博客网站:https://www.zheng-chang-ren.xyz
平台更新优先级说明:所有技术笔记、实验教程、踩坑总结均会优先发布、长期维护于个人独立博客;CSDN 仅作为辅助分发渠道。
若想查阅全部完整文集、获取最新首发内容,建议收藏并优先访问我的个人博客网站。