
真正干过安全运维的人都会有同一个体会网上收藏夹里的“网络安全脚本合集”再丰富真到排查问题时能直接拿起来用的没几个。最近我把攒了两三年的 Python 脚本做了一次彻底整理按网络层、主机层、情报层和工程化四个方向重新归档。这篇文章就是整理结果包括我留下的资源、扔掉的脚本以及每个场景里踩过的坑。围绕“网络安全-python脚本资源整理”这个主题我不会给你一个堆满链接的清单而是按“安全运维实际工作流”来拆解哪些重复劳动该用脚本替代、每个场景最顺手的第三方库是什么、写的时候要注意什么。适合刚接触安全脚本的同学建立自己的工具箱也适合老手对照检查自己的资源体系有没有漏掉关键环节。1. 先别急着收集脚本先画一张安全运维的能力地图1.1 安全脚本真正解决的是这几类重复劳动整理脚本之前我先把自己一天的工作流摊开看看到底哪些环节最浪费时间。最后发现 90% 的重复劳动集中在五类资产盘点、日志初筛、基线核查、情报汇总和报告生成。这五类就是脚本资源的骨架。资产盘点与存活确认网段内有没有新增主机某台服务器的服务端口开放情况有没有变化证书还有多久过期。日志与事件初筛登录失败集中在哪个时间段、哪个来源 IP 最活跃、访问日志的状态码分布是否异常。基线核查与完整性校验服务器上的关键文件是否被动过常用安全配置项是否符合内部规范。外部情报整理将公开威胁情报拉下来去重、落盘再和自有资产做交集比对。报告生成与通知把上面的结果汇总成表格或者推给协作团队。我建议你也先画一张这样的能力地图而不是看到别人分享的脚本就收藏。收藏夹里的东西叫“资源”只有进入你工作流的才叫“工具”。这次整理我才发现自己真正在用的脚本不到收藏量的四成剩下的要么是当时一时兴起要么是依赖太重根本不敢放进生产环境。1.2 选库原则标准库优先第三方库少而精安全脚本有一个特点写完后往往要长期运行。今天跑通下个月还要跑明年换台机器还要跑。所以我在选第三方库时非常克制三条原则用了很久第一标准库能解决的不引第三方依赖。例如socket做端口状态检查、hashlib做哈希、csv写表格这些都已经够稳。第二必须要用的第三方库选社区活跃、接口稳定、依赖尽量少的。我在网络层常用scapy和pyshark在主机层常用psutil情报拉取清一色requests。第三如果一个库只有“看起来炫”的价值没有解决实际痛点那就删掉。我见过别人的脚本仓库里躺着好几个解析库实际没人搞得清它们各自负责什么格式。另外所有涉及主动探测的脚本都有一个前提目标必须在授权范围内。这个边界要在脚本的参数和注释里写清楚不能含糊。自动化工具本身没有善恶但使用边界必须由人定死。2. 网络层脚本资源资产探测与离线流量分析2.1 快速主机存活和端口状态检查资产盘点脚本是我最早写的网络层工具也是复用率最高的。当时的需求很简单给我一个 IP 列表和一个端口列表我要知道哪些主机在线、哪些端口是开的。用socket的connect_ex就能做并不需要上重量级扫描框架。import socket import concurrent.futures def check_port(ip: str, port: int, timeout: float 3.0) - bool: with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: s.settimeout(timeout) return s.connect_ex((ip, port)) 0 def probe_targets(ip_list, port_list, max_workers100): tasks [(ip, port) for ip in ip_list for port in port_list] online [] with concurrent.futures.ThreadPoolExecutor(max_workersmax_workers) as pool: future_map {pool.submit(check_port, ip, port): (ip, port) for ip, port in tasks} for future in concurrent.futures.as_completed(future_map): ip, port future_map[future] if future.result(): online.append((ip, port)) return online这里用connect_ex而不是connect是因为connect_ex不抛异常直接返回错误码判断起来更干净。超时时间 3 秒是我调出来的平衡值内网环境 1 秒就够跨网段或者公网环境可以放宽到 5 秒。实测下来有两个注意事项一是线程数不要盲目调大超过三百以后不仅没有加速反而会因为握手开销和本机文件描述符限制导致大量超时二是结果一定要按“主机聚合”输出不要只给一堆“IP:端口”的平铺列表。我在初版脚本里吃过亏面对三千多行平铺结果根本看不出某台主机整体开了哪些端口后来改成按 IP 分组输出一眼就能对照资产清单。2.2 pcap 离线解析把流量会话变成结构化记录网络层另一个高频场景是分析抓包文件。有时现场只有 pcap没有部署任何流量分析平台这时候我会用pyshark做批量提取。import pyshark import json def summarize_pcap(pcap_path: str, out_path: str): cap pyshark.FileCapture( pcap_path, keep_packetsFalse, only_summariesTrue ) results [] for pkt in cap: try: results.append({ src: pkt.source, dst: pkt.destination, proto: pkt.protocol, len: getattr(pkt, length, ), }) except AttributeError: continue cap.close() with open(out_path, w, encodingutf-8) as f: json.dump(results, f, ensure_asciiFalse, indent2)only_summariesTrue和keep_packetsFalse这两个参数是我推荐必写的。前者只取会话摘要不解析每个包的完整字段速度快很多后者在处理完后释放包内存避免大文件把进程拖垮。我处理过一个几 GB 的 pcap不开这两个参数直接内存飙升开完之后稳定在几百 MB 以内。这个脚本不会告诉你“哪条流量是攻击”但会帮你快速回答“这个时间段网络会话的规模有多大、集中在哪些协议、哪些主机是会话中心”。有了这个基础再去针对具体会话做深入分析就有的放矢了。3. 主机层脚本资源日志里挖异常文件系统里找变化3.1 日志初筛脚本十分钟定位可疑时间段主机层最烦人的工作是看日志。业务日志、系统登录日志、防火墙日志分散在不同位置格式天差地别。我不会试图写一个统一解析器而是针对每种日志写一个“小且稳”的解析函数再组合成巡检脚本。import re from collections import Counter LOG_PATTERN re.compile( r(\d\.\d\.\d\.\d).*?(?:GET|POST|PUT|DELETE) (\S).*? (\d{3}) ) def quick_log_scan(path: str): top_ip Counter() top_url Counter() status_code Counter() with open(path, encodingutf-8, errorsignore) as f: for line in f: m LOG_PATTERN.search(line) if m: ip, url, status m.groups() top_ip[ip] 1 top_url[url] 1 status_code[status] 1 return { top_ip: top_ip.most_common(10), top_url: top_url.most_common(10), status_code: dict(status_code), }这个脚本的价值不在技术含量而在“先有粗筛再做精查”的排查思路。状态码分布能快速告诉你有没有一波集中报错TOP IP 能告诉你请求来源是否集中在预期范围TOP URL 能告诉你有没有异常路径被反复访问。拿到这三张表再决定要不要深入看某条具体请求效率比对着日志文件从头翻高很多。这里有一个我踩过的坑日志里的时间字段不一定统一。有的用 UTC有的用本地时间跨时区对比时经常把时间窗口算错。我在脚本里加了一个timezone配置项所有涉及时间窗口的判断强制先统一成同一个时区这个细节救过我好几次。3.2 文件完整性基线脚本把“不知道文件被谁改过”变成可追查还有一类脚本不能省文件完整性校验。服务器发布新版本之后关键目录被改了哪些文件运维和安全的视角往往对不上。运维说“我们升过级”安全说“这里多了文件没人认领”。与其事后扯皮不如从一开始就建哈希基线。import hashlib import json import os def file_hash(path: str, chunk: int 65536) - str: h hashlib.sha256() with open(path, rb) as f: while True: data f.read(chunk) if not data: break h.update(data) return h.hexdigest() def build_baseline(root: str) - dict: baseline {} for dirpath, _, filenames in os.walk(root): for name in filenames: full os.path.join(dirpath, name) try: baseline[full] file_hash(full) except OSError: continue return baseline def compare_baseline(old: dict, new: dict): changed {k for k in old if k in new and old[k] ! new[k]} added set(new) - set(old) removed set(old) - set(new) return changed, added, removed选择 SHA256 而不是 MD5是因为在完整性和防碰撞需求面前SHA256 是更稳妥的选择而且标准库原生支持没有额外负担。基线文件本身要保存到脚本目录之外的独立位置最好带上一次完整扫描的元数据否则基线一旦跟着被篡改比对就失去意义。我习惯把build_baseline和compare_baseline分成两个独立脚本一个用于发布后建立基线一个用于日常巡检比对。它们共用一个哈希模块但执行频率完全不同。前者可能一个月只跑一次后者建议至少每周一次。不要为了省事合成一个“大脚本”频繁调用会引入不必要的全量扫描。4. 情报层脚本资源自动拉取、去重与批量核查4.1 情报源拉取脚本超时、重试和落盘网络安全工作离不开外部威胁情报。但很多人的“情报收集”只是把接口链接存进收藏夹真要对比时还是手动复制粘贴这样效率太低了。我整理情报层脚本的第一个目标就是把“拉取、去重、落盘”变成全自动。import requests import hashlib def fetch_intel_text(url: str, timeout: int 10) - str: session requests.Session() session.headers.update({User-Agent: security-intel-collector/1.0}) try: resp session.get(url, timeouttimeout) resp.raise_for_status() return resp.text except requests.RequestException as exc: print(f[intel] fetch failed: {exc}) return def dedup_lines(text: str): seen set() for line in text.splitlines(): line line.strip() if line and line not in seen: seen.add(line) return seen第三方接口的稳定性是不可控的所以脚本里必须把超时放在第一位。requests库如果不显式设置timeout默认会一直等下去这在定时任务里就是灾难。一个接口挂掉整个任务卡死后面所有情报源都拉不了。落盘时我坚持用统一的 CSV 或 JSON 结构至少包含指标值、来源标识、首次发现时间、本次拉取时间。这样后续去重和比对才有基础。不要只收藏“一堆文本”没有结构的情报只能看不能查。4.2 批量信誉核查本地规则先行外部接口兜底批量核查 IP 或域名的信誉是安全事件处置里的高频动作。我的原则是本地能判断的先判断外部接口等兜底。因为每次全量走外部接口既不现实响应也慢。判断层级判断方式动作第一层自有资产白名单命中直接标记“可信”第二层历史威胁库命中标记“高危”并输出历史证据第三层规则匹配如端口、开放服务等特征标记“待复核”第四层外部信誉接口仅对前几层无法判定对象查询这个流程的核心思想是“减少不必要的外部依赖”。本地白名单可能覆盖了 70% 的合法流量历史威胁库再覆盖一批已知风险真正需要外呼的只剩少量灰色对象。脚本跑完输出一个带判定等级和证据标签的表格让人来复核。这样既提高了效率也留住了人工判断的空间。我特别想提醒一点自动化核查脚本的结果是“线索”不是“结论”。某几个对象被外部接口标了高危不代表一定有问题还需要结合时间、上下文和业务场景判断。脚本里加一句“仅供初筛参考”不是客套话是对使用者的保护。5. 脚本资源工程化目录结构、调度和常见坑5.1 一个能长期维护的脚本仓库目录长什么样整理资源到最后其实就是整理工程结构。这是我目前觉得最舒服的安全脚本仓库布局security_scripts/ network/ host_probe.py pcap_summary.py host/ log_scan.py file_baseline.py config_baseline.py intel/ fetch_intel.py reputation_check.py lib/ net_utils.py log_utils.py hash_utils.py config/ scope.conf intel_sources.conf report/ output/ requirements.txt README.md横向按网络、主机、情报分模块纵向把公共函数抽到lib配置文件统一放在config报告输出统一走report。这套结构的好处是脚本之间没有复杂的互相调用每个顶层目录里的脚本可以直接独立执行公共函数只维护一份不会出现“两个脚本各写了一份file_hash后来改了一个忘了改另一个”的尴尬。scope.conf是我特别要求保留的文件。里面存的是授权范围内允许探测的网段和主机列表。所有涉及主动探测的脚本启动时都要读这个文件不在范围内直接拒绝执行。这一条既是工程规范也是安全底线。5.2 落地开发时最容易忽略的三个问题工程化过程中有几个坑几乎每次都会遇到我直接列出来。第一个是敏感信息处理。情报接口的 Key 之类的东西绝对不允许硬编码在脚本里。我统一改成从环境变量读取脚本里只留变量名。你在本地测试时随意一点没关系一旦上了计划任务或者交给别人维护硬编码就是定时炸弹。import os API_KEY os.environ.get(INTEL_API_KEY, ) if not API_KEY: raise RuntimeError(missing INTEL_API_KEY environment variable)第二个是幂等性。同一个脚本重复执行两次结果应该一致。比如情报拉取脚本如果每次都简单地“追加写入”第二次运行就会产生大量重复行。我在去重逻辑上特意做了代码审查确保无论任务被调度器触发多少次数据都不会脏掉。第三个是计划任务环境问题。用系统定时任务跑 Python 脚本时PATH和当前目录通常和你命令行里不一样最常见的表现是“脚本明明手工能跑定时任务里却告诉我模块不存在”。我在定时调度里统一用绝对路径调用虚拟环境的解释器并且把工作目录cd到脚本根目录这个问题就消失了。6. 回看这场整理值得投入和果断放弃的脚本6.1 真正值得花时间打磨的脚本这次资源整理让我重新认识了什么叫做“值钱”的脚本。真正值得花时间打磨的不是那些技术看起来高深的而是会反复进入故障排查流程的。资产探测、日志初筛、完整性校验、情报拉取这四个脚本每个星期都会被我用到。它们逻辑简单但稳定性要求极高。打磨它们的目标只有一个不管什么时候跑结果都可预期、可解释、可追溯。有一个细节我想分享这几个核心脚本我都补上了--dry-run参数执行时不产生真实请求只把“将要做什么”打印出来。这个参数在调整规则时价值巨大尤其在范围配置改完以后先预演一遍再跑实际的至少能避开一半误操作。6.2 趁早放弃的脚本类型整理到最后我删掉了不少脚本。一类是自己重造轮子的比如明明用pandas几行就能做好的表格透视非要用纯手写循环和字符串拼接去处理。另一类是什么都想管的“大而全”脚本同时处理资产、日志、情报、报告参数几十个最后谁都不敢改它只敢把它供在目录里。还有一类是一次性脚本当时确实解决了问题但没有注释、没有参数化过几个月再看完全想不起是干什么用的。整理完那一刻我的体会是这样的脚本资源的优劣从来不在于数量多少、用了多前沿的库而在于它能不能在你需要时给出可靠答案。把核心工具做成可维护的稳定件把边缘尝试果断清掉这套资源整理才算真正完成。