跳到主要内容

配置 APISIX 和 etcd 之间的 mTLS

双向 TLS (mTLS) 是一种双向 TLS,其中客户端和服务器相互验证身份。它通常用于防止未经授权的访问并加强安全性。

本文档将向你展示如何使用 Docker 化的 APISIX 和 etcd 配置 APISIX 和 etcd 之间的 mTLS。对于不同的部署方法,请相应调整步骤。

前置条件

  • 安装 Docker
  • 安装 cURL 以向服务发送请求进行验证。

生成证书和密钥

创建一个新目录并进入其中:

mkdir mtls-apisix-etcd && cd mtls-apisix-etcd

生成证书颁发机构 (CA) 密钥和证书:

openssl genrsa -out ca.key 2048
openssl req -new -x509 -days 36500 -sha256 \
-key ca.key \
-out ca.crt \
-subj "/CN=ROOTCA" \
-extensions v3_ca \
-config <(printf "[req]\ndistinguished_name=req\n[ v3_ca ]\nbasicConstraints=critical,CA:TRUE\nkeyUsage=critical,keyCertSign,cRLSign\nsubjectKeyIdentifier=hash\nauthorityKeyIdentifier=keyid:always,issuer")

为 etcd 生成密钥和证书签名请求(CSR):

openssl genrsa -out etcd.key 2048
openssl req -new -sha256 \
-key etcd.key \
-out etcd.csr \
-subj "/CN=ETCD" \
-addext "subjectAltName=DNS:etcd-prod,DNS:localhost,IP:127.0.0.1"

使用 CA 证书签署服务器 CSR,生成服务器证书:

openssl x509 -req -days 36500 -sha256 \
-in etcd.csr \
-CA ca.crt -CAkey ca.key -CAcreateserial \
-out etcd.crt \
-extensions v3_req \
-extfile <(printf "[v3_req]\nbasicConstraints=CA:FALSE\nkeyUsage=digitalSignature,keyEncipherment\nextendedKeyUsage=serverAuth,clientAuth\nsubjectAltName=DNS:etcd-prod,DNS:localhost,IP:127.0.0.1")

为客户端生成密钥和证书签名请求(CSR):

openssl genrsa -out client.key 2048
openssl req -new -sha256 \
-key client.key \
-out client.csr \
-subj "/CN=CLIENT"

使用 CA 证书签署客户端 CSR,生成客户端证书:

openssl x509 -req -days 36500 -sha256 \
-in client.csr \
-CA ca.crt -CAkey ca.key -CAcreateserial \
-out client.crt \
-extensions v3_req \
-extfile <(printf "[v3_req]\nbasicConstraints=CA:FALSE\nkeyUsage=digitalSignature,keyEncipherment\nextendedKeyUsage=clientAuth")

允许对目录中的文件进行读取访问,以避免下游权限问题:

chmod -R a+r ./

将证书和密钥复制到 /opt/mtls-apisix-etcd(或你选择的目录):

mkdir /opt/mtls-apisix-etcd
cp ca.crt etcd.key etcd.crt client.key client.crt /opt/mtls-apisix-etcd

配置 mTLS

你将在 Docker 容器中启动 etcd 和 APISIX,并带有 TLS 证书和密钥,以启用两者之间的 mTLS 通信。

为容器创建 Docker 网络:

docker network create mtls-apisix-etcd-net

启动 etcd

在 Docker 中启动 etcd 服务器:

docker run -d \
--name etcd-prod \
--network mtls-apisix-etcd-net \
-p 2379:2379 \
-v /opt/mtls-apisix-etcd:/certs \
gcr.io/etcd-development/etcd:v3.5.32 \
/usr/local/bin/etcd \
--client-cert-auth \
--cert-file /certs/etcd.crt \
--key-file /certs/etcd.key \
--trusted-ca-file /certs/ca.crt \
--name etcd-prod \
--data-dir /etcd-data \
--listen-client-urls https://0.0.0.0:2379 \
--advertise-client-urls https://etcd-prod:2379 \
--listen-peer-urls http://0.0.0.0:2380 \
--initial-advertise-peer-urls http://etcd-prod:2380 \
--initial-cluster etcd-prod=http://etcd-prod:2380

