Linux 中的网络数据包捕获

161 篇文章 0 订阅
117 篇文章 0 订阅

开始之前

关于本教程

目前,信息要通过管道(也就是网络)传输,需要花很多时间封装在数据包中。在本教程 中,我们将在这些数据包传输过程中捕获它们,捕获数据包所采用的平台是 Linux。

大多数网络应用程序――从虚拟专用网(VPN)到路由程序,再到嗅探器――都具有某种 数据包捕获机制。因此,编写此类软件的任何人都可以从本教程中受益。

由于我们将要研究的几种数据包过滤机制都是内核模块,所以还将简要地介绍这些模块以 及内核编译。

我们还将回顾一些我没有成功使用的机制:我只能获得数据包的一个副本而无法截获最初 的数据包。这里的讨论不仅能省去您重复我所做工作的麻烦,而且还对编写网络应用程序(如嗅探器) 很有用。

除大致熟悉不同的数据包捕获机制(如防火墙钩子、divert socket 和 netfilter)外; 读者还应具备有关 Linux 网络和 TCP/IP 协议栈方面的知识。开始之前最好了解一些源代 码的知识。

前提条件

本教程最适合那些以前在系统编程、Linux 网络和 Linux 内核模块方面 至少有一些经验的读者。但是,本教程尽可能简单地给出一些概念,并在适当的时候给 予详细解释,因此,即使读者缺少一种或多种这方面的知识,也能从本文的讨论中获益。

简介

数据包捕获

TCP/IP 协议栈是 Linux 网络的重要支柱,其体系结构设计得非常优美。数据包 是 TCP/IP 协议栈 中信息流的载体。在 Linux 网络编程中,许多有意义的工作都包括了捕获这些信息丰富的数据包、提取或操作这些数据包所包含的信息。

数据包捕获 对我们而言意味着某种机制,即获取一个数据包,直到达到所要求的目 的后才将其释放,以便该数据包能够按照常规路径通过其余的任何处理。其他相同或相似 操作的术语有 数据包过滤、数据包嗅探、网络嗅探 以及 数据包 或 网络监视

数据包过滤是许多网络软件的基础,这些软件有网络监视工具、VPN、网络分析程序、路由 程序、入侵监测系统(Intrusion Detection Systems,IDS)和嗅探器。

Linux 提供了多处可以捕获数据包的位置,既包括用户空间,又包括内核空间。下图展示了网络数据包流过 TCP/IP 协议栈的路径:

图 1. 网络数据包通过协议栈的路径 
网络数据包通过协议栈的路径

如上图所示,流入的数据包通过以太网层、网络层、TCP 协议栈并穿过套接字层, 然后才能被复制到用户空间中。在所有这些断点处,数据包都很容易被捕获到。本教程讨 论的方法大多在网络层和用户空间中有效。

然而,由于 Linux 和 Linux 内核在不断发展,这里讨论的某些数据包捕获方法仅在特定 的内核中有效。例如,divert socket 对打过补丁的 2.2.12 内核有效,而 netfilter 对 内核 2.4.x 和 2.6.x 有效。在讨论各种方法时始终要注意这些细节。

Linux 可加载的内核模块(LKM)概述

捕获数据包的模块

本教程探讨的大多数数据包捕获机制都是以 Linux 内核模块的方式工作的,因此我们现在简 要讨论一下这些模块。如果您有很强的 LKM 背景,则可以跳至下一节 编译内核 。

什么是 LKM?

可加载内核模块 是内核的扩展,可以在需要时附加到内核中,或从内核中删除。LKM 基本上是设备驱动程序的软件实现,它与真实的或者虚拟的硬件设备协同工作。当 LKM 加 载到内核中时,它们监听和处理对设备的任何请求。由于只加载所需的 LKM,因此使 用 LKM 可使内核变得轻便、模块化、灵活和可伸缩。

LKM 体系结构

