雙重代理(帶有 mTLS 加密)

此沙盒示範基本的「雙重代理」設定,其中一個簡單的 aiohttp 應用程式連線到 PostgreSQL 資料庫,中間有兩個 Envoy 代理。

Envoy (前端) -> aiohttp -> Envoy (postgres-前端) -> Envoy (postgres-後端) -> PostgreSQL

這種設定在服務網格中很常見,其中 Envoy 作為各個服務之間的「Sidecar」。

它也可以用來為應用程式伺服器提供對上游服務或資料庫的存取,這些服務或資料庫可能位於服務網格或基於 Sidecar 的設定之外的不同位置或子網路中。

另一個常見的使用案例是 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 終止模式範例。