Skip to main contentSkip to footer

Cabeceras de seguridad

Las cabeceras de seguridad son líneas en la respuesta de tu servidor web que le dicen al navegador qué debe rechazar: adivinar tipos de archivo, mostrar tus páginas dentro de marcos ajenos, pasar direcciones completas a otros sitios, volver a HTTP o cargar scripts de hosts desconocidos. Hive las define por ti, genera la configuración del servidor web correspondiente y comprueba lo que llega de verdad al visitante. Esta página explica cada cabecera, las tres vías que puede tomar y qué hacer cuando la comprobación señala un problema.

Qué incluye cada plan

Todos los ajustes de cabeceras están en Ajustes de protección → Cortafuegos y bots → Cabeceras de seguridad. El interruptor principal Enviar cabeceras de seguridad está desactivado tras la instalación; la recomendación del inicio rápido lo activa. Las tres cabeceras básicas forman parte del plugin gratuito. Las cabeceras avanzadas llegan con el complemento Pro a partir del plan Professional y funcionan tanto en Local Shield como en la Community Network.

CabeceraPlanValor tras la instalación
X-Content-Type-OptionsGratisnosniff
X-Frame-OptionsGratisSAMEORIGIN
Referrer-PolicyGratisstrict-origin-when-cross-origin
Strict-Transport-Security (HSTS)Desde ProfessionalDesactivado; la recomendación para Professional lo activa, sin preload
Permissions-PolicyDesde Professionalgeolocation=(), camera=(), microphone=(), payment=(), usb=(), magnetometer=()
Content-Security-PolicyDesde ProfessionalDesactivado, política vacía
Cross-Origin-Opener-Policy, -Resource-Policy, -Embedder-PolicyDesde ProfessionalDesactivado

Cada cabecera solo se envía mientras Enviar cabeceras de seguridad está activado. Cuando termina un plan, Hive deja de enviar las cabeceras avanzadas y mantiene las tres básicas. Las cabeceras que hayas copiado en la configuración del servidor web no se ven afectadas por ninguno de los dos casos: el servidor las sigue enviando hasta que las quites de allí.

Tres vías hasta el visitante

El bloque Cómo llegan las cabeceras a tus visitantes, encima de las filas de cabeceras, muestra el estado de cada vía en tu sitio.

  1. Configuración del servidor web. nginx o Apache añaden las cabeceras a cada respuesta: páginas de una caché, imágenes, archivos CSS y JavaScript, la página de acceso y las páginas de error. Es la vía más compatible. Hive genera la configuración a partir de tus ajustes.
  2. Protección ampliada. El cortafuegos que se ejecuta antes de WordPress (ver Cortafuegos y WAF) también envía las cabeceras. Alcanza las páginas que un plugin de caché entrega a través de PHP, por ejemplo desde advanced-cache.php. Solo actúa en peticiones al sitio público que pasan por index.php, no en wp-admin, y envía HSTS solo por HTTPS.
  3. Solo WordPress. Hive añade las cabeceras a cada página pública que genera WordPress. Las páginas de una caché, los archivos estáticos y todo lo que el servidor web responde por su cuenta salen sin ellas.
Tu entornoVía a usar
Sin caché de páginasBasta con WordPress. Activa las cabeceras y lanza la comprobación.
Plugin de caché que sirve las páginas a través de PHP (WP Rocket, WP Super Cache, W3 Total Cache y otros en su configuración habitual)Protección ampliada, o la configuración del servidor web
Caché servida por el servidor web sin PHP: Rocket-Nginx, reglas de reescritura estáticas en el .htaccess, una caché del panel de hostingSolo la configuración del servidor web
Quieres las cabeceras también en imágenes, archivos y la página de accesoSolo la configuración del servidor web
Hosting sin acceso a la configuración del servidorApache con .htaccess: las líneas de Apache; si no, Protección ampliada

Elijas lo que elijas, define cada cabecera en un solo lugar. Una cabecera que el servidor web añade por su cuenta es invisible para WordPress, así que Hive no puede omitirla, y entonces llega dos veces. La comprobación de cabeceras lo detecta.

Configuración paso a paso

1

Activar las cabeceras

Abre Ajustes de protección → Cortafuegos y bots → Cabeceras de seguridad, activa Enviar cabeceras de seguridad y deja las tres cabeceras básicas en sus valores recomendados. Haz clic en Guardar cambios. Todas las filas de cabeceras, el interruptor incluido, están detrás de Mostrar detalles técnicos; el modo experto las abre por defecto.

2

Añadir las cabeceras avanzadas (complemento Pro)

