机顶盒获取局域网已经使用IP,开放的端口号,扫描摄像头,NAS,共享主机等开机自启局域网全量扫描工具

一、创作灵感

日常家庭、小型局域网环境中,我们经常面临内网设备管理混乱的问题:不清楚网段内有哪些存活设备、设备对应IP/MAC地址、开放了哪些服务端口,同时无法快速区分空闲IP与占用IP,排查网络故障、接入新设备时十分繁琐。

闲置的华为EC6108v9C机顶盒硬件性能足够、功耗极低,非常适合作为7×24小时在线的小型内网服务器。因此我将该机顶盒刷入Ubuntu 20.04.6 LTS系统,依托其常驻运行的特性,开发了这款开机自启动局域网自动扫描程序

本程序核心解决手动扫描内网低效、数据零散、无法持续监控的痛点,实现机顶盒开机自动执行全量局域网探测,自动汇总本机网络信息、内网存活设备、端口开放情况、IP占用状态、路由链路等核心数据,生成标准化日志文件,让小型局域网管理、故障排查、设备盘点实现自动化、轻量化,无需人工干预,低成本实现内网运维监控。

二、程序整体介绍

本程序基于Python3开发,适配Ubuntu 20.04系统,专门适配华为EC6108v9C机顶盒运行环境。程序部署后设置为开机自启,设备每次上电开机后,会自动完成局域网全方位扫描、网络信息采集、数据分析,并将所有结果规整写入本地日志文件,全程无人工操作,实现轻量化、无人值守的内网运维监控。

三、程序核心详细功能

1. 自动创建日志目录与文件

程序启动后优先检测日志存储路径 /home/ubuntu/downloads/systeminformation.txt,若上级目录不存在则自动创建,避免路径报错、日志写入失败,保证程序稳定运行,所有扫描数据统一归档,方便后续查看、复盘与故障溯源。

2. 本机基础网络信息采集

自动读取并汇总本机全部核心网络参数,替代手动输入查询命令,精准获取:设备主机名、本机内网IP地址、子网掩码、默认网关、DNS服务器地址,完整记录机顶盒本机网络配置,为内网环境基线记录提供依据。

3. 全网TCP端口智能扫描识别

内置百余种常用端口与服务映射库,覆盖运维、监控、物联网、数据库、视频监控、虚拟化等主流端口(HTTP/HTTPS、SSH、RDP、MySQL、Redis、ONVIF、Docker、SIP等)。程序对内网所有存活设备进行定向TCP端口扫描,自动识别开放端口对应的服务名称,区分已知服务与未知端口,精准检测设备运行服务、潜在暴露端口与安全风险。同时设置合理超时时间,兼顾扫描速度与准确率,适配机顶盒低功耗硬件性能。

4. ARP全网存活设备扫描

调用arp-scan工具遍历整个局域网网段,自动探测所有在线设备,精准采集每台设备的IP地址、MAC地址、设备厂商信息。同时对扫描结果按IP段位自动排序,输出规整清晰的设备列表,完整盘点内网所有在线终端、摄像头、路由器、工控设备、智能家居等设备,解决内网设备台账混乱问题。

5. 单设备端口绑定检测

针对每一台扫描到的内网存活设备,单独执行端口扫描,将设备IP、MAC、厂商、开放端口/服务一一对应展示,直观查看每台设备的运行服务状态,快速发现异常设备、陌生接入终端、违规开放端口,提升内网安全性。

6. 路由链路追踪检测

自动执行路由追踪任务,以公共DNS 114.114.114.114为目标,最大探测10跳路由节点,记录局域网出口路由层级、各跳网关IP地址。可用于排查网络卡顿、断连、路由跳转异常、外网访问故障等问题,快速定位网络链路故障点。

7. 网段IP占用与空闲分析

基于本机CIDR网段信息,自动遍历整个局域网可用IP段,智能区分已占用IP后缀、空闲IP后缀,并分别规整输出。解决内网IP冲突、设备IP分配混乱问题,后续新增内网设备可直接选用空闲IP,无需手动探测,极大提升组网效率。

8. 开机自启+无人值守运行

程序部署完成后配置为Ubuntu开机自启动,机顶盒每次上电开机后自动后台执行全套扫描任务,无需人工登录、手动运行,全程自动化采集数据,开机即更新最新内网全网状态,实现7×24小时轻量化内网监控。

四、运行环境说明

  • 硬件设备:华为EC6108v9C机顶盒

  • 操作系统:Ubuntu 20.04.6 LTS

  • 运行环境:Python3 原生环境,无需额外复杂依赖

  • 依赖工具:arp-scan、traceroute(系统基础工具,安装即可使用)

  • 运行模式:开机自启、无人值守、自动写入日志归档

