Cómo configurar intercambios HTTP firmados (SXG) con nginx

Cómo generar un certificado TLS con extensiones SXG, instalar herramientas para generar archivos SXG y configurar nginx para que entregue archivos SXG.

Hiroki Kumazaki
Hiroki Kumazaki

Los intercambios HTTP firmados (SXG) son una nueva tecnología web que les permite a los usuarios diferenciar a los creadores de contenido de los distribuidores. En esta guía, se muestra cómo configurar SXG.

Compatibilidad con varios navegadores

Varios navegadores basados en Chromium admiten SXG, incluidos Google Chrome, Samsung Internet y Microsoft Edge. Consulta la sección Consenso y estandarización del Intercambios HTTP firmados por el origen para obtener información más actualizada.

Requisitos previos

Para implementar SXG en tu sitio web, debes hacer lo siguiente:

  • Controla tu dominio, incluidas las entradas de DNS.
  • Obtener certificados SXG requiere la emisión de un certificado exclusivo. En particular, no puedes volver a usar tu clave o certificado TLS.
  • Tener un servidor HTTP que pueda generar y entregar SXG mediante HTTPS

Suposiciones

En esta guía, se da por sentado que hiciste lo siguiente:

  • Tener un entorno de OpenSSL 1.1.1 Esta guía se escribió con Ubuntu 18.04 LTS en amd64 ISA.
  • Tener la capacidad de ejecutar sudo para instalar ejecutables
  • Usa nginx como un servidor HTTP.
  • Usan DigiCert para generar certificados que incluyen extensiones relacionadas con SXG, ya que, actualmente, parece ser el único proveedor que admite estas extensiones.

Además, los comandos de ejemplo en este artículo suponen que tu dominio es website.test, por lo que deberás reemplazar website.test con tu dominio real.

Paso 1: Obtén el certificado de SXG

Para generar un SXG, necesitas un certificado TLS con la extensión CanSignHttpExchanges, así como un tipo de clave particular. DigiCert proporciona certificados con esta extensión. Necesitas un archivo CSR para la emisión de un certificado. Por eso, debes generarlo con los siguientes comandos:

openssl ecparam -genkey -name prime256v1 -out mySxg.key
openssl req -new -key mySxg.key -nodes -out mySxg.csr -subj "/O=Test/C=US/CN=website.test"

Obtendrás un archivo CSR que se ve de la siguiente manera:

-----BEGIN CERTIFICATE REQUEST-----
MIHuMIGVAgEAMDMxDTALBgNVBAoMBFRlc3QxCzAJBgNVBAYTAlVTMRUwEwYDVQQD
DAx3ZWJzaXRlLnRlc3QwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAS7IVaeMvid
S5UO7BspzSe5eqT5Qk6X6dCggUiV/vyqQaFDjA/ALyTofgXpbCaksorPaDhdA+f9
APdHWkTbbdv1oAAwCgYIKoZIzj0EAwIDSAAwRQIhAIb7n7Kcc6Y6pU3vFr8SDNkB
kEadlVKNA24SVZ/hn3fjAiAS2tWXhYdJX6xjf2+DL/smB36MKbXg7VWy0K1tWmFi
Sg==
-----END CERTIFICATE REQUEST-----

Asegúrate de lo siguiente:

  • El período de validez no supera los 90 días.
  • Que la casilla de verificación Incluir la extensión CanSignHttpExchanges en el certificado esté habilitada. que se encuentra en Opciones de certificado adicionales.
Marca la casilla de verificación Incluir la extensión CanSignHttpExchanges en el certificado.

Si tu certificado no cumple con estas condiciones, los navegadores y distribuidores rechazarán tu SXG por razones de seguridad. En esta guía, se supone que el nombre de archivo del certificado que obtuviste de DigiCert es mySxg.pem.

Paso 2: Instala libsxg

El formato SXG es complejo y difícil de generar sin usar herramientas. Puedes usar una de las siguientes opciones para generar SXG:

