如何使用 nginx 设置 Signed HTTP Exchange (SXG)

如何生成具有 SXG 扩展程序的 TLS 证书、安装用于生成 SXG 文件的工具,以及配置 nginx 以提供 SXG 文件。

Hiroki Kumazaki
Hiroki Kumazaki

Signed HTTP Exchange (SXG) 是一项新的网络技术,可让用户更轻松地将内容创作者与内容分发者区分开来。本指南介绍了如何设置 SXG。

跨浏览器支持

多种基于 Chromium 的浏览器都支持 SXG,包括 Google Chrome、Samsung Internet 和 Microsoft Edge。如需了解最新信息,请参阅源签名的 HTTP 交换的“共识和标准化”部分。

前提条件

如需在您的网站上实现 SXG,您必须:

  • 控制您的网域,包括 DNS 条目。
  • 获取证书。SXG 要求颁发专用证书。具体来说,您不能重复使用 TLS 密钥或证书。
  • 拥有可通过 HTTPS 生成和提供 SXG 的 HTTP 服务器。

假设

本指南假定您满足以下条件:

  • 拥有 OpenSSL 1.1.1 环境。本指南是使用 amd64 ISA 上的 Ubuntu 18.04 LTS 编写的。
  • 能够运行 sudo 以安装可执行文件。
  • 使用 nginx 作为 HTTP 服务器。
  • 正在使用 DigiCert 生成包含 SXG 相关扩展程序的证书,因为 DigiCert 目前似乎是唯一支持这些扩展程序的提供商。

此外,本文中的示例命令假定您的域名为 website.test,因此您需要将 website.test 替换为您的实际域名。

第 1 步:获取 SXG 证书

如需生成 SXG,您需要具有 CanSignHttpExchanges 扩展名的 TLS 证书以及特定的密钥类型。DigiCert 提供具有此扩展程序的证书。 您需要 CSR 文件来颁发证书,因此请使用以下命令生成此文件:

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"

您将获得如下所示的 CSR 文件:

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

请确保:

  • 有效期不超过 90 天。
  • 已选中“其他证书选项”下的在证书中添加 CanSignHttpExchanges extension 复选框。
选中在证书中添加 CanSignHttpExchanges 扩展程序复选框。

如果您的证书不符合这些条件,出于安全考虑,浏览器和分销商将拒绝您的 SXG。 本指南假定您从 DigiCert 获取的证书的文件名是 mySxg.pem

第 2 步:安装 libsxg

SXG 格式很复杂,不使用工具就难以生成。您可以使用以下选项之一生成 SXG:

本指南使用的是 libsxg

方法 1:通过 Debian 软件包安装 libsxg

只要 OpenSSL (libssl-dev) 版本匹配,您就可以通过常规 Debian 方式安装软件包。

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

方法 2:手动构建 libsxg

如果您使用的环境与 .deb 文件不兼容,则可以自行构建 libsxg。作为前提条件,您需要安装 gitcmakeopensslgcc

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

第 3 步:安装 nginx 插件

借助 nginx 插件,您可以在传送之前动态生成 SXG,而不是静态生成它们。

方法 1:通过 Debian 软件包安装插件

适用于 nginx 的 SXG 模块在 GitHub 上分发。 在基于 Debian 的系统上,您可以将其安装为二进制软件包:

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

方法 2:手动构建插件

构建 nginx 模块需要 nginx 源代码。您可以使用以下命令获取 tar 压缩文件,并将其与 SXG 动态模块一起构建:

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

nginx 配置具有极大的灵活性。将 nginx 安装在系统中的任意位置,然后指定 module/config/log/pidfile 的相应路径。本指南假定您将其安装到 /opt/nginx 中。

第 4 步:配置 nginx 插件以与 SXG 搭配使用

方法 1:配置 installed-from-Debian nginx 模块

如果您之前使用过第 3 步,选项 1,请按照以下说明操作。

提供 SXG 内容需要使用 HTTPS。您可以从 DigiCert、Let's Encrypt 和其他服务获取 SSL/TLS 证书。请注意,您不能将 SXG 证书用于 SSL,反之亦然,因此您将需要两个证书。/etc/nginx/nginx.conf 中的配置文件应如下所示(假设您将 SSL 密钥/证书对放在 /path/to/ssl/ 中,并将 SXG 密钥/证书对放在 /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 是浏览器正确加载 SXG 所必需的,因为它可以找到证书链。证书链包含证书和 OCSP 装订信息(采用 cbor 格式)。请注意,您不必从同一来源传送 cert.cbor 文件。您可以通过任何 CDN 或其他静态文件传送服务提供内容,只要此类服务支持 HTTPS 即可。
  • sxg_validitiy_url 计划提供 SXG-signature-header 相关信息。如果自上次 SXG 以来,某个页面未修改过,则从技术层面而言,无需下载整个 SXG 文件。因此,仅更新签名标头信息预计可以减少网络流量。但相关细节尚未实现。

启动 nginx,即可为 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)

方法 2:配置从源代码构建的 nginx 模块

如果您之前使用过第 3 步,选项 2,请按照以下说明操作。

将安装在 /opt/nginx 下的 nginx 系统配置为类似于以下示例:

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;
    }
}

然后启动 nginx。现在,您可以获得 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)

第 5 步:提供应用后端

在上面的示例中,nginx 在根目录中提供静态文件,但您可以为应用使用上游指令,使 SXG 用于任意 Web 应用后端(例如 Ruby on Rails、Django 或 Express),只要您的 nginx 用作前端 HTTP(S) 服务器即可。

upstream app {
    server 127.0.0.1:8080;
}

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

第 6 步:测试

使用 dump-signed Exchange 工具测试传送的 SXG 是否正确,确保没有报告任何错误,并验证标头和正文是否符合预期。

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

发送反馈

从事 SXG 开发工作的 Chromium 工程师非常期待通过 webpackage-dev@chromium.org 收到您的反馈。 您还可以加入规范讨论或向团队报告 bug。您的反馈将极大地帮助实现标准化过程,并帮助解决实现问题。 谢谢!