五、项目优势

  1. 低成本低功耗:利用闲置机顶盒改造,替代昂贵的专业运维主机、软路由,7×24小时运行功耗极低;

  2. 全自动化运维:开机自动扫描、自动归档、无需人工干预,适合新手与家庭、小型工作室内网使用;

  3. 数据维度全面:涵盖设备盘点、端口检测、路由排查、IP资源分析、本机网络信息五大核心运维维度;

  4. 适配性极强:专门适配机顶盒Ubuntu轻量化系统,运行流畅不卡顿,硬件资源占用极低;

  5. 实用性拉满:可用于内网设备盘点、网络故障排查、安全风险检测、IP资源管理、陌生设备接入监控。

总结常用端口号:

复制代码
PORT_SERVICE_MAP = {
    20: "FTP‑DATA",
    21: "FTP",
    22: "SSH",
    23: "Telnet",
    25: "SMTP",
    42: "WINS",
    49: "TACACS+",
    53: "DNS",
    67: "DHCP‑Server",
    68: "DHCP‑Client",
    69: "TFTP",
    80: "HTTP",
    88: "Kerberos",
    110: "POP3",
    123: "NTP",
    135: "MS‑RPC",
    137: "NetBIOS‑NS",
    138: "NetBIOS‑DGM",
    139: "NetBIOS‑SSN",
    143: "IMAP",
    161: "SNMP",
    162: "SNMP‑Trap",
    179: "BGP",
    194: "IRC",
    322: "ONVIF‑Playback",
    389: "LDAP",
    443: "HTTPS",
    445: "SMB",
    465: "SMTPS",
    514: "Syslog",
    554: "RTSP",
    587: "SMTP‑SUB",
    636: "LDAPS",
    873: "rsync",
    990: "FTPS",
    992: "TelnetS",
    993: "IMAPS",
    995: "POP3S",
    1080: "SOCKS",
    1194: "OpenVPN",
    1433: "MSSQL",
    1521: "Oracle",
    1723: "PPTP",
    1812: "RADIUS",
    1813: "RADIUS‑Accounting",
    2049: "NFS",
    3000: "ONVIF1/Grafana",
    3128: "Squid",
    3268: "LDAP‑GC",
    3306: "MySQL",
    3322: "DVR",
    3389: "RDP",
    34567: "HIK‑ISAPI",
    34599: "HIK‑Manage",
    5000: "UPnP‑RTSP",
    5001: "HTTPS‑Stream",
    5050: "SIP",
    5060: "SIP",
    5061: "SIP‑TLS",
    5432: "PostgreSQL",
    5900: "VNC",
    6036: "UNIVIEW‑Private",
    6060: "UNIVIEW‑Discover",
    6379: "Redis",
    6443: "Kubernetes",
    6667: "IPC‑Private",
    6789: "DAHUA‑Alarm",
    8000: "HIK‑iVMS",
    8008: "HTTP2",
    8080: "HTTP‑Proxy/K8s‑Web",
    8200: "HIK‑SADP",
    8443: "HTTPS‑Alt/K8s‑HTTPS",
    8450: "HIK‑Event",
    8554: "RTSP‑ALT",
    8899: "IPC‑Config",
    9000: "DVR/NVR",
    9090: "Web/Prometheus",
    9200: "Elasticsearch",
    10000: "Webmin",
    10050: "Zabbix‑Agent",
    10051: "Zabbix‑Server",
    10554: "RTSP1",
    19444: "RTSP2",
    19999: "Netdata",
    2375: "Docker",
    2376: "Docker2",
    27017: "MongoDB",
    37777: "DAHUA‑Media",
    37778: "DAHUA‑Stream",
}

程序源文

复制代码
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import os
import ipaddress
import socket
import subprocess

file_path = "/home/ubuntu/downloads/systeminformation.txt"

parent_dir = os.path.dirname(file_path)
if not os.path.exists(parent_dir):
    os.makedirs(parent_dir)
    print(f"目录不存在,已创建目录:{parent_dir}")

