Gateway API 实践之(八)FSM Gateway SSL 代理终端与 TLS 上游

FSM Gateway 流量管理策略系列:


网关使用 HTTP 对外与客户端通信,而与上游服务使用 HTTPS 的功能,是一种常见的网络架构模式。在这种模式下,网关承担了 SSL/TLS 加密的终端角色,确保与上游服务之间的通信安全加密。这意味着,尽管客户端与网关之间的通信使用的是标准的非加密 HTTP 协议,但网关会将这些请求安全地转换为 HTTPS 请求与上游服务进行通信。

这种架构有几个关键优点:

  • 安全性增强:通过在网关层实施 HTTPS,上游服务与网关之间的数据传输得到加密,从而增强了数据的安全性。这对于敏感数据的传输尤其重要。
  • 简化证书管理:所有的 SSL/TLS 证书都可以在网关处集中管理,而不需要在每个上游服务上单独配置和管理。这大大简化了证书的更新和管理工作,降低了出错的可能性。
  • 性能和兼容性:对于某些旧的或受限的客户端设备,可能不支持 HTTPS 或者 HTTPS 的开销过大。使用这种模式,可以在不牺牲内部通信安全的前提下,为这些客户端提供服务。
  • 灵活的安全策略:网关可以根据需要对流量进行检查和修改,例如实施安全策略、进行内容缓存、请求路由等。

接下来,我们一起看下如何使用 FSM Gateway 的 SSL 代理终端模式来实现与上游的 TLS 加密传输。

前置条件

  • Kubernetes 集群
  • kubectl 工具

环境准备

安装 FSM Gateway

FSM Gateway 的安装,可以参考 安装文档。这里选择 CLI 的方式安装。

下载 FSM CLI。

shell 复制代码
system=$(uname -s | tr '[:upper:]' '[:lower:]')
arch=$(uname -m | sed -E 's/x86_/amd/' | sed -E 's/aarch/arm/')
release=v1.2.0
curl -L https://github.com/flomesh-io/fsm/releases/download/$release/fsm-$release-$system-$arch.tar.gz | tar -vxzf -
./$system-$arch/fsm version
sudo cp ./$system-$arch/fsm /usr/local/bin/fsm

在安装 FSM 时启用 FSM Gateway,默认情况是不启用的。

shell 复制代码
fsm install \
    --set=fsm.fsmGateway.enabled=true

部署示例应用

我们的上游应用是 HTTPS 的,因此需要先颁发自签名的证书。下面的命令分别生成了 CA 证书、服务器证书以及密钥。

shell 复制代码
openssl genrsa 2048 > ca-key.pem

openssl req -new -x509 -nodes -days 365000 \
   -key ca-key.pem \
   -out ca-cert.pem \
   -subj '/CN=flomesh.io'

openssl genrsa -out server-key.pem 2048
openssl req -new -key server-key.pem -out server.csr -subj '/CN=foo.example.com'
openssl x509 -req -in server.csr -CA ca-cert.pem -CAkey ca-key.pem -CAcreateserial -out server-cert.pem -days 365

使用服务器证书和密钥创建 Secret server-cert

shell 复制代码
kubectl create namespace httpbin
#TLS cert secret
kubectl create secret generic -n httpbin server-cert \
  --from-file=./server-cert.pem \
  --from-file=./server-key.pem

示例应用依然使用 httpbin 镜像,不过这次将会使用上面创建的证书和密钥开启 TLS。

shell 复制代码
kubectl apply -n httpbin -f - <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
  name: httpbin
spec:
  replicas: 1
  selector:
    matchLabels:
      app: httpbin
  template:
    metadata:
      labels:
        app: httpbin
    spec:
      containers:
      - name: httpbin
        image: kennethreitz/httpbin
        ports:
        - containerPort: 443
        volumeMounts:
        - name: cert-volume
          mountPath: /etc/httpbin/certs  # Mounting path in the container
        command: ["gunicorn"]
        args: ["-b", "0.0.0.0:443", "httpbin:app", "-k", "gevent", "--certfile", "/etc/httpbin/certs/server-cert.pem", "--keyfile", "/etc/httpbin/certs/server-key.pem"]
      volumes:
      - name: cert-volume
        secret:
          secretName: server-cert
---
apiVersion: v1
kind: Service
metadata:
  name: httpbin
spec:
  selector:
    app: httpbin
  ports:
    - protocol: TCP
      port: 8443
      targetPort: 443
EOF

验证 HTTPS 是否已经开启。

shell 复制代码
export HTTPBIN_POD=$(kubectl get po -n httpbin -l app=httpbin -o jsonpath='{.items[0].metadata.name}')

kubectl port-forward -n httpbin $HTTPBIN_POD 8443:443 &
# access with CA cert
curl --cacert ca-cert.pem https://foo.example.com/headers --connect-to foo.example.com:443:127.0.0.1:8443
{
  "headers": {
    "Accept": "*/*",
    "Host": "foo.example.com",
    "User-Agent": "curl/8.1.2"
  }
}