En esta guía, se usa libsxg.

Opción 1: Instala libsxg desde un paquete Debian

Puedes instalar el paquete de la manera habitual de Debian, siempre que la versión de OpenSSL (libssl-dev) coincida.

sudo apt install -y libssl-dev
wget https://github.com/google/libsxg/releases/download/v0.2/libsxg0_0.2-1_amd64.deb
wget https://github.com/google/libsxg/releases/download/v0.2/libsxg-dev_0.2-1_amd64.deb
sudo dpkg -i libsxg0_0.2-1_amd64.deb
sudo dpkg -i libsxg-dev_0.2-1_amd64.deb

Opción 2: Compila libsxg manualmente

Si no usas un entorno compatible con archivos .deb, puedes compilar libsxg por tu cuenta. Como condición previa, debes instalar git, cmake, openssl y gcc.

git clone https://github.com/google/libsxg
mkdir libsxg/build
cd libsxg/build
cmake .. -DRUN_TEST=false -DCMAKE_BUILD_TYPE=Release
make
sudo make install

Paso 3: Instala el complemento nginx

El complemento nginx te permite generar SXG de manera dinámica en lugar de generarlos de forma estática antes de la entrega.

Opción 1: Instala el complemento desde un paquete Debian

El módulo SXG para nginx se distribuye en GitHub. En los sistemas basados en Debian, puedes instalarlo como un paquete binario:

sudo apt install -y nginx=1.15.9-0
wget https://github.com/google/nginx-sxg-module/releases/download/v0.1/libnginx-mod-http-sxg-filter_1.15.9-0ubuntu1.1_amd64.deb
sudo dpkg -i libnginx-mod-http-sxg-filter_1.15.9-0ubuntu1.1_amd64.deb

Opción 2: Compila el complemento de forma manual

La compilación del módulo nginx requiere el código fuente nginx. Puedes obtener el archivo tarball y compilarlo junto con el módulo dinámico de SXG con los siguientes comandos:

git clone https://github.com/google/nginx-sxg-module
wget https://nginx.org/download/nginx-1.17.5.tar.gz
tar xvf nginx-1.17.5.tar.gz
cd nginx-1.17.5
./configure --prefix=/opt/nginx --add-dynamic-module=../nginx-sxg-module --without-http_rewrite_module --with-http_ssl_module
make
sudo make install

La configuración de nginx ofrece una gran flexibilidad. Instala nginx en cualquier lugar de tu sistema y, luego, especifica la ruta de acceso correspondiente de module/config/log/pidfile. En esta guía, se supone que lo instalas en /opt/nginx.

Paso 4: Configura el complemento nginx para que funcione con SXG

Opción 1: Configura un módulo nginx instalado desde Debian

Sigue estas instrucciones si ya usaste el Paso 3, opción 1.

El envío de contenido SXG requiere HTTPS. Puedes obtener un certificado SSL/TLS de DigiCert, Let's Encrypt y otros servicios. Ten en cuenta que NO PUEDES usar un certificado SXG para SSL ni viceversa; por lo tanto, necesitarás dos certificados. El archivo de configuración en /etc/nginx/nginx.conf debería ser similar al siguiente, suponiendo que colocaste el par clave-certificado SSL en /path/to/ssl/ y el par clave-certificado SXG en /path/to/sxg/:

