1. 项目概述:从“makabaka”到实战靶场的构建思路
最近在安全圈子里,一个名为“makabaka的小推车靶场”的项目标题引起了我的注意。乍一看,这个名字充满了网络热梗的趣味性——“makabaka”源自网络流行语,带有一种轻松、甚至有点“摆烂”的戏谑感,而“小推车”则让人联想到一种便携、可移动的工具。但作为一名从业者,我立刻意识到,这绝不是一个简单的玩笑。在网络安全领域,“靶场”是一个极其严肃和核心的概念,它指的是一个用于模拟真实网络环境、进行安全技术研究、攻防演练和技能培训的隔离平台。将“makabaka”和“小推车”与“靶场”结合,背后透露出的是一种全新的、更轻量化、更灵活、更贴近个人学习和研究需求的靶场构建理念。
这个项目本质上是一个个人可快速部署、高度自定义、资源消耗可控的网络安全实战演练环境。它解决的正是传统靶场(无论是企业级大型靶场还是在线CTF平台)对个人学习者不够友好的痛点:部署复杂、资源占用高、场景固定、难以深度定制内部漏洞和网络拓扑。而“小推车”的比喻非常贴切,意味着你可以像推着一辆装满工具的小车一样,随时随地搭建起一个属于你自己的、包含特定漏洞场景的微型实验网络。无论是想复现一个最新的CVE漏洞,还是想搭建一个包含Web应用、数据库、中间件的复杂攻击链进行红队演练,或是单纯为了教学和技能验证,这个“小推车靶场”都能提供一个快速启动的沙箱。
它非常适合网络安全初学者、在校学生、安全研究人员以及希望提升实战能力的运维和开发人员。你不需要拥有庞大的服务器集群,甚至在一台配置不错的个人电脑或云服务器上,就能通过容器化等技术,快速构建出包含多个靶机节点、复杂网络隔离和真实漏洞的微型“战场”。接下来,我将结合我多年的实战和教学经验,为你彻底拆解如何从零开始打造这样一个“makabaka的小推车靶场”,涵盖设计思路、技术选型、实操搭建、场景构建以及排错心得,让你不仅能复现,更能理解其背后的每一个设计决策。
2. 核心架构与技术选型解析
构建一个轻量、可移动的靶场,技术选型是基石。我们需要在功能性、易用性、资源效率和可移植性之间找到最佳平衡点。经过多次实践和对比,我最终确定了以“容器化”为核心,辅以编排工具和虚拟网络的技术栈。这并不是唯一解,但却是目前个人环境下最优雅、最高效的解决方案。
2.1 为什么是Docker与Docker Compose?
首先,为什么选择Docker而不是传统的虚拟机(如VMware、VirtualBox)?核心原因在于资源开销和启动速度。虚拟机需要模拟完整的硬件和操作系统,每个靶机都是一个完整的VM,会消耗大量的CPU、内存和磁盘空间。而Docker容器共享主机内核,只包含应用及其依赖,这使得单个靶机容器可能只需要几十MB到几百MB的资源,启动时间更是秒级。对于“小推车”这种强调灵活、快速迭代的场景,容器无疑是更优的选择。
然而,一个靶场很少只有一个靶机。它通常包含多个服务:一个存在漏洞的Web应用(靶机A)、一个后端数据库(靶机B)、或许还有一个脆弱的中间件(靶机C)。手动管理这些容器的创建、网络互联、启动顺序是灾难性的。这时,Docker Compose就登场了。它允许我们使用一个YAML文件(docker-compose.yml)来定义和运行多容器应用。我们可以在这个文件里清晰地声明:
- 每个“靶机”对应哪个Docker镜像。
- 每个容器需要映射哪些端口到主机。
- 容器之间如何通过自定义网络进行通信(比如,Web应用容器需要能访问数据库容器,但攻击者主机不应该直接访问数据库)。
- 容器的启动顺序和依赖关系。
通过docker-compose up -d一条命令,整个靶场环境就能一键拉起,docker-compose down则能彻底清理,完美符合“小推车”即开即用、即用即收的特性。
2.2 网络拓扑设计:隔离与连通的艺术
靶场的网络设计直接决定了演练的真实性和安全性。我们不能让所有容器都跑在默认的桥接网络里,那样就失去了内部网络分区的意义。一个典型的“小推车靶场”网络拓扑可以这样设计:
- 外部网络(External Network):模拟互联网。通常就是你的Docker主机(你的物理机或云服务器)所在的网络。攻击者(也就是你)从这个网络发起攻击。
- DMZ区(Demilitarized Zone):一个自定义的Docker网络。将面向公众的服务放在这里,比如存在漏洞的Web服务器容器。这个网络需要将特定端口(如80、443)映射到主机的外部网络,允许“攻击者”直接访问。
- 内网区(Internal Network):另一个自定义的Docker网络。将内部服务放在这里,如数据库(MySQL、Redis)、内网应用系统、域控制器(如果模拟内网渗透)等。这个网络不应该有任何端口映射到主机,它对外是完全隔离的。DMZ区的靶机如果需要访问内网服务,需要同时接入DMZ和内网两个网络。
这种设计通过Docker Compose可以轻松实现。你可以在docker-compose.yml中定义两个网络:network_dmz和network_internal。Web容器同时连接network_dmz和network_internal,数据库容器只连接network_internal。这样,你从外部只能访问到Web应用的漏洞,要想获取数据库数据,你必须先攻陷Web服务器,然后以它为跳板,向内网横向移动——这极大地还原了真实攻击场景。
注意:网络命名要有意义,例如
target_dmz和target_internal,避免使用默认的bridge,这有助于后期管理和故障排查。
2.3 镜像来源:用现成的还是自己构建?
靶机的本质是运行特定漏洞应用的容器。镜像来源有两种主要方式:
- 使用公共漏洞镜像:这是最快捷的方式。社区有许多优秀的漏洞靶场镜像,例如
vulhub、vulnerables系列(如vulnerables/web-dvwa)。这些镜像已经集成了完整的漏洞环境,开箱即用。对于快速搭建常见漏洞(如SQL注入、文件上传、反序列化)的练习环境,这是首选。 - 自定义构建镜像:当你需要复现一个特定版本的应用漏洞,或者公共镜像不符合你的需求时,就需要自己编写
Dockerfile来构建。例如,你需要一个特定版本的Apache Struts 2.2.3来复现S2-045漏洞。你需要从官方或源码编译该版本Struts,并部署到一个基础Tomcat镜像中,然后将这个构建过程固化到Dockerfile里。
对于“小推车靶场”,我建议以公共镜像为主,自定义镜像为辅。初期可以大量使用vulhub等项目提供的现成场景,快速搭建起丰富的练习环境。当你的研究深入后,再针对性地构建自定义镜像。Docker Compose可以无缝地混合使用这两种镜像,只需在服务定义中指定image: 公共镜像名或build: ./path/to/Dockerfile即可。
3. 实战搭建:从零构建你的第一个靶场
理论说再多不如动手做一遍。让我们以搭建一个经典的“DVWA(Damn Vulnerable Web Application) + MySQL”漏洞环境为例,这是最入门也是最经典的Web安全靶场之一。我们将通过这个例子,完整走通“小推车靶场”的搭建流程。
3.1 环境准备与工具安装
首先,你需要一个Linux环境。我强烈推荐使用一台Ubuntu 22.04 LTS的云服务器(如各大云厂商的轻量应用服务器)或本地虚拟机。个人电脑上通过WSL2安装Ubuntu也是一个绝佳选择,性能损失小,且能与Windows文件系统互通,非常方便。
更新系统并安装基础工具:
sudo apt update && sudo apt upgrade -y sudo apt install -y curl wget git vim安装Docker Engine:这是核心。遵循Docker官方文档安装是最稳妥的。
# 卸载旧版本(如有) sudo apt remove docker docker-engine docker.io containerd runc # 设置仓库 sudo apt install -y ca-certificates curl gnupg sudo install -m 0755 -d /etc/apt/keyrings curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg sudo chmod a+r /etc/apt/keyrings/docker.gpg echo \ "deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \ "$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | \ sudo tee /etc/apt/sources.list.d/docker.list > /dev/null # 安装Docker sudo apt update sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin安装Docker Compose独立版本:虽然Docker Desktop包含了Compose,但在服务器上我们通常安装独立的CLI工具。由于上一步已经安装了
docker-compose-plugin,我们可以直接使用docker compose命令(注意中间没有横线)。为了兼容一些老教程或脚本,也可以安装独立版本:# 安装独立版本的docker-compose(可选) sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose sudo chmod +x /usr/local/bin/docker-compose # 验证安装 docker --version docker compose version # 或 docker-compose --version(可选但推荐)配置非root用户运行Docker:为了避免每次都要用
sudo,可以将你的用户加入docker组。sudo usermod -aG docker $USER操作后需要退出当前终端并重新登录,这个改动才会生效。
3.2 编写Docker Compose编排文件
这是整个靶场的“蓝图”。我们在项目根目录(例如~/makabaka_range)创建一个docker-compose.yml文件。
version: '3.8' # 指定Compose文件格式版本 services: # 漏洞Web应用 - DVWA dvwa: image: vulnerables/web-dvwa:latest # 使用社区维护的DVWA镜像 container_name: makabaka_dvwa restart: unless-stopped ports: - "8080:80" # 将容器的80端口映射到主机的8080端口,这样我们通过 http://主机IP:8080 访问 networks: - dmz_network - internal_network # DVWA需要连接数据库,所以也加入内网 environment: - PHPIDS=off # 关闭PHP入侵检测系统,避免影响漏洞练习 depends_on: - mysql_db # 声明依赖,确保数据库先启动 # 可以挂载本地目录来持久化配置或网站文件(可选) # volumes: # - ./dvwa_config:/var/www/html/config # 后端数据库 - MySQL mysql_db: image: mysql:5.7 # DVWA兼容MySQL 5.7 container_name: makabaka_mysql restart: unless-stopped networks: - internal_network # 数据库只在内网,对外不可见 environment: - MYSQL_ROOT_PASSWORD=rootpassword # 设置root密码,强烈建议在真实环境使用强密码! - MYSQL_DATABASE=dvwa - MYSQL_USER=dvwa - MYSQL_PASSWORD=p@ssw0rd # 挂载数据卷,防止容器删除后数据丢失 volumes: - mysql_data:/var/lib/mysql # 定义网络 networks: dmz_network: # DMZ区网络,对外暴露服务 driver: bridge ipam: config: - subnet: "172.20.0.0/24" # 可以指定子网,便于识别 internal_network: # 内网区网络,完全隔离 driver: bridge ipam: config: - subnet: "172.30.0.0/24" # 定义数据卷,用于持久化数据 volumes: mysql_data: driver: local这个文件清晰地定义了两个服务(dvwa和mysql_db)和两个网络。dvwa服务暴露了8080端口,并连接了两个网络,意味着它既能被外网(你)访问,也能访问内网的数据库。mysql_db服务则完全隐藏在内网中。
3.3 启动靶场与初始化访问
保存好docker-compose.yml文件后,在同一个目录下执行启动命令:
docker compose up -d-d参数代表在后台运行。你会看到Docker开始拉取镜像(如果本地没有),然后创建网络、卷,最后启动容器。使用以下命令查看状态:
docker compose ps如果状态都是Up,就说明启动成功了。
现在,打开你的浏览器,访问http://你的服务器IP地址:8080(如果是本地WSL2,可能是http://localhost:8080)。你应该能看到DVWA的安装引导页面。
DVWA初始化步骤:
- 在页面点击
Create / Reset Database按钮。这会连接我们刚才定义的MySQL容器,创建所需的数据库表。 - 如果遇到连接数据库的错误,通常是数据库容器还没完全准备好。等待十几秒,或者运行
docker compose logs mysql_db查看数据库日志,确认MySQL已启动完成,然后重试。 - 数据库创建成功后,页面会自动跳转到登录页。默认用户名是
admin,密码是password。 - 登录后,在左侧菜单栏找到
DVWA Security,将安全级别设置为Low。这样所有漏洞的防护都是最低的,方便我们练习。
至此,你的第一个“小推车靶场”实例已经搭建完成!它包含了完整的LAMP(Linux, Apache, MySQL, PHP)栈和一个充满已知漏洞的Web应用。
4. 场景扩展与高级玩法
一个只有DVWA的靶场显然不够“makabaka”。真正的“小推车”应该能灵活装载各种场景。下面介绍几种扩展方式。
4.1 集成更多漏洞场景(Vulhub实战)
Vulhub是一个开源的漏洞环境集合,提供了数百个漏洞的Docker Compose一键搭建脚本。我们可以把它“装”进我们的小推车。
克隆Vulhub仓库:
git clone https://github.com/vulhub/vulhub.git ~/vulhub cd ~/vulhub选择并启动一个场景:Vulhub按漏洞类型和应用分类。例如,我们想搭建一个Apache Flink的漏洞环境。
cd ~/vulhub/flink/CVE-2020-17518 docker compose up -d根据README提示,访问特定端口即可开始漏洞利用练习。练习完后,在对应目录下
docker compose down即可关闭。
如何管理多个场景?你可以在你的“小推车”主目录下,为每个场景创建一个子目录,里面存放其独立的docker-compose.yml。通过切换目录来管理不同场景,互不干扰。这就是“小推车”的模块化思想。
4.2 构建自定义漏洞镜像
假设你想复现一个某OA系统特定版本的漏洞,但没有现成镜像。你需要自己构建。
- 准备漏洞应用:下载该OA系统的漏洞版本安装包(
oa_vulnerable.zip)。 - 编写Dockerfile:在项目目录下创建
Dockerfile。# 使用一个基础Web服务器镜像,例如带有Apache和PHP的 FROM php:7.4-apache # 设置工作目录 WORKDIR /var/www/html # 复制漏洞应用源码到容器 COPY ./oa_vulnerable.zip /tmp/ RUN apt-get update && apt-get install -y unzip \ && unzip /tmp/oa_vulnerable.zip -d /var/www/html/ \ && chown -R www-data:www-data /var/www/html \ && rm /tmp/oa_vulnerable.zip # 暴露端口 EXPOSE 80 # 启动Apache(基础镜像已有默认CMD) - 编写docker-compose.yml:
version: '3.8' services: custom_oa: build: . # 指定从当前目录的Dockerfile构建 container_name: my_custom_oa ports: - "8081:80" networks: - custom_network networks: custom_network: driver: bridge - 构建并运行:
docker compose build # 构建镜像 docker compose up -d # 启动服务
4.3 模拟复杂内网渗透环境
这才是“小推车靶场”的终极形态。我们可以组合多个镜像,模拟一个包含域控(DC)、成员服务器、工作站的内网环境。这里以使用impacket实验室的镜像为例,它是一个经典的域渗透练习环境。
- 准备编排文件:创建一个复杂的
docker-compose.yml,定义多个服务。version: '3.8' services: dc01: image: registry.cn-hangzhou.aliyuncs.com/impacket/dc01:latest container_name: dc01 hostname: DC01.CORP.LOCAL networks: internal_net: ipv4_address: 172.16.10.10 # 固定IP,方便其他机器指向 client01: image: registry.cn-hangzhou.aliyuncs.com/impacket/client01:latest container_name: client01 hostname: CLIENT01.CORP.LOCAL networks: internal_net: ipv4_address: 172.16.10.20 dns: - 172.16.10.10 # DNS指向域控 attacker: image: kalilinux/kali-rolling:latest container_name: attacker networks: - dmz_net - internal_net # 攻击机需要接入内网进行横向移动 tty: true stdin_open: true command: tail -f /dev/null # 保持容器运行 networks: dmz_net: driver: bridge internal_net: driver: bridge ipam: config: - subnet: 172.16.10.0/24 - 启动与渗透:启动后,你可以进入
attacker容器(docker exec -it attacker bash),安装渗透工具(如impacket,nmap,bloodhound-python),然后对内网(172.16.10.0/24)进行扫描、漏洞利用、横向移动和域提权。这完全模拟了一个真实的内部网络攻击场景。
5. 运维、排错与性能优化心得
搭建起来只是第一步,稳定、高效地运行才是长期使用的关键。下面分享一些我踩过坑后总结的经验。
5.1 日常运维命令清单
将这些命令保存为笔记,你会经常用到:
全局状态查看:
docker compose ps # 查看当前目录下compose项目状态 docker ps -a # 查看所有容器 docker network ls # 查看所有网络 docker volume ls # 查看所有数据卷日志查看(排错神器):
docker compose logs [service_name] # 查看某个服务的日志 docker compose logs -f [service_name] # 实时跟踪日志(类似tail -f) docker logs <container_id> # 查看特定容器日志进入容器内部:
docker exec -it <container_name> bash # 如果容器有bash docker exec -it <container_name> sh # 如果只有sh这在调试应用配置、查看文件或手动执行命令时非常有用。
启动、停止、清理:
docker compose up -d # 启动 docker compose stop # 停止服务,保留容器和网络 docker compose down # 停止并移除容器、网络(默认不移除卷) docker compose down -v # 停止并移除容器、网络、卷(数据会丢失!) docker system prune -a # 清理所有未使用的镜像、容器、网络、构建缓存(谨慎使用)
5.2 常见问题与排查技巧
端口冲突:错误提示
Bind for 0.0.0.0:8080 failed: port is already allocated。- 原因:主机上的8080端口已被其他程序(可能是另一个容器)占用。
- 解决:
sudo netstat -tulpn | grep :8080查找占用进程。- 修改
docker-compose.yml中的端口映射,例如改为- "8081:80"。 - 停止占用端口的进程(如果是无关紧要的)。
容器启动后立即退出:
docker compose ps显示状态为Exit (1)。- 原因:容器内的主进程启动失败。常见于应用配置错误、依赖服务未就绪、启动脚本有问题。
- 排查:
docker compose logs [service_name]查看错误日志,这是最重要的线索。docker run -it --rm [image_name] bash尝试以交互模式运行镜像,手动执行启动命令,看报错信息。- 检查
docker-compose.yml中的depends_on是否设置正确,确保依赖服务(如数据库)已健康运行。
网络不通,容器间无法访问:
- 原因:容器不在同一个自定义网络中,或者防火墙规则阻止。
- 排查:
docker network inspect [network_name]查看网络详情,确认容器是否已正确连接。- 进入一个容器(如
dvwa),尝试ping另一个容器的服务名(如ping mysql_db)。Docker内置DNS会将服务名解析为容器IP。 - 确保应用配置中连接数据库的主机名是Docker Compose中定义的服务名(如
mysql_db),而不是localhost或127.0.0.1。
磁盘空间不足:Docker镜像、容器和卷会占用大量空间。
- 监控:
docker system df查看Docker磁盘使用情况。 - 清理:
docker image prune清理悬空镜像。docker volume prune清理未使用的卷(注意备份重要数据)。- 定期删除不再使用的旧镜像和停止的容器。
- 监控:
5.3 性能优化与资源限制
在个人电脑上运行多个容器,资源可能吃紧。可以通过Docker Compose为容器设置资源限制:
services: dvwa: image: vulnerables/web-dvwa deploy: # 注意:在Compose v3+中,资源限制通常在deploy下,或使用旧语法 resources: limits: cpus: '0.5' # 最多使用50%的单个CPU核心 memory: 512M # 内存上限512MB reservations: cpus: '0.1' memory: 256M # 或者使用旧版Compose语法(更通用) # mem_limit: 512m # cpus: "0.5"对于内存敏感的服务(如数据库),合理设置mem_limit可以防止其耗尽主机内存。同时,将不常变化的数据卷(volume)挂载到SSD硬盘上,可以提升IO性能。
最后,一个最重要的心得:为你的每一个“小推车靶场”项目编写清晰的README.md文件。记录下这个靶场的目的、包含的服务、访问方式、默认账号密码、以及你搭建过程中遇到的任何坑和解决方案。时间久了,你会积累下一套宝贵的、可复用的环境库,这才是“makabaka的小推车”真正的价值所在——它不是一次性的玩具,而是你个人网络安全能力成长的便携式工具箱和知识库。