《云原生网络数据面可观测性最佳实践》—— 一、容器网络内核原理——2.netfilter框架(上)

简介: 《云原生网络数据面可观测性最佳实践》—— 一、容器网络内核原理——2.netfilter框架(上)

netfilter框架是Linux操作系统中内置的,通过向内核模块提供对协议栈中的网络数据包进行修改和操作的能力,来实现流量过滤,网络地址转换等高级功能。

 

1) netfilter如何工作

对于网络数据报文,网络设备驱动通过将二层的以太网数据报文按照Linux内核定义的网络设备驱动规范,以sk_buff结构体的方式进行接收或者发送,即通常我们所描述的报文的最小单元skb。

 

内核通过将网络设备缓冲区环形队列中skb取出,并按照以太网层,网络层,传输层顺序处理后,将报文数据放置到对应Socket缓冲区中,通知用户程序进行读取,从而完成收包

内核为Socket缓冲区待发送数据封装为skb,经过传输层,网络层和以太网层依次填充对应报头后,调用网络设备驱动方法将skb发送到网络上,从而完成发包

 

netfilter工作的核心原理则是在网络层,通过在五个不同的内核处理skb数据包的位置,执行注册到netfilter框架中的回调函数,并根据回调函数的返回来选择下一步的处理,实现复杂的功能。

 

netfilter触发时机

 

netfilter在内核网络数据包的处理流程中,注册了5个可以触发的时机,详情如下:

/* IP Hooks */
/* After promisc drops, checksum checks. */
#define NF_IP_PRE_ROUTING0
/* If the packet is destined for this box. */
#define NF_IP_LOCAL_IN1
/* If the packet is destined for another interface. */
#define NF_IP_FORWARD2
/* Packets coming from a local process. */
#define NF_IP_LOCAL_OUT3
/* Packets about to hit the wire. */
#define NF_IP_POST_ROUTING4
#define NF_IP_NUMHOOKS5
#endif /* ! __KERNEL__ */

 

根据源代码中的定义,我们可以参考下图:

 image.png

 从上面的代码定义和示意图中可以知道,在以下几个地方会调用netfilter定义好的方法对数据包进行处理:

 

数据包从网卡进入协议栈后,所有报文都会走到NF_IP_PRE_ROUTING

数据包经过入向路由选择后,确认是由本机传输层进行处理,会进入到NF_IP_LOCAL_IN

数据包经过入向路由选择后,不是由本机处理,需要转发给其他机器,会进入到NF_IP_FORWARD

由本机传输层发出报文,都会经过NF_IP_LOCAL_OUT

经过出向路由选择后报文,会经过NF_IP_POST_ROUTING,包括从本机发出和需要本机转发的。

 

在以上五个时机,当数据包skb到达时,netfilter框架定义的回调方法就会被内核执行。

 

netfilter如何操作网络数据

使用netfilter框架的模块,需要按照netfilter定义的结构体来实现自己的行为,才能正确注册到netfilter框架中,并被内核调用,netfilter约束的注册结构体的定义如下:

struct nf_hook_ops {
    // 这是真正被内核执行的函数,会对skb进行读取和修改
    nf_hookfn*hook;
    struct net_device*dev;
    void*priv;
    u_int8_tpf;
    // hooknum定义了回调函数生效的位置,从上文可知有五个位置可以选择
    unsigned inthooknum;
    // priority定义了回调函数的优先级,通过每个hook时机都会有多个回调函数需要生效
    intpriority;
};

以ipvlan模块为例:

static const struct nf_hook_ops ipvl_nfops[] = {
  {
    .hook     = ipvlan_nf_input,
    .pf       = NFPROTO_IPV4,
    .hooknum  = NF_INET_LOCAL_IN,
    .priority = INT_MAX,
  },
#if IS_ENABLED(CONFIG_IPV6)
  {
    .hook     = ipvlan_nf_input,
    .pf       = NFPROTO_IPV6,
    .hooknum  = NF_INET_LOCAL_IN,
    .priority = INT_MAX,
  },
#endif
};

 

我们可以看到,ipvlan模块根据IP协议的版本定义了两个hook结构体,其中:

hookfn是核心处理逻辑,ipvlan模块注册了ipvlan_nf_input方法

