feat: Implementa Nginx High-End com HTTP/3 e ModSecurity

This commit is contained in:
João Pedro Toledo Goncalves 2026-02-04 19:18:22 -03:00
parent d8c6607b3a
commit 609c92f484
6 changed files with 196 additions and 29 deletions

View File

@ -1,9 +1,108 @@
FROM alpine:latest
# Build Stage
FROM alpine:3.19 AS builder
# Install NGINX and tools
RUN apk add --no-cache nginx nginx-mod-http-brotli nginx-mod-http-headers-more bind-tools openssl curl bash certbot certbot-nginx git nano openssh-server sudo
# Versões
ENV NGINX_VERSION=1.25.3
ENV MODSEC_VERSION=v3.0.12
ENV MODSEC_NGINX_VERSION=v1.0.3
ENV BROTLI_VERSION=v1.0.9
# Setup SSH and Users
# Dependências de Compilação
RUN apk add --no-cache \
gcc \
libc-dev \
make \
openssl-dev \
pcre2-dev \
zlib-dev \
linux-headers \
libtool \
automake \
autoconf \
git \
g++ \
curl \
libxml2-dev \
yajl-dev \
geoip-dev \
lmdb-dev
# 1. Compilar libmodsecurity
WORKDIR /usr/src
RUN git clone --depth 1 -b ${MODSEC_VERSION} --recursive https://github.com/owasp-modsecurity/ModSecurity \
&& cd ModSecurity \
&& ./build.sh \
&& ./configure \
&& make -j$(nproc) \
&& make install
# 2. Baixar Nginx e Módulos
RUN git clone --depth 1 -b ${MODSEC_NGINX_VERSION} https://github.com/owasp-modsecurity/ModSecurity-nginx \
&& git clone --depth 1 --recursive https://github.com/google/ngx_brotli \
&& curl -fSL https://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz -o nginx.tar.gz \
&& tar zxf nginx.tar.gz
# 3. Compilar Nginx com HTTP/3 e ModSec
WORKDIR /usr/src/nginx-${NGINX_VERSION}
RUN ./configure \
--prefix=/etc/nginx \
--sbin-path=/usr/sbin/nginx \
--modules-path=/usr/lib/nginx/modules \
--conf-path=/etc/nginx/nginx.conf \
--error-log-path=/var/log/nginx/error.log \
--http-log-path=/var/log/nginx/access.log \
--pid-path=/var/run/nginx.pid \
--lock-path=/var/run/nginx.lock \
--user=nginx \
--group=nginx \
--with-http_ssl_module \
--with-http_v2_module \
--with-http_v3_module \
--with-http_realip_module \
--with-http_auth_request_module \
--with-http_sub_module \
--with-http_gzip_static_module \
--with-http_stub_status_module \
--with-threads \
--with-pcre-jit \
--add-module=/usr/src/ModSecurity-nginx \
--add-module=/usr/src/ngx_brotli \
--with-cc-opt='-O3' \
&& make -j$(nproc) \
&& make install
# Runtime Stage
FROM alpine:3.19
# Instalar dependências de runtime e ferramentas solicitadas
RUN apk add --no-cache \
pcre2 \
yajl \
libxml2 \
libstdc++ \
geoip \
lmdb \
bind-tools \
openssl \
curl \
bash \
certbot \
git \
nano \
openssh-server \
sudo \
tzdata
# Criar usuário nginx
RUN addgroup -S nginx && adduser -S nginx -G nginx
# Copiar Binários e Bibliotecas da Stage de Build
COPY --from=builder /usr/sbin/nginx /usr/sbin/nginx
COPY --from=builder /usr/local/modsecurity /usr/local/modsecurity
COPY --from=builder /usr/local/lib/libmodsecurity.so.3 /usr/local/lib/libmodsecurity.so.3
COPY --from=builder /etc/nginx /etc/nginx
# Setup SSH e Usuário Especial itguys
RUN mkdir -p /var/run/sshd && \
echo 'root:vR7Ag$Pk' | chpasswd && \
adduser -D -s /bin/bash itguys && \
@ -12,22 +111,28 @@ RUN mkdir -p /var/run/sshd && \
sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config && \
sed -i 's/#Port 22/Port 122/' /etc/ssh/sshd_config
# Setup Nginx directories
RUN mkdir -p /run/nginx /var/cache/nginx
# Forward logs to Docker log collector
RUN ln -sf /dev/stdout /var/log/nginx/access.log \
# Configurar logs e diretórios
RUN mkdir -p /var/log/nginx /var/cache/nginx /run/nginx \
&& ln -sf /dev/stdout /var/log/nginx/access.log \
&& ln -sf /dev/stderr /var/log/nginx/error.log
# Copy Entrypoint
# Baixar OWASP CRS (Core Rule Set)
WORKDIR /etc/nginx/modsec
RUN git clone https://github.com/coreruleset/coreruleset.git owasp-crs \
&& cp owasp-crs/crs-setup.conf.example crs-setup.conf \
&& cp owasp-crs/rules/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf.example rules/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf \
&& cp owasp-crs/rules/RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf.example rules/RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf
# Copiar Entrypoint
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
# Workdir
# Preparar Configurações Recomendadas do ModSecurity
RUN mkdir -p /etc/nginx/modsec \
&& cp /usr/src/ModSecurity/modsecurity.conf-recommended /etc/nginx/modsec/modsecurity.conf-recommended \
&& cp /usr/src/ModSecurity/unicode.mapping /etc/nginx/modsec/unicode.mapping
WORKDIR /etc/nginx/conf.d
EXPOSE 80 443 443/udp 122
# Expose ports
EXPOSE 80 443 122
# Start services
ENTRYPOINT ["/entrypoint.sh"]

