Cabeceras de seguridad HTTP con relayd
Por el 12 de Abril de 2022
Estas son las cabeceras de seguridad que uso para este sitio web y su configuración con relayd(8), el motor web que forma parte de OpenBSD.
Parto de un servidor VPS que corre OpenBSD 7.1 con las siguientes direcciones IP:
El servidor tiene un certificado SSL configurado y funcionando correctamente gracias a acme-client(1):
- Certificado SSL público: /etc/ssl/web.example.com.fullchain.pem
- Certificado SSL privado: /etc/ssl/private/web.example.com.key
relayd se encargará de las conexiones SSL para IPv4 e IPv6 y httpd(8) estará escuchando en la IP 127.0.0.1 en el puerto 8080. Tal y como se explica en el artículo add HTTP security headers with relayd(8), primero hay que enlazar este certificado a ambas direcciones IP:
ln -fs /etc/ssl/private/{web.example.com,203.0.113.1}.key
ln -fs /etc/ssl/private/{web.example.com,2001:0db8:85a3:0000:0000:8a2e:0370:7334}.key
ln -fs /etc/ssl/{web.example.com,203.0.113.1}.fullchain.pem
ln -fs /etc/ssl/{web.example.com,2001:0db8:85a3:0000:0000:8a2e:0370:7334}.fullchain.pem
O, más fácil aún, usando este script:
#!/bin/sh
if [ "$#" -ne 3 ] ; then
echo "Usage: $0 [hostname] [ip4] [ip6]" >&2
exit 1
fi
ln -fs /etc/ssl/private/{$1,$2}.key
ln -fs /etc/ssl/private/{$1,$3}.key
ln -fs /etc/ssl/{$1,$2}.fullchain.pem
ln -fs /etc/ssl/{$1,$3}.fullchain.pem
Configuración de relayd para IPv4 e IPv6
Configuraré las siguientes cabeceras de seguridad:
- Content Security Policy (CSP)
- Permissions-Policy
- Referrer-Policy
-
Strict-Transport-Security - X-Content-Type-Options
- X-Frame-Options
- X-XSS-Protection
Esta es la parte correspondiente de la configuración /etc/relayd.conf para el dominio example.com con IPv4 e IPv6. La idea de separarlos en dos relays distintos la saqué del artículo realyd acceleration:
ipv4="203.0.113.1"
ipv6="2001:0db8:85a3:0000:0000:8a2e:0370:7334"
table <local> { 127.0.0.1 }
http protocol https {
[...]
tls keypair example.com
[...]
match response header set "Content-Security-Policy" value "default-src 'none'; style-src 'self'; img-src 'self'; script-src 'self'; base-uri 'none'; form-action 'self'; frame-ancestors 'none'"
match response header set "Permissions-Policy" value "camera=(), microphone=()"
match response header set "Referrer-Policy" value "no-referrer"
#match response header set "Strict-Transport-Security" value "max-age=31536000; includeSubDomains; preload"
match response header set "X-Content-Type-Options" value "nosniff"
match response header set "X-Frame-Options" value "deny"
match response header set "X-XSS-Protection" value "1; mode=block"
[...]
}
relay wwwtls {
listen on $ipv4 port 443 tls
protocol https
forward to <local> port 8080
}
relay www6tls {
listen on $ipv6 port 443 tls
protocol https
forward to <local> port 8080
}