> For the complete documentation index, see [llms.txt](https://doc.velneo.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://doc.velneo.com/38/modulos-de-seguridad-de-apache-en-velneo-cloud.md).

# Módulos de seguridad de Apache en Velneo Cloud

### 1. Introducción

El Apache de Velneo Cloud incluye cuatro módulos de seguridad opcionales:

| Módulo                                    | Qué hace                                                                                      | Protege frente a                                                          |
| ----------------------------------------- | --------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------- |
| **Rate Limit** (`mod_ratelimit`)          | Limita la velocidad a la que se envían las respuestas                                         | Consumo excesivo de ancho de banda (descargas grandes)                    |
| **Security** (`mod_security` + OWASP CRS) | Firewall de aplicaciones web (WAF): analiza cada petición y bloquea las que contienen ataques | Inyección SQL, XSS, inclusión de ficheros, escáneres de vulnerabilidades… |
| **mod\_qos**                              | Limita las conexiones simultáneas por IP y libera hilos cuando el servidor está cargado       | Agotamiento de recursos por conexiones masivas                            |
| **mod\_evasive**                          | Bloquea temporalmente las IPs que hacen demasiadas peticiones por segundo                     | Denegación de servicio (DoS) y ataques de fuerza bruta                    |

{% hint style="warning" %}
**Los módulos están desactivados por defecto.** Actualizar a la v38 no cambia el comportamiento de ningún Apache: cada cliente decide qué módulos activa y con qué parámetros.
{% endhint %}

{% hint style="warning" %}
**Alcance:** los módulos sólo actúan sobre el tráfico web (HTTP/HTTPS) que pasa por Apache: páginas de `apache2/html`, `Location` con [vModApache](/38/velneo-vmodapache/que-es-velneo-vmodapache.md) (`/api`…) y el [httpServer](/38/velneo-vserver/servicio-https.md) del vServer. **No afectan a las conexiones de vClient con el vServer (vatps)**, que no pasan por Apache.
{% endhint %}

### 2. Buenas prácticas antes de empezar

1. **Guarda una copia de `apache2/001-default-ssl.conf`** antes de modificarlo. Si Apache no arranca, basta con restaurarla y reiniciar.
2. **Activa los módulos de uno en uno** y observa los logs unos días antes de activar el siguiente. Si activas todos a la vez y algo falla, no sabrás cuál es la causa.
3. **Orden recomendado**, de menor a mayor riesgo de bloquear a usuarios legítimos:
   1. **mod\_qos**: con la configuración base sólo actúa cuando el servidor está muy cargado.
   2. **ModSecurity en modo detección**: no bloquea nada, sólo registra.
   3. **mod\_evasive**: empieza a bloquear IPs desde el primer momento.
   4. **ModSecurity en modo bloqueo**: sólo después de revisar los falsos positivos del paso 2.
   5. **Rate Limit**: cuando lo necesites, sólo en las rutas de descarga.
4. **Haz los cambios en horario de poco uso** y comprueba la aplicación justo después.
5. **Revisa los logs** en `apache2/logs/` (accesibles por [SFTP](/38/velneo-cloud/explorador-de-archivos-cloud-sftp.md)):
   * `error.log`: mensajes de los módulos (qué se ha bloqueado y por qué).
   * `access.log`: códigos de respuesta (403 = petición bloqueada).
   * `modsec_audit.log`: detalle completo de las peticiones marcadas por ModSecurity.
6. **Ten en cuenta a los usuarios que comparten IP.** Una oficina, un hotel o una red móvil salen a Internet con una misma IP pública: para Apache son un único cliente. Los límites por IP (mod\_qos, mod\_evasive) deben dar margen para ese caso.

### 3. Activar y desactivar un módulo

#### Activar

1. Conéctate por [SFTP](/38/velneo-cloud/explorador-de-archivos-cloud-sftp.md) y abre `apache2/001-default-ssl.conf`.
2. Añade el `Include` del módulo **al principio del fichero, fuera del `<VirtualHost>`**:

   ```apache
   Include /etc/apache2/conf-available/seguridad-ratelimit.conf
   Include /etc/apache2/conf-available/seguridad-modsecurity.conf
   Include /etc/apache2/conf-available/seguridad-qos.conf
   Include /etc/apache2/conf-available/seguridad-evasive.conf
   ```

   * **URCs creadas a partir vde la v38**: estas líneas ya están en el fichero, comentadas con `#`. Basta con quitar el `#` de las que quieras activar.
   * **URCs anteriores a la v38**: tu fichero no se modifica al actualizar. Añade las líneas a mano.
3. Reinicia la [URC](/38/velneo-cloud/panel-de-control-vserver-cloud/urc.md) para que Apache cargue la nueva configuración.
4. Comprueba que la aplicación responde y revisa `apache2/logs/error.log`.

#### Desactivar

Comenta la línea `Include` del módulo con `#`, junto con las directivas de ese módulo que hayas añadido (si no, Apache no arrancará porque no reconoce la directiva), y reinicia la [URC](/38/velneo-cloud/panel-de-control-vserver-cloud/urc.md).

#### Si Apache no arranca

Normalmente se debe a una directiva mal escrita o a una directiva de un módulo que no está incluido. El motivo aparece en `apache2/logs/error.log`. Restaura la copia del fichero, reinicia y corrige el cambio.

### 4. Cómo ajustar los parámetros

Cada módulo trae una configuración base que no se puede editar, pero **cualquier parámetro se puede redefinir** en tu `001-default-ssl.conf`. Prevalece el último valor.

```apache
Include /etc/apache2/conf-available/seguridad-evasive.conf
# Mis ajustes: van DESPUÉS del Include
DOSPageCount 60
DOSSiteCount 400
```

| Módulo       | Dónde se redefine                                                                                                                             | Alcance                                                                          |
| ------------ | --------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- |
| Rate Limit   | En cada `<Location>` o `<Directory>`                                                                                                          | Sólo esa ruta                                                                    |
| ModSecurity  | Después del `Include`, dentro del `<VirtualHost>` o en los ficheros `apache2/modsecurity/crs-before.conf` y `crs-after.conf` (ver apartado 6) | Global o por `<VirtualHost>`                                                     |
| mod\_qos     | Después del `Include` o dentro del `<VirtualHost>`                                                                                            | Global o por `<VirtualHost>`                                                     |
| mod\_evasive | Después del `Include`                                                                                                                         | **Siempre global**: aunque lo pongas dentro de un `<VirtualHost>` afecta a todos |

Limitaciones:

* **Se pueden cambiar valores, pero no eliminar directivas de la configuración base.** Por eso la base sólo contiene lo que es seguro para cualquier aplicación.
* **Las directivas con varios valores se redefinen completas.** Por ejemplo, `QS_SrvMaxConnPerIP 30` conserva el segundo valor de la base (200); para cambiar los dos hay que escribir `QS_SrvMaxConnPerIP 30 0`.

### 5. Rate Limit (mod\_ratelimit)

#### Qué hace

Limita la velocidad a la que Apache envía cada respuesta. Es útil para que unas pocas descargas grandes no saturen el ancho de banda de la URC.

**El límite es por respuesta, no por usuario:** un usuario con cinco descargas simultáneas tiene cinco veces el límite. Para limitar las conexiones simultáneas de un usuario, combínalo con mod\_qos.

#### Configuración

El `Include` sólo carga el módulo; no limita nada hasta que lo aplicas a una ruta dentro del `<VirtualHost>`:

```apache
<Location /descargas>
    SetOutputFilter RATE_LIMIT
    SetEnv rate-limit 400
    SetEnv rate-initial-burst 512
</Location>
```

| Variable             | Unidad | Significado                                            |
| -------------------- | ------ | ------------------------------------------------------ |
| `rate-limit`         | KiB/s  | Velocidad máxima de cada respuesta                     |
| `rate-initial-burst` | KiB    | Cantidad que se envía sin límite al empezar (opcional) |

#### Buenas prácticas

* **Aplícalo sólo a rutas de descarga de ficheros grandes.** No lo apliques a `/` ni a tu API: las páginas y respuestas pequeñas se ralentizarían sin ningún beneficio.
* Usa `rate-initial-burst` para que los ficheros pequeños de esa ruta se descarguen de golpe y el límite sólo afecte a los grandes.

### 6. Security (mod\_security + OWASP Core Rule Set)

#### Qué hace

ModSecurity analiza cada petición con las reglas **OWASP Core Rule Set (CRS) 3.3**, el conjunto de reglas de referencia para WAF. Cada regla que detecta un indicio de ataque suma puntos; si una petición alcanza el umbral (5 puntos, lo que equivale a una detección grave), se considera ataque.

#### Configuración base

Es la configuración recomendada por el proyecto ModSecurity, con tres cambios propios de Velneo Cloud: el log de auditoría está en tu carpeta de logs, las colecciones persistentes se guardan fuera de `/tmp` y el envío de estadísticas está desactivado.

| Parámetro                    | Valor                           | Significado                                                                               |
| ---------------------------- | ------------------------------- | ----------------------------------------------------------------------------------------- |
| `SecRuleEngine`              | `DetectionOnly`                 | **Registra pero no bloquea**                                                              |
| Nivel de paranoia CRS        | 1                               | El nivel con menos falsos positivos; recomendado para empezar                             |
| Umbral de anomalías          | 5 (entrada) / 4 (salida)        | Puntos a partir de los cuales una petición o respuesta es un ataque                       |
| `SecRequestBodyLimit`        | 12,5 MB                         | Tamaño máximo de una petición con ficheros adjuntos                                       |
| `SecRequestBodyNoFilesLimit` | 128 KB                          | Tamaño máximo de una petición **sin** ficheros (JSON, formularios…)                       |
| `SecRequestBodyLimitAction`  | `Reject`                        | Las peticiones que superan esos límites se rechazan (en modo detección sólo se registran) |
| `SecResponseBodyAccess`      | `On`                            | Analiza las respuestas HTML/texto/XML hasta 512 KB para detectar fugas de datos           |
| `SecAuditLog`                | `apache2/logs/modsec_audit.log` | Detalle de las peticiones marcadas y de las respuestas 4xx (salvo 404) y 5xx              |

#### Puesta en marcha recomendada

1. **Activa el módulo en modo detección** (sólo el `Include`).
2. **Usa la aplicación con normalidad durante unos días**, incluyendo todas las funciones: altas, búsquedas, subida de ficheros, llamadas a la API…
3. **Revisa `error.log`.** Cada detección aparece como una línea `ModSecurity: Warning.` con el identificador de la regla (`[id "..."]`), su descripción (`[msg "..."]`) y la URL (`[uri "..."]`):

   ```
   ModSecurity: Warning. detected SQLi using libinjection ... [id "942100"] [msg "SQL Injection Attack Detected via libinjection"] ... [uri "/api/clientes"]
   ModSecurity: Warning. Operator GE matched 5 at TX:anomaly_score. ... [id "949110"] [msg "Inbound Anomaly Score Exceeded (Total Score: 8)"]
   ```

   Si una línea `949110` ("Inbound Anomaly Score Exceeded") corresponde a una petición legítima de tu aplicación, es un **falso positivo**: con el bloqueo activado, esa petición fallaría. Las líneas anteriores de la misma petición indican qué reglas la han provocado.
4. **Corrige los falsos positivos** (ver "Ajustar las reglas") y repite hasta que no aparezcan.
5. **Activa el bloqueo** añadiendo después del `Include`:

   ```apache
   Include /etc/apache2/conf-available/seguridad-modsecurity.conf
   SecRuleEngine On
   ```

   A partir de ahora, los ataques reciben un error 403.
6. **Comprueba que bloquea** con una petición de prueba (sustituye el dominio por el tuyo). Debe devolver `403`:

   ```
   curl -s -o /dev/null -w "%{http_code}\n" "https://misubdominio.velneo.net/?id=1%27%20OR%20%271%27=%271"
   ```

#### Peticiones grandes (API con JSON)

Con el bloqueo activado, **las peticiones sin ficheros adjuntos de más de 128 KB se rechazan** con un error 400 y esta línea en `error.log`:

```
ModSecurity: Request body no files data length is larger than the configured limit (131072).
```

Si tu API recibe JSON más grandes, amplía el límite al tamaño máximo real que esperas. No lo amplíes más de lo necesario: todo el cuerpo se carga en memoria para analizarlo.

```apache
Include /etc/apache2/conf-available/seguridad-modsecurity.conf
SecRuleEngine On
# 1 MB
SecRequestBodyNoFilesLimit 1048576
```

#### Ajustar las reglas

{% hint style="danger" %}
Nunca desactives ModSecurity entero por un falso positivo: **desactiva sólo la regla concreta y, si es posible, sólo en la ruta afectada.**
{% endhint %}

Crea la carpeta `apache2/modsecurity/` y, dentro, estos ficheros opcionales:

* **`crs-before.conf`** — se carga antes de las reglas CRS. Sirve para:
  * Excluir una regla sólo en una ruta (recomendado):

    ```apache
    # La regla 942100 no se aplica a /api/importar
    SecRule REQUEST_URI "@beginsWith /api/importar" \
        "id:1000,phase:1,pass,nolog,ctl:ruleRemoveById=942100"
    ```
  * Excluir un único parámetro de una regla (aún más preciso):

    ```apache
    # La regla 942100 no analiza el parámetro "consulta" en /api/buscar
    SecRule REQUEST_URI "@beginsWith /api/buscar" \
        "id:1001,phase:1,pass,nolog,ctl:ruleRemoveTargetById=942100;ARGS:consulta"
    ```
  * Cambiar el nivel de paranoia (más reglas y más falsos positivos; sólo si tienes experiencia con el CRS):

    ```apache
    SecAction "id:900000,phase:1,nolog,pass,t:none,setvar:tx.paranoia_level=2"
    ```
* **`crs-after.conf`** — se carga después de las reglas CRS. Sirve para desactivar una regla en todo el sitio:

  ```apache
  SecRuleRemoveById 942100
  ```

Los identificadores (`id`) de tus propias reglas deben ser únicos y estar entre 1 y 99999.

#### Buenas prácticas

* **No actives el bloqueo sin haber pasado por el modo detección.**
* **Revisa `error.log` después de cada cambio** en la aplicación: una función nueva puede disparar reglas que antes no se activaban.
* **Mantén el nivel de paranoia 1** salvo que tengas un motivo concreto y tiempo para ajustar falsos positivos.
* **Documenta cada exclusión** con un comentario (qué regla, por qué y para qué ruta).

### 7. mod\_qos

#### Qué hace

Controla las conexiones simultáneas para que uno o pocos clientes no puedan ocupar todos los hilos de Apache y dejar sin servicio al resto.

#### Configuración base

Basada en los ejemplos de la documentación de mod\_qos, adaptada a la capacidad de Apache en la URC (256 conexiones simultáneas):

| Parámetro            | Valor    | Significado                                                                                                                                         |
| -------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
| `QS_SrvMaxConnPerIP` | `50 200` | Máximo de 50 conexiones simultáneas por IP, **sólo cuando el servidor tiene 200 o más conexiones ocupadas**. Con carga normal no se limita a nadie. |
| `QS_SrvMaxConnClose` | `70%`    | Con más del 70 % de conexiones ocupadas, se cierra la conexión tras cada petición (sin keep-alive) para liberar hilos antes                         |

Cuando mod\_qos rechaza una conexión, aparece en `error.log`:

```
mod_qos(031): access denied, QS_SrvMaxConnPerIP rule: max=50, concurrent connections=51, c=<IP>
```

#### Ajustes habituales

* **Muchos usuarios detrás de una misma IP** (una oficina): sube el límite por IP.

  ```apache
  Include /etc/apache2/conf-available/seguridad-qos.conf
  QS_SrvMaxConnPerIP 150 200
  ```
* **Aplicar el límite por IP siempre**, no sólo con el servidor cargado (el segundo valor a 0):

  ```apache
  Include /etc/apache2/conf-available/seguridad-qos.conf
  QS_SrvMaxConnPerIP 50 0
  ```
* **Protección frente a conexiones lentas** (ataques tipo *slowloris*): no viene activada porque corta las conexiones de larga duración con poco tráfico, como los **websockets (`/ws`) del httpServer del vServer**. Si tu aplicación no los usa, puedes activarla:

  ```apache
  Include /etc/apache2/conf-available/seguridad-qos.conf
  QS_SrvMinDataRate 64 256 150
  ```

  Cuando hay 150 o más conexiones abiertas, cierra las que transfieren menos de 64 bytes/s. El mínimo exigido sube hasta 256 bytes/s a medida que aumenta la carga.

  Aunque no la actives, Apache ya limita el tiempo para recibir las cabeceras y el cuerpo de cada petición (`mod_reqtimeout`).

#### Buenas prácticas

* Mantén el segundo valor de `QS_SrvMaxConnPerIP` (umbral de carga) salvo que tengas un motivo: así el límite sólo actúa cuando realmente hay riesgo de agotar recursos.
* Si ves líneas `mod_qos(031)` con IPs de tus propios usuarios, sube el límite por IP.

### 8. mod\_evasive

#### Qué hace

Cuenta las peticiones de cada IP. Si una IP supera los umbrales, recibe un error 403 durante el periodo de bloqueo. **Cada petición que hace mientras está bloqueada renueva el bloqueo**, así que un atacante que insiste sigue bloqueado.

#### Configuración base

| Parámetro                          | Valor     | Significado                                              |
| ---------------------------------- | --------- | -------------------------------------------------------- |
| `DOSPageCount` / `DOSPageInterval` | 20 / 1 s  | Máximo de peticiones a **la misma URL** por IP y segundo |
| `DOSSiteCount` / `DOSSiteInterval` | 150 / 1 s | Máximo de peticiones **totales** por IP y segundo        |
| `DOSBlockingPeriod`                | 10 s      | Duración del bloqueo                                     |

Los intervalos, el periodo de bloqueo y el tamaño de la tabla interna son los del autor del módulo. Los umbrales son más altos que los de su ejemplo (2 y 50), que bloquean con facilidad a usuarios legítimos: páginas con muchos recursos, aplicaciones que consultan la API con frecuencia o usuarios que comparten IP.

Los contadores se llevan en cada proceso de Apache (hasta 4), por lo que los umbrales son aproximados: en la práctica una IP puede hacer algo más de peticiones antes de ser bloqueada.

Cuando mod\_evasive bloquea, aparece un `403` en `access.log` y en `error.log`:

```
[evasive20:error] [pid ...] [client <IP>:<puerto>] client denied by server configuration: /ruta
```

#### Ajustes habituales

* **La aplicación hace muchas peticiones seguidas a la misma URL** (una API consultada en bucle, un panel que se refresca) **o muchos usuarios comparten IP**: sube los umbrales.

  ```apache
  Include /etc/apache2/conf-available/seguridad-evasive.conf
  DOSPageCount 60
  DOSSiteCount 400
  ```
* **Excluir IPs de confianza** (tu sistema de monitorización, un servidor propio que integra con la API). Se admite `*` en los últimos bloques de la IP:

  ```apache
  Include /etc/apache2/conf-available/seguridad-evasive.conf
  DOSWhitelist 203.0.113.10
  DOSWhitelist 198.51.100.*
  ```

#### Buenas prácticas

* **No uses la lista blanca para tus usuarios.** Sólo para sistemas propios y de confianza: una IP en la lista blanca queda sin protección.
* **No lo pruebes desde la IP de tu oficina**: bloquearías a todos sus usuarios mientras dure el bloqueo.
* Tras activarlo, **busca líneas `evasive20` en `error.log`** durante unos días. Si aparecen IPs de usuarios legítimos, sube los umbrales.

### 9. Resolución de problemas

| Síntoma                                                   | Causa probable                                                   | Qué mirar                                                                                 |
| --------------------------------------------------------- | ---------------------------------------------------------------- | ----------------------------------------------------------------------------------------- |
| Apache no arranca tras un cambio                          | Directiva mal escrita, o directiva de un módulo sin su `Include` | `error.log`; restaura la copia del fichero                                                |
| Error 403 con `ModSecurity: Access denied` en `error.log` | ModSecurity ha bloqueado la petición                             | El `[id "..."]` de las líneas anteriores; si es legítima, crea una exclusión (apartado 6) |
| Error 403 con `[evasive20:error]` en `error.log`          | mod\_evasive ha bloqueado la IP                                  | Sube los umbrales o añade la IP a la lista blanca si es un sistema propio (apartado 8)    |
| Conexiones rechazadas con `mod_qos(031)` en `error.log`   | Límite de conexiones por IP                                      | Sube `QS_SrvMaxConnPerIP` (apartado 7)                                                    |
| Error 400 al enviar un JSON o formulario grande           | Límite de 128 KB de ModSecurity                                  | Amplía `SecRequestBodyNoFilesLimit` (apartado 6)                                          |
| Websockets (`/ws`) que se cortan                          | `QS_SrvMinDataRate` activado                                     | Quita esa directiva (apartado 7)                                                          |
| Descargas más lentas de lo esperado                       | Rate Limit aplicado a esa ruta                                   | Revisa los `<Location>` con `RATE_LIMIT`                                                  |

### 10. Referencias

* [Apache mod\_ratelimit](https://httpd.apache.org/docs/2.4/mod/mod_ratelimit.html)
* [ModSecurity: manual de referencia v2](https://github.com/owasp-modsecurity/ModSecurity/wiki/Reference-Manual-\(v2.x\))
* [OWASP Core Rule Set](https://coreruleset.org/docs/)
* [mod\_qos](https://mod-qos.sourceforge.net/)
* [mod\_evasive](https://github.com/jzdziarski/mod_evasive)