❶ 启用客户端证书身份认证。

❷ 设置 etcd TLS 证书的路径。

❸ 设置 etcd TLS 密钥的路径。

❹ 设置受信任 CA 证书的路径。

要验证 etcd 是否已启动且 mTLS 已正确配置,请使用客户端证书和密钥向 etcd 发送请求以获取 etcd 版本:

curl -iv --resolve "etcd-prod:2379:127.0.0.1" "https://etcd-prod:2379/version" \
--cacert /opt/mtls-apisix-etcd/ca.crt \
--cert /opt/mtls-apisix-etcd/client.crt --key /opt/mtls-apisix-etcd/client.key

如果一切正常,你应该看到带有 etcd 版本的 HTTP/2 200 响应:

{"etcdserver":"3.5.32","etcdcluster":"3.5.0"}

使用相同的客户端证书和密钥验证 etcd v3 API:

curl -iv --resolve "etcd-prod:2379:127.0.0.1" "https://etcd-prod:2379/v3/kv/put" \
--cacert /opt/mtls-apisix-etcd/ca.crt \
--cert /opt/mtls-apisix-etcd/client.crt \
--key /opt/mtls-apisix-etcd/client.key \
-H 'Content-Type: application/json' \
-d '{"key":"a2V5","value":"dmFsdWU="}'

如果一切正常,你应该会看到类似以下的 HTTP/2 200 响应:

{"header":{"cluster_id":"...","member_id":"...","revision":"...","raft_term":"..."}}

启动 APISIX

/opt(或你选择的目录)中创建一个 APISIX 配置文件:

echo 'apisix:
ssl:
ssl_trusted_certificate: /usr/local/apisix/certs/ca.crt
deployment:
role: traditional
role_traditional:
config_provider: etcd
admin:
admin_key_required: true
allow_admin:
- 0.0.0.0/0
admin_key:
-
name: admin
key: Sup3rs3cretWr1teK3y # 请替换为你的写入密钥
role: admin
etcd:
host:
- "https://etcd-prod:2379"
tls:
cert: /usr/local/apisix/certs/client.crt
key: /usr/local/apisix/certs/client.key
' > /opt/config.yaml

❶ 在 Docker 容器中设置受信任 CA 证书的路径。

❷ 在 Docker 容器中设置客户端 TLS 证书的路径。

❸ 在 Docker 容器中设置客户端 TLS 密钥的路径。

在 Docker 中启动一个 APISIX 实例:

docker run -d \
--name apisix \
--network mtls-apisix-etcd-net \
-p 9180:9180 \
-v /opt/mtls-apisix-etcd:/usr/local/apisix/certs \
-v /opt/config.yaml:/usr/local/apisix/conf/config.yaml \
apache/apisix:3.17.0-ubuntu

❶ 将主机上的 TLS 证书和密钥目录挂载到 Docker 容器。

❷ 将主机上的 APISIX 配置文件挂载到 Docker 容器。

本示例允许从所有地址访问 Admin API,以便在主机上进行验证。在生产环境中,请将 0.0.0.0/0 替换为受限的 CIDR 范围。

验证 mTLS

要验证 APISIX 是否已启动且 APISIX 和 etcd 之间的 mTLS 已正确配置,请向 APISIX 发送请求以获取所有路由:

curl -i "http://127.0.0.1:9180/apisix/admin/routes" -H "X-API-KEY: Sup3rs3cretWr1teK3y"

如果成功,你应该看到包含所有 APISIX 路由的 HTTP/1.1 200 OK 响应,例如:

{"list":[],"total":0}