首页 > 所有文章 > 行业 >文章详情

apicloud 获取ip(api接口)

时间:2023-10-28 16:55:54 浏览量:51

绝大多数业务场景都是需要知道客户端IP的 在k8s中运行的业务项目,如何获取到客户端真实IP? 本文总结了通行的2种方式 要答案的直接看方式一、方式二和总结 SEO 关键字 nginx ingress客户端真实ip kubernets获取客户端真实ip rke获取客户端真实ip rancher获取客户端真实ip 本文由 www.iamle.com 流水理鱼 原创,wx公众号同名

7层转发链路 Client(客户端) > Nginx > K8s Ingress(Nginx ingress) 4层转发链路 Client(客户端) > 公有云LB > K8s Ingress(Nginx ingress) ps: 实际业务会串联更多层级的转发。WAF、CDN、Api Gateway一般是http 7层转发,LB一般是4层tcp转发

whomai是一个go编写的调试探针工具,回显http头信息 在k8s中部署一个containous/whoami用来作为探针,配置好ingress公网和访问,这样客户端web访问可以看到基本的http头信息,方便调试

ps:ingress自行增加

客户端web访问,回显http头示例

获得客户端真实IP有针对7层和针对4层两种方式

http工作在网络第7层,http中有个X-Forwarded-For字段

大部分CDN、WAF、LB用X-Forwarded-For字段来存客户端IP,也有用X-Real-Ip字段,cloudflare、百度云加速还扩展了CF-Connecting-IP字段 标准数据为

第一个ip是客户端ip,后面的proxy为路过一层就加一层的ip 这里的proxy可以是WAF、CDN、LB、Api Gateway等

tcp工作在网络第4层,Proxy Protocol就是在tcp中增加一个小的报头,用来存储额外的信息

代理协议即 Proxy Protocol,是haproxy的作者Willy Tarreau于2010年开发和设计的一个Internet协议,通过为tcp添加一个很小的头信息,来方便的传递客户端信息(协议栈、源IP、目的IP、源端口、目的端口等),在网络情况复杂又需要获取客户IP时非常有用。 其本质是在三次握手结束后由代理在连接中插入了一个携带了原始连接四元组信息的数据包。

目前 proxy protocol有两个版本,v1仅支持human-readable报头格式(ASCIII码),v2需同时支持human-readable和二进制格式,即需要兼容v1格式 proxy protocol的接收端必须在接收到完整有效的 proxy protocol 头部后才能开始处理连接数据。因此对于服务器的同一个监听端口,不存在兼容带proxy protocol包的连接和不带proxy protocol包的连接。如果服务器接收到的第一个数据包不符合proxy protocol的格式,那么服务器会直接终止连接。

Proxy protocol是比较新的协议,但目前已经有很多软件支持,如haproxy、nginx、apache、squid、mysql等等,要使用proxy protocol需要两个角色sender和receiver,sender在与receiver之间建立连接后,会先发送一个带有客户信息的tcp header,因为更改了tcp协议头,需receiver也支持proxy protocol,否则不能识别tcp包头,导致无法成功建立连接。 nginx是从1.5.12起开始支持的

适用于7层http转发

查看NGINX Ingress Controller的ConfigMaps配置文档,可以找到以下配置项 use-forwarded-headers 如果为true,NGINX会将传入的 X-Forwarded-* 头传递给upstreams。当NGINX位于另一个正在设置这些标头的 L7 proxy / load balancer 之后时,请使用此选项。 如果为false,NGINX会忽略传入的 X-Forwarded-* 头,用它看到的请求信息填充它们。如果NGINX直接暴露在互联网上,或者它在基于 L3/packet-based load balancer 后面,并且不改变数据包中的源IP,请使用此选项。 ps: NGINX Ingress Controller直接暴露互联网也就是Edge模式不能开启为true,否则会有伪造ip的安全问题。也就是k8s有公网ip,直接让客户端访问,本配置不要设为true!

forwarded-for-header 设置标头字段以标识客户端的原始IP地址。 默认: X-Forwarded-For ps:如果 NGINX Ingress Controller 在CDN,WAF,LB等后面,设置从头的哪个字段获取IP,默认是X-Forwarded-For 这个配置应该和use-forwarded-headers配合使用

compute-full-forwarded-for 将远程地址附加到 X-Forwarded-For 标头,而不是替换它。 启用此选项后,upstreams应用程序将根据其自己的受信任代理列表提取客户端IP

修改configmap nginx-configuration配置

在apiVersion: v1下,kind: ConfigMap上加入

或者直接apply附加配置

ps:如果nginx-configuration不在namespace ingress-nginx中就在namespace kube-system中找

作为Edge需要重写remote_addr,保证了客户端IP不会被伪造 必须:X-Forwarded-For 重写为 $remote_addr 非必须扩展:X-Real-IP 重写为 $remote_addr

客户端是否能伪造IP,取决于边缘节点(Edge)是如何处理X-Forwarded-For字段的。 客户端直接连接的首个proxy节点都叫做边缘节点(Edge),不管是网关、CDN、LB等只要这一层是直接接入客户端访问的,那么他就是一个边缘节点。

不重写-不安全的边缘节点(Edge) 边缘节点如果是透传http头中的X-Forwarded-For字段,那么这个就是不安全的,客户端可以在http中实现包含X-Forwarded-For字段值,这个值又被透传了。

重写-安全的边缘节点(Edge) 边缘节点(Edge)如果重写remote_addr到X-Forwarded-For,那么这就是安全的。边缘节点(Edge)获取的remote_addr就是客户端的真实IP

适用于4层tcp转发 公有云的负载均衡LB一般都支持Proxy Protocol

查看NGINX Ingress Controller的ConfigMaps配置文档,可以找到如何配置Proxy Protocol use-proxy-protocol 启用或禁用roxy Protocol,以接收通过代理服务器和负载均衡器(例如HAProxy和Amazon Elastic Load Balancer(ELB))传递的客户端连接(真实IP地址)信息。

NGINX Ingress Controller 作为receiver角色 Proxy Protocol配置

在apiVersion: v1下,kind: ConfigMap上加入

或者直接apply附加配置

ps: 注意需要上一层LB支持Proxy Protocol,才能这么配置,否则会导致无法链接

7层http头X-Forwarded-For透传 链路proxy有透传X-Forwarded-For 访问链路上多层proxy,任意一个节点不支持Proxy Protocol

4层协议Proxy Protocol透传 上下游可控都支持Proxy Protocol协议 链路proxy中丢失了http头 https反向代理http(某些情况下由于Keep-alive导致不是每次请求都传递x-forword-for

应该用那种方式? 7层用X-Forwarded-For,4层用Proxy Protocol 如果链路的边缘节点(Edge)X-Forwarded-For字段是安全的,建议用X-Forwarded-For 如果链路proxy全路径都支持Proxy Protocol,那么建议用Proxy Protocol 如果有4层tcp业务应用,那么获取客户端IP就的用Proxy Protocol 总之搞清楚了这2种方式的原理按照场景选择