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?