Activa HTTP Strict Transport Security con un max-age de HSTS (segundos) de 300 durante los primeros días. Compara la Permissions-Policy con las funciones que usa tu sitio. Pon la Content-Security-Policy en modo Solo informe, como se describe más abajo. Deja por ahora desactivadas las cabeceras Cross-Origin. Guarda.

3

Lanzar la comprobación de cabeceras

Abre Configuración del servidor y comprobación de cabeceras y haz clic en Comprobar las cabeceras de la página de inicio. Si cada fila dice Llega una vez, tal como se define aquí, la entrega está resuelta. Cualquier otro resultado se explica en La comprobación de cabeceras.

4

Cerrar el hueco en las páginas en caché

Si la comprobación muestra Falta en las páginas en caché, activa la Protección ampliada en Servidor & mantenimiento → Servidor y vuelve a comprobar. Si las cabeceras siguen faltando, tu caché entrega las páginas sin PHP; sigue con el paso 5.

5

Pasar las cabeceras al servidor web (opcional)

Copia las líneas generadas para nginx o Apache en la configuración del servidor y recarga el servidor web. Después desactiva Enviar cabeceras de seguridad en Hive y guarda. Vuelve a comprobar: cada cabecera debería mostrar ahora Definida por el servidor web u otro plugin, que es el resultado correcto para esta vía.

6

Subir HSTS y aplicar la CSP

Tras unos días sin problemas, sube el max-age de HSTS a 31536000 (un año). Pasa la Content-Security-Policy a Aplicar cuando la consola del navegador quede limpia en cada tipo de página.

Cada cabecera en detalle

CabeceraProtege contraRecomendadoPuede romper
X-Content-Type-OptionsMIME sniffing: un archivo subido que dice ser una imagen se ejecuta como scriptActivado, nosniffPrácticamente nada
X-Frame-OptionsClickjacking: un sitio ajeno muestra tu página en un marco invisible y engaña a los visitantes para que hagan clicSAMEORIGINDENY bloquea también los marcos entre tus propias páginas; cualquier valor impide la incrustación en otros dominios
Referrer-PolicyRutas y parámetros de tus direcciones filtrados a otros sitiosstrict-origin-when-cross-originno-referrer te oculta en las estadísticas de referencia de los sitios asociados
Strict-Transport-SecurityVuelta a HTTP y SSL stripping en redes abiertas300 para probar, luego 31536000Cualquier página o archivo que aún cargue por HTTP; con includeSubDomains, cualquier subdominio sin certificado válido
Permissions-PolicyFunciones del navegador usadas por un script inyectadoDesactivar lo que no usesBuscador de tiendas (geolocation), Apple Pay y Google Pay (payment), videollamadas (camera, microphone)
Content-Security-PolicyCross-site scripting y scripts inyectadosPrimero Solo informe, cada servicio externo en la lista, luego AplicarScripts del tema, seguimiento, herramienta de consentimiento, vídeos y mapas incrustados
Cross-Origin-Opener-PolicyAtaques a través de ventanas que tus páginas abren o que las abrensame-origin si no usas ventanas de acceso o de pago de otros dominiosVentanas de PayPal, Google y acceso con redes sociales
Cross-Origin-Resource-PolicyOtros sitios que cargan tus imágenes y scripts en sus páginassame-origin solo sin un nombre de host de CDNEnlaces directos y archivos que tus páginas cargan desde otro nombre de host propio, como un CDN
Cross-Origin-Embedder-PolicySolo necesaria para funciones especiales del navegador (SharedArrayBuffer, temporizadores precisos)Desactivada, salvo que un desarrollador la pidaLa mayoría del contenido de terceros incrustado: vídeos, mapas, fuentes web

Así se ven las cabeceras en una respuesta:

X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
Referrer-Policy: strict-origin-when-cross-origin
Strict-Transport-Security: max-age=31536000; includeSubDomains
Permissions-Policy: geolocation=(), camera=(), microphone=(), payment=(), usb=()
Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Resource-Policy: same-origin

HSTS. En cuanto un navegador ha visto la cabecera, se conecta solo por HTTPS durante el tiempo que indica max-age, y no puedes deshacerlo para los visitantes que ya la tienen. Actívala solo cuando cada página y cada archivo carguen por HTTPS. El valor guardado por defecto es 63072000 (dos años), que también es el límite superior; empieza con 300 (cinco minutos). HSTS includeSubDomains extiende la regla a cada subdominio, incluidos los de correo y tienda. HSTS preload pide a los navegadores que incluyan tu dominio en su lista integrada (hstspreload.org); requiere includeSubDomains y al menos un año, y salir de la lista lleva meses. Hive envía HSTS solo por HTTPS. Detrás de un proxy que termina TLS, WordPress tiene que reconocer la petición como HTTPS; si no, Hive omite HSTS.