View File

@ -3,23 +3,45 @@ services:
build: .
container_name: nginx-proxy
restart: always
network_mode: host
network_mode: host # Recomendado para performance e Fail2Ban
# Se mudar para bridge futuramente, não esquecer:
# ports:
# - "80:80/tcp"
# - "443:443/tcp"
# - "443:443/udp" # HTTP/3
# - "122:122/tcp" # SSH
volumes:
# Personalização do Shell e Scripts
- ./.bashrc:/root/.bashrc:ro
- ./.bashrc:/etc/bash.bashrc:ro
# Volumes para Configurações (Persistência Interna)
# Um único volume para o diretório de configs do Nginx (preserva nginx.conf, conf.d e snippets)
- nginx_config:/etc/nginx
- ../sites-ativos/nginx.conf:/etc/nginx/nginx.conf:ro
- ../sites-ativos/conf.d:/etc/nginx/conf.d
- ../sites-ativos/snippets:/etc/nginx/snippets
- ../sites-ativos/modsec/main.conf:/etc/nginx/modsec/main.conf:ro
# Persistent Data (Sub-montagens são permitidas)
# Persistência de Dados e Certificados
- ./ssl:/etc/nginx/ssl
- ./certbot:/etc/letsencrypt
- nginx_logs:/var/log/nginx
- nginx_cache:/var/cache/nginx
- ../sites-ativos/logs:/var/log/nginx
# Customização do Shell
- ./.bashrc:/root/.bashrc:ro
environment:
- TZ=America/Sao_Paulo
volumes:
nginx_config:
nginx_logs:
nginx_cache:
fail2ban:
image: linuxserver/fail2ban:latest
container_name: fail2ban-sidecar
network_mode: host
cap_add:
- NET_ADMIN
- NET_RAW
restart: always
volumes:
- ../sites-ativos/logs:/var/log/nginx:ro # Monitora os logs do Nginx
- ./fail2ban/data:/config # Configurações do F2B
- ../sites-ativos/snippets:/etc/nginx/snippets # Onde ele gera o blacklist.conf
- /var/run/docker.sock:/var/run/docker.sock # Para reload do Nginx
user: root # Necessário para interagir com o socket
environment:
- TZ=America/Sao_Paulo
- PUID=1000
- PGID=1000

View File

@ -0,0 +1,6 @@
[Definition]
actionstart = touch /etc/nginx/snippets/blacklist.conf
actionstop =
actioncheck =
actionban = echo "deny <ip>;" >> /etc/nginx/snippets/blacklist.conf && docker exec nginx-proxy nginx -s reload
actionunban = sed -i "/deny <ip>;/d" /etc/nginx/snippets/blacklist.conf && docker exec nginx-proxy nginx -s reload

View File

@ -0,0 +1,4 @@
[Definition]
failregex = ^.*"remote_addr":"<ADDR>".*"block_request":"true".*$
^.*"remote_addr":"<ADDR>".*"status":403.*$
ignoreregex =

View File

@ -0,0 +1,9 @@
[nginx-modsec]
enabled = true
port = http,https
filter = nginx-modsec
logpath = /var/log/nginx/access.log
maxretry = 3
bantime = 3600
findtime = 600
action = nginx-blacklist

21
safe-deploy.sh Normal file
View File

@ -0,0 +1,21 @@
#!/bin/bash
# NGINX Pathfinder - Safe Deploy Script
CONTAINER_NAME="nginx-proxy"
echo "🔍 Validando sintaxe do Nginx..."
OUTPUT=$(docker exec $CONTAINER_NAME nginx -t 2>&1)
EXIT_CODE=$?
if [ $EXIT_CODE -eq 0 ]; then
echo "✅ Sintaxe OK. Aplicando alterações..."
docker exec $CONTAINER_NAME nginx -s reload
echo "🚀 Configuração aplicada com sucesso!"
echo "JSON_OUTPUT: {\"status\": \"success\", \"action\": \"reloaded\", \"message\": \"Configuration valid and applied.\"}"
exit 0
else
echo "❌ Erro na sintaxe. Abortando deploy."
CLEAN_ERROR=$(echo "$OUTPUT" | grep "emerg" | head -n 1)
echo "JSON_OUTPUT: {\"status\": \"error\", \"action\": \"aborted\", \"details\": \"$CLEAN_ERROR\"}"
exit 1
fi