PORT_SERVICE_MAP = {
    20: "FTP‑DATA",
    21: "FTP",
    22: "SSH",
    23: "Telnet",
    25: "SMTP",
    42: "WINS",
    49: "TACACS+",
    53: "DNS",
    67: "DHCP‑Server",
    68: "DHCP‑Client",
    69: "TFTP",
    80: "HTTP",
    88: "Kerberos",
    110: "POP3",
    123: "NTP",
    135: "MS‑RPC",
    137: "NetBIOS‑NS",
    138: "NetBIOS‑DGM",
    139: "NetBIOS‑SSN",
    143: "IMAP",
    161: "SNMP",
    162: "SNMP‑Trap",
    179: "BGP",
    194: "IRC",
    322: "ONVIF‑Playback",
    389: "LDAP",
    443: "HTTPS",
    445: "SMB",
    465: "SMTPS",
    514: "Syslog",
    554: "RTSP",
    587: "SMTP‑SUB",
    636: "LDAPS",
    873: "rsync",
    990: "FTPS",
    992: "TelnetS",
    993: "IMAPS",
    995: "POP3S",
    1080: "SOCKS",
    1194: "OpenVPN",
    1433: "MSSQL",
    1521: "Oracle",
    1723: "PPTP",
    1812: "RADIUS",
    1813: "RADIUS‑Accounting",
    2049: "NFS",
    3000: "ONVIF1/Grafana",
    3128: "Squid",
    3268: "LDAP‑GC",
    3306: "MySQL",
    3322: "DVR",
    3389: "RDP",
    34567: "HIK‑ISAPI",
    34599: "HIK‑Manage",
    5000: "UPnP‑RTSP",
    5001: "HTTPS‑Stream",
    5050: "SIP",
    5060: "SIP",
    5061: "SIP‑TLS",
    5432: "PostgreSQL",
    5900: "VNC",
    6036: "UNIVIEW‑Private",
    6060: "UNIVIEW‑Discover",
    6379: "Redis",
    6443: "Kubernetes",
    6667: "IPC‑Private",
    6789: "DAHUA‑Alarm",
    8000: "HIK‑iVMS",
    8008: "HTTP2",
    8080: "HTTP‑Proxy/K8s‑Web",
    8200: "HIK‑SADP",
    8443: "HTTPS‑Alt/K8s‑HTTPS",
    8450: "HIK‑Event",
    8554: "RTSP‑ALT",
    8899: "IPC‑Config",
    9000: "DVR/NVR",
    9090: "Web/Prometheus",
    9200: "Elasticsearch",
    10000: "Webmin",
    10050: "Zabbix‑Agent",
    10051: "Zabbix‑Server",
    10554: "RTSP1",
    19444: "RTSP2",
    19999: "Netdata",
    2375: "Docker",
    2376: "Docker2",
    27017: "MongoDB",
    37777: "DAHUA‑Media",
    37778: "DAHUA‑Stream",
}

SCAN_TCP = sorted(PORT_SERVICE_MAP.keys())
SOCKET_TIMEOUT = 1.2


def scan_open_tcp_ports(ip_str):
    open_list = []
    for p in SCAN_TCP:
        try:
            s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            s.settimeout(SOCKET_TIMEOUT)
            code = s.connect_ex((ip_str, p))
            s.close()
            if code == 0:
                service = PORT_SERVICE_MAP.get(p, "Unknown")
                open_list.append(f"{p}‑{service}")
        except Exception:
            continue
    return open_list


def get_hostname():
    return subprocess.check_output("hostname", shell=True, encoding="utf-8").strip()


def get_lan_info():
    ip_output = subprocess.check_output("ip -4 route show default", shell=True, encoding="utf-8")
    gateway = ""
    for line in ip_output.splitlines():
        if line.startswith("default"):
            gateway = line.split("via")[1].split()[0]
            break
    addr_out = subprocess.check_output("ip -4 addr", shell=True, encoding="utf-8")
    ip_addr = ""
    netmask = ""
    cidr_val = None
    for line in addr_out.splitlines():
        if "inet " in line and not "127.0.0.1" in line:
            parts = line.strip().split()
            ip_cidr = parts[1]
            ip_addr, cidr_str = ip_cidr.split("/")
            cidr_val = int(cidr_str)
            mask = (0xFFFFFFFF << (32 - cidr_val)) & 0xFFFFFFFF
            netmask = f"{(mask>>24)&0xff}.{(mask>>16)&0xff}.{(mask>>8)&0xff}.{mask&0xff}"
            break
    return ip_addr, netmask, gateway, cidr_val


def get_dns():
    dns_list = []
    with open("/etc/resolv.conf", "r", encoding="utf-8") as f:
        for line in f:
            if line.strip().startswith("nameserver"):
                dns = line.strip().split()[1]
                dns_list.append(dns)
    return ",".join(dns_list)


def get_traceroute_hops():
    cmd = ["traceroute", "-n", "-m", "10", "-w", "1", "114.114.114.114"]
    try:
        result = subprocess.check_output(cmd, shell=False, encoding="utf-8", stderr=subprocess.STDOUT)
    except subprocess.CalledProcessError as e:
        result = e.output
    hop_list = []
    for line in result.splitlines():
        if line.startswith("traceroute to"):
            continue
        parts = line.strip().split()
        if len(parts) < 2:
            continue
        try:
            int(parts[0])
            hop_num = int(parts[0])
            hop_ip = parts[1]
            if hop_ip != "*":
                hop_list.append((hop_num, hop_ip))
        except ValueError:
            continue
    return hop_list