Permissions-Policy. feature=() desactiva una función, feature=(self) la permite solo en tus propias páginas. El valor por defecto desactiva payment; una tienda con botones de Apple Pay o Google Pay necesita payment=(self) o quitar la entrada; si no, los botones no aparecen.

X-Frame-Options y la CSP. Los navegadores actuales siguen primero la directiva frame-ancestors de una Content-Security-Policy aplicada. X-Frame-Options se mantiene para navegadores antiguos; mantén ambas en la misma línea, por ejemplo SAMEORIGIN y frame-ancestors 'self'.

La Content-Security-Policy paso a paso

Una CSP es una lista de fuentes desde las que el navegador puede cargar scripts, estilos, imágenes, fuentes, marcos y conexiones. Todo lo demás se rechaza. Es la cabecera más fuerte y la que más rompe, por eso tiene dos modos: Solo informe envía la política como Content-Security-Policy-Report-Only, no se bloquea nada y cada infracción aparece en la consola del navegador. Aplicar envía Content-Security-Policy y bloquea.

  1. Empezar con la política inicial para WordPress. Pon el Modo de Content-Security-Policy en Solo informe y pega la política de abajo en Content-Security-Policy. Encaja con un sitio WordPress sin servicios externos. La mayoría de los temas necesitan 'unsafe-inline' para scripts y estilos, por eso está incluido.
  2. Abrir cada tipo de página. Página de inicio, una entrada, una página, el formulario de contacto, la tienda, el carrito y la caja, con el banner de cookies aceptado, porque el seguimiento y el contenido incrustado a menudo solo cargan tras el consentimiento. Abre la consola del navegador con F12; allí aparece cada fuente que la política no permite, con la directiva infringida.
  3. Añadir cada fuente externa a su directiva. Un host de scripts va en script-src, un host al que la página envía datos en connect-src, un marco de vídeo o mapa en frame-src, un host de fuentes en font-src. Separa las directivas con punto y coma y los hosts con espacios. Guarda, recarga y repite hasta que la consola quede limpia.
  4. Pasar a Aplicar. Pon el modo en Aplicar, abre otra vez los tipos de página y vigila formularios y caja durante unos días.

La política inicial para WordPress que trae el plugin:

default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data:; connect-src 'self'; frame-src 'self'; object-src 'none'; base-uri 'self'; form-action 'self'; frame-ancestors 'self'

Ejemplo: Google Tag Manager con Google Analytics 4. El gestor de etiquetas carga su script desde www.googletagmanager.com, y Analytics envía sus mediciones a dos familias de hosts de Google. Añádelos a script-src y connect-src:

default-src 'self'; script-src 'self' 'unsafe-inline' https://www.googletagmanager.com; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data:; connect-src 'self' https://*.google-analytics.com https://*.analytics.google.com; frame-src 'self'; object-src 'none'; base-uri 'self'; form-action 'self'; frame-ancestors 'self'

Cada etiqueta adicional del contenedor trae sus propios hosts, que la consola nombra. En la política inicial, img-src ya permite imágenes de cualquier host HTTPS, así que los píxeles de seguimiento no necesitan entrada allí. En modo Solo informe los navegadores ignoran frame-ancestors; X-Frame-Options lo cubre hasta que apliques la política.

URI de informes CSP. Opcional. Una dirección HTTPS que recibe cada infracción como informe JSON. Hive la envía como report-uri y, para navegadores actuales, como report-to csp-endpoint junto con una cabecera Reporting-Endpoints:

Content-Security-Policy-Report-Only: default-src 'self'; ...; report-uri https://example.com/csp-report; report-to csp-endpoint
Reporting-Endpoints: csp-endpoint="https://example.com/csp-report"

Privacidad: cada informe contiene la dirección IP del visitante y la dirección que visitó. Un servicio externo de informes trata por tanto datos personales por encargo tuyo, necesita un contrato de encargo de tratamiento y debe figurar en tu política de privacidad. Para la mayoría de los sitios basta con la consola del navegador durante la fase de solo informe; en ese caso deja el campo vacío.

La configuración del servidor web generada

En Configuración del servidor y comprobación de cabeceras, Hive muestra la configuración para nginx y para Apache, generada a partir de los ajustes guardados, cada una con un botón Copiar. Tras un cambio, guarda primero. Con Enviar cabeceras de seguridad desactivado no hay nada que generar: actívalo, guarda, copia y vuelve a desactivarlo cuando la configuración esté activa. Guarda una copia de las líneas, porque cada cambio posterior requiere los mismos pasos. Con las tres cabeceras básicas y HSTS, el resultado es este:

# ReportedIP Hive: security headers for nginx.
# Paste into the server { } block that serves HTTPS, then run: nginx -t && systemctl reload nginx
# A location { } block with its own add_header inherits none of these lines.
# Repeat them there, or keep them in one file and include it in both places.
# Afterwards switch off "Send security headers" in Hive, otherwise every header is sent twice.
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Strict-Transport-Security "max-age=31536000" always;
# ReportedIP Hive: security headers for Apache (.htaccess or virtual host).
# Afterwards switch off "Send security headers" in Hive, otherwise every header is sent twice.
<IfModule mod_headers.c>
	Header always set X-Content-Type-Options "nosniff"
	Header always set X-Frame-Options "SAMEORIGIN"
	Header always set Referrer-Policy "strict-origin-when-cross-origin"
	Header always set Strict-Transport-Security "max-age=31536000" "expr=%{HTTPS} == 'on'"
</IfModule>

En qué fijarse:

  • always. Sin él, nginx solo añade cabeceras a las respuestas correctas. Con él llegan también a las páginas de error y a las redirecciones.
  • Los bloques location no heredan. nginx solo pasa las líneas add_header a los bloques que no tienen ninguna propia. Un bloque location que define su propia cabecera, típicamente Cache-Control para imágenes o el bloque de caché de Rocket-Nginx, pierde todas las cabeceras de seguridad. Guarda las líneas en un archivo e inclúyelo en el bloque server y en cada uno de esos bloques location.
  • Bloque server de HTTPS. Las líneas de nginx van en el bloque que sirve el puerto 443. Un bloque que solo redirige de HTTP a HTTPS no las necesita.
  • Probar antes de recargar. nginx -t comprueba la sintaxis; recarga solo cuando indique éxito.
  • IfModule en Apache. Si falta mod_headers, Apache se salta el bloque en lugar de responder a cada petición con un error 500. La comprobación muestra entonces las cabeceras como ausentes, y el proveedor tiene que activar el módulo.
  • HSTS en Apache. La condición expr=%{HTTPS} == 'on' limita HSTS a HTTPS, así que las mismas líneas funcionan en un .htaccess que sirve ambos protocolos.
  • Desactivar después «Enviar cabeceras de seguridad». Si no, WordPress añade cada cabecera por segunda vez a las páginas que genera.

El archivo de inclusión para nginx, como ejemplo:

# /etc/nginx/snippets/security-headers.conf holds the generated add_header lines
server {
    listen 443 ssl;
    server_name example.com;
    include snippets/security-headers.conf;

    location ~* \.(css|js|jpg|jpeg|png|webp|svg|woff2)$ {
        add_header Cache-Control "public, max-age=2592000";
        include snippets/security-headers.conf;
    }
}

La comprobación de cabeceras

Comprobar las cabeceras de la página de inicio carga la página de inicio de tu sitio tres veces desde el propio servidor: dos veces como un visitante, para que la segunda petición la responda una caché de páginas si existe, y una vez con un parámetro adicional que evita la caché. Después compara lo que llega con tus ajustes. Solo se solicita tu propia dirección; no se envía nada a reportedip.com. La comprobación cubre la página de inicio; para otras páginas, archivos o la página de acceso usa la pestaña de red de las herramientas del navegador, curl -sI https://example.com/ o la herramienta gratuita Security Headers.

ResultadoSignificadoQué hacer
Llega una vez, tal como se define aquíLa cabecera llega exactamente una vez con tu valor, en la página en caché y en la que no lo está.Nada.
Falta en las páginas en cachéWordPress envía la cabecera, pero la caché de páginas entrega las páginas sin ella.Activa la Protección ampliada. Si ya está activa, tu caché funciona sin PHP: usa la configuración del servidor web.
Falta en todas las páginasHive prevé la cabecera, pero no llega ni desde la caché ni sin ella. Algo entre WordPress y el visitante la elimina, como un proxy, un CDN o la configuración del hosting, o la página de inicio no viene de WordPress.Define la cabecera en la configuración del servidor web y revisa el CDN o el proxy en busca de reglas que eliminen cabeceras de respuesta.
Enviada dos veces, por el servidor web y desde aquíLa misma cabecera llega más de una vez, normalmente porque el servidor web o el hosting la define y Hive también la envía. Los navegadores usan entonces uno de los valores o aplican ambos, lo que rara vez es lo deseado.Mantén una sola fuente: quita la cabecera del servidor o desactívala aquí. Cuando todo esté en el servidor, desactiva Enviar cabeceras de seguridad.
Llega otro valor, lo define el servidor web o un pluginLlega un valor, pero no el tuyo. El servidor web, el hosting, un CDN u otro plugin define la cabecera y se impone.Encuentra la otra fuente y decide dónde vive la cabecera. Cambia o quita el valor allí.
Definida por el servidor web u otro pluginHive no prevé esta cabecera, porque está desactivada aquí o no forma parte de tu plan, pero llega.Es lo esperado tras pasar las cabeceras al servidor web. Comprueba que el valor sea el que quieres.

