Nginx Gateway Fabric TLS配置实战:手把手教你加固网关

63 阅读6分钟

本教程为Nginx Gateway Fabric部署添加TLS加密和HTTP到HTTPS重定向。通过Gateway API,配置证书、HTTPS监听器及RequestRedirect过滤器,实现生产级安全流量管理。

译自:Tutorial: Add TLS to Nginx Gateway Fabric

作者:Janakiram MSV

上一个教程中,我们部署了 Nginx Gateway Fabric 并配置了 HTTP 路由,通过 Kubernetes Gateway API 暴露内部服务。虽然这对于开发是可用的,但生产部署需要 TLS 加密 来保护客户端和网关之间的流量。

本教程通过在网关添加 TLS 终止并实现自动 HTTP 到 HTTPS 重定向来扩展我们现有的设置。完成本教程后,您将拥有一个生产就绪的配置,可加密所有客户端流量。

先决条件

本教程假定您已完成第一部分,并且运行着以下资源:

  • Nginx Gateway Fabric 部署在 nginx-gateway 命名空间中。
  • 一个名为 demo-gateway 的 Gateway 资源,在端口 80 上有一个 HTTP 监听器。
  • 示例应用程序 (demo-web 和 demo-api) 运行在 demo 命名空间中。
  • 配置为将流量路由到后端服务的 HTTPRoute。
  • 本地安装了 OpenSSL (用于证书生成)。

验证您现有的设置:

kubectl get gateway -n nginx-gateway
kubectl get httproute -n demo
kubectl get pods -n demo

第一步:生成 TLS 证书

在本教程中,我们将创建一个自签名证书。在生产环境中,您将使用 cert-manager 结合 Let's Encrypt 或来自您组织 CA 的证书。`12

创建目录并生成证书:

mkdir -p ~/gateway-certs && cd ~/gateway-certs

# Generate private key
openssl genrsa -out tls.key 2048

# Generate self-signed certificate with SAN
openssl req -new -x509 -key tls.key -out tls.crt -days 365 \
  -subj "/CN=demo.example.com" \
  -addext "subjectAltName=DNS:demo.example.com,DNS:*.demo.example.com"

重要提示: 请将 demo.example.com 替换为您的实际域名。现代浏览器和客户端接受证书需要主题备用名称 (SAN)。

验证证书:

openssl x509 -in tls.crt -text -noout | grep -A1 "Subject Alternative Name"

第二步:创建 Kubernetes TLS Secret

将证书和密钥存储在 Kubernetes secret 中。该 secret 必须与 Gateway 位于同一命名空间(nginx-gateway)中。

kubectl create secret tls demo-tls-secret \
  --cert=tls.crt \
  --key=tls.key \
  -n nginx-gateway

验证 secret:

kubectl describe secret demo-tls-secret -n nginx-gateway

您应该在 Data 部分看到 tls.crttls.key

第三步:更新 Gateway 以支持 HTTPS

修改 Gateway 以在现有 HTTP 监听器旁添加一个 HTTPS 监听器。创建一个名为 gateway-tls.yaml 的文件:

apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: demo-gateway
  namespace: nginx-gateway
spec:
  gatewayClassName: nginx
  listeners:
    # Existing HTTP listener - kept for redirect
    - name: http
      port: 80
      protocol: HTTP
      hostname: demo.example.com
      allowedRoutes:
        namespaces:
          from: All
    # New HTTPS listener with TLS termination
    - name: https
      port: 443
      protocol: HTTPS
      hostname: demo.example.com
      tls:
        mode: Terminate
        certificateRefs:
          - kind: Secret
            name: demo-tls-secret
      allowedRoutes:
        namespaces:
          from: All

关键配置元素:tls.mode: Terminate 设置在网关执行 TLS 终止,在通过纯 HTTP 转发到后端服务之前解密流量。certificateRefs 指向我们的 TLS secret。

应用更新后的 Gateway:

kubectl apply -f gateway-tls.yaml

验证两个监听器都已配置:

kubectl get gateway demo-gateway -n nginx-gateway -o yaml | grep -A5 "listeners:"

第四步:创建 HTTPS 路由

创建一个使用 sectionName 字段绑定到 HTTPS 监听器的 HTTPRoute。另存为 route-https.yaml

apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: demo-route-https
  namespace: demo
spec:
  parentRefs:
    - name: demo-gateway
      namespace: nginx-gateway
      sectionName: https
  hostnames:
    - demo.example.com
  rules:
    - matches:
        - path:
            type: PathPrefix
            value: /api
      backendRefs:
        - name: demo-api
          port: 80
    - matches:
        - path:
            type: PathPrefix
            value: /
      backendRefs:
        - name: demo-web
          port: 80