创建网关和路由

接下来创建网关并为 Service httpbin 创建路由。

shell 复制代码
kubectl apply -n httpbin -f - <<EOF
apiVersion: gateway.networking.k8s.io/v1beta1
kind: Gateway
metadata:
  name: simple-fsm-gateway
spec:
  gatewayClassName: fsm-gateway-cls
  listeners:
  - protocol: HTTP
    port: 8000
    name: http
    allowedRoutes:
      namespaces:
        from: Same
---
apiVersion: gateway.networking.k8s.io/v1beta1
kind: HTTPRoute
metadata:
  name: http-route-foo
spec:
  parentRefs:
  - name: simple-fsm-gateway
    port: 8000
  hostnames:
  - foo.example.com
  rules:
  - matches:
    - path:
        type: PathPrefix
        value: /
    backendRefs:
    - name: httpbin
      port: 8443
EOF

此时,我们通过网关无法访问 httpbin,因为 httpbin 开启了 TLS 而网关无法验证 httpbin 的服务器证书。

shell 复制代码
curl http://foo.example.com/headers --connect-to foo.example.com:80:$GATEWAY_IP:8000
curl: (52) Empty reply from server

上游 TLS 策略验证

我们使用前面创建的 CA 证书创建一个 Secret https-cert

shell 复制代码
#CA cert secret
kubectl create secret generic -n httpbin https-cert --from-file=ca.crt=ca-cert.pem

接下来创建上游 TLS 策略 UpstreamTLSPolicy。参考文档 UpstreamTLSPolicy,为上游服务 httpbin 指定承载了 CA 证书的 Secret https-cert,网关将使用该证书验证 httpbin 的服务器证书。

shell 复制代码
kubectl apply -n httpbin -f - <<EOF
apiVersion: gateway.flomesh.io/v1alpha1
kind: UpstreamTLSPolicy
metadata:
  name: upstream-tls-policy-sample
spec:
  targetRef:
    group: ""
    kind: Service
    name: httpbin
    namespace: httpbin
  ports:
  - port: 8443
    config:
      certificateRef:
        namespace: httpbin
        name: https-cert
      mTLS: false
EOF

应用该策略,待策略生效后,再次尝试通过网关访问 httpbin 服务。

shell 复制代码
curl http://foo.example.com/headers --connect-to foo.example.com:80:$GATEWAY_IP:8000
{
  "headers": {
    "Accept": "*/*",
    "Connection": "keep-alive",
    "Host": "10.42.0.25:443",
    "User-Agent": "curl/8.1.2"
  }
}

关于 Flomesh

Flomesh(易衡科技)成立于 2018 年,自主研发并开源了高性能可编程代理 Pipy(https://github.com/flomesh-io/pipy)。以 Pipy 为基础,Flomesh 研发了软件负载均衡、服务网格两款软件产品。为工信部认证的可信云产品、可信开源项目。

Flomesh 核心竞争力来自完全自研的核心组件 Pipy,该组件高性能、高可靠、低延迟、可编程、可扩展、低依赖,采用 C++ 开发,内置自研的 JS 引擎,支持适用 JS 脚本做扩展开发。支持包括 x86、arm、龙芯、海光等硬件 CPU 架构;支持 Linux、FreeBSD、OpenWrt 等多种核心的操作系统。

Flomesh 成立以来,以技术为根基、以客户为导向,产品被应用在头部股份制商业银行总行、大型保险公司、运营商总部以及研究院等众多客户和多个场景。

相关推荐
Anna_Tong6 小时前
全局流量管理:提升用户体验与保障服务稳定性
运维·服务器·网络·数据库·安全·负载均衡
开着拖拉机回家12 小时前
【Ambari】使用 Knox 进行 LDAP 身份认证
大数据·hadoop·gateway·ambari·ldap·knox
洛神灬殇1 天前
彻底认识和理解探索分布式网络编程中的SSL安全通信机制
网络·分布式·ssl
m0_748238271 天前
WebClient HTTP 请求问题处理模板(泛型响应、忽略 SSL 证书等)
网络协议·http·ssl
୧⍢⃝୨ LonelyCoder1 天前
FreePBX修改IP地址和端口以及添加SSL证书开启HTTPS访问
tcp/ip·https·ssl
群联云防护小杜2 天前
如何给负载均衡平台做好安全防御
运维·服务器·网络·网络协议·安全·负载均衡
ljh5746491192 天前
负载均衡的原理
运维·负载均衡
BothSavage2 天前
Knife4j在Gateway下的URI优化以及热刷新
windows·gateway
与君共勉121382 天前
Nginx 负载均衡的实现
运维·服务器·nginx·负载均衡
壹佰大多3 天前
【spring-cloud-gateway总结】
java·spring·gateway