PoC BunkerWeb 1.6.17 : docker-compose sur Proxmox, déployé par Ansible
Stack BunkerWeb (scheduler, UI, MariaDB, Redis), sites de test (nginx, Juice Shop, go-httpbin), filtrage DOCKER-USER, script de tests, README et schéma d'architecture. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
commit
099584c95c
42 files changed
+4260
No files matched your search
@@ -0,0 +1,41 @@
|
||||
# Ansible managed
|
||||
# Sites de test du PoC BunkerWeb, mode split
|
||||
# Ports publiés sur 192.168.200.62, filtrés par la chaîne iptables BWPOC :
|
||||
# seul le WAF (192.168.200.61) peut les joindre.
|
||||
|
||||
services:
|
||||
www:
|
||||
image: nginx:1.30-alpine
|
||||
container_name: poc-www
|
||||
restart: unless-stopped
|
||||
read_only: true
|
||||
tmpfs:
|
||||
- /var/cache/nginx
|
||||
- /run
|
||||
- /tmp
|
||||
volumes:
|
||||
- ./www:/usr/share/nginx/html:ro
|
||||
ports:
|
||||
- "192.168.200.62:8081:80"
|
||||
networks: [apps]
|
||||
|
||||
shop:
|
||||
image: bkimminich/juice-shop:v20.3.0
|
||||
container_name: poc-shop
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "192.168.200.62:8082:3000"
|
||||
networks: [apps]
|
||||
|
||||
api:
|
||||
image: mccutchen/go-httpbin:2.26.0
|
||||
container_name: poc-api
|
||||
restart: unless-stopped
|
||||
read_only: true
|
||||
ports:
|
||||
- "192.168.200.62:8083:8080"
|
||||
networks: [apps]
|
||||
|
||||
networks:
|
||||
apps:
|
||||
name: poc-apps
|
||||
@@ -0,0 +1,155 @@
|
||||
# Ansible managed
|
||||
# Stack BunkerWeb 1.6.17 : WAF + scheduler + UI + MariaDB + Redis
|
||||
# Mode split, applis sur 192.168.200.62
|
||||
x-db-env: &db-env
|
||||
DATABASE_URI: "mariadb+pymysql://bunkerweb:CHANGEME@bw-db:3306/db"
|
||||
|
||||
x-api-env: &api-env
|
||||
API_WHITELIST_IP: "127.0.0.0/8 10.20.30.0/24"
|
||||
|
||||
services:
|
||||
bunkerweb:
|
||||
image: bunkerity/bunkerweb:1.6.17
|
||||
container_name: bunkerweb
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "80:8080/tcp"
|
||||
- "443:8443/tcp"
|
||||
- "443:8443/udp" # HTTP/3 (QUIC)
|
||||
labels:
|
||||
- "bunkerweb.INSTANCE=yes"
|
||||
environment:
|
||||
<<: [*db-env, *api-env]
|
||||
networks:
|
||||
- bw-universe
|
||||
- bw-services
|
||||
|
||||
bw-scheduler:
|
||||
image: bunkerity/bunkerweb-scheduler:1.6.17
|
||||
container_name: bw-scheduler
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- bunkerweb
|
||||
- bw-db
|
||||
- bw-redis
|
||||
volumes:
|
||||
- bw-storage:/data
|
||||
environment:
|
||||
<<: [*db-env, *api-env]
|
||||
BUNKERWEB_INSTANCES: "bunkerweb"
|
||||
SERVER_NAME: "www.bwpoc.internal shop.bwpoc.internal api.bwpoc.internal bwui.bwpoc.internal"
|
||||
# --- Réglages globaux ---
|
||||
MULTISITE: "yes"
|
||||
DISABLE_DEFAULT_SERVER: "yes"
|
||||
SERVE_FILES: "no"
|
||||
GENERATE_SELF_SIGNED_SSL: "yes"
|
||||
AUTO_REDIRECT_HTTP_TO_HTTPS: "yes"
|
||||
USE_MODSECURITY: "yes"
|
||||
USE_MODSECURITY_CRS: "yes"
|
||||
MODSECURITY_CRS_VERSION: "4"
|
||||
USE_BAD_BEHAVIOR: "yes"
|
||||
BAD_BEHAVIOR_THRESHOLD: "10"
|
||||
BAD_BEHAVIOR_COUNT_TIME: "1m"
|
||||
BAD_BEHAVIOR_BAN_TIME: "5m"
|
||||
USE_BLACKLIST: "yes"
|
||||
BLACKLIST_USER_AGENT: "PoC-EvilBot"
|
||||
USE_GZIP: "yes"
|
||||
USE_BROTLI: "yes"
|
||||
USE_REDIS: "yes"
|
||||
REDIS_HOST: "bw-redis"
|
||||
REDIS_PASSWORD: "CHANGEME"
|
||||
SEND_ANONYMOUS_REPORT: "no"
|
||||
# --- www.bwpoc.internal ---
|
||||
www.bwpoc.internal_USE_REVERSE_PROXY: "yes"
|
||||
www.bwpoc.internal_REVERSE_PROXY_URL: "/"
|
||||
www.bwpoc.internal_REVERSE_PROXY_HOST: "http://192.168.200.62:8081"
|
||||
www.bwpoc.internal_SELF_SIGNED_SSL_SUBJ: "/CN=www.bwpoc.internal/"
|
||||
www.bwpoc.internal_USE_ANTIBOT: "javascript"
|
||||
www.bwpoc.internal_LIMIT_REQ_RATE: "10r/s"
|
||||
# --- shop.bwpoc.internal ---
|
||||
shop.bwpoc.internal_USE_REVERSE_PROXY: "yes"
|
||||
shop.bwpoc.internal_REVERSE_PROXY_URL: "/"
|
||||
shop.bwpoc.internal_REVERSE_PROXY_HOST: "http://192.168.200.62:8082"
|
||||
shop.bwpoc.internal_SELF_SIGNED_SSL_SUBJ: "/CN=shop.bwpoc.internal/"
|
||||
shop.bwpoc.internal_REVERSE_PROXY_WS: "yes"
|
||||
shop.bwpoc.internal_LIMIT_REQ_RATE: "30r/s"
|
||||
shop.bwpoc.internal_COOKIE_FLAGS: "* SameSite=Lax"
|
||||
# --- api.bwpoc.internal ---
|
||||
api.bwpoc.internal_USE_REVERSE_PROXY: "yes"
|
||||
api.bwpoc.internal_REVERSE_PROXY_URL: "/"
|
||||
api.bwpoc.internal_REVERSE_PROXY_HOST: "http://192.168.200.62:8083"
|
||||
api.bwpoc.internal_SELF_SIGNED_SSL_SUBJ: "/CN=api.bwpoc.internal/"
|
||||
api.bwpoc.internal_ALLOWED_METHODS: "GET|POST|HEAD"
|
||||
api.bwpoc.internal_MAX_CLIENT_SIZE: "1m"
|
||||
api.bwpoc.internal_LIMIT_REQ_RATE: "5r/s"
|
||||
api.bwpoc.internal_CUSTOM_CONF_MODSEC_poc-rule: "SecRule ARGS:poc \"@streq attack\" \"id:10001,phase:2,deny,status:403,log,msg:'PoC BunkerWeb : regle maison'\""
|
||||
# --- bwui.bwpoc.internal ---
|
||||
bwui.bwpoc.internal_USE_REVERSE_PROXY: "yes"
|
||||
bwui.bwpoc.internal_REVERSE_PROXY_URL: "/"
|
||||
bwui.bwpoc.internal_REVERSE_PROXY_HOST: "http://bw-ui:7000"
|
||||
bwui.bwpoc.internal_SELF_SIGNED_SSL_SUBJ: "/CN=bwui.bwpoc.internal/"
|
||||
bwui.bwpoc.internal_USE_TEMPLATE: "ui"
|
||||
networks:
|
||||
- bw-universe
|
||||
- bw-db
|
||||
|
||||
bw-ui:
|
||||
image: bunkerity/bunkerweb-ui:1.6.17
|
||||
container_name: bw-ui
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- bw-db
|
||||
volumes:
|
||||
- bw-ui-data:/data # secrets Flask, clés TOTP et Biscuit
|
||||
environment:
|
||||
<<: *db-env
|
||||
ADMIN_USERNAME: "admin"
|
||||
ADMIN_PASSWORD: "CHANGEME"
|
||||
TZ: "Europe/Paris"
|
||||
networks:
|
||||
- bw-universe
|
||||
- bw-db
|
||||
|
||||
bw-db:
|
||||
image: mariadb:11
|
||||
container_name: bw-db
|
||||
restart: unless-stopped
|
||||
command: --max-allowed-packet=67108864
|
||||
environment:
|
||||
MYSQL_RANDOM_ROOT_PASSWORD: "yes"
|
||||
MYSQL_DATABASE: "db"
|
||||
MYSQL_USER: "bunkerweb"
|
||||
MYSQL_PASSWORD: "CHANGEME"
|
||||
volumes:
|
||||
- bw-data:/var/lib/mysql
|
||||
networks:
|
||||
- bw-db
|
||||
|
||||
bw-redis:
|
||||
image: redis:8-alpine
|
||||
container_name: bw-redis
|
||||
restart: unless-stopped
|
||||
command: ["redis-server", "--requirepass", "CHANGEME", "--save", "60", "1"]
|
||||
volumes:
|
||||
- bw-redis:/data
|
||||
networks:
|
||||
- bw-universe
|
||||
|
||||
volumes:
|
||||
bw-data:
|
||||
bw-storage:
|
||||
bw-ui-data:
|
||||
bw-redis:
|
||||
|
||||
networks:
|
||||
bw-universe:
|
||||
name: bw-universe
|
||||
ipam:
|
||||
driver: default
|
||||
config:
|
||||
- subnet: 10.20.30.0/24 # seul réseau autorisé à parler à l'API BunkerWeb
|
||||
bw-services:
|
||||
name: bw-services # réseau des applis (mode single), créé par Ansible
|
||||
external: true
|
||||
bw-db:
|
||||
name: bw-db
|
||||
@@ -0,0 +1,16 @@
|
||||
#!/bin/sh
|
||||
# Ansible managed
|
||||
# N'autorise que le WAF (et les sources listées) à joindre les ports publiés
|
||||
# des applis. Les règles vont dans DOCKER-USER, consultée par Docker avant
|
||||
# ses propres règles ; --ctorigdstport filtre sur le port publié (avant DNAT).
|
||||
set -eu
|
||||
IFACE="ens18"
|
||||
PORTS="8081:8083"
|
||||
|
||||
iptables -N BWPOC 2>/dev/null || iptables -F BWPOC
|
||||
iptables -A BWPOC -s 192.168.200.61 -j RETURN
|
||||
iptables -A BWPOC -j DROP
|
||||
|
||||
RULE="-i $IFACE -p tcp -m conntrack --ctstate NEW --ctorigdstport $PORTS -j BWPOC"
|
||||
# shellcheck disable=SC2086
|
||||
iptables -C DOCKER-USER $RULE 2>/dev/null || iptables -I DOCKER-USER $RULE
|
||||
Reference in new issue
Block a user