Hardening de Apache y Nginx
El hardening de servidores web es una práctica de seguridad crítica que protege tu infraestructura de ciberataques, violaciones de datos y acceso no autorizado. Tanto Apache como Nginx son servidores web potentes, pero sus configuraciones predeterminadas a menudo priorizan la facilidad de uso sobre la seguridad. Esta guía completa cubre técnicas esenciales de hardening para Apache y Nginx, ayudándote a construir una postura de seguridad robusta que proteja tus aplicaciones, datos y usuarios de amenazas en evolución.
El hardening de servidores implica implementar múltiples capas de controles de seguridad incluyendo ocultar información del servidor, restringir acceso, deshabilitar características innecesarias, implementar protocolos de comunicación seguros y configurar permisos de archivos apropiados. Ya sea que estés ejecutando plataformas de comercio electrónico, sitios web corporativos o servicios de API, el hardening apropiado del servidor web es fundamental para tu estrategia de seguridad general y requisitos de cumplimiento.
Tabla de Contenidos
- Prerequisitos
- Comprendiendo el Hardening de Servidores Web
- Hardening de Apache
- Hardening de Nginx
- Medidas de Seguridad Comunes
- Hardening SSL/TLS
- Control de Acceso
- Cabeceras de Seguridad
- Verificación y Pruebas
- Solución de Problemas
- Mejores Prácticas
- Conclusión
Prerequisitos
Antes de hardening de tus servidores web, asegúrate de tener:
- Sistema Operativo: Ubuntu 20.04/22.04, Debian 10/11, CentOS 8/Rocky Linux 8, o similar
- Servidor Web: Apache 2.4+ o Nginx 1.18+ instalado y en ejecución
- Acceso root o sudo: Requerido para modificar configuraciones de sistema y servidor
- Respaldo: Respaldo completo de archivos de configuración actuales
- Certificado SSL/TLS: Certificado SSL válido para implementación HTTPS
- Conocimiento básico: Comprensión de HTTP, configuración de servidores web y administración Linux
- Entorno de pruebas: Recomendado para probar cambios antes de aplicar en producción
Comprendiendo el Hardening de Servidores Web
¿Qué es el Hardening de Servidores Web?
El hardening de servidores web es el proceso de mejorar la seguridad del servidor reduciendo su superficie de ataque, eliminando servicios innecesarios, implementando controles de seguridad y siguiendo mejores prácticas de seguridad. El objetivo es minimizar vulnerabilidades que los atacantes podrían explotar.
Objetivos clave:
- Minimizar la superficie de ataque deshabilitando características innecesarias
- Implementar el principio de mínimo privilegio
- Cifrar datos en tránsito con SSL/TLS fuerte
- Ocultar información del servidor de los atacantes
- Implementar controles de acceso y autenticación
- Monitorear y registrar eventos de seguridad
- Mantener el software actualizado con parches de seguridad
Vulnerabilidades Comunes de Servidores Web
Divulgación de información: Información de versión del servidor y configuración expuesta SSL/TLS débil: Protocolos obsoletos y suites de cifrado débiles Directory traversal: Acceso no autorizado al sistema de archivos Clickjacking: Embedding malicioso en iframe Cross-Site Scripting (XSS): Inyección de scripts del lado del cliente Ataques DDoS: Ataques de agotamiento de recursos Mala configuración: Configuraciones predeterminadas inseguras Software obsoleto: Vulnerabilidades conocidas en versiones antiguas
Hardening de Apache
Ocultar Versión y SO de Apache
Prevenir divulgación de información ocultando detalles del servidor:
# Edit Apache security configuration
sudo nano /etc/apache2/conf-available/security.conf
Agregar o modificar:
# Hide Apache version
ServerTokens Prod
# Hide server signature
ServerSignature Off
# Disable TRACE HTTP method (prevents XST attacks)
TraceEnable Off
Habilitar configuración y reiniciar:
sudo a2enconf security
sudo systemctl restart apache2
Deshabilitar Módulos Innecesarios
Reducir superficie de ataque deshabilitando módulos no utilizados:
# List enabled modules
apache2ctl -M
# Disable unnecessary modules
sudo a2dismod status # Server status
sudo a2dismod userdir # User directories
sudo a2dismod autoindex # Directory listing
sudo a2dismod cgi # CGI execution
sudo a2dismod dav # WebDAV
sudo a2dismod dav_fs # WebDAV filesystem
# Keep only essential modules:
# - ssl (for HTTPS)
# - rewrite (for URL rewriting)
# - headers (for security headers)
# - expires (for caching)
# Restart Apache
sudo systemctl restart apache2
Permisos y Opciones de Directorio
Configurar permisos estrictos de directorio:
# Edit main configuration or virtual host
sudo nano /etc/apache2/apache2.conf
# Default restrictive policy
<Directory />
Options None
AllowOverride None
Require all denied
</Directory>
# Web root configuration
<Directory /var/www/html>
# Disable directory listing
Options -Indexes -Includes -ExecCGI
# Allow symbolic links (if needed)
# Options +FollowSymLinks
# Disable .htaccess if not needed (better performance)
AllowOverride None
# Or allow specific overrides only
# AllowOverride FileInfo AuthConfig
# Access control
Require all granted
# Limit HTTP methods
<LimitExcept GET POST HEAD>
Require all denied
</LimitExcept>
</Directory>
# Protect sensitive files
<FilesMatch "^\.ht">
Require all denied
</FilesMatch>
# Protect backup and config files
<FilesMatch "\.(bak|config|sql|fla|psd|ini|log|sh|inc|swp|dist)$">
Require all denied
</FilesMatch>
Limitar Tamaño de Peticiones
Prevenir ataques DoS limitando tamaños de peticiones:
sudo nano /etc/apache2/apache2.conf
# Limit request body size (10MB example)
LimitRequestBody 10485760
# Limit request field size
LimitRequestFieldSize 8190
# Limit number of request fields
LimitRequestFields 100
# Limit request line size
LimitRequestLine 8190
# Timeout configurations
Timeout 60
KeepAliveTimeout 5
Configurar ModSecurity (Web Application Firewall)
Instalar y configurar ModSecurity:
# Install ModSecurity
sudo apt install libapache2-mod-security2 -y
# Enable module
sudo a2enmod security2
# Copy recommended configuration
sudo cp /etc/modsecurity/modsecurity.conf-recommended /etc/modsecurity/modsecurity.conf
# Edit configuration
sudo nano /etc/modsecurity/modsecurity.conf
# Enable ModSecurity
SecRuleEngine On
# Set audit log
SecAuditEngine RelevantOnly
SecAuditLogRelevantStatus "^(?:5|4(?!04))"
SecAuditLogParts ABIJDEFHZ
SecAuditLogType Serial
SecAuditLog /var/log/apache2/modsec_audit.log
# Request body access
SecRequestBodyAccess On
SecRequestBodyLimit 13107200
SecRequestBodyNoFilesLimit 131072
# Response body access
SecResponseBodyAccess On
SecResponseBodyLimit 524288
Instalar OWASP Core Rule Set:
# Download OWASP CRS
cd /tmp
wget https://github.com/coreruleset/coreruleset/archive/v3.3.4.tar.gz
tar -xvzf v3.3.4.tar.gz
sudo mv coreruleset-3.3.4 /etc/modsecurity/crs
cd /etc/modsecurity/crs
sudo cp crs-setup.conf.example crs-setup.conf
# Load CRS rules
sudo nano /etc/apache2/mods-enabled/security2.conf
Agregar:
IncludeOptional /etc/modsecurity/*.conf
IncludeOptional /etc/modsecurity/crs/crs-setup.conf
IncludeOptional /etc/modsecurity/crs/rules/*.conf
# Restart Apache
sudo systemctl restart apache2
Configuración de Usuario y Grupo
Ejecutar Apache con mínimos privilegios:
# Edit Apache configuration
sudo nano /etc/apache2/envvars
# Use dedicated non-privileged user
export APACHE_RUN_USER=www-data
export APACHE_RUN_GROUP=www-data
Establecer propiedad de archivos apropiada:
# Set ownership of web files
sudo chown -R www-data:www-data /var/www/html
# Set directory permissions (755)
sudo find /var/www/html -type d -exec chmod 755 {} \;
# Set file permissions (644)
sudo find /var/www/html -type f -exec chmod 644 {} \;
Hardening de Nginx
Ocultar Versión de Nginx
Prevenir divulgación de información de versión:
# Edit main Nginx configuration
sudo nano /etc/nginx/nginx.conf
http {
# Hide Nginx version
server_tokens off;
# Additional headers will be configured per server block
}
Deshabilitar Módulos Innecesarios
Nginx es modular; compilar solo módulos necesarios o usar módulos dinámicos:
# Check compiled modules
nginx -V 2>&1 | grep -o with-[a-z_-]*
# For custom builds, recompile without unnecessary modules
# Example: ./configure --without-http_autoindex_module --without-http_ssi_module
Configurar Bloques de Servidor de Forma Segura
Implementar configuración segura de bloques de servidor:
sudo nano /etc/nginx/sites-available/default
server {
listen 80;
server_name example.com www.example.com;
# Redirect to HTTPS
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name example.com www.example.com;
root /var/www/html;
index index.html index.php;
# Hide Nginx version
server_tokens off;
# Security headers (will configure later)
include /etc/nginx/snippets/security-headers.conf;
# SSL configuration (will configure later)
include /etc/nginx/snippets/ssl-params.conf;
# Disable unwanted HTTP methods
if ($request_method !~ ^(GET|HEAD|POST)$ ) {
return 405;
}
# Limit request size
client_max_body_size 10M;
client_body_buffer_size 128k;
# Timeouts
client_body_timeout 10s;
client_header_timeout 10s;
keepalive_timeout 5s 5s;
send_timeout 10s;
# Disable directory listing
autoindex off;
# Protect sensitive files
location ~ /\. {
deny all;
access_log off;
log_not_found off;
}
# Protect backup and config files
location ~* \.(bak|config|sql|fla|psd|ini|log|sh|inc|swp|dist)$ {
deny all;
}
# Main location
location / {
try_files $uri $uri/ =404;
}
# PHP processing (if needed)
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
# Security for PHP
fastcgi_param PHP_VALUE "open_basedir=/var/www/html:/tmp";
fastcgi_param PHP_ADMIN_VALUE "disable_functions=exec,passthru,shell_exec,system";
}
# Deny access to uploads directory PHP execution
location ~* /uploads/.*\.php$ {
deny all;
}
# Static files caching
location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|woff|woff2|ttf|eot)$ {
expires 30d;
add_header Cache-Control "public, immutable";
}
# Logs
access_log /var/log/nginx/example.com-access.log;
error_log /var/log/nginx/example.com-error.log;
}
Limitación de Tasa
Implementar limitación de tasa para prevenir abuso:
sudo nano /etc/nginx/nginx.conf
http {
# Define rate limit zones
limit_req_zone $binary_remote_addr zone=general:10m rate=10r/s;
limit_req_zone $binary_remote_addr zone=login:10m rate=5r/m;
limit_req_zone $binary_remote_addr zone=api:10m rate=100r/s;
# Connection limits
limit_conn_zone $binary_remote_addr zone=conn_limit:10m;
# In server block:
server {
# Apply general rate limit
limit_req zone=general burst=20 nodelay;
limit_conn conn_limit 10;
# Login endpoint with stricter limits
location = /login {
limit_req zone=login burst=5 nodelay;
}
# API with higher limits
location /api/ {
limit_req zone=api burst=50 nodelay;
}
}
}
Protección contra Desbordamiento de Buffer
Configurar tamaños de buffer para prevenir ataques de desbordamiento:
http {
# Buffer size for POST submissions
client_body_buffer_size 128k;
client_max_body_size 10m;
# Buffer size for request headers
client_header_buffer_size 1k;
large_client_header_buffers 4 16k;
# Connection settings
client_body_timeout 10s;
client_header_timeout 10s;
send_timeout 10s;
# Keep-alive settings
keepalive_timeout 5s 5s;
keepalive_requests 100;
}
Configuración de Usuario y Grupo
Ejecutar Nginx con privilegios mínimos:
# Edit main configuration
sudo nano /etc/nginx/nginx.conf
# Run as non-privileged user
user www-data;
# Worker processes (set to auto or number of CPU cores)
worker_processes auto;
# Worker connections
events {
worker_connections 1024;
}
Establecer permisos de archivo apropiados:
# Set ownership
sudo chown -R www-data:www-data /var/www/html
# Set directory permissions
sudo find /var/www/html -type d -exec chmod 755 {} \;
# Set file permissions
sudo find /var/www/html -type f -exec chmod 644 {} \;
Medidas de Seguridad Comunes
Implementar Fail2Ban
Proteger contra ataques de fuerza bruta:
# Install Fail2Ban
sudo apt install fail2ban -y
# Create local configuration
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
sudo nano /etc/fail2ban/jail.local
[DEFAULT]
bantime = 3600
findtime = 600
maxretry = 5
destemail = [email protected]
sendername = Fail2Ban
action = %(action_mwl)s
# Apache jail
[apache-auth]
enabled = true
port = http,https
logpath = /var/log/apache*/*error.log
[apache-badbots]
enabled = true
port = http,https
logpath = /var/log/apache*/*access.log
[apache-noscript]
enabled = true
port = http,https
logpath = /var/log/apache*/*error.log
# Nginx jail
[nginx-http-auth]
enabled = true
port = http,https
logpath = /var/log/nginx/*error.log
[nginx-limit-req]
enabled = true
port = http,https
logpath = /var/log/nginx/*error.log
[nginx-botsearch]
enabled = true
port = http,https
logpath = /var/log/nginx/*access.log
maxretry = 2
# Restart Fail2Ban
sudo systemctl restart fail2ban
# Check status
sudo fail2ban-client status
Mantener Software Actualizado
Actualizar regularmente el software del servidor web:
# Ubuntu/Debian
sudo apt update
sudo apt upgrade apache2 nginx -y
# CentOS/Rocky Linux
sudo dnf update httpd nginx -y
# Enable automatic security updates
sudo apt install unattended-upgrades -y
sudo dpkg-reconfigure -plow unattended-upgrades
Deshabilitar Servicios Innecesarios
Eliminar o deshabilitar servicios no utilizados:
# List running services
systemctl list-units --type=service --state=running
# Disable unnecessary services (examples)
sudo systemctl stop telnet.socket
sudo systemctl disable telnet.socket
# Only run required web server
# If running Nginx, stop Apache and vice versa
Hardening SSL/TLS
Generar Parámetros DH Fuertes
# Generate 4096-bit DH parameters (takes several minutes)
sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 4096
Configuración SSL de Apache
sudo nano /etc/apache2/mods-available/ssl.conf
<IfModule mod_ssl.c>
# Enable SSL
SSLEngine on
# Modern SSL protocols only
SSLProtocol -all +TLSv1.2 +TLSv1.3
# Strong cipher suites
SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384
SSLHonorCipherOrder off
# SSL compression (disable to prevent CRIME attack)
SSLCompression off
# SSL session cache
SSLSessionCache shmcb:/var/cache/apache2/ssl_scache(512000)
SSLSessionCacheTimeout 300
# Disable SSL session tickets
SSLSessionTickets off
# OCSP Stapling
SSLUseStapling on
SSLStaplingCache shmcb:/var/cache/apache2/stapling_cache(128000)
# DH parameters
SSLOpenSSLConfCmd DHParameters /etc/ssl/certs/dhparam.pem
</IfModule>
Configuración SSL de Nginx
Crear snippet de configuración SSL:
sudo nano /etc/nginx/snippets/ssl-params.conf
# SSL certificates
ssl_certificate /etc/ssl/certs/example.com.crt;
ssl_certificate_key /etc/ssl/private/example.com.key;
# SSL protocols
ssl_protocols TLSv1.2 TLSv1.3;
# SSL ciphers
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384';
ssl_prefer_server_ciphers off;
# SSL session cache
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_session_tickets off;
# DH parameters
ssl_dhparam /etc/ssl/certs/dhparam.pem;
# OCSP Stapling
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
Control de Acceso
Control de Acceso Basado en IP
Apache:
<Directory /var/www/html/admin>
<RequireAll>
Require ip 192.168.1.0/24
Require ip 10.0.0.100
</RequireAll>
</Directory>
Nginx:
location /admin {
allow 192.168.1.0/24;
allow 10.0.0.100;
deny all;
}
Autenticación Básica
Apache:
# Create password file
sudo htpasswd -c /etc/apache2/.htpasswd admin
# Configure protection
sudo nano /etc/apache2/sites-available/example.conf
<Directory /var/www/html/admin>
AuthType Basic
AuthName "Admin Area"
AuthUserFile /etc/apache2/.htpasswd
Require valid-user
</Directory>
Nginx:
# Create password file
sudo htpasswd -c /etc/nginx/.htpasswd admin
# Configure protection
sudo nano /etc/nginx/sites-available/example
location /admin {
auth_basic "Admin Area";
auth_basic_user_file /etc/nginx/.htpasswd;
}
Cabeceras de Seguridad
Cabeceras de Seguridad de Apache
sudo nano /etc/apache2/conf-available/security-headers.conf
<IfModule mod_headers.c>
# HTTP Strict Transport Security
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
# Prevent clickjacking
Header always set X-Frame-Options "SAMEORIGIN"
# Prevent MIME sniffing
Header always set X-Content-Type-Options "nosniff"
# XSS Protection
Header always set X-XSS-Protection "1; mode=block"
# Referrer Policy
Header always set Referrer-Policy "strict-origin-when-cross-origin"
# Content Security Policy
Header always set Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline';"
# Permissions Policy
Header always set Permissions-Policy "geolocation=(), microphone=(), camera=()"
# Remove server information
Header unset Server
Header unset X-Powered-By
</IfModule>
sudo a2enconf security-headers
sudo systemctl reload apache2
Cabeceras de Seguridad de Nginx
sudo nano /etc/nginx/snippets/security-headers.conf
# HTTP Strict Transport Security
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
# Prevent clickjacking
add_header X-Frame-Options "SAMEORIGIN" always;
# Prevent MIME sniffing
add_header X-Content-Type-Options "nosniff" always;
# XSS Protection
add_header X-XSS-Protection "1; mode=block" always;
# Referrer Policy
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
# Content Security Policy
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline';" always;
# Permissions Policy
add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always;
Incluir en bloque de servidor:
server {
include /etc/nginx/snippets/security-headers.conf;
}
Verificación y Pruebas
Verificar Configuración SSL
# Test with SSL Labs
# https://www.ssllabs.com/ssltest/
# Check locally with openssl
openssl s_client -connect example.com:443 -tls1_2
# Check certificates
openssl x509 -in /etc/ssl/certs/example.com.crt -text -noout
Validación de Cabeceras de Seguridad
# Check headers with curl
curl -I https://example.com
# Or use online tools:
# Security Headers: https://securityheaders.com
# Mozilla Observatory: https://observatory.mozilla.org
Escaneo de Vulnerabilidades
# Install Nikto web scanner
sudo apt install nikto -y
# Scan web server
nikto -h https://example.com
# Install and run nmap
sudo apt install nmap -y
nmap -sV -p 80,443 example.com
Solución de Problemas
Errores 403 Forbidden
Causa: Permisos o controles de acceso demasiado restrictivos
Solución:
# Check file permissions
ls -la /var/www/html
# Fix permissions
sudo chown -R www-data:www-data /var/www/html
sudo find /var/www/html -type d -exec chmod 755 {} \;
sudo find /var/www/html -type f -exec chmod 644 {} \;
# Check Apache/Nginx error logs
sudo tail -f /var/log/apache2/error.log
sudo tail -f /var/log/nginx/error.log
Problemas de Certificado SSL
Solución:
# Check certificate validity
openssl x509 -in /etc/ssl/certs/example.com.crt -noout -dates
# Verify certificate chain
openssl verify -CAfile /etc/ssl/certs/chain.pem /etc/ssl/certs/example.com.crt
# Check SSL configuration
apache2ctl configtest
nginx -t
Limitación de Tasa Demasiado Agresiva
Solución:
# Adjust Nginx rate limits
limit_req zone=general burst=50 nodelay; # Increase burst
# Or increase rate
limit_req_zone $binary_remote_addr zone=general:10m rate=20r/s;
Mejores Prácticas
- Defensa en Profundidad: Implementar múltiples capas de seguridad
- Principio de Mínimo Privilegio: Otorgar permisos mínimos necesarios
- Actualizaciones Regulares: Mantener software actualizado con parches de seguridad
- SSL/TLS Fuerte: Usar TLS 1.2+ y cifrados fuertes
- Monitorear Logs: Revisar regularmente logs de acceso y errores
- Escaneo Automatizado: Implementar escaneo regular de vulnerabilidades
- Respaldo de Configuraciones: Mantener respaldos antes de cambios
- Probar Cambios: Verificar que las medidas de seguridad no rompan funcionalidad
- Documentación: Documentar todas las configuraciones de seguridad
- Mantenerse Informado: Seguir avisos de seguridad y mejores prácticas
Conclusión
El hardening de servidores web es esencial para proteger tu infraestructura de amenazas cibernéticas. Al implementar las medidas de seguridad descritas en esta guía—incluyendo ocultar información del servidor, configurar SSL/TLS fuerte, implementar controles de acceso, agregar cabeceras de seguridad y usar Web Application Firewalls—reduces significativamente tu superficie de ataque y mejoras tu postura de seguridad general.
Puntos clave:
- Ocultar Información: Prevenir divulgación de información sobre versión y configuración del servidor
- SSL/TLS Fuerte: Usar protocolos modernos y suites de cifrado fuertes
- Control de Acceso: Implementar restricciones basadas en IP y autenticación
- Cabeceras de Seguridad: Agregar cabeceras para prevenir ataques web comunes
- Limitación de Tasa: Proteger contra ataques de fuerza bruta y DDoS
- Actualizaciones Regulares: Mantener software actualizado con parches de seguridad
- Monitorear y Probar: Monitorear continuamente logs y probar configuraciones
La seguridad es un proceso continuo, no una tarea única. Revisa y actualiza regularmente tus configuraciones de seguridad, mantente informado sobre nuevas vulnerabilidades e implementa estrategias de defensa en profundidad para proteger tu infraestructura web efectivamente.


