简介:一份2020年4月形成的网络安全攻防实验室建设方案,面向高校网络空间安全专业、职业院校实训中心以及社会培训机构的建设与教学负责人,帮助解决实验室整体规划、教学功能设计和设备选型等常见问题。文档覆盖网络空间安全人才需求、当前安全教学中的痛点误区、攻防实验室特点、设备选型与沙盒应用、网络拓扑设计、DCNSA/DCNSE课程体系以及基础与扩展实验项目,并配有实验室布局平面图、效果图和机柜摆放说明,能为撰写立项报告或组织实验室建设提供直接参照。包内仅含1个docx文件,大小约984KB,方案层级清晰、目录完整,适合在此基础上进行本地化调整和二次编辑。目前该文档已有850人学习下载,适合需要快速把握攻防实验室建设框架、课程安排和硬件选型思路的高校教师、实验员及培训讲师。
1. 一份 2020 年的攻防实验室建设方案,今天还要不要照着做
我手里这份《网络安全攻防实验室建设方案(2020年4月).docx》更像施工图,不像汇报材料。它回答了三个到现在都没变的问题:靶场怎么隔离、靶标怎么布、对抗怎么留证据。按它拆过两轮,骨架不过时,但落到实现时要在网络分段、靶标形态和日志采集三处做修正。
适合看的人很明确:想在部门内部搭小规模红蓝对抗队伍,预算有限、没独立机房、不上云;或在培训机构带实验课,需要一晚上跑通环境、第二天让学员动手。这两种场景都逃不开三个决策:网络分几段、靶标什么形态、监控日志怎么落地。想不清楚就动手,后面至少翻车两次。
按我踩过坑的顺序展开,只讲今天能直接复现的部分,以及那些会导致返工的真实细节。
2. 先定形态再做拓扑:靶场建设的三类选型与量化估算
直接开始装虚拟化平台、解压漏洞环境的人,后面大概率要返工。因为物理机、纯虚拟机、混合部署这三种形态,决定了网络拓扑怎么画、IP 段怎么划、恢复策略怎么定。2020 年那份文档的建议是“虚拟化为主、物理设备为辅”,这个结论到今天依然成立,但要补一个前提:先算清楚你的队伍规模和演练频次。
2.1 物理机、虚拟机还是云靶场:三种形态的成本和边界差异
先放下设备品牌和配置排名,三种形态各有合适场景,也各有各的坑。下表是我做选型时的真实对比,不是纸面算账。
| 形态 | 硬件投入 | 维护成本 | 适合场景 | 最明显的短板 |
|---|---|---|---|---|
| 纯物理机 | 高,按机架位和功率算 | 高,每台要独立维护 | 需要真实硬件漏洞、固件层和带外管理口对抗 | 快照和恢复全靠手工,演练准备时间极长 |
| 纯虚拟机 | 低,一台高密度服务器即可 | 中,模板化运维 | Web渗透、主机提权、域内横向、流量分析 | 对内核漏洞、虚拟机逃逸类课题表现失真 |
| 混合形态 | 中高,虚拟化集群加少量物理设备 | 中,分层管理 | 最接近真实业务:虚拟化承载靶标,物理设备承载网络和安全设备 | 状态一致性难保证,靠配置管理和快照约束 |
我一般建议,20人以下的小队伍纯虚拟机就够用;超过 20 人,或者有专门的攻防靶场课程要做常态演练,必须混合形态。纯虚拟化环境里的交换机、防火墙都是软件模拟的,策略生效行为和硬件设备不完全一致,训练出来的人到了真实环境,容易把ACL顺序和方向搞错。
另一个选型关键是快照与回滚的粒度。VMware vSphere 和 VirtualBox 都支持快照,私有云还能做模板机,但要提前想清楚是按“整场演练”回滚,还是按“每一轮攻击”回滚。按轮回滚对存储 IO 的消耗成倍上涨,我见过一个团队每五分钟打一次快照,练到第三天存储池满了,靶标机全线卡死。选型阶段就把快照策略定下来,比事后写清理脚本省事得多。
云靶场只适合两类情况:一类是演练需要大量平行环境,比如 40 个人同时打同一个 Web 靶标,本地服务器起不来,云上拉模板更稳;另一类是跨地域红蓝对抗,人不在同一个物理地点。其余场景我不建议把攻防实验室放云上,内网横向、域渗透这类课程在云上会受到安全组策略干扰,行为跟本地二层网络差异很大,学员练完回来还是不会处理真实内网。
2.2 网络隔离怎么设计:双网分段和防火墙策略的最小集合
攻防实验室最常犯的错误,是把靶标、攻击机、日志服务器全部丢进同一个二层网络。这种拓扑确实好连通,但复盘阶段直接傻眼:蓝队的流量分析设备跟靶标在同一个网段,根本分不清哪个包是攻击流量,哪个是管理流量。专业一点的方案,会把实验室切成三张网,这里给出可直接套用的规划。
| 网段 | 用途 | 互访策略 |
|---|---|---|
| 管理网 192.168.10.0/24 | 宿主机、虚拟化平台、NAS、备份 | 只允许运维终端访问 |
| 演练网 192.168.20.0/24 | 攻击机、Web靶标、域控、跳板机 | 内部全互通,出管理网仅允许特定端口 |
| 审计网 192.168.30.0/24 | 日志服务器、流量分析、裁判台 | 只收流量和日志,禁止主动连接其他网段 |
最小防火墙策略只有三条:管理网只放行运维终端 IP 的 22、443、3389 端口;演练网内的靶标区禁止主动访问管理网;审计网只能单向接收演练网的镜像流量,不配回程路由。如果实验室还要模拟对外攻防,就在防火墙外口再接一条独立线路,把演练流量和办公上网流量在物理上分开。
这里有个常被忽略的点:DNS 和 DHCP 属于基础服务,但它们的部署位置决定了整张网能不能转起来。我习惯把 DNS 和 DHCP 放在管理网内的独立 Linux 虚拟机里,用固定 IP,不给它做快照回滚——因为回滚一次,全实验室的域名解析和地址租约全部回到旧状态,靶标集体失联的“灵异事件”大多是这么来的。
2.3 算力预算:20 人的红蓝队伍需要多少台虚拟机
算力预算不需要按最大并发来,但开机总量要算清。假设 20 人分两班,攻击机 8 台、靶标机 12 台、域控 2 台、日志和裁判服务器各 1 台,一共 24 台虚拟机。按常见经验:Web 靶标每台给 2 核 4GB,域控给 4 核 8GB,日志服务器给 8 核 16GB,攻击机给 4 核 8GB,加起来大约 96 核、320GB 内存。不是同时满载,但开机的资源额度就是这么多。
存储比内存更容易爆。漏洞环境拉下来常用 10GB 起步,再加上快照,每台靶标平均需要 80GB 的磁盘空间。一台 Windows 域控开了快照,跑一次横向移动演练,C 盘里留下的临时日志可能就有几百 MB。我的做法是给虚拟化池配 4TB 起步的存储,其中 SSD 做热存储、机械盘做冷归档。如果只有 1TB,演练第三天快照就会把存储挤爆。
内存开销还有一个隐蔽大头:蓝队监控端。如果要上 ELK 全家桶,光日志分析集群内存就得 32GB 以上。小队伍没必要硬上,一台 8 核 16GB 的服务器跑轻量日志接收,或者直接用 syslog 集中收纳,等演练结束后再离线分析,能省掉一大半资源。2020 年文档里如果写了“建议部署态势感知平台”,按小队伍规模把它替换成轻量方案更实际。
3. 把靶场从 0 搭到能跑:最小网络、漏洞靶标与审计链路
选型定完,动作要快。我一般要求团队一个周末把最小环境跑通,标准是:能发起一次 Web 渗透、一次内网横向,能抓到全过程的流量和日志。下面按我实际操作的顺序来,第一步是网络基础服务,第二步是 Web 靶标,第三步是域控和主机靶标,第四步打通审计链路。
3.1 网络与基础服务的初始化:DNS、DHCP、时间同步一次配齐
先不要急着装漏洞环境。数据平面不通,后面所有靶标的 IP 都是乱的。第一件事,在一台 Linux 服务器上配好 DHCP,给演练网内的虚拟机做固定 IP 分配。以下是一个最小可用的 ISC DHCP 配置,对应配置文件为 /etc/dhcp/dhcpd.conf:
subnet 192.168.20.0 netmask 255.255.255.0 { range 192.168.20.100 192.168.20.200; option routers 192.168.20.1; option domain-name-servers 192.168.20.1; option subnet-mask 255.255.255.0; default-lease-time 43200; max-lease-time 86400; } host attacker-01 { hardware ethernet 00:0c:29:aa:bb:01; fixed-address 192.168.20.101; }先动态分配100到200这一段,再把需要稳定入口的攻击机和域控用 host 段做 MAC 绑定。写完后执行 systemctl restart isc-dhcp-server ,用 dhcp-lease-list 检查客户端是否拿到租约。如果客户端一直获取不到地址,先看宿主机自带的虚拟网络 DHCP 是不是还开着,两个 DHCP 同时存在必然乱套。
DNS 配置在同时刻完成。靶标不建议直接走公网解析,演练既要模拟内网域名又要断外网,不如下面这样直接内网自建 zone:
zone "lab.local" { type master; file "/etc/bind/db.lab.local"; };db.lab.local 里至少写三条 A 记录:www.lab.local 指向 Web 靶标,dc.lab.local 指向域控,log.lab.local 指向日志服务器。配完用 dig www.lab.local 验证,能解析出地址再往下走。
提示:时间同步容易被跳过,但攻防演练的时间轴全靠它。在每台虚拟机上配 NTP 指向宿主机,或者搭一个内部 NTP 服务器,让所有靶标和攻击机统一时钟源。否则复盘时流量时间戳和日志时间戳差十几分钟,整条攻击链都没法对齐。
3.2 用 Docker Compose 快速部署 Web 漏洞靶标:最小配置示例
Web 靶标最常见的做法是拉漏洞应用镜像,用 Docker Compose 统一管理。Compose 的好处是升级、重启、数据卷都写在一个 yml 里,有版本记录,重建环境时不会漏配置。下面是一个最小可用的 docker-compose.yml,包含 DVWA 和一个带 SQL 注入的测试应用:
version: '3' services: dvwa: image: vulnerables/web-dvwa:latest container_name: dvwa ports: - "8080:80" environment: - DB_HOST=mysql volumes: - ./dvwa-data:/var/www/html restart: unless-stopped depends_on: - mysql mysql: image: mysql:5.7 container_name: mysql-dvwa environment: MYSQL_ROOT_PASSWORD: rootpass MYSQL_DATABASE: dvwa volumes: - ./mysql-data:/var/lib/mysql sqli: image: vulnerables/web-sqli-labs:latest container_name: sqli-labs ports: - "8081:80" volumes: - ./sqli-data:/var/www/html这里把两个 Web 靶标跑在同一台宿主机上,分别映射到宿主机 8080 和 8081 端口。ports 的格式是宿主机端口:容器内端口,改宿主端口就能避免和其他靶标冲突;volumes 把容器内目录挂载到宿主机,容器重建后现场数据还在;depends_on 保证 MySQL 先于 DVWA 启动。启动命令是 docker-compose up -d ,然后访问 http://宿主机IP:8080/login.php 看是否正常。
如果按 2020 年的文档清单去拉老镜像,大概率会遇到不兼容新 Docker 引擎的问题。常见的处理方式是加 compatibility 模式,或者到镜像仓库的 tag 列表里挑一个最近更新的版本重新拉取。Web 靶标起来后别急着用,先确认数据库表初始化是否成功——DVWA 的 setup 页面要执行一次建库,不然登录进去全是报错。多等 30 秒,别拿浏览器一打开没反应就说环境坏了。
3.3 Windows 域控和主机靶标:搭建 AD 的最低步骤
域控是攻防演练里的关键节点,内网横向、Kerberos 攻击、GPO 滥用都依赖活动目录域环境。即便全是虚拟机的环境,也要把域建起来。Windows Server 2019 或 2022 上装 AD,先将主机名改成 win-dc,设置静态 IP 为 192.168.20.10,然后在 PowerShell 里执行:
Install-WindowsFeature AD-Domain-Services -IncludeManagementTools Install-ADDSForest ` -DomainName "lab.local" ` -DomainNetbiosName "LAB" ` -ForestMode "WinThreshold" ` -DomainMode "WinThreshold" ` -InstallDns:$true ` -SafeModeAdministratorPassword (ConvertTo-SecureString "LabPass@2024" -AsPlainText -Force) ` -Force:$true第一条命令安装 AD 域服务角色,第二条命令在 lab.local 的私有域名下建立域控,同时安装 DNS 服务。参数里关键的是 -DomainName ,只能用私有域名后缀,用 lab.local 比 lab.com 稳妥,不会和真实公网 DNS 产生歧义;-InstallDns:$true 让域控自己承载内部 DNS;最后的密码是目录服务还原模式密码,演练结束后立即修改。
域控起来后,把 Windows 靶标加入域。在靶标机上用管理员 PowerShell 执行 Add-Computer -DomainName "lab.local" -Restart ,输入一次域管理员密码,重启后即可用域账号登录。这里最容易被忽略的是:靶标机的 DNS 必须指向 192.168.20.10,否则加入域时找不到域控,这一步也是新手翻车最多的地方。
域内只放 Windows 靶标不够。我习惯在域里放两台 Linux,一台装 MySQL 当数据库服务器,一台开 NFS 模拟老系统。横向移动演练里的信息收集阶段,网络共享和数据库口令经常是突破口,没有这些角色就练不到位。
3.4 攻击机工具箱与流量审计链路的打通
攻击机标配 Kali Linux,不用多介绍。但要注意版本和快照状态:攻击机要始终保持干净,每轮演练结束后直接回滚到初始快照,不要在里面安装各种个人工具带进演练,否则到判定阶段,出现“脏工具”会影响结果可信度。
流量层面至少要做两步。第一步,宿主机或交换机上做端口镜像。如果靶标跑在 VMware Workstation 里,在虚拟网络编辑器打开混杂模式,宿主机就能抓到靶标流量;如果靶标走的是物理交换机,配置本地镜像端口。常见的交换机配置是把靶标上联口复制到审计口:
# 进入配置模式后启用镜像会话 monitor session 1 source interface Gi1/0/24 both monitor session 1 destination interface Gi1/0/23source 后面跟的是靶标区上联的物理端口,both 表示收和发都镜像;destination 是接日志服务器的口。配置完用 show monitor session 1 确认状态是 active。
第二步,日志审计。至少在每台靶标上装 syslog 客户端,把系统日志送到日志服务器。Linux 靶标的 rsyslog 配置如下:
echo '*.* @@192.168.30.5:514' >> /etc/rsyslog.conf systemctl restart rsyslog@@ 表示走 TCP,@ 是 UDP。攻防演练里建议走 TCP,审计链路更可靠。192.168.30.5 是日志服务器地址,514 是 syslog 默认端口。Windows 靶标可以用 NxLog 或直接配置事件转发,推荐在域控组策略里设置集中日志,统一好时区、统一好转发地址,比一台一台手工点界面可控得多。
流量和日志都接通后,做一次自测:攻击机对 Web 靶标发起一个扫描,到日志服务器确认能看到对应时段的连接记录。这一步不通过,别急着进入演练,否则复盘时没有任何数据支撑。
4. 攻防实验室落地避坑:五个能让你翻车的隐蔽问题
前面那套步骤,按顺序走完,半天时间能跑通。但真正让实验室“看起来能用、一用就坏”的问题,几乎都藏在细节里。下面五条是我自己踩过、也帮别人排查过的坑,按现象到原因到解决的顺序写,每条都能直接对照排查。
4.1 快照恢复后靶标失联:网络配置残留导致 IP 冲突
现象:演练结束后回滚 Windows 靶标到开场前快照,虚拟机开机后进不了域,Ping 域控不通,登录界面卡在“正在应用计算机设置”很久。
原因:快照回滚会把系统状态恢复到旧时间点,但网络配置如果用的是 DHCP 获取,恢复后的租约记录和当前 DHCP 服务器上的租约不一致,有时候就拿到一个跟其他机器重复的 IP。更隐蔽的是,靶标之前被手工改过静态 IP,恢复后旧 IP 又写回系统配置,两台机器同时在用 192.168.20.15。
解决:给所有参加演练的靶标做 IP 与 MAC 固定绑定,而不是靠动态分配。DNS 指向域控或日志服务器的固定地址。回滚后强制释放再重新获取地址,Windows 执行 ipconfig /release && ipconfig /renew ,Linux 执行 dhclient -r && dhclient ,再做一次全网的 ARP 缓存清理,能消掉绝大多数 IP 冲突问题。
4.2 镜像端口收不到流量:交换机的 ACL 把监控口拦了
现象:流量镜像配置好之后,审计服务器上 tcpdump 一直没输出,检查端口状态却显示 up。
原因:不少网管交换机的 ACL 只对正常转发口生效,镜像目的口在 ACL 过滤之后才复制报文。如果 ACL 里有一条 deny 语句恰好匹配了源 IP 或端口,镜像流量就到不了审计口。这是最让人头疼的地方:监控口明明通着,抓包就是没有结果。
解决:在交换机上给监控口加一条匹配所有流量的 permit ip any any ,放在 ACL 列表最前面,再确认监控口本身不属于隔离 VLAN。配置完做一次检测,从攻击机发一个 ping ,到日志服务器抓包看 ICMP 是否进来。别一配完就去刷 Web 靶场页面,流量太小看不出问题。
4.3 内网 DNS 解析错乱:靶标的解析走回了宿主机
现象:在 Web 靶标容器里访问 http://www.lab.local ,时而能开,时而提示无法解析;攻击机访问却一直正常。
原因:容器内部默认的 DNS 是桥接网卡下宿主机分配的地址,而宿主机可能开着 dnsmasq 或系统解析接管了部分查询。更重要的是,Docker 容器自身有 /etc/resolv.conf ,重启后会被重建,nameserver 指向宿主机而不是域控 192.168.20.10。
解决:在 docker-compose.yml 里给每个容器显式指定 DNS :
dns: - 192.168.20.10这里填的是自建 DNS 服务器地址,改完执行 docker-compose down && docker-compose up -d 重建容器,再进入容器 cat /etc/resolv.conf 确认。注意,如果容器用了 host 网络模式,这个配置不会生效,所以 Web 靶标统一用 bridge 模式。
4.4 日志采集缺三丢四:syslog 端口和格式没对齐
现象:日志服务器上能看到 Linux 靶标的日志,但 Windows 靶标一条都没有,或者时间全部是 UTC ,跟攻击机对不上。
原因:Windows 自带的 Syslog 机制和 Linux 不同,默认不往 514 端口发数据,要用 NxLog 这类 agent 或者走 Windows 事件转发。转发配完还要单独开放防火墙端口。另一个问题是 Linux 靶标如果不改时区,打到日志服务器的就是 UTC 时间,复盘时换算成北京时间要加减 8 小时,非常容易判错。
解决:Windows 靶标通过域控组策略统一推送 WEF 订阅,或安装 NxLog 时把 source 指向 EventLog ,destination 端口 514 协议 TCP 。时区问题,所有靶标用统一 NTP 服务器,并在日志服务器上把时间格式强制写成带时区的模板,例如在 rsyslog.conf 里定义 timestamp 加 timezone 。我自己的实验室所有服务器一律 TZ=Asia/Shanghai ,省去所有换算。
4.5 Web 靶场容器重启变白纸:数据目录没有挂载到宿主机
现象:头天晚上给 DVWA 里灌了一批测试数据,第二天一早容器重启,登录进去表全没了,或者所有密码都进不去。
原因:Docker 容器默认的用户数据写在容器可写层,容器一旦被 down 掉再 up -d ,可写层丢弃,数据立即清空。如果 docker-compose.yml 里只写了 image 和 ports 却没写 volumes ,等于开了一个用完即走的靶标。
解决:所有有状态的靶标,都要把数据目录挂载到宿主机。也就是前面 3.2 节配置里 volumes 那几行必须保留,并写成 ./dvwa-data:/var/www/html 这样的相对路径。很多从旧文档模板里拉出来的 compose 文件,volumes 会写成一个命名卷名,比如 dvwa:/var/www/html ,这样数据跟着 Docker 卷生命周期走,回滚快照时容易找不着。换成相对路径后,恢复完进页面看一眼数据库表还在不在,确认没问题再开始演练。
5. 从演练到复盘:任务脚本、自动评分与证据链整理
环境稳了,实验室才有一半价值;另一半价值是把一次攻防演练真正跑完。2020 年那篇方案的后半部分,写的是演练组织和评分模板,框架现在还能用,但我要补强自动化程度——让任务可验证、让评分可复现,而不是靠裁判用肉眼看屏幕算分。
5.1 任务脚本的标准化:把“渗透成功”变成可校验的观察项
攻防演练里最怕的不是攻不下,而是攻下了裁判没看到。传统做法是交截图,截图可以补拍,存在大量主观性。我现在把所有演练步骤都转成可校验的观察项:目标机是否创建了指定文件、是否读到指定字符串、是否改动某个配置项、是否在目标网段抓到数据包。观察项用脚本检查,脚本输出 0 或 1 ,裁判只复核脚本结果。
举个例子,一场模拟演练,红队的终极目标是攻破数据库服务器并在上面留下 flag 文件。检查脚本这样写:
#!/bin/bash # check_db_flag.sh —— 校验红队是否在数据库服务器上留下有效flag DB_HOST="192.168.20.30" FLAG_VALUE="LAB{2024_spring_db_pwned}" # 检查1: 目标服务器指定路径是否存在flag文件 ssh -o ConnectTimeout=5 -o StrictHostKeyChecking=no \ labuser@$DB_HOST "test -f /tmp/flag.txt" if [ $? -eq 0 ]; then echo "观察项[1/2] PASS: 目标机上存在flag文件" else echo "观察项[1/2] FAIL: 未找到flag文件" exit 1 fi # 检查2: flag文件内容是否与预设一致 CONTENT=$(ssh -o ConnectTimeout=5 labuser@$DB_HOST "cat /tmp/flag.txt") if [ "$CONTENT" == "$FLAG_VALUE" ]; then echo "观察项[2/2] PASS: flag内容正确,判定目标被成功攻破" exit 0 else echo "观察项[2/2] FAIL: flag内容不一致" exit 1 fi这个脚本用 ssh 连接目标机做两步验证。参数意义:-o ConnectTimeout 限制连接等待时间,避免脚本卡死;-o StrictHostKeyChecking=no 去掉首次连接的确认提示,便于无人值守执行;前面把 labuser 的 SSH 密钥预置到目标机,保证免密执行。退出码 0 代表目标达成,退出码 1 代表未达成,这个结果直接作为评分依据。所有检查脚本统一放在裁判台 Linux 机器上,裁判台本身不装任何渗透工具,保持干净。
5.2 从比赛到演练:时间窗口、权限边界和允许动作的设定
攻防演练和 CTF 不一样。CTF 以题目为单位,攻防演练以场景为单位。我常用的做法是:红蓝双方各在一个网段并行操作,给定三个网段边界,红队不允许出演练网,不允许攻击宿主机和管理网,禁止在未授权节点上安装持久后门。下面是一份可直接使用的边界表。
| 项目 | 设定值 | 说明 |
|---|---|---|
| 演练时长 | 4 小时一轮,中场清场 15 分钟 | 红蓝双方各有 2 小时进攻和 2 小时防守 |
| 允许动作 | Web攻击、口令猜解、横向移动、权限提升 | 不允许 DoS,不允许勒索软件演示 |
| 禁止动作 | 攻击宿主机、破坏快照、关闭审计链 | 这三项动到基础设施,一票否决 |
| 协同通道 | 独立 IM 群组,禁发截图到外界 | 截图只在复盘时使用 |
| 数据脱敏 | 靶标上的业务数据全部用伪造数据替换 | 防止演练期间泄出真实数据 |
时间窗口是最容易被低估的变量。我见过一整队红队在一个后门通道上扯皮两小时,白白错失黄金时间。所以会安排一个教练角色,在第 30 分钟和第 90 分钟各插入一次暂停,提醒双方检查时间预算和执行状态。加了这个设置以后,演练质量提升非常明显。
5.3 评分与审计的最小实现:一个能直接跑的统计脚本
评分逻辑的落点,是一句话命令能出结果。把上一节的检查脚本全部放进同一个目录,再用一个汇总脚本循环执行目录内所有脚本,输出汇总:
#!/bin/bash # score_aggregator.sh —— 遍历所有观察项脚本,汇总得分 SCORE_DIR="./check_scripts" PASS_COUNT=0 TOTAL_COUNT=0 for script in $SCORE_DIR/check_*.sh; do TOTAL_COUNT=$((TOTAL_COUNT+1)) if bash "$script" > /tmp/check_log_$$.txt 2>&1; then PASS_COUNT=$((PASS_COUNT+1)) echo "[$script] PASS" else echo "[$script] FAIL —— 执行输出:" sed 's/^/ /' /tmp/check_log_$$.txt fi done echo "----------------------------------------" echo "总通过: $PASS_COUNT / $TOTAL_COUNT"逻辑是每个检查脚本返回 0 就计一次通过,返回非零计一次失败。每次执行的输出写到 /tmp/check_log_$$.txt ,$$ 是当前进程号,避免多轮同时执行时互相覆盖。如果某个观察项在演练后 20 分钟才应出现,那对应检查脚本里加 sleep 设置检查点,防止评分器因为执行太早给出错误结论。
评分结果落两份:一份打印在控制台,另一份写进当天日期文件,比如 /var/log/redline/score_20250412.log ,复盘时把每一次输出和原始时间戳对起来。小规模演练不需要数据库支撑,单文件文本足够;等到每天跑一场、脚本执行次数多到这个文件吃不下的时候,再考虑上检索系统不迟。
5.4 复盘报告怎么出:数据引用、截图与时间轴三者对应
复盘报告是实验室存在的理由,不是交个表格就完事。我的复盘报告模板是:攻击链时间轴、攻击机操作记录、靶标日志对拍、流量包关键路径、红蓝双方评语、改进项清单。最重要的部分是时间轴对拍——红队操作记录、蓝队告警记录、流量包时间戳三者必须对齐到秒级。对不齐,先查 NTP,再看日志时区,这两处细节决定了复盘是否可信。
报告生成的基本流程是:裁判台脚本把演练时段内所有日志合并,按秒对齐输出时间轴,再让红蓝双方各自写一段评语。我不建议完全用工具自动生成叙述性报告,因为表述性的东西机器写出来很难让人信服。最后能说服人的,永远是那份时间轴和对应的截图。没有时间轴,其他都是空谈。
6. 把实验室内化成常态平台:快照回滚与健康检查自动化
搭建完成、演练跑通,还不等于实验室能日复一日稳定地支起队伍。最让人头疼的是环境状态一致性。每次演练完不恢复初始状态,下一场演练就带着上一场的痕迹跑,红队上轮装的 WebShell 还挂在靶标上,结果判定无从入手。我的做法是把回滚做成一条命令,把健康检查做成脚本,每天早上到实验室先备份,再执行回滚和检查。
快照回滚脚本在 VMware Workstation 上的最小实现:
#!/bin/bash # rollback_lab.sh —— 把指定靶标回滚到开场快照并重新启动 SNAPSHOT_NAME="pre-exercise-clean" VM_LIST=("win-dc" "linux-db" "web-dvwa") for vm in "${VM_LIST[@]}"; do echo "[$(date +%H:%M:%S)] Reverting $vm ..." # 回滚到指定快照,-T ws 表示 Workstation 虚拟机 vmrun -T ws revert "/data/vms/$vm/$vm.vmx" "$SNAPSHOT_NAME" # 回滚完成后以无界面模式启动 vmrun -T ws start "/data/vms/$vm/$vm.vmx" nogui done循环里的 VM_LIST 是要回滚的靶标名,按顺序写在数组里,方便增删。vmrun 是 VMware 命令行工具,-T ws 指定 Workstation 格式,revert 后面依次是 vmx 文件路径和快照名。启动参数 nogui 表示不打开图形界面,适合无人值守。快照名统一用 pre-exercise-clean ,每次建快照都用这个名字覆盖,避免快照文件越堆越多。真实项目里最容易翻车的点就是快照名漂移,统一命名才能让自动化脚本一直可用。
回滚之后立即做健康检查,确认靶标活过来了:
#!/bin/bash # health_check.sh —— 回滚后验证靶标的关键端口是否可达 TARGETS="192.168.20.10:3389 192.168.20.30:22 192.168.20.40:8080" for item in $TARGETS; do ip=${item%%:*} port=${item##*:} nc -zv -w 5 "$ip" "$port" > /dev/null 2>&1 if [ $? -eq 0 ]; then echo "HEALTH_PASS ${ip}:${port}" else echo "HEALTH_FAIL ${ip}:${port}" fi donenc -z 做端口探测,-w 5 表示每个端口最多等 5 秒,避免卡在无响应的地址上。输出行包含 HEALTH_PASS 或 HEALTH_FAIL ,一眼能看出哪台机器需要手动排查。把两个脚本合并成一条命令,比如 ./rollback_lab.sh && ./health_check.sh ,每天早上到实验室花 10 分钟执行一遍,靶场就永远处于可战斗状态。
我自己的习惯是每周一早上八点半把整套流程跑一遍,雷打不动。有一次因为跳过了健康检查直接进演练,结果域控没起来,十个人在等一个环境的修复。从那以后入口处强制加了一条脚本,不允许任何人以任何理由跳过。环境建设最怕的不是初始搭不好,而是搭完没人维持,用自动化把这层补上,实验室才真正从一个文档变成一个能长期运转的平台。希望这套回滚和检查脚本帮到你。
本文还有配套的精品资源,点击获取