nginx를 사용하여 서명된 HTTP 교환 (SXG)을 설정하는 방법

SXG 확장자가 있는 TLS 인증서를 생성하고, SXG 파일을 생성하기 위한 도구를 설치하고, SXG 파일을 제공하도록 nginx를 구성하는 방법

Hiroki Kumazaki
Hiroki Kumazaki

서명된 HTTP 교환 (SXG)은 사용자가 콘텐츠 크리에이터와 콘텐츠 배급자를 더 쉽게 구분할 수 있는 새로운 웹 기술입니다. 이 가이드에서는 SXG를 설정하는 방법을 보여줍니다.

Google Chrome, Samsung Internet, Microsoft Edge 등 여러 Chromium 기반 브라우저에서 SXG를 지원합니다. 최신 정보는 출처 서명 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 파일이 필요하므로 다음 명령어를 사용하여 생성합니다.

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를 직접 빌드할 수 있습니다. 기본적으로 git, cmake, openssl, 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

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단계: SXG와 호환되도록 nginx 플러그인 구성

옵션 1: Debian에서 설치된 nginx 모듈 구성

이전에 3단계, 옵션 1을 사용한 경우 다음 안내를 따르세요.

SXG 콘텐츠를 전송하려면 HTTPS가 필요합니다. DigiCert, Let's Encrypt, 기타 서비스에서 SSL/TLS 인증서를 가져올 수 있습니다. SSL에 SXG 인증서를 사용하거나 그 반대로 할 수 없으므로 인증서가 두 개 필요합니다. 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 파일을 제공할 필요는 없습니다. HTTPS를 지원하는 한 CDN 또는 기타 정적 파일 제공 서비스를 통해 제공할 수 있습니다.
  • 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는 루트 디렉터리의 정적 파일을 제공하지만, nginx가 프런트 HTTP (S) 서버로 작동하는 한 애플리케이션의 업스트림 디렉티브를 사용하여 임의의 웹 애플리케이션 백엔드(예: Ruby on Rails, Django, Express)의 SXG를 만들 수 있습니다.

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에서 의견을 기다리고 있습니다. 사양 토론에 참여하거나 팀에 버그를 신고할 수도 있습니다. 보내주신 의견은 표준화 프로세스와 구현 문제를 해결하는 데 큰 도움이 됩니다. 감사합니다.