pf是netfilter协议版本,ipvlan模块分别注册了IPv6和IPv4对应方法

hooknum定义了这个hook在netfilter中生效位置,ipvlan模块将自己回调方法注册到了NF_INET_LOCAL_IN,也就是完成路由之后,进入传输层之前

priotity定义了hook优先级

 

那么,hookfn作为真正核心的处理逻辑,他是如何工作的呢?

 

以ipvlan注册在NF_INET_LOCAL_IN上的hook方法ipvlan_nf_input为例:

 

unsigned int ipvlan_nf_input(void *priv, struct sk_buff *skb,
           const struct nf_hook_state *state)
{
    // 参数中可以看到,有前一个生效的hook结构体,当前处理的skb报文本身以及当前netfilter框架的上下文信息
  struct ipvl_addr *addr;
  unsigned int len;
  addr = ipvlan_skb_to_addr(skb, skb->dev);
  if (!addr)
    goto out;
  skb->dev = addr->master->dev;
  len = skb->len + ETH_HLEN;
  ipvlan_count_rx(addr->master, len, true, false);
out:
    // 这里返回了netfilter框架规定的返回码
  return NF_ACCEPT;
}

 从ipvlan_nf_input可以看到,注册到netfilter中的回调函数的核心在于两个约束:

● 回调函数的入参定义,可以接受协议栈中真正的报文结构体skb以及netfilter的上下文状态为参数。

● 回调函数的返回值,需要是netfilter规定好的返回值,他们的定义如下:

/* Responses from hook functions. */
#define NF_DROP 0
#define NF_ACCEPT 1
#define NF_STOLEN 2
#define NF_QUEUE 3
#define NF_REPEAT 4
#define NF_STOP 5/* Deprecated, for userspace nf_queue compatibility. */
#define NF_MAX_VERDICT NF_STOP

从以上的分析不难看出,只要满足netfilter的注册条件,就可以在回调函数中直接对数据报文skb内容进行读取和修改操作,而通过返回值的定义,则可以借助netfilter框架完成对数据包的处理,比如丢弃,接收或者传递到用户态进行处理。

 

netfilter的内核实现

在负责对所有hook方法进行遍历处理的函数中,可以看到,netfilter核心的工作流程就是在相应的触发时机调用这个时机上注册的所有方法,按照优先级进行处理,并根据每一次处理的结果进行操作,包括丢弃,传输给用户态等等:

int nf_hook_slow(struct sk_buff *skb, struct nf_hook_state *state,
     const struct nf_hook_entries *e, unsigned int s)
{
  unsigned int verdict;
  int ret;
  for (; s < e->num_hook_entries; s++) {
        // 在这里调用对应的hook时机上的所有注册的hook回调方法,然后根据结果选择是不是继续循环
    verdict = nf_hook_entry_hookfn(&e->hooks[s], skb, state);
    switch (verdict & NF_VERDICT_MASK) {
    case NF_ACCEPT:
      break;
    case NF_DROP:
      kfree_skb(skb);
      ret = NF_DROP_GETERR(verdict);
      if (ret == 0)
        ret = -EPERM;
      return ret;
    case NF_QUEUE:
      ret = nf_queue(skb, state, e, s, verdict);
      if (ret == 1)
        continue;
      return ret;
    default:
      /* Implicit handling for NF_STOLEN, as well as any other
       * non conventional verdicts.
       */
      return 0;
    }
  }
  return 1;

 

更多精彩内容,欢迎观看:

《云原生网络数据面可观测性最佳实践》—— 一、容器网络内核原理——2.netfilter框架(下):https://developer.aliyun.com/article/1221729?spm=a2c6h.13148508.setting.16.15f94f0e18Oqpt

相关文章
|
10天前
|
Kubernetes Cloud Native Docker
云原生时代的容器化实践:Docker和Kubernetes入门
【10月更文挑战第37天】在数字化转型的浪潮中,云原生技术成为企业提升敏捷性和效率的关键。本篇文章将引导读者了解如何利用Docker进行容器化打包及部署,以及Kubernetes集群管理的基础操作,帮助初学者快速入门云原生的世界。通过实际案例分析,我们将深入探讨这些技术在现代IT架构中的应用与影响。
42 2
|
8天前
|
运维 Cloud Native 虚拟化
一文吃透云原生 Docker 容器,建议收藏!
本文深入解析云原生Docker容器技术,涵盖容器与Docker的概念、优势、架构设计及应用场景等,建议收藏。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
一文吃透云原生 Docker 容器,建议收藏!
|
10天前
|
运维 Kubernetes Cloud Native
云原生技术:容器化与微服务架构的完美结合
【10月更文挑战第37天】在数字化转型的浪潮中,云原生技术以其灵活性和高效性成为企业的新宠。本文将深入探讨云原生的核心概念,包括容器化技术和微服务架构,以及它们如何共同推动现代应用的发展。我们将通过实际代码示例,展示如何在Kubernetes集群上部署一个简单的微服务,揭示云原生技术的强大能力和未来潜力。
|
2天前
|
Kubernetes Cloud Native Docker
云原生之旅:从传统架构到容器化服务的演变
随着技术的快速发展,云计算已经从简单的虚拟化服务演进到了更加灵活和高效的云原生时代。本文将带你了解云原生的概念、优势以及如何通过容器化技术实现应用的快速部署和扩展。我们将以一个简单的Python Web应用为例,展示如何利用Docker容器进行打包和部署,进而探索Kubernetes如何管理这些容器,确保服务的高可用性和弹性伸缩。
|
4天前
|
运维 Cloud Native 云计算
云原生之旅:Docker容器化实战
本文将带你走进云原生的世界,深入理解Docker技术如何改变应用部署与运维。我们将通过实际案例,展示如何利用Docker简化开发流程,提升应用的可移植性和伸缩性。文章不仅介绍基础概念,还提供操作指南和最佳实践,帮助你快速上手Docker,开启云原生的第一步。
|
9天前
|
Cloud Native API 持续交付
云原生之旅:从容器到微服务的演进之路
【10月更文挑战第39天】在这篇文章中,我们将一起探索云原生技术的奥秘。通过浅显易懂的语言和生动的比喻,我们将了解云原生技术如何改变软件开发的世界。文章将带领读者从容器的基本概念出发,逐步深入到微服务架构的实践,揭示这些技术如何助力现代应用的快速迭代与可靠部署。准备好,让我们启程进入云原生的精彩世界吧!
|
11天前
|
Kubernetes Cloud Native Docker
云原生技术探索:容器化与微服务的实践之道
【10月更文挑战第36天】在云计算的浪潮中,云原生技术以其高效、灵活和可靠的特性成为企业数字化转型的重要推手。本文将深入探讨云原生的两大核心概念——容器化与微服务架构,并通过实际代码示例,揭示如何通过Docker和Kubernetes实现服务的快速部署和管理。我们将从基础概念入手,逐步引导读者理解并实践云原生技术,最终掌握如何构建和维护一个高效、可扩展的云原生应用。
|
13天前
|
存储 安全 网络安全
网络安全法律框架:全球视角下的合规性分析
网络安全法律框架:全球视角下的合规性分析
28 1
|
19天前
|
Kubernetes Cloud Native 微服务
云原生之旅:从容器到微服务
【10月更文挑战第29天】在这篇文章中,我们将一起探索云原生的奥秘。云原生不仅仅是一种技术,更是一种文化和方法论。我们将从容器技术开始,逐步深入到微服务架构,最后探讨如何在云平台上实现高效的服务部署和管理。无论你是初学者还是有经验的开发者,这篇文章都将为你提供有价值的见解和实用的技能。让我们一起踏上这段激动人心的云原生之旅吧!
|
19天前
|
Cloud Native 持续交付 云计算
云原生入门指南:从容器到微服务
【10月更文挑战第28天】在数字化转型的浪潮中,云原生技术成为推动现代软件开发的关键力量。本篇文章将带你了解云原生的基本概念,探索它如何通过容器化、微服务架构以及持续集成和持续部署(CI/CD)的实践来提升应用的可伸缩性、灵活性和可靠性。你将学习到如何利用这些技术构建和部署在云端高效运行的应用,并理解它们对DevOps文化的贡献。
41 2

热门文章

最新文章