1. 项目概述:为什么我们需要一个企业级漏洞测试平台?

在安全圈子里混了十几年,我见过太多团队在安全测试这件事上“凑合”。开发同学临时搭个靶场,结果环境死活起不来;安全工程师想复现一个CVE,花半天时间配环境,漏洞还没摸到,热情先耗光了。更别提在企业里,新员工入职安全培训、红蓝对抗演练、产品上线前的安全自检,如果每次都要从零开始折腾,效率低不说,还容易出错。这就是为什么,一个稳定、可控、可复现的企业级漏洞测试平台,不是“锦上添花”,而是“雪中送炭”的基建。

Vulhub的出现,恰好解决了这个痛点。它不是一个复杂的平台软件,而是一个精心编排的漏洞环境“食谱”集合。你可以把它理解为一个漏洞博物馆的“展品清单”和“搭建说明书”。它的核心价值在于“标准化”和“可复现”。任何一个已知的漏洞,从古老的Struts2到最新的Spring Cloud Gateway,Vulhub都为你准备好了开箱即用的Docker Compose配置。你不需要去研究漏洞的依赖项、特定版本的服务配置,甚至不需要深厚的Docker知识,一条命令,环境就绪。

但把Vulhub用在一个人的电脑上,和把它部署成一个团队乃至整个公司都能随时使用的“平台”,中间隔着巨大的鸿沟。个人使用,你可能只关心“这个漏洞能不能复现”;但在企业级场景下,你需要考虑的是:环境如何持久化并供多人同时访问?如何管理数十上百个不同的漏洞环境镜像?如何控制资源消耗,避免某个测试把服务器拖垮?如何与现有的CI/CD流程或安全运营平台(SOAR)对接?这些,就是“从零搭建企业级漏洞测试平台”要解决的核心问题。这不是简单地跑通Vulhub的README,而是以Vulhub为基石,构建一套可持续运营的安全测试基础设施。

2. 平台架构设计与核心思路拆解

搭建企业级平台,第一步不是敲命令,而是画蓝图。我们需要一个清晰、可扩展且易于维护的架构。直接在一台物理服务器上裸跑Docker是最简单的,但也是最脆弱的。我推荐的是一种分层架构,它能让平台更健壮。

2.1 核心架构:三层分离模型

我的设计思路是“三层分离”: 资源层、服务层和应用层

资源层 是基石,通常是一台或多台Linux服务器(物理机或云主机)。我强烈建议使用Ubuntu Server LTS版本,比如22.04或24.04,它在内核版本、软件包管理和Docker兼容性上最为均衡。如果预算和需求允许,可以采用Kubernetes集群作为资源层,这为未来的弹性伸缩和高级调度打下了基础,但对于初期或中小团队,一台配置足够的宿主机(建议至少4核CPU,8GB内存,100GB SSD存储)完全够用。

服务层 是核心,运行在资源层之上。这里的主角当然是Docker Engine。但仅仅安装Docker是不够的。我们需要一套编排和管理的“管家系统”。我的方案是: Docker Engine + Docker Compose Plugin + 反向代理(Nginx/Traefik) + 监控(cAdvisor + Prometheus) 。Docker Compose Plugin(内置于现代Docker)用于定义和启动Vulhub的多个环境;反向代理负责将不同的漏洞环境(每个环境可能运行在不同的容器端口上)通过统一的域名或路径暴露给内网用户;监控组件则让我们能实时掌握CPU、内存、网络IO,避免某个“重量级”漏洞环境(比如一个包含完整Weblogic的漏洞)吃光所有资源。

应用层 是用户直接交互的部分。最轻量的方式,就是通过反向代理生成一个Web访问列表。例如,访问 http://vulhub-platform.internal.company.com/cve-2017-5638 ,就能自动代理到运行Apache Struts2 S2-045漏洞环境的容器。更进一步,我们可以开发一个简单的Web门户,用数据库记录环境状态、使用记录,甚至集成用户认证和权限管理。但对于MVP(最小可行产品)而言,一个清晰的Nginx配置加上一个静态HTML索引页,已经能解决80%的问题。

2.2 方案选型背后的考量:为什么是Docker Compose而非K8s?

