双代理(使用 mTLS 加密)

此沙盒演示了一个基本的“双代理”配置,其中一个简单的 aiohttp 应用程序连接到 PostgreSQL 数据库,中间有两个 Envoy 代理。

Envoy (front) -> aiohttp -> Envoy (postgres-front) -> Envoy (postgres-back) -> PostgreSQL

这种类型的设置在服务网格中很常见,其中 Envoy 充当各个服务之间的“边车”。

它也可以用作一种方法,为应用程序服务器提供访问上游服务或数据库的权限,这些服务或数据库可能位于不同的位置或子网中,位于服务网格或基于边车的设置之外。

另一个常见的用例是使用 Envoy 配置在云的边缘提供“存在点”,并将请求中继到上游服务器和服务。

此示例对两个中间代理之间的数据传输进行加密,并使用 mTLS 提供相互身份验证。

如果代理在物理上分离或通过不可信网络传输数据,这将很有用。

为了使用沙盒,您首先需要生成必要的 SSL 密钥和证书。

此示例将逐步介绍如何创建证书颁发机构,并使用它创建域密钥和签署代理证书。

更改到 examples/double-proxy 目录。

步骤 1:创建证书颁发机构

首先为证书颁发机构创建密钥

$ pwd
envoy/examples/double-proxy
$ mkdir -p certs
$ openssl genrsa -out certs/ca.key 4096
Generating RSA private key, 4096 bit long modulus (2 primes)
..........++++
..........................................................................................................++++
e is 65537 (0x010001)

现在使用密钥生成证书颁发机构证书。

如果需要,您可以交互式地更改证书中的字段。

在本例中,默认值应该足够了。

$ openssl req -x509 -new -nodes -key certs/ca.key -sha256 -days 1024 -out certs/ca.crt

You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:
State or Province Name (full name) [Some-State]:
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:
Email Address []:

步骤 2:创建域密钥

为示例域创建密钥

$ openssl genrsa -out certs/example.com.key 2048
Generating RSA private key, 2048 bit long modulus (2 primes)
..+++++
.................................................+++++
e is 65537 (0x010001)

步骤 3:为代理生成证书签名请求

使用域密钥为每个代理生成证书签名请求

$ openssl req -new -sha256 \
     -key certs/example.com.key \
     -subj "/C=US/ST=CA/O=MyExample, Inc./CN=proxy-postgres-frontend.example.com" \
     -out certs/proxy-postgres-frontend.example.com.csr
$ openssl req -new -sha256 \
     -key certs/example.com.key \
     -subj "/C=US/ST=CA/O=MyExample, Inc./CN=proxy-postgres-backend.example.com" \
     -out certs/proxy-postgres-backend.example.com.csr

步骤 4:签署代理证书

您现在可以使用您创建的证书颁发机构来签署证书请求。

请注意 subjectAltName。这用于相互匹配和验证证书。

$ openssl x509 -req \
     -in certs/proxy-postgres-frontend.example.com.csr \
     -CA certs/ca.crt \
     -CAkey certs/ca.key \
     -CAcreateserial \
     -extfile <(printf "subjectAltName=DNS:proxy-postgres-frontend.example.com") \
     -out certs/postgres-frontend.example.com.crt \
     -days 500 \
     -sha256
Signature ok
subject=C = US, ST = CA, O = "MyExample, Inc.", CN = proxy-postgres-frontend.example.com
Getting CA Private Key

$ openssl x509 -req \
     -in certs/proxy-postgres-backend.example.com.csr \
     -CA certs/ca.crt \
     -CAkey certs/ca.key \
     -CAcreateserial \
     -extfile <(printf "subjectAltName=DNS:proxy-postgres-backend.example.com") \
     -out certs/postgres-backend.example.com.crt \
     -days 500 \
     -sha256
Signature ok
subject=C = US, ST = CA, O = "MyExample, Inc.", CN = proxy-postgres-backend.example.com
Getting CA Private Key

此时,您应该拥有确保代理之间连接安全所需的密钥和证书。

密钥和证书存储在 certs/ 目录中。

步骤 5:启动所有容器

构建并启动容器。

这将把所需的密钥和证书加载到前端和后端代理中。

$ pwd
envoy/examples/double-proxy
$ docker compose pull
$ docker compose up --build -d
$ docker compose ps

       Name                                      Command                State              Ports
-------------------------------------------------------------------------------------------------------------
double-proxy_app_1                       python3 /code/service.py       Up (healthy)
double-proxy_postgres_1                  docker-entrypoint.sh postgres  Up           5432/tcp
double-proxy_proxy-frontend_1            /docker-entrypoint.sh /usr ... Up           0.0.0.0:10000->10000/tcp
double-proxy_proxy-postgres-backend_1    /docker-entrypoint.sh /usr ... Up           10000/tcp
double-proxy_proxy-postgres-frontend_1   /docker-entrypoint.sh /usr ... Up           10000/tcp

步骤 6:检查 aiohttp 应用程序是否可以连接到数据库

检查 https://127.0.0.1:10000 上的响应,您应该看到来自 aiohttp 应用程序的输出

$ curl -s https://127.0.0.1:10000
Connected to Postgres, version: PostgreSQL 13.0 (Debian 13.0-1.pgdg100+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 8.3.0-6) 8.3.0, 64-bit

另请参见

保护 Envoy 快速入门指南

保护 Envoy 的关键概念概述。

TLS 沙盒

Envoy 中各种 TLS 终止模式的示例。