En Debian y Ubuntu, Nginx registra en /var/log/nginx/access.log y error.log, y Apache en /var/log/apache2/access.log y error.log. En RHEL, Rocky y Alma, Apache utiliza /var/log/httpd/access_log y error_log, con guiones bajos y sin extensión. En contenedores construidos a partir de la imagen oficial de Nginx, no hay archivos de registro: todo se envía a stdout y stderr, por lo que docker logs es tu exportación.
El registro del servidor web es a menudo el primer lugar donde una intrusión deja un rastro: el escáner barrido en busca de archivos .env, la cadena de explotación, el POST a un archivo que no debería existir. Prime Core tiene 812 reglas de detección para registros de servidores web, mapeadas a 337 técnicas MITRE ATT&CK. Entre ellas: explotación de aplicaciones expuestas a Internet (T1190), web shells (T1505.003) y escaneo de vulnerabilidades (T1595.002).
Antes de empezar
Encuentra las rutas reales. Los hosts virtuales a menudo registran en ubicaciones personalizadas. Pregunta al propio servidor:
# Nginx: extrae la configuración efectiva completa y selecciona las directivas de registro
sudo nginx -T 2>/dev/null | grep -E 'access_log|error_log'
# Apache
sudo apachectl -S
sudo grep -Ri -E 'CustomLog|ErrorLog' /etc/apache2/ /etc/httpd/ 2>/dev/null
En Apache basado en Debian, los hosts virtuales sin su propio CustomLog terminan en other_vhosts_access.log. La gente olvida ese todo el tiempo.
Verifica de quién estás registrando la IP. Detrás de un balanceador de carga, CDN o proxy inverso, cada solicitud puede parecer provenir del proxy. Eso sucede a menos que el servidor esté configurado para registrar el cliente real: set_real_ip_from y real_ip_header en Nginx, mod_remoteip en Apache. Si cada línea muestra las mismas pocas IP internas, la dirección del atacante solo está en X-Forwarded-For, si la registras, o en los registros del propio proxy.
Verifica el formato. Ambos servidores tienen como predeterminado el formato “combinado”, pero muchas configuraciones lo personalizan (log_format en Nginx, LogFormat en Apache). Nota cómo luce el tuyo antes de subirlo.
Permisos. En Debian y Ubuntu, estos registros son legibles por root y el grupo adm; en otros lugares, planifica usar sudo.
Exporta desde archivos de registro
Los registros rotan diariamente o semanalmente, así que incluye los archivos rotados. zcat -f lee archivos normales y comprimidos por igual:
# Nginx, actual y rotado, el más antiguo primero
sudo zcat -f $(ls -tr /var/log/nginx/access.log*) > web-03_nginx_access.log
# Apache en RHEL
sudo zcat -f $(ls -tr /var/log/httpd/access_log*) > web-03_httpd_access.lo
Para un solo día, las marcas de tiempo en formato combinado hacen que grep sea suficiente:
grep '19/Oct/2026' web-03_nginx_access.log > web-03_access_1019.log
Toma también el registro de errores. Fallos aguas arriba, errores de PHP y algunos intentos de explotación solo aparecen allí.
Exportar desde contenedores
# Docker: stdout es el registro de acceso, stderr es el registro de errores
docker logs --since 2026-10-19T00:00:00 --until 2026-10-20T00:00:00 nginx > nginx_access.log 2> nginx_error.log
# Kubernetes
kubectl logs deploy/nginx --since=24h > nginx.log
Los registros de contenedores desaparecen con el contenedor a menos que algo los recoja. Si el pod fue reemplazado, revisa el recolector de registros de tu clúster en su lugar.
Qué buscar
| Patrón | Lo que generalmente significa |
|---|---|
| Explosiones de 404s para /.env, /.git/config, /wp-login.php, /phpmyadmin | Escaneo automatizado |
| ../, ${jndi:, union select, <script> en la URL | Intentos de explotación: traversal, Log4Shell, inyección SQL, XSS |
| 200 en un POST a un archivo extraño en un directorio de subida | Posible web shell; mira qué más solicitó esa IP |
| Agentes de usuario como sqlmap, nikto, nuclei | Herramientas que no se molestaron en ocultarse |
| Un pico de 5xx justo después de solicitudes extrañas | Algo se rompió, posiblemente porque un exploit hizo efecto |
Sube, sanitiza y revisa en LogTotal
- Subir. Abre logtotal.com y suelta el archivo.
- Sanitizar. [what gets masked: client IPs, hostnames, usernames and tokens in URLs]. Look it over before you continue. Query strings often carry session tokens.
- Revisar.
Cuando sale mal
| Síntoma | Causa probable | Fix |
|---|---|---|
| No /var/log/nginx | Ruta personalizada, o se ejecuta en un contenedor | nginx -T, o docker logs |
| access.log existe pero está vacío | Los registros van a stdout, o access_log está desactivado | Revisa la configuración y el contenedor |
| Cada solicitud proviene de las mismas IPs | Proxy o balanceador de carga delante; IP real no configurada | Usa X-Forwarded-For o los registros del proxy |
| Solo los últimos días | Archivos rotados dejados fuera | Usa el comando zcat -f con el * glob |
| Permiso denegado | No root, no en adm | sudo |
FAQ
¿Qué importa más, el registro de acceso o el registro de errores?
El registro de acceso te dice qué se solicitó. El registro de errores te dice qué se rompió. En un caso de explotación, quieres ambos, lado a lado.
¿Qué pasa con IIS?
IIS escribe logs W3C en C:inetpublogsLogFiles por defecto. Eso tiene su propia guía.