很多刚接触容器化的朋友会想,既然是企业级,是不是直接上Kubernetes更“高大上”?我的经验是: 杀鸡勿用牛刀,合适比先进更重要

Vulhub的每个漏洞环境,本质上都是一个独立的、一次性(ephemeral)的测试沙盒。它的生命周期通常是“创建 -> 测试 -> 销毁”。我们几乎不需要对这个环境进行滚动更新、服务发现、复杂负载均衡。Docker Compose完美匹配了这个场景:一个 docker-compose.yml 文件定义一组服务(比如一个带漏洞的Web应用和其数据库),一条 docker compose up 命令拉起整个环境。它的学习成本低,配置直观,与Vulhub项目原生兼容。

相反,如果使用K8s,我们需要为每个漏洞环境编写Deployment、Service、Ingress等一堆YAML文件,引入了Pod调度、网络策略等复杂性,但并没有带来对等的好处。当然,如果你的企业已经全面K8s化,有成熟的运维体系,将Vulhub环境打包成Helm Chart在K8s中运行,可以实现更精细的资源配额和命名空间隔离,这是后话。对于从零开始,Docker Compose是最高效、最稳妥的起点。

2.3 存储与网络规划:容易被忽略的关键

存储和网络是平台稳定性的“暗礁”。Vulhub环境在拉取镜像和启动时,会在 /var/lib/docker 产生大量数据。我们必须确保宿主机有充足的空间(建议预留50GB以上)。更关键的是,所有Vulhub环境目录(即你clone下来的代码)应该放在一个独立的数据盘或分区,并做好定期备份。因为你的平台配置、自定义脚本都存放在这里。

网络方面,我建议为这个平台单独规划一个VLAN或子网。所有漏洞环境容器使用一个自定义的Docker网络(例如 vulhub-net ),而不是默认的bridge。这样做有两个好处:一是隔离,避免漏洞测试环境意外访问到生产网络;二是便于管理,我们可以在这个自定义网络上为Nginx反向代理配置固定的容器别名,实现稳定的内部服务发现。

3. 基础环境部署与核心组件配置

理论说完,我们开始动手。假设我们有一台全新的Ubuntu 22.04 LTS服务器,主机名设为 vulhub-platform

3.1 宿主机系统级优化

在安装任何服务前,先对宿主机进行基础优化,这能避免很多后期奇怪的问题。

# 更新系统并安装常用工具
sudo apt update && sudo apt upgrade -y
sudo apt install -y curl wget git vim net-tools htop

# 调整系统参数,防止Docker容器过多导致“无法打开更多文件”的错误
echo "fs.file-max = 6553560" | sudo tee -a /etc/sysctl.conf
echo "* soft nofile 65535" | sudo tee -a /etc/security/limits.conf
echo "* hard nofile 65535" | sudo tee -a /etc/security/limits.conf
echo "session required pam_limits.so" | sudo tee -a /etc/pam.d/common-session
sudo sysctl -p

注意: ulimit 设置对于运行像Elasticsearch这类在Kali上可能出问题的漏洞环境至关重要。很多Docker容器内部会继承宿主机的限制。

3.2 Docker与Docker Compose Plugin安装

遵循Vulhub的推荐,我们使用官方脚本安装Docker。这里有个小技巧,使用国内镜像加速安装过程。

# 使用阿里云镜像站下载安装脚本,速度更快
curl -fsSL https://get.docker.com -o get-docker.sh
# 或者直接使用国内镜像
# curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun

sudo sh get-docker.sh

# 将当前用户加入docker组,避免每次都要sudo
sudo usermod -aG docker $USER
newgrp docker # 刷新组权限,或退出重新登录

# 验证安装
docker --version

现代Docker(20.10.0以上版本)已经内置了Compose Plugin,我们不需要单独安装 docker-compose 命令行工具。验证方式:

docker compose version

如果输出类似 Docker Compose version v2.24.0 ,说明一切就绪。

3.3 配置Docker镜像加速与存储驱动

为了后续快速拉取漏洞环境镜像,必须配置镜像加速器。这里以阿里云容器镜像服务为例(需要注册阿里云账号获取专属加速器地址)。

sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["https://your-own-mirror.mirror.aliyuncs.com"],
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "100m",
    "max-file": "3"
  },
  "storage-driver": "overlay2"
}
EOF

https://your-own-mirror.mirror.aliyuncs.com 替换为你从阿里云控制台获取的真实地址。 log-driver 配置防止容器日志撑爆磁盘, storage-driver 使用性能更好的 overlay2

# 重启Docker服务使配置生效
sudo systemctl daemon-reload
sudo systemctl restart docker
sudo systemctl enable docker

3.4 部署Nginx作为反向代理网关

我们将使用Nginx作为统一入口,根据访问路径将请求分发到不同的漏洞环境容器。

# 安装Nginx
sudo apt install -y nginx

# 创建平台专用的Nginx配置目录
sudo mkdir -p /etc/nginx/vulhub-platform

接下来,创建主配置文件 /etc/nginx/vulhub-platform/vulhub-proxy.conf 。这个配置的核心思路是使用 map 指令和 proxy_pass

# /etc/nginx/vulhub-platform/vulhub-proxy.conf
# 定义一个映射,将访问路径前缀映射到对应的容器服务名和端口
map $request_uri $backend {
    default                                     localhost:8080; # 默认页或未匹配时
    ~^/cve-2017-5638(/|$)                      vulhub_struts2_s2-045:8080;
    ~^/cve-2014-6271(/|$)                      vulhub_bash_shellshock:80;
    ~^/cve-2017-7494(/|$)                      vulhub_samba_cve-2017-7494:139;
    # 后续每新增一个环境,就在这里添加一行映射
}

server {
    listen 80;
    server_name vulhub-platform.internal.company.com; # 替换为你的内网域名或IP

    location / {
        # 如果路径匹配到映射,则代理到对应的容器
        if ($backend) {
            proxy_pass http://$backend;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
        }
        # 如果没有匹配(访问根路径),则展示一个静态索引页
        root /var/www/vulhub-index;
        index index.html;
        try_files $uri $uri/ =404;
    }
}

这里有个关键点: vulhub_struts2_s2-045:8080 中的 vulhub_struts2_s2-045 是我们在Docker Compose文件中为服务定义的名字, 8080 是该服务容器内部暴露的端口。Nginx必须能通过这个服务名解析到容器的IP,这要求Nginx容器和漏洞环境容器在同一个Docker网络中。我们将在后面创建这个网络。

然后,在Nginx的主配置 /etc/nginx/nginx.conf http 块内,包含我们的自定义配置:

