在容器服务中获取客户端真实源 IP

适用范围:腾讯云容器服务(Tencent Kubernetes Engine ,TKE), 如下简称 TKE。nginx

为何须要获取客户端真实源 IP?

当须要能感知到服务请求来源去知足一些业务需求时,就须要后端服务能准确获取到请求客户端的真实源 IP, 好比如下场景:后端

  1. 对服务请求的来源有作审计的需求,如异地登录告警。
  2. 针对安全或安全事件溯源需求,如 APT 、DDoS ***等。
  3. 业务场景数据分析需求,如业务请求区域统计。
  4. 其余须要获取客户端地址的需求。

在 TKE 使用场景下如何获取客户端真实源 IP?

在TKE中默认的外部负载均衡器是 腾讯云负载均衡器,做为服务流量的访问首入口,腾讯云负载均衡器会将请求流量负载转发到 Kubernetes 工做节点的 Kubernets Service(默认),此负载均衡过程会保留客户端真实源 IP(透传转发),但在 Kubernetes Service 转发场景下,不管是使用 iptbales 仍是 ipvs 的负载均衡转发模式,转发时都会对数据包作 SNAT,即不会保留客户端真实源 IP,为了可以准确的获取到客户端的真实源 IP,在 TKE 使用场景下,主要有四种方法获取客户端真实源 IP,下面将逐个展开介绍下。api

1、经过 Service 资源的配置选项保留客户端源 IP

要启用保留客户端 IP 功能,可在 Service 资源中配置字段 Service.spec.externalTrafficPolicy,此字段表示服务是否但愿将外部流量路由到节点本地或集群范围的端点。有两个选项值:Cluster(默认)和 Local 方式,以下图所示:安全

img

Cluster 表示隐藏了客户端源 IP, LoadBalancerNodePort 类型服务流量可能会被转发到其余节点的 Pods; Local 表示保留客户端源 IP 并避免 LoadBalancerNodePort 类型的服务流量转发到其余节点的 Pods,详情请参考 kubernets设置外部负载均衡器说明。相关 YAML 配置示例以下:服务器

apiVersion: v1
kind: Service
metadata:
  name: example-Service
spec:
  selector:
    app: example-Service
  ports:
    - port: 8765
      targetPort: 9376
  externalTrafficPolicy: Local
  type: LoadBalancer

优势:只须要修改 Kubernets Service 资源配置便可。网络

缺点:会存在潜在的 Pods(Endpoints)流量负载不均衡风险。app

2、经过TKE原生的 CLB 直通 Pod 转发模式获取

使用TKE原生支持的 CLB 直通 Pod 的转发功能(CLB 透传转发,并绕过 Kubernetes Service 流量转发),后端 Pods 收到的请求的源IP便是客户端真实源IP,此方式不管是在四层仍是七层服务的转发场景下都适用,转发原理以下图:负载均衡

img

详细介绍和配置请参考文档 TKE场景下腾讯云CLB直通Pod使用场景介绍ide

优势:TKE原生支持的功能特性,只需在控制台按照文档配置便可。函数

缺点:集群须要开启 VPC-CNI 模式网络,详情参考文档 VPC-CNI 模式说明

3、经过 HTTP Header 获取

在七层(HTTP/HTTPS)服务转发场景下,能够经过获取 Http Header 中 X-Forwarded-ForX-Real-IP 字段的值来获取客户端真实源 IP, TKE 中有两种场景使用方式,原理介绍以下:

img

在场景一中,腾讯云负载均衡器(CLB 七层) 默认会将客户端真实源IP放到 HTTP Header 的 X-Forwarded-ForX-Real-IP 字段,当服务流量在通过 Service 四层转发后会保留上述字段,后端经过WEB服务器代理配置或应用代码方式获取到客户端真实源IP,详情参考请文档 负载均衡如何获取客户端真实 IP - 最佳实践 - 文档中心 - 腾讯云

在场景二中, Nginx Ingress 服务部署须要 Nginx Ingress 能直接感知客户端真实源 IP,能够采用保留客户端源IP的配置方式(详情参考 kubernets设置外部负载均衡器说明 ),或经过 CLB 直通 Pod 的方式(详情参考 TKE场景下腾讯云CLB直通Pod使用场景介绍),当 Nginx Ingress 在转发请求时会经过 X-Forwarded-ForX-Real-IP 字段来记录客户端源 IP,后端能够经过此字段得到客户端真实源 IP。

下面详细介绍在 TKE 中两种场景的配置使用方法:

  • 场景一:使用 TKE Ingress 获取真实源 IP

    在TKE控制台先为工做负载建立一个主机端口访问方式的 Service 资源,以下图:

img

而后在控制台为 Service 新建一个对应的 Ingress 访问入口,以下图:

img

待配置生效后,在后端经过获取 HTTP Header 中的 X-Forwarded-ForX-Real-IP 字段值获得客户端真实源 IP。后端抓包测试结果示例以下:

img

  • 场景二: 使用 Nginx Ingress 获取真实源 IP

Nginx Ingress 能够经过 TKE 应用商店、自定义 YAML 配置或使用官方(helm 安装)方式安装,原理和部署方法可参考文档 在 TKE 上部署 Nginx Ingress 中的部署方案一或方案三,若选择方案一部署,则须要修改 Nginx Ingress Controller Service 的 externalTrafficPolicy 字段值为 Local 。安装完成后,会在TKE控制台自动为 Nginx Ingress Controller 服务建立一个 CLB(四层)访问入口,以下图所示:

img

为要转发的后端服务建立一个 Ingress 资源并配置转发规则, 能够使用如下 YAML 建立:

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  annotations:
    kubernetes.io/ingress.class: nginx  # ingressClass类为"nginx"
  name: example
  namespace: default
spec:
  rules:  # 配置服务转发规则
     - http:
        paths:
          - backend:
              serviceName: nginx  
              servicePort: 80
            path: /

待配置生效后,在后端获取 Http Header 中的 X-Forwarded-ForX-Real-IP 字段值获得客户端真实源 IP,后端抓包测试结果示例以下:

img

以上介绍的两种场景均可以知足获取客户端真实源 IP 的需求,且具备如下优势和缺点:

优势:在七层(HTTP/HTTPS)流量转发场景下比较推荐,可经过WEB服务代理的配置或后端应用代码直接获取 Http Header 中的字段便可拿到客户端真实IP,很是简单高效。

缺点:仅适用于七层(HTTP/HTTPS)流量转发场景,不适用于四层转发场景,若是是四层转发场景,请使用后面介绍的其余方式。

4、经过 TOA 内核模块加载获取真实源 IP

TOA 内核模块原理和加载方式参考 全球应用加速 获取访问用户真实 IP - 操做指南 - 文档中心 - 腾讯云 文档。

优势:对于 TCP 传输方式,在内核层面且仅对 TCP 链接的首包进行改造,几乎没有性能损耗。

缺点

  1. 须要在集群工做节点上加载 TOA 内核模块,且需在服务端经过函数调用获取携带的源 IP、端口信息,配置使用比较麻烦。
  2. 对于 UDP 传输方式,会对每一个数据包改造添加 option 数据(源 IP 和源端口),带来网络传输通道性能损耗。

总结

本文主要介绍了在TKE使用场景下服务端如何获取客户端真实源 IP,以知足用户相关使用场景的需求,用户可经过对比上述四几种方式的优势和缺点,选择适合实际需求场景的最佳方案。

参考资料

相关文章
相关标签/搜索