通过二层和三层查询空闲IP

一、网络分层基础(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 仅作为辅助分发渠道。

若想查阅全部完整文集、获取最新首发内容,建议收藏并优先访问我的个人博客网站。