脚本如何发现内网在线设备

wen 实用脚本 21

本文目录导读:

脚本如何发现内网在线设备

  1. 核心原理
  2. 方案一:使用 Python 脚本(最灵活、跨平台)
  3. 方案二:使用 Shell 脚本(简单、Linux/macOS 原生)
  4. 方案三:使用 Windows PowerShell(Windows 原生)
  5. 如何选择与注意事项

发现内网在线设备是网络管理和安全审计中的常见需求,实现这一目标的核心原理通常基于网络层(IP)链路层(MAC) 的协议交互。

由于你提到的“脚本”,以下将介绍几种常用的脚本实现方式,涵盖不同的原理、适用场景以及对应的示例代码(主要使用Python和Shell)。

核心原理

  1. ICMP Ping 请求:向目标IP发送ICMP Echo Request,等待响应。
  2. ARP 请求:在本地广播域发送ARP请求,询问“谁是IP X.X.X.X?”。
  3. TCP/UDP 端口探测:尝试连接目标的特定端口(如80, 445, 22),根据连接是否成功判断设备是否在线。

使用 Python 脚本(最灵活、跨平台)

Python 拥有丰富的网络库,适合构建更复杂的扫描逻辑。

基于 Ping 的简单方法(需要系统权限)

这种方法最直接,但速度较慢,且容易被防火墙拦截。

import subprocess
import platform
def ping_host(ip):
    """Ping 一个 IP 地址,返回是否在线。"""
    # 根据系统选择 ping 参数
    param = "-n" if platform.system().lower() == "windows" else "-c"
    # -W 1 设置超时 1 秒 (Linux/macOS), windows 用 -w 1000 (毫秒)
    command = ["ping", param, "1", "-W", "1", ip] if platform.system().lower() != "windows" else ["ping", param, "1", "-w", "1000", ip]
    try:
        # 执行命令, 不显示输出, 设置超时
        result = subprocess.run(command, capture_output=True, timeout=2)
        return result.returncode == 0
    except subprocess.TimeoutExpired:
        return False
def scan_network_ping(network_prefix):
    """扫描 /24 网段 (192.168.1.0/24)"""
    online_devices = []
    for i in range(1, 255):  # 去掉 .0 (网络地址) 和 .255 (广播地址)
        ip = f"{network_prefix}.{i}"
        if ping_host(ip):
            print(f"[+] 设备在线: {ip}")
            online_devices.append(ip)
    return online_devices
if __name__ == "__main__":
    # 请根据你的网络修改前缀,"192.168.1"
    scan_network_ping("192.168.1")

基于 ARP 请求的高效方法(推荐,仅限局域网)

使用 scapy 库构造和发送 ARP 包,这是局域网发现最准确、快速的方法之一,但需要 root/管理员权限。

from scapy.all import ARP, Ether, srp
import sys
def scan_network_arp(target_ip):
    """
    使用 ARP 请求扫描网段。
    :param target_ip: "192.168.1.0/24"
    """
    # 创建 ARP 请求包
    arp_request = ARP(pdst=target_ip)
    # 创建以太网广播帧
    broadcast = Ether(dst="ff:ff:ff:ff:ff:ff")
    # 组合包
    packet = broadcast / arp_request
    # 发送包并接收响应
    # timeout: 等待响应的秒数
    # verbose: 是否显示详细信息
    answered_list = srp(packet, timeout=2, verbose=False)[0]
    devices = []
    for element in answered_list:
        device_info = {
            "ip": element[1].psrc,   # 响应者的 IP
            "mac": element[1].hwsrc  # 响应者的 MAC 地址
        }
        devices.append(device_info)
        print(f"[+] 设备在线: IP={device_info['ip']:15} MAC={device_info['mac']}")
    return devices
if __name__ == "__main__":
    # 需要 root 权限运行
    scan_network_arp("192.168.1.0/24")

基于 TCP 连接探测(穿透性强)

尝试连接常见端口(如 80, 445, 22),如果目标主机在线且端口开放,连接会成功。

import socket
import concurrent.futures
def check_tcp_port(ip, port, timeout=1):
    """尝试 TCP 连接一个端口"""
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.settimeout(timeout)
    try:
        result = sock.connect_ex((ip, port))
        if result == 0:
            return True
        else:
            return False
    except socket.error:
        return False
    finally:
        sock.close()
