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

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

Hiroki Kumazaki
Hiroki Kumazaki

Signed HTTP Exchanges (SXG) 是一种新的 Web 技术,可让用户更轻松地将内容创作者与内容分销商区分开来。本指南介绍了如何设置 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 相关扩展程序的证书,因为它目前似乎是唯一支持这些扩展程序的提供商。

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

第 1 步:获取 SXG 证书

如需生成 SXG,您需要具有 CanSignHttpExchanges 扩展的 TLS 证书以及特定的密钥类型。DigiCert 提供带有此扩展的证书。您需要 CSR 文件才能签发证书,因此请使用以下命令生成 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 扩展复选框处于启用状态,该复选框位于“其他证书选项”下。
在证书中添加 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 源代码。您可以使用以下命令获取 tarball 并将其与 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:配置从 Debian 安装的 nginx 模块

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

提交 SXG 内容需要使用 HTTPS。您可以从 DigiCert、Let's Encrypt 和其他服务获取 SSL/TLS 证书。请注意,您不能将 SXG 证书用于 SSL,反之亦然,因此您需要两个证书。假设您将 SSL 密钥/证书对放在 /path/to/ssl/ 中,并将 SXG 密钥/证书对放在 /path/to/sxg/ 中,/etc/nginx/nginx.conf 中的配置文件应类似于以下内容:

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 至关重要,因为它会定位证书链。证书链包含采用 cbor 格式的证书和 OCSP 订阅信息。请注意,您不必从同一来源提供 cert.cbor 文件。您可以通过任何 CDN 或其他静态文件传送服务(只要它们支持 HTTPS)来传送该文件。
  • sxg_validitiy_url 计划提供与 SXG 签名标头相关的信息。从技术层面讲,如果网页自上次 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 会在根目录中提供静态文件,但您可以为应用使用上游指令,为任意 Web 应用后端(例如 Ruby on Rails、Django 或 Express)制作 SXG,前提是 nginx 用作前端 HTTP(S) 服务器。

upstream app {
    server 127.0.0.1:8080;
}

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

第 6 步:测试

使用 dump-signedexchange 工具测试所提供的 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。 您的反馈将对标准化流程大有帮助,也有助于解决实现问题。 谢谢!