feat: initial setup for PVE security scanner VM
Scripts for deploying a hardened internal network security scanner on Proxmox VE: - PVE-level firewall and VM creation - System hardening (sysctl, auditd, AIDE) - nftables firewall with dynamic IP blocking - SSH hardening with fail2ban - Security tools (OpenVAS, Nmap, Nuclei, httpx, Nikto, testssl, NetExec) - Monitoring, logging, and Docker autostart
This commit is contained in:
476
vm/04-install-tools.sh
Normal file
476
vm/04-install-tools.sh
Normal file
@@ -0,0 +1,476 @@
|
||||
#!/bin/bash
|
||||
# =============================================================================
|
||||
# Security Scanning Tools Installation
|
||||
# Run this inside the VM as root
|
||||
# =============================================================================
|
||||
set -euo pipefail
|
||||
|
||||
echo "============================================"
|
||||
echo " Security Tools - Installation"
|
||||
echo "============================================"
|
||||
|
||||
# --- 1. Base dependencies ---
|
||||
echo "[+] Installing base dependencies..."
|
||||
apt install -y \
|
||||
curl wget git \
|
||||
net-tools iproute2 \
|
||||
dnsutils whois \
|
||||
python3 python3-pip python3-venv \
|
||||
jq tmux htop \
|
||||
ca-certificates gnupg
|
||||
|
||||
# --- 2. Docker (for Greenbone OpenVAS) ---
|
||||
if ! command -v docker &>/dev/null; then
|
||||
echo "[+] Installing Docker..."
|
||||
install -m 0755 -d /etc/apt/keyrings
|
||||
curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc
|
||||
chmod 644 /etc/apt/keyrings/docker.asc
|
||||
|
||||
# Detect distro (debian or ubuntu)
|
||||
. /etc/os-release
|
||||
DOCKER_DISTRO="${ID}" # "debian" or "ubuntu"
|
||||
DOCKER_CODENAME="${VERSION_CODENAME}"
|
||||
echo \
|
||||
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] \
|
||||
https://download.docker.com/linux/${DOCKER_DISTRO} \
|
||||
${DOCKER_CODENAME} stable" | \
|
||||
tee /etc/apt/sources.list.d/docker.list > /dev/null
|
||||
|
||||
apt update
|
||||
apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
|
||||
systemctl enable docker
|
||||
fi
|
||||
|
||||
# --- 3. Nmap (network scanner) ---
|
||||
echo "[+] Installing Nmap..."
|
||||
apt install -y nmap
|
||||
|
||||
# --- Helper: download and verify binary from GitHub ---
|
||||
install_github_binary() {
|
||||
local REPO="$1" # e.g., projectdiscovery/nuclei
|
||||
local NAME="$2" # e.g., nuclei
|
||||
local ARCH="linux_amd64"
|
||||
|
||||
echo "[+] Installing ${NAME}..."
|
||||
local VERSION
|
||||
VERSION=$(curl -s "https://api.github.com/repos/${REPO}/releases/latest" | jq -r '.tag_name' | sed 's/^v//')
|
||||
|
||||
local ZIP_URL="https://github.com/${REPO}/releases/download/v${VERSION}/${NAME}_${VERSION}_${ARCH}.zip"
|
||||
local CHECKSUM_URL="https://github.com/${REPO}/releases/download/v${VERSION}/${NAME}_${VERSION}_checksums.txt"
|
||||
|
||||
wget -q "${ZIP_URL}" -O "/tmp/${NAME}.zip"
|
||||
wget -q "${CHECKSUM_URL}" -O "/tmp/${NAME}_checksums.txt"
|
||||
|
||||
# Verify checksum
|
||||
local EXPECTED_SHA
|
||||
EXPECTED_SHA=$(grep "${ARCH}.zip" "/tmp/${NAME}_checksums.txt" | awk '{print $1}')
|
||||
local ACTUAL_SHA
|
||||
ACTUAL_SHA=$(sha256sum "/tmp/${NAME}.zip" | awk '{print $1}')
|
||||
|
||||
if [[ "${EXPECTED_SHA}" != "${ACTUAL_SHA}" ]]; then
|
||||
echo "[ERROR] Checksum verification failed for ${NAME}!" >&2
|
||||
echo " Expected: ${EXPECTED_SHA}" >&2
|
||||
echo " Actual: ${ACTUAL_SHA}" >&2
|
||||
rm -f "/tmp/${NAME}.zip" "/tmp/${NAME}_checksums.txt"
|
||||
return 1
|
||||
fi
|
||||
echo " Checksum verified for ${NAME} v${VERSION}"
|
||||
|
||||
unzip -o "/tmp/${NAME}.zip" -d "/tmp/${NAME}-bin"
|
||||
mv "/tmp/${NAME}-bin/${NAME}" "/usr/local/bin/${NAME}"
|
||||
chmod +x "/usr/local/bin/${NAME}"
|
||||
rm -rf "/tmp/${NAME}.zip" "/tmp/${NAME}-bin" "/tmp/${NAME}_checksums.txt"
|
||||
}
|
||||
|
||||
# --- 4. Nuclei (fast vulnerability scanner) ---
|
||||
install_github_binary "projectdiscovery/nuclei" "nuclei"
|
||||
|
||||
# Update Nuclei templates
|
||||
nuclei -update-templates 2>&1 | logger -t nuclei-setup || true
|
||||
|
||||
# --- 5. httpx (HTTP toolkit) ---
|
||||
install_github_binary "projectdiscovery/httpx" "httpx"
|
||||
|
||||
# --- 6. Nikto (web server scanner) ---
|
||||
echo "[+] Installing Nikto..."
|
||||
apt install -y nikto
|
||||
|
||||
# --- 7. testssl.sh (TLS/SSL testing) ---
|
||||
echo "[+] Installing testssl.sh..."
|
||||
git clone --depth 1 https://github.com/drwetter/testssl.sh.git /opt/testssl
|
||||
ln -sf /opt/testssl/testssl.sh /usr/local/bin/testssl
|
||||
|
||||
# --- 8. CrackMapExec / NetExec (network assessment) ---
|
||||
echo "[+] Installing NetExec..."
|
||||
python3 -m pip install --break-system-packages netexec 2>/dev/null || \
|
||||
pipx install netexec 2>/dev/null || \
|
||||
echo "[!] NetExec install failed - install manually if needed"
|
||||
|
||||
# --- 9. Greenbone OpenVAS (Docker Compose) ---
|
||||
echo "[+] Setting up Greenbone OpenVAS..."
|
||||
mkdir -p /opt/greenbone
|
||||
cat > /opt/greenbone/docker-compose.yml << 'COMPEOF'
|
||||
name: greenbone-community-edition
|
||||
|
||||
services:
|
||||
vulnerability-tests:
|
||||
image: registry.community.greenbone.net/community/vulnerability-tests
|
||||
environment:
|
||||
FEED_RELEASE: "24.10"
|
||||
KEEP_ALIVE: 1
|
||||
volumes:
|
||||
- vt_data_vol:/mnt
|
||||
|
||||
notus-data:
|
||||
image: registry.community.greenbone.net/community/notus-data
|
||||
environment:
|
||||
KEEP_ALIVE: 1
|
||||
volumes:
|
||||
- notus_data_vol:/mnt
|
||||
|
||||
scap-data:
|
||||
image: registry.community.greenbone.net/community/scap-data
|
||||
environment:
|
||||
KEEP_ALIVE: 1
|
||||
volumes:
|
||||
- scap_data_vol:/mnt
|
||||
|
||||
cert-bund-data:
|
||||
image: registry.community.greenbone.net/community/cert-bund-data
|
||||
environment:
|
||||
KEEP_ALIVE: 1
|
||||
volumes:
|
||||
- cert_data_vol:/mnt
|
||||
|
||||
dfn-cert-data:
|
||||
image: registry.community.greenbone.net/community/dfn-cert-data
|
||||
environment:
|
||||
KEEP_ALIVE: 1
|
||||
volumes:
|
||||
- cert_data_vol:/mnt
|
||||
depends_on:
|
||||
cert-bund-data:
|
||||
condition: service_healthy
|
||||
|
||||
data-objects:
|
||||
image: registry.community.greenbone.net/community/data-objects
|
||||
environment:
|
||||
FEED_RELEASE: "24.10"
|
||||
KEEP_ALIVE: 1
|
||||
volumes:
|
||||
- data_objects_vol:/mnt
|
||||
|
||||
report-formats:
|
||||
image: registry.community.greenbone.net/community/report-formats
|
||||
environment:
|
||||
FEED_RELEASE: "24.10"
|
||||
KEEP_ALIVE: 1
|
||||
volumes:
|
||||
- data_objects_vol:/mnt
|
||||
depends_on:
|
||||
data-objects:
|
||||
condition: service_healthy
|
||||
|
||||
gpg-data:
|
||||
image: registry.community.greenbone.net/community/gpg-data
|
||||
volumes:
|
||||
- gpg_data_vol:/mnt
|
||||
|
||||
redis-server:
|
||||
image: registry.community.greenbone.net/community/redis-server
|
||||
restart: on-failure
|
||||
volumes:
|
||||
- redis_socket_vol:/run/redis/
|
||||
|
||||
pg-gvm-migrator:
|
||||
image: registry.community.greenbone.net/community/pg-gvm-migrator:stable
|
||||
restart: "no"
|
||||
volumes:
|
||||
- psql_data_vol:/var/lib/postgresql
|
||||
- psql_socket_vol:/var/run/postgresql
|
||||
|
||||
pg-gvm:
|
||||
image: registry.community.greenbone.net/community/pg-gvm:stable
|
||||
restart: on-failure:10
|
||||
volumes:
|
||||
- psql_data_vol:/var/lib/postgresql
|
||||
- psql_socket_vol:/var/run/postgresql
|
||||
depends_on:
|
||||
pg-gvm-migrator:
|
||||
condition: service_completed_successfully
|
||||
|
||||
gvmd:
|
||||
image: registry.community.greenbone.net/community/gvmd:stable
|
||||
restart: on-failure
|
||||
volumes:
|
||||
- gvmd_data_vol:/var/lib/gvm
|
||||
- scap_data_vol:/var/lib/gvm/scap-data/
|
||||
- cert_data_vol:/var/lib/gvm/cert-data
|
||||
- data_objects_vol:/var/lib/gvm/data-objects/gvmd
|
||||
- vt_data_vol:/var/lib/openvas/plugins
|
||||
- psql_data_vol:/var/lib/postgresql
|
||||
- gvmd_socket_vol:/run/gvmd
|
||||
- ospd_openvas_socket_vol:/run/ospd
|
||||
- psql_socket_vol:/var/run/postgresql
|
||||
depends_on:
|
||||
pg-gvm:
|
||||
condition: service_started
|
||||
scap-data:
|
||||
condition: service_healthy
|
||||
cert-bund-data:
|
||||
condition: service_healthy
|
||||
dfn-cert-data:
|
||||
condition: service_healthy
|
||||
data-objects:
|
||||
condition: service_healthy
|
||||
report-formats:
|
||||
condition: service_healthy
|
||||
|
||||
gsa:
|
||||
image: registry.community.greenbone.net/community/gsa:stable-slim
|
||||
environment:
|
||||
MOUNT_PATH: "/mnt/web"
|
||||
KEEP_ALIVE: 1
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "test -e /run/gsa/copying.done"]
|
||||
start_period: 5s
|
||||
volumes:
|
||||
- gsa_data_vol:/mnt/web
|
||||
|
||||
gsad:
|
||||
image: registry.community.greenbone.net/community/gsad:stable
|
||||
restart: on-failure
|
||||
environment:
|
||||
GSAD_ARGS: "--listen=0.0.0.0 --http-only --api-only -f"
|
||||
volumes:
|
||||
- gvmd_socket_vol:/run/gvmd
|
||||
depends_on:
|
||||
gvmd:
|
||||
condition: service_started
|
||||
|
||||
gvm-config:
|
||||
image: registry.community.greenbone.net/community/gvm-config:latest
|
||||
environment:
|
||||
ENABLE_NGINX_CONFIG: "true"
|
||||
ENABLE_TLS_GENERATION: "true"
|
||||
volumes:
|
||||
- nginx_config_vol:/mnt/nginx/configs
|
||||
- nginx_certificates_vol:/mnt/nginx/certs
|
||||
|
||||
nginx:
|
||||
image: registry.community.greenbone.net/community/nginx:latest
|
||||
ports:
|
||||
- "0.0.0.0:9392:9392"
|
||||
volumes:
|
||||
- nginx_config_vol:/etc/nginx/conf.d:ro
|
||||
- nginx_certificates_vol:/etc/nginx/certs:ro
|
||||
- gsa_data_vol:/usr/share/nginx/html:ro
|
||||
depends_on:
|
||||
gvm-config:
|
||||
condition: service_completed_successfully
|
||||
gsa:
|
||||
condition: service_healthy
|
||||
gsad:
|
||||
condition: service_started
|
||||
|
||||
configure-openvas:
|
||||
image: registry.community.greenbone.net/community/openvas-scanner:stable
|
||||
volumes:
|
||||
- openvas_data_vol:/mnt
|
||||
- openvas_log_data_vol:/var/log/openvas
|
||||
command:
|
||||
- /bin/sh
|
||||
- -c
|
||||
- |
|
||||
printf "table_driven_lsc = yes\nopenvasd_server = http://openvasd:80\n" > /mnt/openvas.conf
|
||||
sed "s/127/128/" /etc/openvas/openvas_log.conf | sed 's/gvm/openvas/' > /mnt/openvas_log.conf
|
||||
chmod 644 /mnt/openvas.conf
|
||||
chmod 644 /mnt/openvas_log.conf
|
||||
touch /var/log/openvas/openvas.log
|
||||
chmod 666 /var/log/openvas/openvas.log
|
||||
|
||||
openvas:
|
||||
image: registry.community.greenbone.net/community/openvas-scanner:stable
|
||||
restart: on-failure
|
||||
volumes:
|
||||
- openvas_data_vol:/etc/openvas
|
||||
- openvas_log_data_vol:/var/log/openvas
|
||||
command:
|
||||
- /bin/sh
|
||||
- -c
|
||||
- |
|
||||
cat /etc/openvas/openvas.conf
|
||||
tail -f /var/log/openvas/openvas.log
|
||||
depends_on:
|
||||
configure-openvas:
|
||||
condition: service_completed_successfully
|
||||
|
||||
openvasd:
|
||||
image: registry.community.greenbone.net/community/openvas-scanner:stable
|
||||
restart: on-failure
|
||||
environment:
|
||||
OPENVASD_MODE: service_notus
|
||||
GNUPGHOME: /etc/openvas/gnupg
|
||||
LISTENING: 0.0.0.0:80
|
||||
volumes:
|
||||
- openvas_data_vol:/etc/openvas
|
||||
- openvas_log_data_vol:/var/log/openvas
|
||||
- gpg_data_vol:/etc/openvas/gnupg
|
||||
- notus_data_vol:/var/lib/notus
|
||||
depends_on:
|
||||
vulnerability-tests:
|
||||
condition: service_healthy
|
||||
notus-data:
|
||||
condition: service_healthy
|
||||
configure-openvas:
|
||||
condition: service_completed_successfully
|
||||
gpg-data:
|
||||
condition: service_completed_successfully
|
||||
networks:
|
||||
default:
|
||||
aliases:
|
||||
- openvasd
|
||||
|
||||
ospd-openvas:
|
||||
image: registry.community.greenbone.net/community/ospd-openvas:stable
|
||||
restart: on-failure
|
||||
hostname: ospd-openvas.local
|
||||
# SECURITY NOTE: NET_ADMIN, NET_RAW, and seccomp=unconfined are required
|
||||
# for raw packet scanning (SYN scans, OS detection). Risk is mitigated by
|
||||
# host-level nftables, PVE firewall, and VM-level isolation.
|
||||
cap_add:
|
||||
- NET_ADMIN
|
||||
- NET_RAW
|
||||
security_opt:
|
||||
- seccomp=unconfined
|
||||
- apparmor=unconfined
|
||||
command:
|
||||
[
|
||||
"ospd-openvas",
|
||||
"-f",
|
||||
"--config",
|
||||
"/etc/gvm/ospd-openvas.conf",
|
||||
"--notus-feed-dir",
|
||||
"/var/lib/notus/advisories",
|
||||
"-m",
|
||||
"666",
|
||||
]
|
||||
volumes:
|
||||
- gpg_data_vol:/etc/openvas/gnupg
|
||||
- vt_data_vol:/var/lib/openvas/plugins
|
||||
- notus_data_vol:/var/lib/notus
|
||||
- ospd_openvas_socket_vol:/run/ospd
|
||||
- redis_socket_vol:/run/redis/
|
||||
- openvas_data_vol:/etc/openvas/
|
||||
- openvas_log_data_vol:/var/log/openvas
|
||||
depends_on:
|
||||
redis-server:
|
||||
condition: service_started
|
||||
gpg-data:
|
||||
condition: service_completed_successfully
|
||||
configure-openvas:
|
||||
condition: service_completed_successfully
|
||||
vulnerability-tests:
|
||||
condition: service_healthy
|
||||
notus-data:
|
||||
condition: service_healthy
|
||||
|
||||
gvm-tools:
|
||||
image: registry.community.greenbone.net/community/gvm-tools
|
||||
volumes:
|
||||
- gvmd_socket_vol:/run/gvmd
|
||||
- ospd_openvas_socket_vol:/run/ospd
|
||||
depends_on:
|
||||
- gvmd
|
||||
- ospd-openvas
|
||||
|
||||
volumes:
|
||||
gpg_data_vol:
|
||||
scap_data_vol:
|
||||
cert_data_vol:
|
||||
data_objects_vol:
|
||||
gvmd_data_vol:
|
||||
psql_data_vol:
|
||||
vt_data_vol:
|
||||
notus_data_vol:
|
||||
psql_socket_vol:
|
||||
gvmd_socket_vol:
|
||||
ospd_openvas_socket_vol:
|
||||
redis_socket_vol:
|
||||
openvas_data_vol:
|
||||
openvas_log_data_vol:
|
||||
gsa_data_vol:
|
||||
nginx_config_vol:
|
||||
nginx_certificates_vol:
|
||||
COMPEOF
|
||||
|
||||
# --- 10. Create scan scripts directory ---
|
||||
mkdir -p /opt/scans/{results,scripts}
|
||||
|
||||
# Quick scan helper script
|
||||
cat > /opt/scans/scripts/quick-scan.sh << 'SCANEOF'
|
||||
#!/bin/bash
|
||||
# Quick internal network scan
|
||||
# Usage: ./quick-scan.sh 192.168.1.0/24
|
||||
set -euo pipefail
|
||||
|
||||
TARGET="${1:?Usage: $0 <target-subnet>}"
|
||||
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
|
||||
RESULTS_DIR="/opt/scans/results/${TIMESTAMP}"
|
||||
mkdir -p "${RESULTS_DIR}"
|
||||
|
||||
echo "[+] Starting quick scan of ${TARGET}"
|
||||
echo "[+] Results will be saved to ${RESULTS_DIR}"
|
||||
|
||||
# Step 1: Host discovery
|
||||
echo "[+] Step 1/4: Host discovery..."
|
||||
nmap -sn "${TARGET}" -oG "${RESULTS_DIR}/hosts-alive.gnmap"
|
||||
HOSTS=$(grep "Up" "${RESULTS_DIR}/hosts-alive.gnmap" | awk '{print $2}')
|
||||
echo "${HOSTS}" > "${RESULTS_DIR}/hosts-alive.txt"
|
||||
HOST_COUNT=$(wc -l < "${RESULTS_DIR}/hosts-alive.txt")
|
||||
echo " Found ${HOST_COUNT} alive hosts"
|
||||
|
||||
# Step 2: Port scan top 1000
|
||||
echo "[+] Step 2/4: Port scanning (top 1000 ports)..."
|
||||
nmap -sV --script=safe -T4 --top-ports 1000 -iL "${RESULTS_DIR}/hosts-alive.txt" \
|
||||
-oA "${RESULTS_DIR}/port-scan"
|
||||
|
||||
# Step 3: HTTP service detection
|
||||
echo "[+] Step 3/4: HTTP service detection..."
|
||||
grep -oP '\d+\.\d+\.\d+\.\d+' "${RESULTS_DIR}/hosts-alive.txt" | \
|
||||
httpx -silent -ports 80,443,8080,8443,9090 -o "${RESULTS_DIR}/http-services.txt" 2>/dev/null || true
|
||||
|
||||
# Step 4: Nuclei scan on HTTP services
|
||||
if [ -s "${RESULTS_DIR}/http-services.txt" ]; then
|
||||
echo "[+] Step 4/4: Vulnerability scanning with Nuclei..."
|
||||
nuclei -l "${RESULTS_DIR}/http-services.txt" \
|
||||
-severity medium,high,critical \
|
||||
-o "${RESULTS_DIR}/nuclei-findings.txt" 2>/dev/null || true
|
||||
else
|
||||
echo "[+] Step 4/4: No HTTP services found, skipping Nuclei."
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "[+] Scan complete. Results in: ${RESULTS_DIR}"
|
||||
echo " - hosts-alive.txt: Live hosts"
|
||||
echo " - port-scan.*: Port scan results"
|
||||
echo " - http-services.txt: HTTP endpoints"
|
||||
echo " - nuclei-findings.txt: Vulnerabilities found"
|
||||
SCANEOF
|
||||
chmod +x /opt/scans/scripts/quick-scan.sh
|
||||
|
||||
echo ""
|
||||
echo "[+] All security tools installed."
|
||||
echo ""
|
||||
echo "Tool summary:"
|
||||
echo " nmap - Network discovery and port scanning"
|
||||
echo " nuclei - Fast vulnerability scanner"
|
||||
echo " httpx - HTTP probing"
|
||||
echo " nikto - Web server scanner"
|
||||
echo " testssl - TLS/SSL testing"
|
||||
echo " netexec - Network assessment (SMB, RDP, etc.)"
|
||||
echo " OpenVAS (Docker) - Full vulnerability management"
|
||||
echo ""
|
||||
echo "Quick start:"
|
||||
echo " cd /opt/greenbone && docker compose up -d # Start OpenVAS"
|
||||
echo " /opt/scans/scripts/quick-scan.sh 192.168.1.0/24 # Quick scan"
|
||||
Reference in New Issue
Block a user