istio流量拦截原理

环境

这里我们是在本机使用kind,安装

查看容器对应的虚拟设备对

for container in `crictl ps -q`
do
iflink=`crictl exec $container cat /sys/class/net/eth0/iflink`
iflink=`echo $iflink|tr -d '\r'`
veth=`grep -l $iflink /sys/class/net/*/ifindex`
veth=`echo $veth|sed -e 's;^.*net/\(.*\)/ifindex$;\1;'`
echo $container:$veth
done

查看iptables规则

ip netns exec cni-bf783dac-fe05-cb35-4d5a-848449119b19 iptables -L -t nat

-A PREROUTING -p tcp -j ISTIO_INBOUND                          # PREROUTING全部转发到INBOUND,PREROUTING发生在流入的数据包进入路由表之前
-A OUTPUT -p tcp -j ISTIO_OUTPUT                               # 由本机产生的数据向外转发的
-A ISTIO_INBOUND -p tcp -m tcp --dport 22 -j RETURN            # 22 15090  15021 15020的不转发到ISTIO_REDIRECT 
-A ISTIO_INBOUND -p tcp -m tcp --dport 15090 -j RETURN         
-A ISTIO_INBOUND -p tcp -m tcp --dport 15021 -j RETURN
-A ISTIO_INBOUND -p tcp -m tcp --dport 15020 -j RETURN
-A ISTIO_INBOUND -p tcp -j ISTIO_IN_REDIRECT                   # 剩余的流量都转发到ISTIO_REDIRECT
-A ISTIO_IN_REDIRECT -p tcp -j REDIRECT --to-ports 15006       # 转发到15006
-A ISTIO_OUTPUT -s 127.0.0.6/32 -o lo -j RETURN                # 127.0.0.6是InboundPassthroughBindIpv4,代表原地址是passthrough的流量都直接跳过,不劫持
-A ISTIO_OUTPUT ! -d 127.0.0.1/32 -o lo -m owner --uid-owner 1337 -j ISTIO_IN_REDIRECT  #lo网卡出流量,目标地址不是localhost的,且为同用户的流量进入ISTIO_IN_REDIRECT
-A ISTIO_OUTPUT -o lo -m owner ! --uid-owner 1337 -j RETURN    # lo网卡出流量 非同用户的不劫持
-A ISTIO_OUTPUT -m owner --uid-owner 1337 -j RETURN            # 剩下的同用户的都跳过
-A ISTIO_OUTPUT ! -d 127.0.0.1/32 -o lo -m owner --gid-owner 1337 -j ISTIO_IN_REDIRECT  # lo网卡出流量,目标地址非本地,同用户组的流量进入ISTIO_IN_REDIRECT
-A ISTIO_OUTPUT -o lo -m owner ! --gid-owner 1337 -j RETURN    # lo网卡出流量非同组的不劫持
-A ISTIO_OUTPUT -m owner --gid-owner 1337 -j RETURN            # 剩余的同用户的不劫持
-A ISTIO_OUTPUT -d 127.0.0.1/32 -j RETURN                      # 剩余的目标地址为127的不劫持
-A ISTIO_OUTPUT -j ISTIO_REDIRECT                              # 剩下的都进入 ISTIO_REDIRECT
-A ISTIO_REDIRECT -p tcp -j REDIRECT --to-ports 15001          # 转达到15001 outbond
COMMIT

请求流程分析

现在有httpbin和sleep两个服务,如果httpbin要访问sleep

  • httpbin访问sleep:80端口

  • iptables拦截转发到15001 的15001端口

virtualOutbound Listener

use_original_dst: 如果使用iptables重定向连接,则代理在其上接收连接的端口可能与原始目标地址不同.当此标志设置为true时,监听器将重定向到与原始目标地址关联的监听器的重定向连接.如果没有与原始目标地址关联的监听器,则连接由接收该监听器的监听器处理.默认为false。

我们原本请求的是 sleep:80,则在PassthroughCluster之后重新匹配符合sleep:80的规则

PassthroughCluster

匹配sleep:80的listener

匹配 route 80

因为配置较多 我们值展示对应sleep的route config

这里我们可以看到最终请求到了outbound|80||sleep.foo.svc.cluster.local 这个cluster,只有一个ep 10.244.1.12:80

sleep接收请求

sleep接收到请求将被iptables重定向到inboud port 15006

为了选择过滤器链,传入连接必须满足其所有条件,连接的属性由网络堆栈和/或监听器过滤器设置。

以下顺序适用:

  • 目的端口。

  • 目的IP地址。

  • 服务器名称(例如TLS协议的SNI),

  • 传输协议。

  • 应用协议(例如用于TLS协议的ALPN)。

prefix_ranges如果为非空,则在监听器绑定到0.0.0.0/::或指定use_original_dst时,指定IP地址和前缀长度以匹配地址。

流量到达sleep进行匹配

流量到达sleep的 inbound|80|http|sleep.foo.svc.cluster.local cluster

InboundPassthroughClusterIpv4

Last updated

Was this helpful?