En lugar de la tabla pueden aparecer otros dos mensajes:

  • «No llega ninguna cabecera de seguridad a la página de inicio, ni de WordPress ni del servidor web.» No hay nada definido en ningún sitio. Activa Enviar cabeceras de seguridad y guarda, o comprueba que la configuración del servidor esté activa.
  • «No se pudo cargar la página de inicio» con un mensaje de error. El servidor no alcanza su propia dirección: una protección con contraseña en un sitio de pruebas, un cortafuegos del hosting que bloquea las peticiones del servidor a sí mismo o un dominio que apunta a otro lugar. Comprueba entonces las cabeceras desde fuera con las herramientas citadas arriba.

El registro de Estado del sistema muestra la sugerencia A las páginas en caché les faltan las cabeceras de seguridad cuando las cabeceras están activadas, hay una caché de páginas activa y la Protección ampliada no está en marcha. Desaparece en cuanto la Protección ampliada funciona. Si usas la configuración del servidor web y has desactivado Enviar cabeceras de seguridad, no aparece.

Solución de problemas

Una cabecera llega dos veces, aunque solo la definí en Hive

Entonces el hosting también la define. Los lugares habituales son las opciones de seguridad o SSL del panel de hosting (un interruptor de HSTS es frecuente), un .htaccess escrito por otro plugin o por el proveedor, el campo de directivas de nginx del panel y reglas del CDN que añaden cabeceras. Busca allí el nombre de la cabecera, mantén una sola fuente y vuelve a comprobar.

La comprobación muestra «Falta en las páginas en caché» aunque la Protección ampliada está activa

Tu caché de páginas entrega los archivos sin PHP, por ejemplo Rocket-Nginx, reglas de reescritura estáticas o una caché de servidor del hosting. Solo la configuración del servidor web llega a esas páginas. Con Rocket-Nginx incluye el archivo de cabeceras también en sus bloques location de caché, porque definen sus propias cabeceras.

Tras el cambio, las páginas en caché siguen mostrando valores antiguos

Según el plugin, una caché de páginas guarda las cabeceras junto con la página al crear el archivo de caché. Vacía la caché de páginas y la del CDN tras cada cambio de cabeceras y vuelve a comprobar.

¿Dónde van las líneas en un panel de hosting?

Las líneas de Apache van en el .htaccess del directorio de WordPress, encima del bloque de WordPress. Los paneles con nginx suelen ofrecer por dominio un campo para directivas adicionales de nginx (en Plesk en los ajustes de Apache y nginx, en ISPConfig en la pestaña Opciones); pega allí las líneas add_header. Algunos paneles colocan ese campo dentro de un bloque location, así que lanza la comprobación después. En un hosting compartido sin ninguna de las dos opciones, usa la Protección ampliada.

Han desaparecido los botones de pago, el mapa o el vídeo

Mira la consola del navegador. Una infracción de la CSP nombra el host bloqueado: añádelo a la directiva correspondiente. Un botón de Apple Pay o Google Pay ausente apunta a payment=() en la Permissions-Policy, un buscador de tiendas sin ubicación a geolocation=(). Si el contenido incrustado se rompe tras activar Cross-Origin-Embedder-Policy, la cabecera tiene que volver a desactivarse.

Un subdominio ya no es accesible

HSTS con includeSubDomains impone HTTPS en cada subdominio. Un subdominio sin certificado válido queda inaccesible para cada visitante que haya visto la cabecera, hasta que venza el max-age. Dale un certificado al subdominio y, si no es posible, desactiva includeSubDomains.

Faltan las cabeceras en wp-admin y en la página de acceso

Es lo previsto: WordPress y la Protección ampliada solo añaden las cabeceras a las páginas públicas. La configuración del servidor web cubre también wp-admin y la página de acceso.

Última actualización: · Mantenido por el equipo de ReportedIP

Security Focused
Conforme al RGPD
Made in Germany
Volver a la documentación