FSM Gateway 流量管理策略系列:
故障注入黑白名单访问控制限速重试会话保持健康检查负载均衡算法TLS 上游双向 TLS
网关使用 HTTP 对外与客户端通信,而与上游服务使用 HTTPS 的功能,是一种常见的网络架构模式。在这种模式下,网关承担了 SSL/TLS 加密的终端角色,确保与上游服务之间的通信安全加密。这意味着,尽管客户端与网关之间的通信使用的是标准的非加密 HTTP 协议,但网关会将这些请求安全地转换为 HTTPS 请求与上游服务进行通信。
这种架构有几个关键优点:
安全性增强:通过在网关层实施 HTTPS,上游服务与网关之间的数据传输得到加密,从而增强了数据的安全性。这对于敏感数据的传输尤其重要。简化证书管理:所有的 SSL/TLS 证书都可以在网关处集中管理,而不需要在每个上游服务上单独配置和管理。这大大简化了证书的更新和管理工作,降低了出错的可能性。性能和兼容性:对于某些旧的或受限的客户端设备,可能不支持 HTTPS 或者 HTTPS 的开销过大。使用这种模式,可以在不牺牲内部通信安全的前提下,为这些客户端提供服务。灵活的安全策略:网关可以根据需要对流量进行检查和修改,例如实施安全策略、进行内容缓存、请求路由等。
接下来,我们一起看下如何使用 FSM Gateway 的 SSL 代理终端模式来实现与上游的 TLS 加密传输。
前置条件
Kubernetes 集群kubectl 工具
环境准备
安装 FSM Gateway
FSM Gateway 的安装,可以参考 安装文档。这里选择 CLI 的方式安装。
下载 FSM CLI。
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,默认情况是不启用的。
fsm install \
--set=fsm.fsmGateway.enabled=true
部署示例应用
我们的上游应用是 HTTPS 的,因此需要先颁发自签名的证书。下面的命令分别生成了 CA 证书、服务器证书以及密钥。
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。
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。
kubectl apply -n httpbin -f - < 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 是否已经开启。 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 创建路由。 kubectl apply -n httpbin -f - < 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 的服务器证书。 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。 #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 的服务器证书。 kubectl apply -n httpbin -f - < 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 服务。 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 成立以来,以技术为根基、以客户为导向,产品被应用在头部股份制商业银行总行、大型保险公司、运营商总部以及研究院等众多客户和多个场景。 好文阅读
发表评论