Skip to content

Instantly share code, notes, and snippets.

@horacioibrahim
Created August 10, 2025 11:30
Show Gist options
  • Select an option

  • Save horacioibrahim/bb1fdf3db3fa8dc1891f0ef9af9264bb to your computer and use it in GitHub Desktop.

Select an option

Save horacioibrahim/bb1fdf3db3fa8dc1891f0ef9af9264bb to your computer and use it in GitHub Desktop.
harden-nginx-drop-ip.sh
#!/usr/bin/env bash
# curl -fsSL https://example.com/harden-nginx-drop-ip.sh -o harden-nginx-drop-ip.sh
# sudo bash harden-nginx-drop-ip.sh
set -euo pipefail
SITES_AVAIL="/etc/nginx/sites-available"
SITES_ENABL="/etc/nginx/sites-enabled"
SELF_DIR="/etc/nginx/selfsigned"
WEBROOT="/var/www/certbot"
HTTP_DROP="${SITES_AVAIL}/00-drop-ip-http"
HTTPS_DROP="${SITES_AVAIL}/00-drop-ip-https"
SELF_KEY="${SELF_DIR}/default.key"
SELF_CRT="${SELF_DIR}/default.crt"
log(){ printf "\033[1;34m›\033[0m %s\n" "$*"; }
ok(){ printf "\033[1;32m✔\033[0m %s\n" "$*"; }
err(){ printf "\033[1;31m✖ %s\033[0m\n" "$*" >&2; }
require_root(){
if [[ ${EUID:-$(id -u)} -ne 0 ]]; then
err "Rode como root: sudo $0"
exit 1
fi
}
ensure_pkgs(){
# nginx e openssl costumam já estar, mas garantimos
apt-get update -y >/dev/null
apt-get install -y nginx openssl >/dev/null
}
disable_default_site(){
if [[ -e "${SITES_ENABL}/default" ]]; then
log "Removendo sites-enabled/default…"
rm -f "${SITES_ENABL}/default"
ok "default desabilitado."
else
log "default já não está habilitado — ok."
fi
}
write_http_drop(){
log "Escrevendo ${HTTP_DROP}…"
cat > "${HTTP_DROP}" <<'EOF'
server {
listen 80 default_server;
server_name _;
# ACME webroot (Let's Encrypt HTTP-01)
location ^~ /.well-known/acme-challenge/ {
root /var/www/certbot;
default_type "text/plain";
}
# Demais requisições para IP cru: derruba
location / { return 444; }
}
EOF
ln -sf "${HTTP_DROP}" "${SITES_ENABL}/00-drop-ip-http"
ok "HTTP drop criado/atualizado."
}
gen_selfsigned(){
mkdir -p "${SELF_DIR}"
if [[ -s "${SELF_KEY}" && -s "${SELF_CRT}" ]]; then
log "Self-signed já existe — pulando geração."
return
fi
log "Gerando certificado self-signed (RSA 2048, 825 dias)…"
openssl req -x509 -nodes -days 825 -newkey rsa:2048 \
-keyout "${SELF_KEY}" -out "${SELF_CRT}" \
-subj "/CN=localhost" >/dev/null 2>&1
chmod 600 "${SELF_KEY}"
ok "Self-signed gerado em ${SELF_DIR}."
}
write_https_drop(){
log "Escrevendo ${HTTPS_DROP}…"
cat > "${HTTPS_DROP}" <<EOF
server {
listen 443 ssl default_server;
http2 on;
server_name _;
ssl_certificate ${SELF_CRT};
ssl_certificate_key ${SELF_KEY};
# Derruba imediatamente conexões no IP cru
return 444;
}
EOF
ln -sf "${HTTPS_DROP}" "${SITES_ENABL}/00-drop-ip-https"
ok "HTTPS drop criado/atualizado."
}
harden_server_tokens(){
# Desliga o banner "nginx" nas respostas
if grep -q '^\s*server_tokens' /etc/nginx/nginx.conf; then
sed -i 's/^\s*server_tokens\s\+.*;/server_tokens off;/' /etc/nginx/nginx.conf
else
# insere no bloco http { } se não existir
awk '
BEGIN{inserted=0}
/http\s*{/ && !inserted { print; print " server_tokens off;"; inserted=1; next }
{ print }
' /etc/nginx/nginx.conf > /etc/nginx/nginx.conf.tmp && mv /etc/nginx/nginx.conf.tmp /etc/nginx/nginx.conf
fi
ok "server_tokens off configurado."
}
reload_nginx(){
log "Validando configuração…"
nginx -t
log "Recarregando nginx…"
systemctl reload nginx
ok "Nginx recarregado."
}
ensure_webroot(){
mkdir -p "${WEBROOT}/.well-known/acme-challenge"
ok "Webroot ACME pronto em ${WEBROOT}."
}
######## main
require_root
ensure_pkgs
disable_default_site
ensure_webroot
write_http_drop
gen_selfsigned
write_https_drop
harden_server_tokens
reload_nginx
echo
ok "Pronto! IP em 80/443 agora não serve conteúdo (80 só ACME; 443 drop com self-signed)."
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment