更多精彩内容,欢迎观看:
《云原生网络数据面可观测性最佳实践》—— 一、容器网络内核原理———2.netfilter框架(上):https://developer.aliyun.com/article/1221730?groupCode=supportservice
2) netfilter的常见应用
conntrack连接跟踪
conntrack是netfilter提供的核心功能之一,通过对tcp,udp等协议的连接状态的记录,来实现连接的会话状态保持的功能,例如:
● 对于iptables或者ipvs进行的NAT操作,可以记录单个已经建立的连接的NAT信息,对于相同的tcp连接,可以减少NAT操作中分配五元组计算的频率,保持连接状态的存续。
● 对于没有建立完成的连接,也不是握手请求的情况,可以在查不到conntrack的情况下避免其进入协议栈,从而减少非必要的消耗。
● 在Linux中,我们可以借助conntrack-tools工具提供的conntrack命令来管理conntrack操作,常见的使用方法如下:
# 输出当前netns中所有的conntrack条目信息 conntrack -L # 通过netlink stream的方式实时观察conntrack的写入事件 conntrack -E # 查看按照cpu进行统计的conntrack数据 conntrack -S
conntrack在内核中也是通过注册在netfilter上的hook函数进行工作的,此外,conntrack机制还依赖于按照cpu的数量来为每一个cpu分配一块用于存放conntrack信息的内存,以下是conntrack机制在Linux上的实现:
static const struct nf_hook_ops ipv4_conntrack_ops[] = { { .hook = ipv4_conntrack_in, .pf = NFPROTO_IPV4, .hooknum = NF_INET_PRE_ROUTING, .priority = NF_IP_PRI_CONNTRACK, }, { .hook = ipv4_conntrack_local, .pf = NFPROTO_IPV4, .hooknum = NF_INET_LOCAL_OUT, .priority = NF_IP_PRI_CONNTRACK, }, { .hook = ipv4_helper, .pf = NFPROTO_IPV4, .hooknum = NF_INET_POST_ROUTING, .priority = NF_IP_PRI_CONNTRACK_HELPER, }, { .hook = ipv4_confirm, .pf = NFPROTO_IPV4, .hooknum = NF_INET_POST_ROUTING, .priority = NF_IP_PRI_CONNTRACK_CONFIRM, }, { .hook = ipv4_helper, .pf = NFPROTO_IPV4, .hooknum = NF_INET_LOCAL_IN, .priority = NF_IP_PRI_CONNTRACK_HELPER, }, { .hook = ipv4_confirm, .pf = NFPROTO_IPV4, .hooknum = NF_INET_LOCAL_IN, .priority = NF_IP_PRI_CONNTRACK_CONFIRM, }, };
网络地址转换
NAT网络地址转换是netfilter框架提供的核心功能之一,NAT作为网络中非常重要的概念,在云原生场景下提供很多功能,包括:
● 在多种cni插件的数据面设计中,依赖nat实现跨节点的pod之间的通信。
● 通过nat实现service与pod之间的负载均衡。
iptables和ipvs都可以实现NAT功能,其中ipvs通常都是用于对目的地址进行NAT操作,也就是DNAT,iptables则具有包括masquerade在内的多种NAT组合而来的复杂功能,例如,在默认的docker容器访问公网的场景中,为了能够让节点内的,只有内网地址的docker容器可以正常访问公网,就需要添加如下的一条规则:
# 对于从eth0出节点的流量,访问目的为123.12.23.43的,自动将源地址切换为节点的出公网地址 iptables -t nat -A POSTROUTING -o eth0 -j SNAT --to 123.12.23.43
iptables的NAT有多个实现,目前版本较新并且被广泛采用的是基于nft的iptables,对于IPv4协议,nft实现的NAT功能在netfilter中注册的hook方法有如下几个:
static const struct nf_hook_ops nf_nat_ipv4_ops[] = { /* Before packet filtering, change destination */ { .hook = nf_nat_ipv4_in, .pf = NFPROTO_IPV4, .hooknum = NF_INET_PRE_ROUTING, .priority = NF_IP_PRI_NAT_DST, }, /* After packet filtering, change source */ { .hook = nf_nat_ipv4_out, .pf = NFPROTO_IPV4, .hooknum = NF_INET_POST_ROUTING, .priority = NF_IP_PRI_NAT_SRC, }, /* Before packet filtering, change destination */ { .hook = nf_nat_ipv4_local_fn, .pf = NFPROTO_IPV4, .hooknum = NF_INET_LOCAL_OUT, .priority = NF_IP_PRI_NAT_DST, }, /* After packet filtering, change source */ { .hook = nf_nat_ipv4_fn, .pf = NFPROTO_IPV4, .hooknum = NF_INET_LOCAL_IN, .priority = NF_IP_PRI_NAT_SRC, }, };
2) netfilter在云原生中的应用
基于ipvs实现Service
ipvs是基于netfilter框架实现的Linux内核态负载均衡器,通过DNAT方式来实现负载均衡,在云原生场景下,由于性能上的优势,ipvs是实现Service功能的首选,我们可以通过以下命令来简单的查看Service真正产生在网络数据面的ipvs规则:
# 查看ipvs connection信息,在出节点是,ipvs connection是独立并且优先于conntrack机制的选择,即流量会优先匹配到ipvs的规则,如果没有命中,才会进入conntrack的匹配逻辑 ipvsadm -Lnc # 添加一个service 192.168.1.100:80,将192.168.1.123作为他的一个real server后端 ipvsadm -A -t 192.168.1.100:80 -s rr ipvsadm -a -t 192.168.1.100:80 -r 192.168.1.123 -g -w 2 # 查看不同的ipvs service的数据统计 ipvsadm -Ln --stats
基于iptables实现NetworkPolicy
NetworkPolicy是云原生网络中非常重要的网络功能,其核心在于如何对流量进行权限管理,通常cni插件会采用iptables队policy未放行的流量进行屏蔽操作,实现NetworkPolicy的功能。
ipables实现NetworkPolicy功能的数据面原理非常简单,通过白名单放行的方式,默认丢弃所有流量,只允许白名单中的流量,即可实现简单的NetworkPolicy功能,我们可以通过以下几个命令简单模拟iptables实现的NetworkPolicy:
# 默认丢弃所有流量 iptables -A INPUT -j DROP # 将192.168.1.100的80端口进行放行 iptables -A INPUT -s 192.168.1.100 -p tcp -m tcp --dport 80 -j ACCEPT