Harden nginx: real client IP, HSTS, custom dotfile 404 (PT-01/02/04)
PT-01: Add set_real_ip_from/real_ip_header/real_ip_recursive to restore real client IP from X-Forwarded-For. Rate limiting now keys on actual client IP instead of the Pangolin proxy IP. PT-02: Add Strict-Transport-Security header (max-age 1 year) to both the server block and static assets block. PT-04: Replace bare 404 on dotfile requests with JSON response to suppress nginx server identity disclosure in error pages. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
ccfc5e151a
commit
7721bf5cec
@ -21,15 +21,26 @@ server {
|
||||
# Suppress nginx version in Server header
|
||||
server_tokens off;
|
||||
|
||||
# ── Real client IP restoration (PT-01) ────────────────────────────
|
||||
# Pangolin (TLS-terminating reverse proxy) connects via Docker bridge.
|
||||
# Restore the real client IP from X-Forwarded-For so that limit_req_zone
|
||||
# (which keys on $binary_remote_addr) throttles per-client, not per-proxy.
|
||||
# Safe to trust all sources: nginx is only reachable via Docker networking,
|
||||
# never directly internet-facing. Tighten if deployment model changes.
|
||||
set_real_ip_from 0.0.0.0/0;
|
||||
real_ip_header X-Forwarded-For;
|
||||
real_ip_recursive on;
|
||||
|
||||
# Gzip compression
|
||||
gzip on;
|
||||
gzip_vary on;
|
||||
gzip_min_length 1024;
|
||||
gzip_types text/plain text/css text/xml text/javascript application/x-javascript application/xml+rss application/javascript application/json;
|
||||
|
||||
# Block dotfiles (except .well-known for ACME/Let's Encrypt)
|
||||
# Block dotfiles (except .well-known for ACME/Let's Encrypt) (PT-04)
|
||||
location ~ /\.(?!well-known) {
|
||||
return 404;
|
||||
default_type application/json;
|
||||
return 404 '{"detail":"Not Found"}';
|
||||
}
|
||||
|
||||
# Rate-limited auth endpoints (keep in sync with proxy-params.conf)
|
||||
@ -104,6 +115,7 @@ server {
|
||||
add_header X-Content-Type-Options "nosniff" always;
|
||||
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
|
||||
add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; img-src 'self' data:; font-src 'self' https://fonts.gstatic.com; connect-src 'self';" always;
|
||||
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
|
||||
}
|
||||
|
||||
# Security headers
|
||||
@ -111,4 +123,5 @@ server {
|
||||
add_header X-Content-Type-Options "nosniff" always;
|
||||
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
|
||||
add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; img-src 'self' data:; font-src 'self' https://fonts.gstatic.com; connect-src 'self';" always;
|
||||
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user