def scan_network_tcp(network_prefix, ports=[80, 445, 22]):
    """扫描网段,使用多线程加速"""
    online_devices = []
    # 使用线程池加快扫描速度
    with concurrent.futures.ThreadPoolExecutor(max_workers=50) as executor:
        # 为所有 IP 创建任务
        future_to_ip = {executor.submit(check_tcp_port, f"{network_prefix}.{i}", ports[0]): f"{network_prefix}.{i}" for i in range(1, 255)}
        for future in concurrent.futures.as_completed(future_to_ip):
            ip = future_to_ip[future]
            try:
                if future.result():
                    online_devices.append(ip)
                    print(f"[+] 设备可能在线: {ip} (端口 {ports[0]} 开放)")
            except:
                pass
    return online_devices
if __name__ == "__main__":
    scan_network_tcp("192.168.1")

使用 Shell 脚本(简单、Linux/macOS 原生)

对于 Linux/macOS 系统,Shell 脚本非常高效。

使用 fping (比普通 ping 快很多)

#!/bin/bash
# 需要先安装 fping: brew install fping (macOS), apt install fping (Ubuntu)
network="192.168.1"
echo "扫描 ${network}.0/24 网段..."
# -a: 只显示活动主机
# -g: 扫描一个网段
# -r 0: 不重试
fping -a -g ${network}.0/24 -r 0 -q 2>/dev/null
# 或者输出到变量
# online_hosts=$(fping -a -g ${network}.0/24 -r 0 -q 2>/dev/null)

使用 arp-scan (最专业,需要 root)

#!/bin/bash
# 需要安装: apt install arp-scan (Linux)
# 扫描本地网络
sudo arp-scan --localnet
# 或者指定接口和网段
# sudo arp-scan --interface eth0 192.168.1.0/24

配合 nmap (功能最全面)

如果系统上有 nmap,这是最专业的扫描工具。

# 简单的 Ping 扫描,发现在线主机 (不进行端口扫描)
nmap -sn 192.168.1.0/24
# 更快的扫描 (使用 -T4 激进模式)
nmap -sn -T4 192.168.1.0/24
# MAC 地址也会一并显示

使用 Windows PowerShell(Windows 原生)

对于 Windows 用户,PowerShell 提供了内置的 Test-ConnectionGet-NetNeighbor

使用 Test-Connection (慢,但不需要额外工具)

# 扫描 1-254 地址
1..254 | ForEach-Object -Parallel {
    $ip = "192.168.1.$_"
    if (Test-Connection -ComputerName $ip -Count 1 -Quiet -TimeToLive 1) {
        Write-Host "[+] 设备在线: $ip"
    }
} -ThrottleLimit 50

使用 Get-NetNeighbor (快速查看 ARP 表)

# 查看本地 ARP 缓存中已经发现的设备 (不是扫描,是查看已缓存的)
Get-NetNeighbor | Where-Object {$_.State -eq 'Reachable'}
# 主动触发扫描的方法 (略复杂,需要调用API或使用arp命令)
# 更简单的是利用 cmd 的 arp -a
cmd /c arp -a

如何选择与注意事项

方法 速度 准确度 权限要求 隐蔽性 适用场景
ARP (scapy/arp-scan) 极快 极高 root 低 (广播) 局域网内最佳选择
TCP 端口扫描 (多线程) 普通用户 跨网段、防火墙限制环境
ICMP Ping (fping) 普通用户 低 (ICMP) 简单快速的可用性检查
ICMP Ping (subprocess) 普通用户 跨平台兼容性需求

重要注意事项:

  1. 权限问题:ARP 扫描必须要有 root / 管理员权限,因为需要发送原始数据包。
  2. 安全性与合规性未经授权扫描他人网络是违法的,请确保你拥有对目标网络的合法管理权限。
  3. 防火墙:目标主机可能启用了防火墙(如 Windows 防火墙、iptables),会阻止 ICMP Ping 或 TCP 探测,ARP 因为工作在链路层,通常无法被本网段防火墙阻止。
  4. 网络负载:大量并发扫描(如脚本中的多线程)可能会对交换机或路由器造成短暂负载,甚至触发 IDS/IPS 告警。
  5. 网络范围:确定你的 IP 地址范围,常见的是 /24 (254个IP),也有 /16 (6.5万个IP),对于大规模扫描,建议使用 arp-scannmap 并合理设置超时。

对于最简单的单文件脚本,推荐使用 Python + scapy 进行 ARP 扫描(局域网最快最准),或者 Python + socket 进行 TCP 端口探测(跨网段),如果不想依赖第三方库,Shell 脚本 + fpingPowerShell + Test-Connection 是内置的好方案。

抱歉,评论功能暂时关闭!