编写 Linux 内核模块的体系结构如下:

  1. init_module 
    这个 LKM 初始化函数是强制执行的。当 LKM 加载到内核时触发该函数,因此 所有初始化工作都是在这个函数中完成的。
  2. 处理特定的函数 
    这些函数执行实际的工作,如读、写、打开、关闭设备,等等。
  3. cleanup_module 
    当从内核中删除 LKM 时,调用 LKM 的这个强制执行函数。因此,所有清除工作 如释放内存等都应在这个函数中执行。

编译 LKM

编写 LKM 后,可以采用下列命令编译它:

   gcc -c -g  <module_name>.c -I/usr/src/linux/include

该命令产生一个名为 <module_name>.o 的文件,它就是 LKM,可以使用下列命令将它加载到 内核中:

   insmod -f <module_name>.o

-f  选项意味着强制加载。)

如果在加载模块时遇到任何内核版本问题,可以通过在加载 LKM 时包含这个特定内核 的头文件来解决问题。因此,在编译内核时,请使用 -I/usr/src/linux/include

还可以使用 Makefile 来解决此类版本问题,但这超出了本教程的范围。在本教程的末 尾,您还可以在 参考资源 中找到有关 LKM 编程的更多信息。

卸载 LKM

一旦模块加载到内核中,它将开始执行预定的功能。使用命令 lsmod 可 以看到当前所有加载的 LKM 的列表。

可以使用 rmmod <module_name> 从内核中加载或删除模块。

编译内核

回顾

本教程讨论的许多机制都要求设置某些内核选项,然后重新编译内核。因此在开始前,我 们将复习内核编译的步骤。如果您已经了解内核编译,则可以跳至下一 节 数据包截获:防火墙钩子 ,在那里开始复习数据包捕获机制。

步骤

重新编译内核:

  1. make xconfig 
    允许设置不同的内核选项。(也可以使用 make menuconfig 或 make config;这只是个人偏好问题。)
  2. make dep 
    解决内核编译的文件依赖性。
  3. make bzImage 
    编译(make)内核映像并将其存储在 vmlinuz 中。
  4. make install 
    将 vmlinuz 复制到 /boot 目录中,并将二进制文件复制到正确的位置。
  5. make modules 
    编译所有内核模块。
  6. make modules_install 
    在正确的位置安装模块(通常位于 /lib/modules/<kernel-version> )。

接着,您应将关于最近编译内核的信息添加到 /etc/lilo.conf(如果不在该位置的 话),然后重新启动机器。您会在重新启动过程的开始看到列出的新内核选项。

数据包截获:防火墙钩子

概述

防火墙钩子(Firewall hook) 已引入到 2.2.16 内核中,它是 2.2.x 内核运行的数据包截获方法。 防火墙钩子在 TCP/IP 协议栈的 IP 层截获数据包。

防火墙钩子在功能上充当 Linux 可加载内核模块(LKM)或伪设备驱动程序,可以根据 需要从内核中加载或卸载。

要使用防火墙钩子,请在内核编译期间启用 firewalling 选项 (在 Networking 选项下列出)。

您可以使用该数据包截获机制来开发路由程序、VPN、数据包嗅探器或位于网络边 缘且要求实时捕获数据包的任何其他网络应用程序。

填充结构

内核定义的 firewall_ops 结构是防火墙钩子的基础。可以用这些结构来指定各种 数据包策略,这些策略可以是非常特殊的,也可以是很普通的。

firewall_ops 结构位于 /usr/src/linux/include/linux/firewall.h 中,类似如下:

   struct firewall_ops

   {

              struct firewall_ops next;

              int (*fw_forward)(struct firewall_ops *this, int pf,

                                struct device *dev, void *phdr, void
   *arg, struct

                               sk_buff **pskb);

              int (*fw_input)(struct firewall_ops *this, int pf,

                                       struct device *dev, void *phdr,
   void *arg, struct sk_buff

                                       **pskb);

              int (*fw_output)(struct firewall_ops *this, int pf,

                                       struct device *dev, void *phdr,
   void *arg, struct sk_buff

                                       **pskb);

              int fw_pf;

              int fw_priority;

   };

这种机制是作为 LKM 来实现的。同样,它需要 init_module(用于初始 化模块)、cleanup_module 和某些特定处理的函数:

next指向下一个钩子的指针
fw_forward转发数据包的函数指针
fw_input流入数据包的函数指针
fw_output流出数据包的函数指针
fw_pf协议簇
fw_priority所选防火墙的优先权

这些都是实际的函数指针;相应的函数在下一个屏中定义。

函数

为了处理数据包,需要定义三个函数:

流入的数据包处理:

   static int fw_input(struct firewall_ops *this,int pf,struct device
   *dev,void

                                   *phdr,void *arg,struct sk_buff **pskb)

对所有流入的数据包都要调用该函数。如果需要对流入的数据包进行任何处理(也称为 "mangling"),如添加额外的字段,可以在此进行处理。

流出的数据包处理:

   static int fw_output(struct firewall_ops *this,int pf,struct device
   *dev,void

                                   *phdr,void *arg,struct sk_buff **pskb)

对所有流出的数据包(源自主机)调用该函数。可以在这里对此类数据包进行任何额外处理。

转发数据包处理:

   static int fw_forward(struct firewall_ops *this,int pf,struct device
   *dev,void

                                   *phdr,void *arg,struct sk_buff **pskb)

对所有转发的数据包调用该函数。

下面是在上述函数中传递参数的详细信息。

*this指向防火墙钩子结构的指针
pf代表协议簇
*dev指向以太网卡设备结构的指针 card
*phdr指向 IP 地址缓冲区的指针
*arg额外的参数,在需要时传递给函数 function
**pskb指向 TCP_IP 协议栈的 sk_buff 层的指针

对于上述每个函数,数据包的返回值(或对数据包的操作)可以是:

  • Accept 
    该操作由 FW_ACCEPT 宏完成。它接受数据包并且数据包遵循正常的 TCP/IP 协议栈路径。
  • Reject 
    该操作由 FW_REJECT 宏完成。它拒绝所有数据包,既没有网络流量流出, 又没有网络流量流入。
  • Redirect 
    该操作由 FW_REDIRECT 宏完成。它将数据包重定向到特定的主机。

函数(续)

现在,我们将把上一屏中定义的函数赋值给 firewall_ops 结构中的指针。一旦赋值 完成,firewall_ops 结构将被填充,函数将由系统本身调用――这就是术语 回调函 数

下面是要填充的字段:

      struct firewall_ops * next;      		/*Pointer to the next
					   	firewall hook structure */

      int fw_pf;                         	/* Protocol family */

      int fw_priority;                      	/* Priority of chosen
   						firewalls */

现在,防火墙结构与下面的代码类似:

   /* Filling the firewall_ops structure */

   static struct firewall_ops myOps = {NULL,

            fw_forward,

           fw_input,

          fw_output,


   PF_INET,               			/* Protocol family */

   1                                     	/* Priority of chosen
						firewalls*/

   };

Kernel 注册

现在,您需要将 firewall_ops 结构注册到内核:

         register_firewall(protocol family, struct firewall_ops *);

在 LKM 的 init_module 代码中进行注册。

取消注册 firewall_ops 结构

当卸载 LKM 时,cleanup_module 函数应包含

         unregister_firewall(protocol family, struct firewall_ops *);

对 LKM 进行编码、编译并加载到内核后,您的数据包拦截器就准备工作了。

完成在接下来的两屏中给出的这个 LKM 的源代码和使用说明。

