跳到主要内容

配置网关与上游之间的 mTLS

双向 TLS(mTLS)是一种客户端和服务器彼此进行身份验证的双向 TLS 协议,通常用于防止未授权访问并增强安全性。

本文介绍如何通过 Ingress Controller 配置网关,使其通过双向 TLS(mTLS)与上游服务通信。

前提条件

  1. 完成设置 Ingress Controller 和网关

生成证书和密钥

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

openssl genrsa -out ca.key 2048
openssl req -new -x509 -days 36500 -sha256 \
-key ca.key \
-out ca.crt \
-subj "/CN=MyTestCA" \
-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")

生成服务端密钥和证书签名请求(CSR):

openssl genrsa -out server.key 2048
openssl req -new -sha256 \
-key server.key \
-out server.csr \
-subj "/CN=test.com"

使用 CA 证书对服务端 CSR 进行签名,生成服务端证书:

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

为客户端生成密钥和证书签名请求(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")

配置上游 Service

本文使用 NGINX 作为示例上游服务来演示双向 TLS(mTLS)。

为 NGINX 创建 Kubernetes Secret:

kubectl create secret generic nginx-certs \
--from-file=server.crt=server.crt \
--from-file=server.key=server.key \
--from-file=ca.crt=ca.crt \
--namespace=aic

创建 NGINX 使用的 ConfigMap,并在其中配置 TLS 证书:

nginx-cm.yaml
apiVersion: v1
kind: ConfigMap
metadata:
namespace: aic
name: nginx-config
data:
default.conf: |
server {
listen 8443 ssl;
server_name test.com;
ssl_certificate /etc/nginx/ssl/server.crt;
ssl_certificate_key /etc/nginx/ssl/server.key;
ssl_client_certificate /etc/nginx/ssl/ca.crt;
ssl_verify_client on;
location /hello {
return 200 "Hello World!";
}
}

server_name:设置为 test.com,与服务端证书的 CN 值保持一致。

ssl_certificate:配置服务端证书公钥 server.crt 的路径。

ssl_certificate_key:配置服务端证书私钥 server.key 的路径。

ssl_client_certificate:配置 CA 证书公钥 ca.crt 的路径。

ssl_verify_client:设置为 on 以验证客户端证书。

创建 Kubernetes manifest 文件,定义 NGINX 示例上游服务的 Deployment 和 Service:

nginx.yaml
apiVersion: v1
kind: Service
metadata:
namespace: aic
name: quickstart-nginx
spec:
type: NodePort
selector:
app: quickstart-nginx
ports:
- name: https
port: 8443
targetPort: 8443
---
apiVersion: apps/v1
kind: Deployment
metadata:
namespace: aic
name: quickstart-nginx
spec:
replicas: 1
selector:
matchLabels:
app: quickstart-nginx
template:
metadata:
labels:
app: quickstart-nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 8443
volumeMounts:
- name: config
mountPath: /etc/nginx/conf.d
- name: certs
mountPath: /etc/nginx/ssl
volumes:
- name: config
configMap:
name: nginx-config
- name: certs
secret:
secretName: nginx-certs

将配置应用到集群:

kubectl apply -f nginx-cm.yaml -f nginx.yaml

如需验证 NGINX 实例是否已正确配置,将 NGINX Service 端口转发到本地:

kubectl port-forward service/quickstart-nginx 8443:8443 &

携带客户端证书和密钥向 NGINX 服务路由发送请求:

curl -ik "https://127.0.0.1:8443/hello" --cert client.crt --key client.key

你应收到 HTTP/1.1 200 OK 响应,并看到以下消息:

Hello World!

如果不携带任何客户端证书或密钥发送请求:

curl -ik "https://127.0.0.1:8443/hello"

你应收到 HTTP/1.1 400 Bad Request 响应。

在网关上配置 mTLS

Ingress Controller 目前不支持使用 Gateway API 配置上游 mTLS。

验证

如需验证网关与上游服务之间的 mTLS,向路由发送请求:

curl -ikv "http://127.0.0.1:9080/hello"

你应收到 HTTP/1.1 200 OK 响应,并看到以下消息:

Hello World!

这表示网关与上游服务之间已成功建立 mTLS。