应用 HTTPS 路由:

kubectl apply -f route-https.yaml

第五步:配置 HTTP 到 HTTPS 重定向

为确保所有流量都使用 HTTPS,请创建一个重定向路由,该路由捕获 HTTP 请求并返回 301 重定向。另存为 http-redirect.yaml

apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: http-to-https-redirect
  namespace: demo
spec:
  parentRefs:
    - name: demo-gateway
      namespace: nginx-gateway
      sectionName: http
  hostnames:
    - demo.example.com
  rules:
    - filters:
        - type: RequestRedirect
          requestRedirect:
            scheme: https
            statusCode: 301

此路由绑定到 HTTP 监听器 (sectionName: http) 并应用 RequestRedirect 过滤器,将方案更改为 HTTPS 并返回 301 永久重定向。

应用重定向路由:

kubectl apply -f http-redirect.yaml

现在您可以删除第一部分中的原始 HTTP 路由,因为所有 HTTP 流量都将被重定向:

kubectl delete httproute demo-route -n demo

第六步:测试 TLS 配置

首先,获取 HTTP 和 HTTPS 的 NodePort 分配:

kubectl get svc -n nginx-gateway

注意映射到 80 (HTTP) 和 443 (HTTPS) 的端口。在此示例中,我们假设 HTTP 在端口 31080 上,HTTPS 在端口 31443 上。

测试 HTTPS 访问

使用 curl 结合 --resolve 将主机名映射到您的节点 IP。-k 标志跳过自签名证书的验证:

# Test web endpoint over HTTPS
curl -k --resolve demo.example.com:31443:<NODE_IP> \
  https://demo.example.com:31443/web

# Test API endpoint over HTTPS
curl -k --resolve demo.example.com:31443:<NODE_IP> \
  https://demo.example.com:31443/api

测试 HTTP 重定向

验证 HTTP 请求是否收到 301 重定向到 HTTPS:

curl -I --resolve demo.example.com:31080:<NODE_IP> \
  http://demo.example.com:31080/

预期响应: HTTP/1.1 301 Moved Permanently Location: https://demo.example.com/

验证证书详细信息

检查网关提供的证书:

echo | openssl s_client -connect <NODE_IP>:31443 \
  -servername demo.example.com 2>/dev/null | \
  openssl x509 -noout -subject -dates

总结

您已成功为您的 Nginx Gateway Fabric 部署添加了 TLS 支持。最终配置包括:

  • 一个带有 HTTP (端口 80) 和 HTTPS (端口 443) 监听器的 Gateway。
  • 使用 Kubernetes secret 在网关处进行 TLS 终止。
  • 一个用于 HTTPS 流量的 HTTPRoute,绑定到 https 监听器。
  • 使用 Gateway API 的原生 RequestRedirect 过滤器实现 HTTP 到 HTTPS 的自动重定向。

本教程中创建的资源:

资源名称命名空间
Secretdemo-tls-secretnginx-gateway
Gatewaydemo-gateway (已更新)nginx-gateway
HTTPRoutedemo-route-httpsdemo
HTTPRoutehttp-to-https-redirectdemo

生产环境建议

对于生产部署,请使用 cert-manager 自动化证书管理来替换自签名证书:

# Install cert-manager
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.14.0/cert-manager.yaml

为 Let’s Encrypt 创建一个 ClusterIssuer,并为您的 Gateway 添加注解以自动配置证书。有关 Gateway API 集成详情,请参阅 cert-manager 文档。

额外的安全强化:

  • 使用 Prometheus 指标监控证书过期。
  • 使用 Nginx Gateway Fabric 的策略资源实现 HSTS 标头。
  • 为不同的域名或环境使用独立的证书。
  • 证书至少每年轮换一次,最好通过自动化更频繁地轮换。

展望未来

本教程演示了如何通过 TLS 终止和自动 HTTP 重定向来保护您的 Gateway API 实现。Gateway API 对这些模式的本地支持——通过 tls.mode: TerminateRequestRedirect 过滤器——消除了 Ingress 配置中困扰已久的供应商特定注解的需求。

在后续教程中,我们将探索高级流量管理模式,包括带流量拆分的金丝雀部署、基于标头的 A/B 测试路由、速率限制和请求节流,以及多租户集群的跨命名空间路由。

您在此处构建的安全基础——包括适当的 TLS 终止和重定向处理——是这些生产场景必不可少的基础工作。敬请关注!