TLS 服务器名称指示 (SNI)

此示例演示了一个 Envoy 代理,它在同一个 IP 地址上侦听三个 TLS 域。

前两个域 (domain1domain2) 终止 TLS 并代理到上游 HTTP 主机。

另一个域 (domain3) 基于 SNI 标头被代理未终止。

它还演示了 Envoy 充当客户端代理,连接到上游 SNI 服务。

步骤 1:为每个域端点创建密钥对

将目录更改为 Envoy 存储库中的 examples/tls-sni

该示例创建了两个 Envoy TLS 端点,它们将需要自己的密钥对。

为这些端点创建自签名证书,如下所示

$ pwd
envoy/examples/tls-sni

$ mkdir -p certs

$ openssl req -new -newkey rsa:2048 -days 365 -nodes -x509 \
         -subj "/C=US/ST=CA/O=MyExample, Inc./CN=domain1.example.com" \
         -keyout certs/domain1.key.pem \
         -out certs/domain1.crt.pem
Generating a RSA private key
.............+++++
...................+++++
writing new private key to 'certs/domain1.key.pem'
-----

$ openssl req -new -newkey rsa:2048 -days 365 -nodes -x509 \
         -subj "/C=US/ST=CA/O=MyExample, Inc./CN=domain2.example.com" \
         -keyout certs/domain2.key.pem \
         -out certs/domain2.crt.pem
Generating a RSA private key
.............+++++
...................+++++
writing new private key to 'certs/domain2.key.pem'
-----

警告

SNI 验证所呈现的证书是否适合域,或者它们是否由公认的证书颁发机构颁发。

有关 验证证书 的更多信息,请参阅 保护 Envoy 快速入门指南

步骤 2:启动容器

构建并启动容器。

这将启动两个上游 HTTP 容器,它们在内部 Docker 网络上的端口 80 上侦听,以及一个上游 HTTPS 服务,它在内部端口 443 上侦听

在这些容器前面是一个 Envoy 代理,它在 https://127.0.0.1:10000 上侦听,并提供三个 SNI 路由的 TLS

  • domain1.example.com

  • domain2.example.com

  • domain3.example.com

前两个域使用 您在步骤 1 中创建的 密钥和证书来终止 TLS 并代理到两个上游 HTTP 服务器。

第三个域根据请求的 SNI 地址代理到上游 TLS 服务器,但本身不执行 TLS 终止。

该组合还启动了一个 Envoy 代理客户端,它在 https://127.0.0.1:20000 上侦听。

客户端代理没有 TLS 终止,而是代理三个路由路径 - /domain1/domain2/domain3 - 到启用 SNI 的代理。

$ pwd
envoy/examples/tls-sni
$ docker compose pull
$ docker compose up --build -d
$ docker compose ps

       Name                        Command                State         Ports
-------------------------------------------------------------------------------------------
tls-sni_http-upstream1_1   node ./index.js                Up
tls-sni_http-upstream2_1   node ./index.js                Up
tls-sni_http-upstream3_1   node ./index.js                Up
tls-sni_proxy_1            /docker-entrypoint.sh /usr ... Up      0.0.0.0:10000->10000/tcp
tls-sni_proxy-client_1     /docker-entrypoint.sh /usr ... Up      0.0.0.0:20000->10000/tcp

步骤 2:使用 curl 直接查询 SNI 端点

您可以使用 curl 直接查询 Envoy 代理的 SNI 路由的 HTTPS 端点。

为此,您必须明确告诉 curl 正确解析端点的 DNS

每个端点都应代理到相应的 http-upstreamhttps-upstream 服务。

$ curl -sk --resolve domain1.example.com:10000:127.0.0.1 \
      https://domain1.example.com:10000 \
     | jq -r '.os.hostname'
http-upstream1

$ curl -sk --resolve domain2.example.com:10000:127.0.0.1 \
      https://domain2.example.com:10000 \
     | jq -r '.os.hostname'
http-upstream2

$ curl -sk --resolve domain3.example.com:10000:127.0.0.1 \
      https://domain3.example.com:10000 \
     | jq -r '.os.hostname'
https-upstream3

步骤 3:通过 Envoy 代理客户端查询 SNI 端点

接下来,使用路由路径查询 Envoy 代理客户端。

这些路径通过 SNI 代理端点路由到相应的 http-upstreamhttps-upstream 服务。

$ curl -s https://127.0.0.1:20000/domain1 \
     | jq '.os.hostname'
http-upstream1

$ curl -s https://127.0.0.1:20000/domain2 \
     | jq '.os.hostname'
http-upstream2

$ curl -s https://127.0.0.1:20000/domain3 \
     | jq '.os.hostname'
https-upstream3

另请参阅

保护 Envoy 快速入门指南

保护 Envoy 的关键概念概述。

TLS 沙箱

沙箱,其中包含 Envoy 如何配置以使用通过 TLSHTTP 进行加密连接的示例。

双代理沙箱

使用 mTLS(带非 HTTP 流量)进行验证和双向身份验证来保护代理之间流量的示例。