From 3d9bdc04b256e5b909f9d28186b5df9355e3fa54 Mon Sep 17 00:00:00 2001 From: elAgala Date: Sun, 26 Jan 2025 01:35:59 -0300 Subject: [PATCH] Add full caddy installation (Coraza WAF + Crowdsec) - Remove security issue when exposing ports in a docker container: Use intranet instead - Modify install_caddy to use new template --- images/caddy_full/Dockerfile | 23 ++++++++++ templates/caddy/full/.env | 1 + templates/caddy/full/caddy/Caddyfile | 39 +++++++++++++++++ .../caddy/full/caddy/coraza/coraza_rules.conf | 15 +++++++ templates/caddy/full/crowdsec/acquis.yaml | 6 +++ templates/caddy/full/docker-compose.yml | 43 +++++++++++++++++++ .../monitoring/docker-compose.grafana.yml | 12 +++--- templates/monitoring/docker-compose.yml | 2 + web/install_caddy.sh | 18 ++++++-- 9 files changed, 149 insertions(+), 10 deletions(-) create mode 100644 images/caddy_full/Dockerfile create mode 100644 templates/caddy/full/.env create mode 100644 templates/caddy/full/caddy/Caddyfile create mode 100644 templates/caddy/full/caddy/coraza/coraza_rules.conf create mode 100644 templates/caddy/full/crowdsec/acquis.yaml create mode 100644 templates/caddy/full/docker-compose.yml diff --git a/images/caddy_full/Dockerfile b/images/caddy_full/Dockerfile new file mode 100644 index 0000000..af580f6 --- /dev/null +++ b/images/caddy_full/Dockerfile @@ -0,0 +1,23 @@ +# Build stage with xcaddy +FROM caddy:builder AS builder + +# Install xcaddy and build Caddy with plugins +RUN xcaddy build \ + --with github.com/corazawaf/coraza-caddy \ + --with github.com/hslatman/caddy-crowdsec-bouncer/http + +# Stage to download OWASP CRS +FROM alpine:latest AS crs +RUN apk add --no-cache git && \ + git clone --depth 1 --branch v4.0.0 \ + https://github.com/coreruleset/coreruleset.git /coreruleset && \ + mv /coreruleset/crs-setup.conf.example /coreruleset/crs-setup.conf + +# Final stage +FROM caddy:latest + +# Copy custom Caddy binary +COPY --from=builder /usr/bin/caddy /usr/bin/caddy + +# Copy OWASP CRS from the crs stage +COPY --from=crs /coreruleset /etc/caddy/coreruleset diff --git a/templates/caddy/full/.env b/templates/caddy/full/.env new file mode 100644 index 0000000..6ba8595 --- /dev/null +++ b/templates/caddy/full/.env @@ -0,0 +1 @@ +CROWDSEC_API_KEY=${CROWDSEC_API_KEY} diff --git a/templates/caddy/full/caddy/Caddyfile b/templates/caddy/full/caddy/Caddyfile new file mode 100644 index 0000000..fc7dd9b --- /dev/null +++ b/templates/caddy/full/caddy/Caddyfile @@ -0,0 +1,39 @@ +{ + # Put Coraza in front of every request + order coraza_waf first + + # Logging + log { + level DEBUG + format console + } + + # Allow CrowdSec globally + crowdsec { + api_url http://crowdsec:8080 + api_key {$CROWDSEC_API_KEY} + } + +} + +# Example static +static.example.com { + coraza_waf { + directives ` + Include /etc/caddy/coraza.conf + ` + } + + root * /src/static/test + file_server +} + +api.example.com { + coraza_waf { + directives ` + Include /etc/caddy/coraza.conf + ` + } + + reverse_proxy * http://{CONTAINER_NAME}:{CONTAINER_PORT} +} diff --git a/templates/caddy/full/caddy/coraza/coraza_rules.conf b/templates/caddy/full/caddy/coraza/coraza_rules.conf new file mode 100644 index 0000000..0aad078 --- /dev/null +++ b/templates/caddy/full/caddy/coraza/coraza_rules.conf @@ -0,0 +1,15 @@ +# OWASP CRS rules +Include /etc/caddy/coreruleset/crs-setup.conf.example +Include /etc/caddy/coreruleset/rules/*.conf + +# Custom rules +SecRuleEngine On + +# Block SQLi +SecRule ARGS "@detectSQLi" \ + "id:1000,\ + phase:2,\ + deny,\ + status:403,\ + msg:'SQL Injection Detected'" + diff --git a/templates/caddy/full/crowdsec/acquis.yaml b/templates/caddy/full/crowdsec/acquis.yaml new file mode 100644 index 0000000..0e56265 --- /dev/null +++ b/templates/caddy/full/crowdsec/acquis.yaml @@ -0,0 +1,6 @@ +# Parse Caddy JSON logs +filenames: + - /var/log/caddy/access.log +labels: + type: caddy + diff --git a/templates/caddy/full/docker-compose.yml b/templates/caddy/full/docker-compose.yml new file mode 100644 index 0000000..0499a71 --- /dev/null +++ b/templates/caddy/full/docker-compose.yml @@ -0,0 +1,43 @@ +services: + crowdsec: + image: crowdsecurity/crowdsec:latest + container_name: crowdsec + volumes: + - ./crowdsec/acquis.yaml:/etc/crowdsec/acquis.yaml + - ./crowdsec/data:/var/lib/crowdsec/data + - ./caddy/logs:/var/log/caddy:ro + environment: + - COLLECTIONS=crowdsecurity/caddy crowdsecurity/whitelist-good-actors crowdsecurity/http-cve + - BOUNCER_KEY_CADDY=${CROWDSEC_API_KEY} + networks: + - caddy_net + restart: unless-stopped + + caddy: + image: ghcr.io/elagala/server-initializer/caddy-waf-crowdsec:latest + container_name: caddy + ports: + - "80:80" + - "443:443" + environment: + - CROWDSEC_API_KEY=${CROWDSEC_API_KEY} + volumes: + - ../static:/src/static # Your static files location + - ./caddy/Caddyfile:/etc/caddy/Caddyfile + - ./caddy/coraza/coraza.conf:/etc/caddy/coraza.conf + - ./caddy/logs:/var/log/caddy + - caddy_data:/data + - caddy_config:/config + networks: + - caddy_net + depends_on: + - crowdsec + restart: unless-stopped + +volumes: + caddy_data: + caddy_config: + +networks: + caddy_net: + external: true diff --git a/templates/monitoring/docker-compose.grafana.yml b/templates/monitoring/docker-compose.grafana.yml index 86300eb..ea96ed2 100644 --- a/templates/monitoring/docker-compose.grafana.yml +++ b/templates/monitoring/docker-compose.grafana.yml @@ -1,22 +1,20 @@ services: + # PORT 9090 prometheus: image: prom/prometheus:latest container_name: prometheus restart: always - ports: - - "9090:9090" volumes: - ./prometheus.yml:/etc/prometheus/prometheus.yml networks: - monitoring_net - caddy_net + # PORT 3000 grafana: image: grafana/grafana:latest container_name: grafana restart: always - ports: - - "3000:3000" environment: - GF_SECURITY_ADMIN_PASSWORD=YOUR_PASSWORD - GE_SERVER_ROOT_URL=YOUR_URL @@ -24,17 +22,19 @@ services: - prometheus networks: - monitoring_net + - caddy_net + # PORT 9100 node_exporter: image: prom/node-exporter:latest container_name: node-exporter restart: always - ports: - - "9100:9100" networks: - monitoring_net networks: monitoring_net: driver: bridge + caddy_net: + external: true diff --git a/templates/monitoring/docker-compose.yml b/templates/monitoring/docker-compose.yml index 86acf7f..a15cd10 100644 --- a/templates/monitoring/docker-compose.yml +++ b/templates/monitoring/docker-compose.yml @@ -1,4 +1,5 @@ services: + # PORT 9099 prometheus: image: prom/prometheus:latest container_name: prometheus @@ -9,6 +10,7 @@ services: - monitoring_net - caddy_net + # PORT 9100 node_exporter: image: prom/node-exporter:latest container_name: node-exporter diff --git a/web/install_caddy.sh b/web/install_caddy.sh index b99954d..ac5d8c3 100644 --- a/web/install_caddy.sh +++ b/web/install_caddy.sh @@ -3,14 +3,24 @@ function install_caddy() { REPO_URL="https://raw.githubusercontent.com/elAgala/server-initializer/master" - TEMPLATE_PATH="/templates/caddy" + TEMPLATE_PATH="/templates/caddy/full" + username="$1" - caddy_dir="/home/$username/caddy" + caddy_dir="/home/$username/web-server" echo "[ WEB ]: Starting Caddy setup" mkdir -p "$caddy_dir" - mkdir -p "$caddy_dir/settings" + mkdir -p "$caddy_dir/crowdsec" + mkdir -p "$caddy_dir/caddy" + mkdir -p "$caddy_dir/caddy/coraza" + wget "$REPO_URL/$TEMPLATE_PATH/docker-compose.yml" -O "$caddy_dir/docker-compose.yml" - wget "$REPO_URL/$TEMPLATE_PATH/Caddyfile" -O "$caddy_dir/settings/Caddyfile" + wget "$REPO_URL/$TEMPLATE_PATH/caddy/Caddyfile" -O "$caddy_dir/caddy/Caddyfile" + wget "$REPO_URL/$TEMPLATE_PATH/caddy/coraza/coraza_rules.conf" -O "$caddy_dir/caddy/coraza/coraza_rules.conf" + wget "$REPO_URL/$TEMPLATE_PATH/crowdsec/acquis.yaml" -O "$caddy_dir/crowdsec/acquis.yaml" + echo "[ WEB ]: Caddy setup succesfully. You can find the Caddyfile under /home/$username/caddy/settings" + echo "[ WEB ]: Do not forget to update the .env file located under $caddy_dir" + docker network create caddy_net + echo "[ WEB ]: Created caddy intranet 'caddy_net'" }