源代码:防火墙钩子程序

   /* This is an insertable module that uses the firewall hooks mechanism
   on 2.2.16 to intercept a packet */

   /* gcc -O -c NetFWHook.c -I/usr/src/linux/include*/

   /* No one can then telnet,ftp,ping your machine */


   /*NetFWHook.c*/


   #define MODULE

   #define __KERNEL__


   #include<linux/config.h>

   #include<linux/module.h>

   #include<linux/version.h>


   #include<linux/netdevice.h>

   #include<net/protocol.h>

   #include<net/pkt_sched.h>

   #include<net/tcp.h>

   #include<net/ip.h>


   #include<linux/if_ether.h>

   #include<linux/ip.h>

   #include<linux/tcp.h>

   #include<linux/skbuff.h>

   #include<linux/icmp.h>


   #include<linux/kernel.h>

   #include<linux/mm.h>

   #include<linux/file.h>

   #include<linux/firewall.h>

   #include<asm/uaccess.h>


   //Function for forwarded packets

   static int fw_forward(struct firewall_ops *this,int pf,struct device
   *dev,void *phdr,void *arg,struct sk_buff **pskb)

   {

               struct iphdr *hdr = (struct iphdr *)(*pskb)->h.ipiph;

               printk("\n\tfw_forward)() called...");

               printk("\n\t\tThe source of this packet is:
   %s",in_ntoa(hdr->saddr));

               return FW_ACCEPT;

   }


   /*Function for incoming packets*/

   static int fw_input(struct firewall_ops *this,int pf,struct device
   *dev,void *phdr,void *arg,struct sk_buff **pskb)

   {

               struct iphdr *iph;

               iph = (struct iphdr*)(*pskb)->h.ipiph;

               printk("\n\tfw_input() called...");

               printk("\n\t\tThe source of this packet is:
   %s",in_ntoa(iph->saddr));

               return FW_ACCEPT;

   }


   /*Function for outgoing packets*/

   static int fw_output(struct firewall_ops *this,int pf,struct device
   *dev,void *phdr,void *arg,struct sk_buff **pskb)

   {

               struct iphdr *iph;

               iph = (struct iphdr*)(*pskb)->h.ipiph;

               printk("\n\tfw_output)() called...");

               printk("\n\tThis packet is destined for:
   %s",in_ntoa(iph->daddr));

               return FW_ACCEPT;

   }


   /*Filling the firewall_ops structure*/

   static struct firewall_ops myOps =
   {NULL,fw_forward,fw_input,fw_output,PF_INE int fw_pf; /* Protocol
   family*/,int fw_priority;       /* Priority of chosen firewalls
   */T,1};


   /*First function to be called at the time of loading of module*/

   int init_module(void)

   {

           /*registering the firewall_ops structure*/

               if(register_firewall(PF_INET,&myOps) < 0)

               {

                           printk("\n\n\tERROR...firewall main aag lag
   gayee!!!");

                           return -1;

               }

               else

               {

                           printk("\n\n\tFirewall registered");

               }

               return 0;

   }



   /*Function that is called when the module is unloaded*/

   void cleanup_module(void)

   {

           /*Unregistering the firewall_ops structure*/

               if(unregister_firewall(PF_INET,&myOps)<0)

               {

                           printk("\n\n\tError....Firewall can't be
   unregistered");

               }

               else

               {

                           printk("\n\n\tFirewall unregistered");

               }


   }

使用防火墙钩子程序

  1. 编译和运行防火墙钩子程序:
       gcc -c -O NetFWHook.c -I/usr/src/linux/include/
    

  2. 您将得到一个名为 NetFWHook.o 的文件。请使用下列命令将其插入到内核中:
       /sbin/insmod  -f NetFWHook.o
    

  3. 要查看由这个 LKM 生成的消息,请运行 dmesg 命令。

数据包截获:Netfilter

概述

Netfilter 是由内核 2.4.x 和 2.6.x 提供的数据包截获机制,它替代了内核 2.2.x 中 使用的 ipchains、防火墙钩子和其他方法。Netfilter 也可以作为 LKM 获得。

要使用 netfilter,在内核编译时设置 Packet Filtering 选项。

可以对采用防火墙钩子机制的同类应用程序使用 netfilter 机制,这些应 用程序有:路由程序、数据包嗅探器和其他位于网络边缘并访问通信流的实体。

使用 Netfilter

Netfilter 可以在通过 TCP/IP 协议栈的路径中的几个定义良好的点上捕获数据包:

  • NF_IP_PRE_ROUTING 
    在对数据包进行初始正确性检查(校验和等)后,保存该数据包。
  • NF_IP_LOCAL_IN 
    如果数据包将要到达本地主机,则捕获该数据包。
  • NF_IP_FORWARD 
    如果数据包将要到达某些其他主机,则捕获该数据包。
  • NF_IP_LOCAL_OUT 
    在本地捕获其目的地是外部的已创建的数据包。
  • NF_IP_POST_ROUTING 
    这是最后的钩子,在此之后将传输数据包。

当数据包穿过 TCP/IP 协议栈后,协议调用带有数据包和钩子号的 netfilter 框架。钩子也 可以指派优先级。

函数的返回值包括:

  • NF_ACCEPT 
    数据包继续在正常的 TCP/IP 路径上传输。
  • NF_DROP 
    丢弃数据包;不进一步处理。
  • NF_STOLEN 
    已获得数据包;不进一步处理。
  • NF_QUEUE 
    对数据包排队(通常用于用户空间处理)。
  • NF_REPEAT 
    再次触发这个钩子。

步骤

Netfilter 的工作方式与防火墙钩子非常相似。作为 LKM 注册到内核的结构 调用特定于进程的函数。任何基于 netfilter 的数据包拦截器都必须遵循开发 LKM 所采 用的步骤。

特定于进程的函数

特定于进程的函数(或钩子)的原型如下所示:

   static unsigned int packet_interceptor_hook(unsigned int hook, struct
   sk_buff **pskb,

   const struct net_device *indev, const struct net_device *outdev, int

   (*okfn) (struct sk_buff *))

您可以将字段定义为:

  • hook 
    您感兴趣的钩子的编号;例如 NF_IP_LOCAL_OUTNF_IP_LOCAL_INNF_IP_ FORWARD 等。
  • **pskb 
    指向 TCP/IP 协议栈中数据包容器的指针;例如 sk_buff。
  • *indev & *outdev 
    指向流入和流出网络设备的设备结构的指针。在内核中注册的每种设备(例如,以太网卡)都 有一个由 IRQ、IO 地址等组成的设备结构。当机器只有一个网络接口来处理流入和流 出流量时,这两个结构是相同的。当流入和流出的流量由两种设备处理时,这两种结构是 不同的。
  • (*okfn) (struct sk_buff *) 
    在激活钩子时调用该函数。

netfilter 结构

核心 netfilter 结构在 /usr/src/include/linux/netfilter.h 中定义,类似如下:

struct nf_hook_ops
{
         struct list_head list;

         /* User fills in from here down. */
         nf_hookfn *hook;
         int pf;
         int hooknum;
         /* Hooks are ordered in ascending priority. */
         int priority;
};

参数是:

  • list 
    Netfilter 本身是一个钩子链;它指向 netfilter 钩子的头部,通常设置为 { NULL, NULL }
  • hook 
    该函数在数据包碰到钩子点时被调用。该函数与前面描述的函数相同,它必须返回 NF_ACCEPTNF_DROP 或 NF_QUEUE。如 果返回 NF_ACCEPT,则下一个钩子将被附加到将要调用的点。如 果返回 NF_DROP,则数据包被丢弃。如果返回 NF_QUEUE,则对数据包 进行排队。sk_buff 指针被传递到该函数中,并用数据包信息如 IP 报头、TCP 报头等进 行填充。您可以使用 sk_buff 结构指针来操作或删除数据包(要删除数据包,只需将 skb 指 针设置为空即可)。
  • pf 
    协议簇;例如,适用于 IPv4 的 PF_INET
  • hooknum 
    您感兴趣的钩子号;例如 NF_IP_LOCAL_IN 等。

内核注册

在 LKM 的 init_module 函数中,需要注册在内核中填充的结构:

int nf_register_hook(struct nf_hook_ops *req);

这里,nf_hook_ops 是 netfilter 操作结构。

一旦该结构注册到内核中,Linux 将调用这里定义的函数来处理数据包。

取消注册 netfilter 结构

卸载 LKM 时,netfilter 结构需要从内核中取消注册。这一操作在 cleanup_module 函数中完成:

void nf_unregister_hook(struct nf_hook_ops *req);

nf_hook_ops 也是 netfilter 操作结构。

数据包截获:Divert socket

概述

2.2.12 内核的其中一个补丁引入了一种新类型的原始套接字(raw socket),称 为 divert socket,该套接字按照防火墙规范过滤数据包,并将其发送到用户空 间。数据包从这里开始进行处理或简单地再放回到 TCP/IP 协议栈中。

Divert socket 是一种特殊类型的原始套接字,与任何其他套接字一样,通过该套接字 可以接收和发送数据包。Divert socket 使用 Linux 内核的 firewalling 功能:可以 将 Linux firewalling 设置为对流入、流出和转发数据包应用受限的策略,然后将其重 定向到指定的端口。Divert socket 将在该端口进行监听,然后进一步重定向数据包。

使用 divert socket 的主要缺点是将数据包复制到用户空间的开销,这会占用时间 和资源,从而降低了网络性能。

任何没有对数据包实时处理施加硬性限制的联网应用程序(如嗅探 器),您都可以使用 divert socket。

内核编译选项

Linux firewalling 是使用 divert socket 的先决条件,因此应在内核编译时启用该 选项。某些选项已专门为 divert socket 引入到内核中,并应在编译时设置它们:

  • Firewalling 
    启用内核的 firewalling 功能。
  • IP Firewalling 
    启用内核的数据包过滤功能。
  • IP:divert sockets 
    在内核中启用 divert socket。
  • IP:divert pass-through 
    如果已设置了该选项并且没有应用程序正在监听 divert socket 端口,则该数据包不转 移,只按照正常的路径传输。
  • IP:always defragment 
    如果设置该选项,则整理内核中的所有碎片,这会严重降低性能。

ipchains 控制网络数据包传输的路径。要将 ipchains 与 divert socket 一起使用, 应下载、编译和安装打了补丁的 ipchains 版本 ipchains-1.3.9。

在下一屏对 ipchains 进行一般性介绍。

ipchains 简介

  • Input chain 
    允许所有流入的数据包(目的地是主机的数据包和转发的数据包)穿过。
  • Output chain 
    允许所有流出的数据包(源自主机的数据包和转发的数据包)穿过。
  • Forward chain 
    只允许转发的数据包穿过。

转发的数据包按以下顺序穿过链:

  1. 输入
  2. 转发
  3. 输出

数据包截获:内核改动

概述

在此,我们将操作内核源代码以扩展内核本地数据包截获能力。

内核源文件位于 /usr/src/linux,要修改的两个主要文件 是 ip_input.c 和 ip_output。这两个文件位于 /usr/src/linux/net/ipv4/ 目录中。

源文件修改:ip_input.c

ip_input.c 包含这两个函数,可以为所有流入数据包调用它们: incoming packets:

  ip_local_deliver(struct sk_buff, struct device,struct packet_type)

为所有的流入数据包执行而不考虑目的地

   ip_rcv(struct sk_buff, struct device,struct packet_type)

为目的地是本地机器的所有数据包进行调用

  • sk_buff 
    TCP/IP 协议栈中数据包的容器。
  • device 
    设备结构。
  • packet_type 
    数据包的类型:流入或流出。

ip_rcv 执行 IP 层所需的几个任务,包括重新装配、校验和计算等。

由于 ip_rcv 处理所有流入的 IP 数据包,因此这是一个添 加要对流入数据包执行任何附加代码的好地方。其他选项是用于编写自己 的 ip_rcv 例程的。

源文件修改:ip_output.c

与 ip_output 一样,ip_output.c 位于 /usr/src/linux/net/ipv4/ 目录中,它处理 流出的数据包。它的四个函数是:

     ip_build_and_sent_pkt(struct sk_buff,struct sock,u32 saddr,u32
   daddr, struct ip_options)

将 IP 报头添加到 sk_buff 并将其发送出去

    ip_queue_xmit(struct sk_buff)

对要发送的数据包排队

    ip_build_xmit_slow()

构建和传送数据包

      ip_build_xmit()

“快速”构建和传送数据包,该选项只用于无需碎片整理的选项。

只有 ip_build_xmit_slow 和 ip_build_xmit 处理所有 流出的 IP 数据包,因此任何额外处理均可在任何阶段完成。对 于 ip_input.c,其他选项用于编写自己的例程,然后从这些例程中调用最初的函数。您 选择的策略依赖于您要实现的功能。

使用 Makefiles 修改源代码

可以使用 Makefiles 动态修改内核源代码;Makefile 脚本确保对源代码做必需的 修改。可以使用一条命令(make install 或 make uninstall)添加或删除数据包拦截器,然后重新编译内核并重新启动机器。

由于该机制要求修改 Linux 内核源代码,所以快速调试可能非常困难。而且,由于该 方法要求重新编译内核,所以这个过程是冗长、复杂且不灵活的。

数据包截获:创建数据包的副本

概述

某些数据包捕获机制仅提供数据包的副本而非数据包本身。但是,我们前面提到过,在开发 网络嗅探器应用程序时,数据包的副本仍然是很有用的。

协议处理程序

协议处理程序是另一种充当 LKM 的机制。

协议处理程序对处理通过以太网卡传来的数据包。为此,协议处理程序必须注册到网络设备中;在本例中,应该注册到以太网卡的设备结构中。

网卡设备结构还包含一个指向 init 函数的指针,该函数初始化设备。

实现协议处理程序

实现协议处理程序的步骤:

  1. 为以太网接口创建设备结构的实例,并将其注册到内核中。
  2. 注册处理程序例程,用于处理具有设备结构的数据包。

现在,通过以太网接口的任何数据包都能得到正确处理。对 数据包的副本 而非最初 的数据包进行处理。不可能通过 TCP/IP 协议栈转移来自最初路径的数据包,因此只有数据包的 副本到达协议处理程序本身。

中断处理程序

顾名思义,该机制是以中断处理作为基础的,也可以作为 LKM 来实现。不论何时,只 要有数据包到达以太网卡,就会生成中断。通过编写自己的中断处理程序,您就可以捕获数据包 并对其进行任何必要的处理。

幸运的是,无论何时只要有数据包穿过 TCP/IP 协议栈,就会生成中断,这会设置以太网卡中的标志,表 示数据包是流入的还是流出的。这个中断通常是中断 9,因此,您可以编写中断处理程序 来处理中断 9 的信号,然后处理数据包。

在这种情况下,由于有了协议处理程序,只有 数据包的副本 发送给中断处理程序,而 最初的数据包未受任何阻碍,通过 TCP/IP 协议栈正常传输。

结束语和参考资料

数据包截获机制的总结

机制模块?可伸缩?性能(TCP/IP 吞吐量)可插入/可删除?
防火墙钩子是,可以将其作为 LKM 插入是,可以通过更改 LKM 的源代码并重新编译来增强该性 能降低大约 50%是,使用 insmod 命令
Netfilter是,可以作为 LKM 插入它是,可以通过更改 LKM 的源代码并重新编译来增强该功能下降大约 50%是,使用 insmod 命令
Divert socket否,divert socket 数据包必须直接应用到内核代码冗长乏味,因为整个内核需要编译太慢而无法度量否,因为它不是模块
内核改动否,内核数据包拦截器代码必须直接集成到内核源代码中冗长乏味,因为整个内核需要编译通常快于 LKM 方法(如果正确实现)是,如果将 Makefile 用于安装和卸载

防火墙钩子和 netfilter 是模块化的、灵活的和动态加载的(可删除) ,它们只对系统的性能产生适度的影响。

对于预计流量很大且实时处理时有硬性限制的应用程序而言,最适合使用内核改动方法。

如果数据包处理没有计时问题,则可以使用 Divert socket。Divert socket 在用户空间中是一种分 析和控制网络流量的非常有用的方法。

反馈

请让我们知道本教程是否对您有帮助,以及我们如何才能做得更好。我们 还希望了解您想要阅读的其他教程主题。

如果对本教程的内容有疑问,请通过 achauras@in.ibm.com 与作者 Ashish Chaurasia 联系。

参考资料


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值