def get_arp_scan_sorted():
    cmd = ["arp-scan", "--localnet"]
    try:
        out = subprocess.check_output(cmd, shell=False, encoding="utf-8", stderr=subprocess.STDOUT)
    except subprocess.CalledProcessError as e:
        out = e.output

    device_list = []
    used_ip_set = set()
    for line in out.splitlines():
        line = line.strip()
        if not line:
            continue
        if line.startswith("Interface:") or line.startswith("Starting") or line.startswith("Ending") or line.startswith("#"):
            continue
        parts = line.split("\t")
        if len(parts) < 2:
            continue
        ip_str = parts[0].strip()
        mac_str = parts[1].strip()
        vendor_str = parts[2].strip() if len(parts)>=3 else "Unknown"
        if vendor_str == "(Unknown)":
            vendor_str = "Unknown"
        try:
            ip_obj = ipaddress.IPv4Address(ip_str)
            device_list.append((ip_obj, ip_str, mac_str, vendor_str))
            used_ip_set.add(ip_str)
        except ipaddress.AddressValueError:
            continue
    device_list.sort(key=lambda x:x[0])

    out_lines = []
    sep = "----------------------------------------"
    for _, ip, mac, vendor in device_list:
        port_items = scan_open_tcp_ports(ip)
        port_text = " ".join(port_items) if port_items else "无开放端口"
        out_lines.append(f"{ip}  {mac}")
        out_lines.append(f"{vendor}")
        out_lines.append(f"开放TCP端口:{port_text}")
        out_lines.append(sep)
    return out_lines, used_ip_set


def calc_free_used_ip_suffix(local_ip_str, cidr, occupied_ip_set):
    local_ip = ipaddress.IPv4Address(local_ip_str)
    net = ipaddress.IPv4Network(f"{local_ip}/{cidr}", strict=False)
    free_suffix = []
    used_suffix = []
    for host_ip in net.hosts():
        ip_str = str(host_ip)
        suffix = int(ip_str.split(".")[-1])
        if ip_str in occupied_ip_set:
            used_suffix.append(suffix)
        else:
            free_suffix.append(suffix)
    free_suffix.sort()
    used_suffix.sort()
    return net, free_suffix, used_suffix


if __name__ == "__main__":
    print(f"目标文件:{file_path}")
    host_name = get_hostname()
    ip_local, netmask, gateway, cidr = get_lan_info()
    dns = get_dns()
    hops = get_traceroute_hops()
    arp_devices, occupied_ips = get_arp_scan_sorted()
    net_obj, free_suffix_list, used_suffix_list = calc_free_used_ip_suffix(ip_local, cidr, occupied_ips)

    content_lines = [
        f"本机的名称是:{host_name}",
        f"本机的IP地址是:{ip_local}",
        f"网关:{gateway}",
        f"子网掩码:{netmask}",
        f"DNS:{dns}",
        "路由追踪(最大10跳,目标114.114.114.114):"
    ]
    for num, ip_hop in hops:
        content_lines.append(f"第{num}层路由器IP地址:{ip_hop}")

    content_lines.append("")
    content_lines.append("ARP扫描内网存活设备:")
    if len(arp_devices) > 0:
        content_lines.extend(arp_devices)
    else:
        content_lines.append("未扫描到内网设备或需要sudo权限运行")

    content_lines.append("")
    content_lines.append("网段IP地址分析:")
    content_lines.append(f"本机IP:{ip_local}")
    content_lines.append("空闲IP后缀:" + " ".join(str(x) for x in free_suffix_list))
    content_lines.append("不可用IP后缀:" + " ".join(str(x) for x in used_suffix_list))

    with open(file_path, "w", encoding="utf-8") as f:
        for line in content_lines:
            f.write(line + "\n")
    print("写入完成!")
相关推荐
知行产研1 小时前
中国矿山无人驾驶出海的三重门
数据库·mysql·php
l1258651 小时前
# RAG低延迟架构设计:从5秒到500ms的优化全链路
数据库·人工智能·python·langchain
RisunJan2 小时前
Linux命令-vgdisplay(显示卷组详细属性)
linux·运维·数据库
Mr. zhihao2 小时前
从零手写一个 RPC 框架:用一条因果链推导出 Dubbo 的骨架
网络协议·rpc·dubbo
爱和冰阔落2 小时前
【MySQL 慢查询排查实战】列表接口逐渐变慢时,怎样从请求链路定位原因
android·数据库·mysql
JacksonMx2 小时前
企业级 JPA 与数据库架构落地指南
数据库·数据库架构
Dxy12393102162 小时前
MySQL有哪些锁?InnoDB锁体系完整梳理博客
数据库·mysql
dog2502 小时前
多路径聚合效率的统计理论
网络·tcp/ip
剑锋所指,所向披靡!3 小时前
TCP并发服务器
服务器·网络·tcp/ip