PAYATHON 2026

如何防止绕过 Kong API gateway 直接访问微服务 API

支付阿杰

结论

不要把微服务端口直接暴露到公网。Kong 应当是唯一的公开入口,Payment service 只接受来自 Kong 的网络连接。如果内部网络也不可信,还需要使用 mTLS,确认调用方确实是 Kong。

API key、Basic Auth、HMAC 等机制用于验证外部客户端,适合配置在 Kong 上。防止请求绕过网关,则要依靠网络隔离和服务身份认证,不能只靠这些插件。

建议按以下顺序部署防护措施:

  1. 只为 Kong 配置公网入口。
  2. Payment service 使用私有地址,不配置公网负载均衡或端口映射。
  3. 通过防火墙、安全组或 Kubernetes NetworkPolicy,只允许 Kong 访问 Payment service。
  4. 为高风险服务配置 Kong 到上游服务的 mTLS。
  5. Payment service 无需重复验证客户端 API key,但仍要执行业务授权和数据权限检查。

为什么只在 Kong 中验证 API key 仍然安全

认证逻辑可以集中在网关上,但后端服务必须位于网关保护的信任边界内:

Internet
   |
   v
[Kong: client authentication]
   |
   | private network / mTLS
   v
[Payment service]

别人知道 Payment service 的地址,不代表能够访问它。需要关注的是网络路径是否可达,以及服务是否会接受该连接。

如果 Payment service 拥有公网 IP,或者任意主机都能访问其端口,攻击者确实可以绕过 Kong。隐藏 IP、使用难以猜测的域名,或者检查自定义 HTTP Header,都无法解决这个问题。

不要把下面这种 Header 当作安全凭据:

X-Request-From: kong

客户端也能构造相同的 Header。只有网络访问控制、TLS 客户端证书或其他不可伪造的服务身份,才能可靠地证明请求来自 Kong。

Kong 的认证配置

下面是一个简化的 Kong declarative configuration。外部请求通过 key-auth 插件验证后,才会转发到 Payment service:

_format_version: "3.0"

services:
  - name: payment-service
    url: http://payment.default.svc.cluster.local:8080

    routes:
      - name: payment-route
        paths:
          - /payments
        strip_path: false

    plugins:
      - name: key-auth
        config:
          key_names:
            - apikey
          hide_credentials: true

外部客户端通过 Kong 发起请求:

curl \
  -H "apikey: <client-api-key>" \
  https://api.example.com/payments

API key 应通过 Kong 支持的管理方式安全创建和保存,不要将真实密钥提交到代码仓库。声明式字段和管理接口可能随 Kong 版本及部署模式变化,具体配置应以当前所用版本的 Kong 文档为准。

在 Kubernetes 中限制后端访问

Payment service 应使用默认的 ClusterIP,不要配置为 LoadBalancer,也不要通过 NodePort 对外开放:

apiVersion: v1
kind: Service
metadata:
  name: payment
  namespace: payments
spec:
  type: ClusterIP
  selector:
    app: payment
  ports:
    - name: http
      port: 8080
      targetPort: 8080

再通过 NetworkPolicy,只允许 Kong namespace 中带有指定标签的 Pod 访问 Payment service:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: payment-ingress-from-kong
  namespace: payments
spec:
  podSelector:
    matchLabels:
      app: payment

  policyTypes:
    - Ingress

  ingress:
    - from:
        - namespaceSelector:
            matchLabels:
              kubernetes.io/metadata.name: kong
          podSelector:
            matchLabels:
              app: kong
      ports:
        - protocol: TCP
          port: 8080

该策略选中 Payment Pod 后,只允许规则中明确声明的入站流量。部署时还要确认以下事项:

  • 集群使用的 CNI 插件支持并实际执行 NetworkPolicy。
  • app: kong 等标签与实际部署一致。
  • 如果监控、健康检查或运维工具需要访问 Payment service,也要为它们显式添加规则。
  • hostNetwork、节点级代理和某些特殊网络模式可能影响策略效果,需要在实际集群中验证。

即使攻击者知道 payment.payments.svc.cluster.local 或对应的 Cluster IP,只要连接不来自允许访问的 Kong Pod 身份和网络范围,仍会被拒绝。

在云服务器或虚拟机中限制访问

如果 Kong 和服务运行在虚拟机上,可以用私有子网和安全组建立相同的访问边界:

Kong security group:
  inbound  443  <- Internet
  outbound 8080 -> Payment security group

Payment security group:
  inbound 8080 <- Kong security group only
  no public IP

优先按照安全组身份授权,不要写死 Kong 的单个 IP。Kong 扩容、故障迁移或地址变化时,基于安全组的规则更容易维护。

如果环境只能使用主机防火墙,Payment service 应绑定到私有网卡地址,并且只允许 Kong 节点访问服务端口。规则在逻辑上应满足:

ALLOW tcp/8080 FROM <Kong private subnet or hosts>
DENY  tcp/8080 FROM all other sources

不要让 Payment service 监听公网网卡,也不要通过 Docker ports、云负载均衡或路由器端口转发将其发布到公网。

内部网络不可信时使用 mTLS

限制 Kong 所在网段访问,可以阻止公网请求绕过网关,但未必能防住内网中已经失陷的主机。如果 Payment 是资金类高风险服务,建议在 Kong 和 Payment service 之间启用 mTLS:

  • Payment service 持有服务端证书。
  • Kong 验证 Payment service 的服务端证书。
  • Kong 使用专用客户端证书连接 Payment service。
  • Payment service 只信任签发 Kong 客户端证书的内部 CA。
  • 没有提供有效客户端证书的连接会在 TLS 握手阶段被拒绝。

两类认证分别承担不同职责:

Client -- API key / HMAC --> Kong -- mTLS --> Payment service

API key 或 HMAC 用于证明「外部客户端是谁」,mTLS 用于证明「调用 Payment service 的是 Kong」。Kong 上游 TLS 和客户端证书的配置方式取决于 Kong 版本、部署模式以及是否使用 Ingress Controller,需要根据实际版本配置,不能用一个自定义 Header 代替。

后端仍然需要保留哪些安全逻辑

把认证集中到 Kong,不代表 Payment service 可以忽略其他安全问题。后端至少还要负责:

  • 校验业务输入,不能假设经过网关的数据天然可信。
  • 检查用户是否有权访问对应的账户、订单或支付记录。
  • 防止越权、重复支付、金额篡改和重放等业务攻击。
  • 不盲目信任客户端传入的身份 Header。
  • 为敏感操作记录审计日志,并设置超时和幂等机制。

如果 Kong 通过 Header 将认证后的用户信息传给 Payment service,必须先删除客户端可能提交的同名 Header,再写入由 Kong 生成的值。与此同时,Payment service 仍然只能允许 Kong 访问。否则,攻击者可以绕过 Kong,直接伪造这些身份 Header。

运维入口也不要破坏隔离

开发人员或运维系统需要直接调试 Payment service 时,不要为了方便临时把端口暴露到公网。可以使用以下方式:

  • VPN 或零信任访问代理;
  • 堡垒机;
  • Kubernetes port-forward;
  • 独立的内部管理网关;
  • 有审计能力的短期访问授权。

生产环境中的健康检查接口、指标接口和调试接口也应位于私有网络内,必要时可以使用独立端口,并配置更严格的访问规则。

Kong 负责认证外部客户端,基础设施保证后端只能由 Kong 访问,微服务负责业务授权。把这三层职责分开,既能避免每个服务重复实现 API key 或 HMAC 验证,也能防止外部请求绕过网关直接访问后端。

备注:内容仅供参考。