9.4 KiB
9.4 KiB
created, type, status, deadline, tags
| created | type | status | deadline | tags | ||||
|---|---|---|---|---|---|---|---|---|
| 2026-03-08 | project | active |
|
PVE Security Scanner
Goal
在 Proxmox VE 上搭建一台专用的内网安全扫描 VM,用于定期进行网络安全评估、漏洞扫描和合规检查。
Architecture
+------------------+
| PVE Host |
| +--------------+| PVE Firewall (Layer 1)
| | Scanner VM || - IN: only admin IPs -> SSH/9392
| | Ubuntu 24.04 || - OUT: internal nets + update_targets IPSET
| | 4C / 8G / 80G||
| +--------------+|
| | |
+--------|--------+
| vmbr0 (bridge)
|
======|==================== Internal Network (192.168.68.0/24)
| | | |
[Host] [Host] [Host] [Switch/Router]
VM Specs
| Resource | Value |
|---|---|
| Hostname | network-scanner |
| IP | 192.168.68.84 |
| OS | Ubuntu 24.04 (cloud-init) |
| Kernel | 6.8.0-101-generic |
| CPU | 4 cores (host type) |
| RAM | 8 GB |
| Disk | 80 GB |
| Network | vmbr0 bridge, 192.168.68.0/24 |
| SSH User | kai (1Password managed key) |
| Admin User | scanner-admin |
Security Architecture (Defense in Depth)
Layer 1: PVE Firewall (Hypervisor)
在 Proxmox 层面限制 VM 网络访问,即使 VM 被攻陷也无法绕过。
| Direction | Rule | Purpose |
|---|---|---|
| IN | Admin IPs -> TCP 22 | SSH 管理 |
| IN | Admin IPs -> TCP 443, 9392 | OpenVAS Web UI |
| IN | Internal nets -> ICMP | Ping |
| OUT | -> Internal nets (all) | 扫描内网 |
| OUT | -> update_targets IPSET TCP 80/443 | 漏洞库更新、包管理 |
| OUT | -> UDP 53/123 | DNS / NTP |
| Default | DROP | 其他全部拒绝 |
Config: /etc/pve/firewall/200.fw
Admin IPs 默认 192.168.68.0/24(整个内网段),可通过 SCANNER_ADMIN_IPS 环境变量覆盖。
Layer 2: nftables (VM Internal)
VM 内部使用 nftables 做第二层防护,包含动态封禁功能。
Key features:
blocked_ipsset: 动态 IP 封禁(带超时自动解封)ssh_bruteforceset: SSH 暴力破解自动检测(3次/分钟触发,15分钟封禁)- Output policy DROP: 出站默认拒绝,仅白名单放行
- 所有 DROP 事件记录日志
- Docker 接口使用
iifname "docker*"/iifname "br-*"通配(不要求接口预先存在)
管理命令:
# 查看规则
nft list ruleset
# 手动封禁 IP(1小时)
nft add element inet firewall blocked_ips { 1.2.3.4 timeout 1h }
# 查看被封禁的 IP
nft list set inet firewall blocked_ips
# 重载规则
systemctl restart nftables
Config: /etc/nftables.conf
Layer 3: SSH Hardening
| Setting | Value |
|---|---|
| Authentication | Public key only (1Password) |
| Root login | Disabled |
| Max auth tries | 10 |
| Ciphers | chacha20-poly1305, aes256-gcm |
| KEX | sntrup761x25519, curve25519 |
| Fail2ban | 3 failures -> 1h ban (nftables backend) |
| AllowUsers | scanner-admin kai |
| Forwarding | DisableForwarding yes |
| Banner | /etc/issue.net |
Config: /etc/ssh/sshd_config.d/99-scanner-hardening.conf
Layer 4: System Hardening
Kernel (sysctl):
- IP forwarding disabled
- ICMP redirects ignored
- SYN flood protection (syncookies)
- Reverse path filtering (anti-spoofing)
- Martian packet logging
- ASLR enabled, ptrace restricted
Auditing:
auditd: 监控 /etc, auth, sudo, network, cron, scanner config 变更AIDE: 文件完整性检查 (daily 3am)Lynis: 安全审计 (weekly Sunday 2am)- Core dumps disabled
Config: /etc/sysctl.d/99-security-scanner.conf, /etc/audit/rules.d/scanner-audit.rules
Installed Tools
| Tool | Purpose | Usage |
|---|---|---|
| OpenVAS/Greenbone | 全面漏洞管理平台 | Web UI https://192.168.68.84 (nginx -> gsad) |
| Nmap | 网络发现、端口扫描 | nmap -sV --script=safe <target> |
| Nuclei | 快速漏洞扫描 (模板驱动, SHA256 校验) | nuclei -u <url> |
| httpx | HTTP 探测、服务识别 (SHA256 校验) | httpx -l hosts.txt |
| Nikto | Web 服务器扫描 | nikto -h <url> |
| testssl.sh | TLS/SSL 安全检测 | testssl <host:port> |
| NetExec | SMB/RDP/WinRM 评估 | netexec smb <target> |
Scanning Workflow
Quick Scan (Automated)
/opt/scans/scripts/quick-scan.sh 192.168.68.0/24
Steps:
- Host discovery (
nmap -sn) - Port scan top 1000 (
nmap -sV --script=safe) - HTTP service detection (
httpx) - Vulnerability scan (
nucleimedium/high/critical)
Results saved to /opt/scans/results/<timestamp>/
Full Scan (OpenVAS)
- Start containers:
cd /opt/greenbone && docker compose up -d - Wait for feed sync (first time: 30-60 min)
- Access Web UI:
https://192.168.68.84(self-signed cert, accept warning) - Create Target -> Create Task -> Run Scan
- Export report (PDF/CSV)
Targeted Scans
# TLS/SSL audit
testssl 192.168.68.10:443
# Web server scan
nikto -h https://192.168.68.10
# SMB assessment
netexec smb 192.168.68.0/24
# Full port scan single host
nmap -sV --script=safe -p- -T4 192.168.68.10
Monitoring
| Check | Schedule | Tool |
|---|---|---|
| Disk usage | Every 6h | /opt/scans/scripts/check-disk.sh |
| OpenVAS health | Every 30min | /opt/scans/scripts/check-openvas.sh |
| File integrity | Daily 3am | AIDE |
| Security audit | Weekly Sun 2am | Lynis |
| Old results cleanup | Weekly Sun 4am | find (maxdepth 1, >90 days, logged) |
| Nuclei templates | Weekly Mon 5am | nuclei -update-templates |
| Daily summary | Daily | Logwatch |
Logs: /var/log/scanner/
Deployment
Method: Cloud-Init Template Clone
- PVE Web UI -> 选中 Cloud-Init 模板 -> 右键 Clone (Full Clone)
- Cloud-Init 标签设置: user
kai, SSH key (1Password), IP192.168.68.84/24 - Hardware: 4C / 8G / 80G disk
Copy Scripts to VM
scp -r C:/Users/yaoji/git/pve-security-scanner/vm kai@192.168.68.84:/tmp/scanner-setup
Execute (in order)
# 设置环境变量
export SCANNER_ADMIN_IPS='192.168.68.0/24'
export SCANNER_DNS_SERVERS='192.168.68.1'
# 一键执行(或逐个执行)
sudo -E bash /tmp/scanner-setup/setup.sh
# 或逐个:
sudo -E bash /tmp/scanner-setup/01-system-harden.sh
sudo -E bash /tmp/scanner-setup/02-firewall.sh
sudo -E bash /tmp/scanner-setup/04-install-tools.sh # Docker 先装
sudo usermod -aG docker scanner-admin # 补加 docker 组
sudo -E bash /tmp/scanner-setup/03-ssh-harden.sh # 再跑 SSH
sudo -E bash /tmp/scanner-setup/05-monitoring.sh
sudo -E bash /tmp/scanner-setup/06-docker-autostart.sh
# OpenVAS 密码
cd /opt/greenbone && docker compose up -d
docker compose exec -u gvmd gvmd gvmd --user=admin --new-password=<PASSWORD>
# 重启
sudo shutdown -r now
Post-Deployment Checklist
- VM created from cloud-init template
- SSH key configured (1Password, ed25519)
- System hardening (01) applied
- nftables firewall (02) applied - ADMIN_IPS = 192.168.68.0/24
- Docker installed (Ubuntu source fix applied)
- SSH hardening (03) applied - AllowUsers scanner-admin kai, MaxAuthTries 10
- Security tools (04) installed
- Monitoring (05) configured
- Docker autostart (06) enabled - systemd greenbone-openvas.service
- OpenVAS Web UI accessible -
https://192.168.68.84(nginx port 443+9392) - Feed sync complete (in progress, ~30-60 min)
- First quick scan completed
lynis audit systemscore verified
Deployment Notes
Issues Encountered
- Docker source wrong distro: 脚本原写 Debian 源,实际系统是 Ubuntu 24.04 (noble)。已修复为自动检测
${ID}(debian/ubuntu) - nftables rate limit 不能用 define:
define SSH_RATE_LIMIT = 5/minute语法错误,nftables 不支持 define 变量做 rate limit,改为内联值 iif "docker0"要求接口已存在: Docker 未安装时 docker0 不存在导致报错,改为iifname "docker*"通配- 03-ssh-harden.sh docker 组不存在: 需先运行 04 安装 Docker,再运行 03 创建用户
- SSH
sshd.servicenot found: Ubuntu 用ssh.service,已修复为ssh 2>/dev/null || sshd - AllowUsers 只有 scanner-admin: cloud-init 用户
kai被拒绝登录,已加入 AllowUsers - MaxAuthTries 3 太小: 1Password 管理多个 key 逐个尝试会超限,改为 10
- ADMIN_IPS 设成 VM 自身 IP: 导致工作站无法 SSH,改为整网段
192.168.68.0/24 - Greenbone 镜像名变更:
greenbone/xxx已迁移到registry.community.greenbone.net/community/xxx,架构改为 nginx + gsad + gsa 分离 - nginx 9392 端口重定向到 443: 需同时暴露 443 端口,docker-compose 已加
0.0.0.0:443:443
Recommended Execution Order (revised)
01 -> 02 -> 04 (Docker) -> 03 (SSH, needs docker group) -> 05 -> 06
Scripts Location
Repo: https://git.colacoder.com/kai/pve-security-scanner
pve-security-scanner/
├── pve/
│ ├── create-vm.sh # VM creation (idempotent)
│ └── firewall.sh # PVE-level firewall (env var guard)
├── vm/
│ ├── setup.sh # One-click ordered execution
│ ├── 01-system-harden.sh # OS hardening
│ ├── 02-firewall.sh # nftables rules
│ ├── 03-ssh-harden.sh # SSH + fail2ban
│ ├── 04-install-tools.sh # Security tools (auto-detect distro)
│ ├── 05-monitoring.sh # Logging + cron
│ └── 06-docker-autostart.sh # OpenVAS systemd service
└── README.md