user www-data;
include /etc/nginx/modules-enabled/*.conf;

events {
     worker_connections 768;
}

http {
    include       mime.types;
    default_type  application/octet-stream;
    add_header  X-Content-Type-Options nosniff;

    server {
        listen 443 ssl;
        ssl_certificate     /path/to/ssl/fullchain.pem;
        ssl_certificate_key /path/to/ssl/privkey.pem;
        server_name  website.test;

        sxg on;
        sxg_certificate     /path/to/sxg/mySxg.pem;
        sxg_certificate_key /path/to/sxg/mySxg.key;
        sxg_cert_url        https://website.test/certs/cert.cbor;
        sxg_validity_url    https://website.test/validity/resource.msg;
        sxg_cert_path       /certs/cert.cbor;

        root /var/www/html;
    }
}
  • sxg_cert_url es esencial para que los navegadores carguen SXG correctamente porque localiza la cadena de certificados. La cadena de certificados contiene información de engrapamiento de certificados y OCSP con formato cbor. Ten en cuenta que no debes entregar el archivo cert.cbor desde el mismo origen. Puedes entregarla a través de cualquier CDN u otro servicio de entrega de archivos estáticos, siempre y cuando sea compatible con HTTPS.
  • Se planea que sxg_validitiy_url publique información relacionada con el encabezado de la firma SXG. Si una página no se modificó desde el último SXG, técnicamente no es necesario descargar el archivo SXG completo. Por lo tanto, se espera que solo actualizar la información del encabezado de la firma reduzca el tráfico de red. Sin embargo, aún no se implementaron los detalles.

Inicia nginx y estará todo listo para publicar anuncios de SXG.

sudo systemctl start nginx.service
curl -H"Accept: application/signed-exchange;v=b3" https://website.test/ > index.html.sxg
cat index.html.sxg
sxg1-b3...https://website.test/...(omit)

Opción 2: Configura un módulo nginx compilado a partir de la fuente

Sigue estas instrucciones si ya usaste el Paso 3, opción 2.

Configura tu sistema nginx instalado en /opt/nginx para que se vea similar al siguiente ejemplo:

load_module "/opt/nginx/modules/ngx_http_sxg_filter_module.so";

events {
    worker_connections 768;
}

http {
    include       mime.types;
    default_type  application/octet-stream;
    add_header X-Content-Type-Options nosniff;

    server {
        listen 443 ssl;
        ssl_certificate     /path/to/ssl/fullchain.pem;
        ssl_certificate_key /path/to/ssl/privkey.pem;
        server_name  example.com;

        sxg on;
        sxg_certificate     /path/to/sxg/mySxg.pem;
        sxg_certificate_key /path/to/sxg/mySxg.key;
        sxg_cert_url        https://website.test/certs/cert.cbor;
        sxg_validity_url    https://website.test/validity/resource.msg;
        sxg_cert_path       /certs/cert.cbor;

        root /opt/nginx/html;
    }
}

Luego, inicia nginx. Ya puedes conseguir tu SXG.

cd /opt/nginx/sbin
sudo ./nginx
curl -H "Accept: application/signed-exchange;v=b3" https://website.test/ > index.html.sxg
less index.html.sxg
sxg1-b3...https://website.test/...(omit)

Paso 5: Entrega el backend de tu aplicación

En los ejemplos anteriores, nginx entrega archivos estáticos en el directorio raíz, pero puedes usar directivas ascendentes para que tus aplicaciones creen SXG para backends de aplicaciones web arbitrarias (como Ruby on Rails, Django o Express) siempre que tu nginx funcione como un servidor HTTP(S) frontal.

upstream app {
    server 127.0.0.1:8080;
}

server {
    location / {
        proxy_pass http://app;
    }
}

Paso 6: Realiza una prueba

Usa la herramienta dump-signedexchange para probar que los SXG que se entregan sean correctos, asegurarse de que no se informen errores y verificar que los encabezados y cuerpo sean los esperados.

go get -u github.com/WICG/webpackage/go/signedexchange/cmd/dump-signedexchange
export PATH=$PATH:~/go/bin
dump-signedexchange -verify -uri https://website.test/ | less

Enviar comentarios

Los ingenieros de Chromium que trabajan en SXG están dispuestos a recibir tus comentarios en webpackage-dev@chromium.org. También puedes unirte al debate de las especificaciones o informar un error al equipo. Tus comentarios serán de gran ayuda con el proceso de estandarización y también abordarán los problemas de implementación. ¡Gracias!