如何使用 nginx 设置签名 HTTP 交换 (SXG)

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

签名 HTTP 交换 (SXG) 是一项新的 Web 技术,使用户更容易区分内容创建者和内容分发者。本指南向您展示如何设置 SXG。

跨浏览器支持

包括 Google Chrome、Samsung Internet 和 Microsoft Edge 在内的几款基于 Chromium 的浏览器都支持 SXG。有关最新信息,请参阅“Origin-Signed HTTP Exchanges”的“共识和标准化”部分。

先决条件

要在您的网站上实施 SXG,您必须

  • 控制您的域名,包括 DNS 条目。
  • 获取证书。SXG 需要颁发专用证书。特别是,您不能重用您的 TLS 密钥或证书。
  • 拥有一个可以通过 HTTPS 生成和提供 SXG 的 HTTP 服务器。

假设

本指南假设您

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

此外,本文中的示例命令假设您的域名为 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 扩展”复选框,该复选框位于“其他证书选项”下。
“在证书中包含 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.ac.cn/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 至关重要,因为它定位证书链。证书链包含证书和 OCSP Stapling 信息,采用 cbor 格式。请注意,您不必从同一来源提供 cert.cbor 文件。只要它支持 HTTPS,您就可以通过任何 CDN 或其他静态文件服务服务提供它。
  • 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 提供根目录中的静态文件,但是您可以为您的应用程序使用 upstream 指令,以便为任意 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

发送反馈

Chromium 中从事 SXG 工作的工程师非常希望在 webpackage-dev@chromium.org 听到您的反馈。您也可以加入规范讨论,或向团队报告错误。您的反馈将极大地帮助标准化过程,并有助于解决实施问题。谢谢!