http {
    ...
    include /etc/nginx/vulhub-platform/*.conf;
}

最后,创建索引页目录和文件:

sudo mkdir -p /var/www/vulhub-index
sudo tee /var/www/vulhub-index/index.html <<-'EOF'
<!DOCTYPE html>
<html>
<head><title>企业漏洞测试平台</title></head>
<body>
<h1>漏洞环境列表</h1>
<ul>
<li><a href="/cve-2017-5638">CVE-2017-5638 - Apache Struts2 S2-045</a></li>
<li><a href="/cve-2014-6271">CVE-2014-6271 - Bash Shellshock</a></li>
<!-- 后续动态生成或手动添加 -->
</ul>
</body>
</html>
EOF
sudo nginx -t # 测试配置
sudo systemctl reload nginx

4. Vulhub环境集成与平台化改造

现在,基础服务已经就绪,我们要把Vulhub本身“请”进来,并把它改造成适合平台化运行的样子。

4.1 获取与组织Vulhub代码

我们不建议直接在平台服务器上 git clone ,因为这样会包含完整的git历史,体积大且更新麻烦。更好的方式是定期下载归档的发布版本,或者使用 git clone --depth 1 只拉取最新代码。

# 在平台数据目录下操作
cd /opt
sudo git clone --depth 1 https://github.com/vulhub/vulhub.git
sudo chown -R $USER:$USER vulhub/ # 更改属主,方便操作

此时, /opt/vulhub 目录下是按漏洞分类的无数个子目录。我们需要为平台运行建立一个“工作区”。

mkdir -p /opt/vulhub-platform/environments
cd /opt/vulhub-platform

我的策略是:不为每个漏洞环境单独维护一份 docker-compose.yml ,而是通过符号链接(symlink)指向Vulhub原目录。这样做的好处是,当Vulhub官方更新时,我们只需要更新源目录,所有链接自动生效。

# 示例:将Struts2 S2-045环境链接到平台工作区
ln -s /opt/vulhub/struts2/s2-045 /opt/vulhub-platform/environments/cve-2017-5638

这样,我们在 /opt/vulhub-platform/environments 下管理的就是一个个清晰的、以CVE编号或漏洞名称命名的目录,每个目录都链接着真实的Vulhub配置。

4.2 创建统一的Docker网络

为了让所有漏洞环境容器和Nginx能互相通信,我们需要创建一个自定义的Docker网络。

docker network create vulhub-platform-net

这个网络名字 vulhub-platform-net 需要与前面Nginx配置中 proxy_pass 使用的网络名对应。但注意,Nginx配置里写的是服务名,Docker Compose会自动在它所属的网络中,将服务名解析为容器的IP。因此,我们需要确保每个漏洞环境的 docker-compose.yml 文件都指定使用这个网络。

4.3 改造Vulhub的docker-compose.yml

这是最关键的一步。Vulhub原生的 docker-compose.yml 是为单次、独立运行设计的。我们需要对它进行平台化改造,主要涉及三点: 网络、容器命名、资源限制

/opt/vulhub/struts2/s2-045/docker-compose.yml 为例,原始内容可能很简单:

version: '2'
services:
  web:
    image: vulhub/struts2:2.3.32-s2-045
    ports:
      - "8080:8080"

我们需要将其改造为:

version: '3.8' # 使用较新的版本以支持更多特性
services:
  vulhub_struts2_s2-045: # 服务名改为全局唯一且具有描述性的名字
    image: vulhub/struts2:2.3.32-s2-045
    container_name: platform_struts2_s2_045_${INSTANCE_ID:-default} # 容器名加入实例ID,支持多实例
    networks:
      - vulhub-platform-net # 加入我们创建的统一网络
    # ports: # 注释掉端口映射,我们不直接暴露宿主机端口
    #   - "8080:8080"
    expose:
      - 8080 # 只在Docker网络内部暴露端口
    deploy: # 使用deploy限制资源(Compose v3语法)
      resources:
        limits:
          cpus: '1' # 限制最多使用1个CPU核心
          memory: 512M # 限制最多使用512MB内存
    restart: "no" # 漏洞环境通常不需要自动重启
    labels:
      - "vulhub.platform.environment=true"
      - "vulhub.cve=CVE-2017-5638"

networks:
  vulhub-platform-net:
    external: true # 使用外部已创建的网络

改造要点解析:

  1. 服务名 :改为 vulhub_struts2_s2-045 ,与Nginx配置中的 $backend 映射严格对应。这是服务发现的关键。
  2. 网络 :加入 vulhub-platform-net ,并声明为 external 。这确保了所有环境在同一个“局域网”内。
  3. 端口 :将 ports 映射改为 expose expose 只向Docker网络内的其他容器公开端口,而不绑定到宿主机端口,更安全,也避免了端口冲突。
  4. 资源限制 :使用 deploy.resources.limits 为容器设置CPU和内存上限。这是企业级平台防止单个环境耗尽资源、影响其他环境或宿主机稳定的必备措施。
  5. 标签 :添加 labels ,便于后期用Docker命令过滤和管理所有平台创建的环境。

我们需要为每一个计划集成到平台的漏洞环境都做这样的改造。可以编写一个脚本来自动化这个过程。

4.4 编写环境管理脚本

手动进入每个目录执行 docker compose up -d 太低效。我们需要一个中心化的管理脚本。创建 /opt/vulhub-platform/manage.sh

#!/bin/bash
# 企业级Vulhub平台管理脚本
ENV_ROOT="/opt/vulhub-platform/environments"
NETWORK="vulhub-platform-net"

case "$1" in
    start)
        ENV_NAME="$2"
        if [ -z "$ENV_NAME" ]; then
            echo "Usage: $0 start <environment-name>"
            exit 1
        fi
        ENV_PATH="$ENV_ROOT/$ENV_NAME"
        if [ ! -d "$ENV_PATH" ]; then
            echo "环境目录不存在: $ENV_PATH"
            exit 1
        fi
        cd "$ENV_PATH"
        # 注入实例ID(例如时间戳),用于支持同一环境多实例
        export INSTANCE_ID=$(date +%s)
        docker compose up -d
        echo "环境 [$ENV_NAME] 启动成功,实例ID: $INSTANCE_ID"
        ;;
    stop)
        ENV_NAME="$2"
        if [ -z "$ENV_NAME" ]; then
            echo "Usage: $0 stop <environment-name>"
            exit 1
        fi
        ENV_PATH="$ENV_ROOT/$ENV_NAME"
        if [ ! -d "$ENV_PATH" ]; then
            echo "环境目录不存在: $ENV_PATH"
            exit 1
        fi
        cd "$ENV_PATH"
        docker compose down -v
        echo "环境 [$ENV_NAME] 已停止并清理"
        ;;
    list)
        echo "已集成的漏洞环境:"
        for env in $(ls -1 $ENV_ROOT); do
            if [ -f "$ENV_ROOT/$env/docker-compose.yml" ]; then
                echo "  - $env"
            fi
        done
        echo ""
        echo "正在运行的环境容器:"
        docker ps --filter "label=vulhub.platform.environment=true" --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
        ;;
    status)
        ENV_NAME="$2"
        if [ -z "$ENV_NAME" ]; then
            docker ps -a --filter "label=vulhub.platform.environment=true"
        else
            docker ps -a --filter "label=vulhub.cve=$ENV_NAME"
        fi
        ;;
    update)
        # 更新Vulhub源
        cd /opt/vulhub
        git pull origin master
        echo "Vulhub源码更新完成。请注意检查现有环境的docker-compose.yml是否需要同步更新。"
        ;;
    *)
        echo "企业级Vulhub平台管理工具"
        echo "用法: $0 {start|stop|list|status|update} [环境名]"
        exit 1
        ;;
esac

给脚本执行权限: chmod +x /opt/vulhub-platform/manage.sh 。现在,你可以通过 ./manage.sh list 查看环境,通过 ./manage.sh start cve-2017-5638 一键启动环境。

5. 平台运维、监控与安全加固

平台搭建起来只是第一步,让它稳定、安全、易用地运行起来,才是真正的挑战。

5.1 资源监控与告警

无监控,不运维。我们需要知道平台的整体资源消耗和每个漏洞环境的运行状态。一个轻量级的方案是使用cAdvisor(容器监控)+ Prometheus(指标存储)+ Grafana(可视化)。

# 使用Docker Compose部署监控栈
cd /opt/vulhub-platform
mkdir -p monitoring && cd monitoring

创建 docker-compose-monitor.yml :

version: '3.8'
services:
  cadvisor:
    image: gcr.io/cadvisor/cadvisor:latest
    container_name: cadvisor
    privileged: true
    devices:
      - /dev/kmsg:/dev/kmsg
    volumes:
      - /:/rootfs:ro
      - /var/run:/var/run:ro
      - /sys:/sys:ro
      - /var/lib/docker/:/var/lib/docker:ro
    ports:
      - "8081:8080"
    networks:
      - monitor-net
    restart: unless-stopped

  prometheus:
    image: prom/prometheus:latest
    container_name: prometheus
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml
      - prometheus_data:/prometheus
    command:
      - '--config.file=/etc/prometheus/prometheus.yml'
      - '--storage.tsdb.path=/prometheus'
      - '--web.console.libraries=/etc/prometheus/console_libraries'
      - '--web.console.templates=/etc/prometheus/consoles'
      - '--storage.tsdb.retention.time=200h'
      - '--web.enable-lifecycle'
    ports:
      - "9090:9090"
    networks:
      - monitor-net
    restart: unless-stopped

  grafana:
    image: grafana/grafana:latest
    container_name: grafana
    volumes:
      - grafana_data:/var/lib/grafana
    environment:
      - GF_SECURITY_ADMIN_PASSWORD=admin123 # 请修改!
    ports:
      - "3000:3000"
    networks:
      - monitor-net
    restart: unless-stopped

networks:
  monitor-net:
    name: monitor-net

volumes:
  prometheus_data:
  grafana_data:

创建Prometheus配置文件 prometheus.yml :

global:
  scrape_interval: 15s

scrape_configs:
  - job_name: 'cadvisor'
    static_configs:
      - targets: ['cadvisor:8080']
  - job_name: 'node'
    static_configs:
      - targets: ['your-host-ip:9100'] # 需要额外安装node-exporter

启动监控栈: docker compose -f docker-compose-monitor.yml up -d 。访问 http://your-server-ip:3000 登录Grafana(初始账号admin/你设置的密码),添加Prometheus数据源(地址填 http://prometheus:9090 ),然后导入cAdvisor相关的Dashboard(如ID 193 ),即可看到容器级别的CPU、内存、网络、磁盘监控图表。

5.2 日志集中收集

Docker容器的日志默认在 /var/lib/docker/containers/ 下,分散且不易查看。我们可以配置Docker的日志驱动为 json-file 并设置大小(前面已做),同时使用 docker logs 命令查看。对于平台化运维,可以进一步使用 docker-compose logs -f [service-name] 来查看特定环境的日志。

更高级的方案是集成ELK或Loki,但对于初期平台,一个简单的日志轮转和归档脚本已经足够。在 /etc/logrotate.d/docker-vulhub 中配置:

/var/lib/docker/containers/*/*.log {
    daily
    rotate 7
    compress
    delaycompress
    missingok
    copytruncate
}

5.3 安全加固措施

漏洞测试平台本身必须安全,不能成为新的攻击入口。

  1. 网络隔离 :我们已经使用了自定义的Docker网络。此外,应在宿主机防火墙(如UFW)中,只允许特定IP段(如公司内网)访问平台的80端口(Nginx)和监控端口(如3000, 9090)。

    sudo ufw allow from 10.0.0.0/8 to any port 80 proto tcp
    sudo ufw allow from 10.0.0.0/8 to any port 3000 proto tcp
    sudo ufw --force enable
    
  2. 容器安全

    • 非Root用户运行 :在改造 docker-compose.yml 时,尽可能在镜像支持的情况下,通过 user: 指令指定非root用户运行容器进程。
    • 只读根文件系统 :对于大多数漏洞环境,容器内部不需要写入。可以添加 read_only: true 来增强安全性。
    • 限制能力 :使用 cap_drop: 丢弃所有不必要的Linux能力(如 ALL ),然后按需添加。例如,一个Web应用通常不需要 SYS_ADMIN 能力。
  3. 镜像安全 :定期扫描平台使用的漏洞镜像是否有新的安全漏洞。可以使用 trivy docker scout 等工具。

    # 示例:使用Trivy扫描镜像
    docker pull vulhub/struts2:2.3.32-s2-045
    trivy image vulhub/struts2:2.3.32-s2-045
    
  4. 访问控制 :基础的Nginx索引页没有任何权限控制。在生产环境,至少应该配置HTTP Basic认证,或者集成公司的单点登录(SSO)。可以在Nginx配置的 location / 块中添加:

    auth_basic "Vulhub Platform";
    auth_basic_user_file /etc/nginx/.htpasswd;
    

    使用 htpasswd 命令创建用户密码文件。

6. 典型问题排查与实战技巧

在实际运营中,你会遇到各种各样的问题。这里记录几个最常见的问题和我的解决思路。

6.1 环境启动失败:镜像拉取超时或错误

这是最常见的问题,尤其在国内网络环境下。

  • 现象 docker compose up -d 时卡在 Pulling ,或报错 net/http: TLS handshake timeout
  • 排查 :首先 docker pull 单独拉取镜像,确认是否是网络问题。
  • 解决
    1. 确认 /etc/docker/daemon.json 中的镜像加速器配置正确且生效( sudo systemctl restart docker )。
    2. 对于某些特别大的镜像,可以尝试在夜间网络空闲时拉取。
    3. 如果加速器也不行,考虑在海外VPS上拉取镜像,然后导出为tar文件,再导入到平台服务器:
      # 在海外机器
      docker pull vulhub/xxx:tag
      docker save vulhub/xxx:tag -o xxx.tar
      # 将xxx.tar传输到平台服务器
      # 在平台服务器
      docker load -i xxx.tar
      

6.2 容器启动后服务不可访问

  • 现象 docker compose up -d 成功,但通过Nginx访问返回502 Bad Gateway或连接超时。
  • 排查步骤
    1. 检查容器状态 docker ps 查看对应容器是否处于 Up 状态。如果是 Exited ,用 docker logs <container_id> 查看启动日志。
    2. 检查容器内服务 :进入容器内部检查服务是否真的在监听端口。 docker exec -it <container_name> sh ,然后 netstat -tlnp ps aux
    3. 检查网络连通性 :在Nginx容器内(如果Nginx也容器化)或在宿主机上,使用 docker network inspect vulhub-platform-net 查看容器IP,然后尝试 curl http://<容器IP>:<内部端口>
    4. 检查Nginx配置 :确认Nginx配置中的 proxy_pass 地址(服务名和端口)与 docker-compose.yml 中的 services 名称和 expose 端口完全一致。服务名不能包含下划线以外的特殊字符,且需在同一个网络。
    5. 检查防火墙 :确保宿主机防火墙和Docker自身的防火墙规则(如果有)没有阻断容器间通信。

6.3 平台性能突然下降

  • 现象 :平台响应变慢,甚至影响宿主机。
  • 排查
    1. 快速定位问题容器 :使用 docker stats 命令实时查看所有容器的CPU、内存占用。一眼就能看出哪个容器是“资源黑洞”。
    2. 检查监控 :查看Grafana Dashboard,确认是CPU、内存还是磁盘IO瓶颈。
    3. 常见原因与解决
      • 某个漏洞环境被恶意循环攻击 :在测试时,如果利用脚本写错了,可能变成对平台自身的DoS攻击。通过 docker logs 查看异常请求,并临时 docker pause 该容器。
      • 磁盘空间不足 :Docker的日志、镜像、容器层会占用大量空间。定期清理: docker system prune -a -f (谨慎使用,会清理未使用的镜像、容器、网络)。更安全的是只清理日志: find /var/lib/docker/containers/ -name \"*.log\" -size +100M -delete
      • 内存泄漏 :某些老旧的漏洞应用可能存在内存泄漏。为容器设置更严格的内存限制( mem_limit ),并在达到限制后自动重启(在 docker-compose.yml 中配置 restart: on-failure )。

6.4 如何管理多个并发的相同环境?

有时培训或演练需要多个学员同时操作同一个漏洞,但又不希望互相干扰。

  • 解决方案 :利用我们脚本中的 INSTANCE_ID 变量和Docker Compose的项目名( -p 参数)功能。
  • 操作 :启动环境时,指定不同的项目名,它们会创建独立的容器组,但共享相同的镜像和配置。
    cd /opt/vulhub-platform/environments/cve-2017-5638
    export INSTANCE_ID=team_a
    docker compose -p vulhub_struts2_team_a up -d
    export INSTANCE_ID=team_b
    docker compose -p vulhub_struts2_team_b up -d
    
    此时,会启动两组容器,服务名会带上前缀,例如 vulhub_struts2_team_a_vulhub_struts2_s2-045_1 。你需要在Nginx配置中为 team_a team_b 配置不同的访问路径和反向代理规则。这虽然增加了配置复杂性,但实现了真正的多租户隔离。

搭建企业级漏洞测试平台,技术实现只是骨架,真正的血肉是围绕它建立的流程和规范。比如,规定所有新的漏洞环境在集成前,必须经过资源评估和安全扫描;建立定期更新机制,同步Vulhub官方的最新漏洞环境;编写详细的使用手册和培训材料。这个平台的价值,会随着使用它的次数和人数,呈指数级增长。它从一个小工具,逐渐演变为企业安全能力的一部分,让安全测试从一种“手艺”变成一种可重复、可衡量的“工艺”。

更多推荐