Linux-2.6.32内核编译流量计数器nfacct

近期一直想看的一本书是《一朵桔梗花》,和技术无关的一本书,但是这并不能表达我对IT技术已经没有兴趣。事实证明,当我无法理解生活百态,无法理解肮脏的领导人心理,无法理解自认为自己可怜却处处步步为营的肮脏轨迹,无法理解不干活儿却从来都是显得自己很累,无法理解上位后的沉默寡言,无法理解拉窗帘,无法理解由于寂寥而加班从而博彩,无法理解省去了租住房的电费后又得到了功勋,无法理解.......等等之后,我TMD能蹂躏的就是:把Linux-3.17的功能移植到Linux-0.01上!
       我的时间为我掌控,这是我最大的财富!早上9点多到公司,一直到下班,这段时间有偿的坐班,我不会估计自己的事情,下班到家直到家人睡去,这段时间有偿的坐班,我不会顾及自己的事情,之后就是急促的喘息的夜,我的愿望刻在上帝的喉咙,希望通过推翻身边的拿人性做抵押的否认之墙,来从容面对恐惧(这是形容死亡金属的)!
       好了!受虐自是开端!且看且珍惜:
Netfilter早在xtables-addons-1.46(更早的版本我没有亲自试验,因此不便述说)中就内置了一个ACCOUNT模块,用来在iptables的框架内支持流量计数,它的用法如下:

iptables -A XXX (any matches) -j ACCOUNT  --addr 0.0.0.0/0  --tname $acctname

作用是凡是匹配any matches的流量均计入acctname这个计数器。可以通过:

iptaccount -l $acctname

来显示流量信息。但是它有一个缺点,那就是ACCOUNT作为iptables的一个target存在,这就是说流量统计之外,一条iptables规则不能再做别的了。有时候,你总是希望流量计数是作为一个“额外”的动作而存在,比如在DROP的同时记录一下,或者在NAT的同时记录一下等。将流量计数作为match会更好,因为match可以有多个!另外,ipset-6.23也支持流量计数,但是本文不谈那个。本文谈的是nfacct。
       nfacct是Netfilter的一个项目。我不得不再次怒发冲冠!Netfilter上的凄凉项目不少,nfacct真不算凄凉,但是起码它在Linux 2.6.32上是不能用的,事实上,由于nfacct项目根本就没有内置kernel模块,也就是说,Netfilter如今只负责用户态的模块,至于kernel那部分,只好等Linux kernel的trunk树给与支持了,而我查了资料后,发现在3.3以及之后的版本才给了nfacct内核态的支持。至于nfacct用户态的代码,例行的configure/make install就可以直接编译通过并安装,给人一种它已经可用的假象,但是当你使用nfacct add test的时候,便会报错:错误的参数!
       2.6.32根本就没有nfacct内核部分的支持,所以netlink报错。接下来的事就是移植3.3版本的nfnetlink_acct内核模块到2.6.32版本内核了。我选择3.3版本是因为它是离2.6.32版本最近的支持nfacct的内核,虽然内核API可能发生变化,但是起码移植工作量可以最小化。
.       在开工之前,我给出我编译环境的目录树结构:
|-- iptables-1.4.21.tar.bz2
|-- kernel
|   |-- net
|   |   `-- netfilter
|   |       |-- Makefile
|   |       |-- nfnetlink_acct.c
|   |       |-- nfnetlinkacct.h
|   |       |-- nfnetlink.c
|   |       |-- nfnetlink.h
|   |       |-- xt_nfacct.c
|   |       `-- xt_nfacct.h
|   `-- README
|-- libnetfilter_acct-1.0.2.tar.bz2
`-- nfacct-1.0.1.tar.bz2

iptables-1.4.21.tar.bz2是目前最新的iptables版本,2.6.32直接可以编译安装,nfacct-1.0.1.tar.bz2是nfacct的用户态部分,依赖libnetfilter_acct-1.0.2.tar.bz2,这两者均可以成功编译安装,剩下的就是内核态的工作了,置于我新建的kernel目录,其中的文件来自Linux 3.3内核:
nfnetlink_acct.c:cp $3.3/net/netfilter/nfnetlink_acct.c net/netfilter/nfnetlink_acct.c
此文件需要修改的地方有:
1.将include文件nfnetlink.h绝对路径改为相对路径,即本目录。
2.将include文件nfnetlink_acct.h绝对路径改为相对路径,即本目录的nfnetlinkacct.h
3.将kfree_rcu改为kfree,或者重新定义kfree_rcu

nfnetlinkacct.h:cp $3.3/include/linux/netfilter/nfnetlink_acct.h net/netfilter/nfnetlinkacct.h
nfnetlink.c:cp /lib/modules/`uname -r`/build/net/netfilter/nfnetlink.c net/netfilter/nfnetlink.c
此文件需要修改的地方有:
1.将include文件nfnetlink.h绝对路径改为相对路径,即本目录。
nfnetlink.h:cp /lib/modules/`uname -r`/build/include/linux/netfilter/nfnetlink.h net/netfilter/nfnetlink.h
此文件需要修改的地方有:
1.定义新的netlink子系统:

#define NFNL_SUBSYS_IPSET               6
#define NFNL_SUBSYS_ACCT                7
#define NFNL_SUBSYS_COUNT              8

注意,移植此文件到当前编译目录的目的是为了不影响系统头文件,要知道,由于nfnetlink模块要重新编译,我将nfnetlink也移了过来,它们都是2.6.32内核的文件。
xt_nfacct.c:cp $3.3/net/netfilter/xt_nfacct.c net/netfilter/xt_nfacct.c
此文件需要修改的地方有:
1.定义xt_action_param:

#define xt_action_param xt_match_param

这是因为2.6.32中match和target在接口上是分开的,不像3.X内核上将其作为union封装进xt_action_param结构体。
2.改变checkentry的返回值:

/* 万分注意!从3.x移植过来的checkentry的返回值是int,0为成功,非0为失败,
 * 然则2.6.32的对应返回值是bool,0为失败,非0为成功。
 * 完全相反的API规范,弄反了就panic吧 :(
 **/
static int
nfacct_mt_checkentry(const struct xt_mtchk_param *par)
{
    struct xt_nfacct_match_info *info = par->matchinfo;
    struct nf_acct *nfacct;

    nfacct = nfnl_acct_find_get(info->name);
    if (nfacct == NULL) {
        pr_info("xt_nfacct: accounting object with name `%s‘ "
            "does not exists\n", info->name);
        return 0;
    }
    info->nfacct = nfacct;
    return 1;
}

xt_nfacct.h:cp $3.3/include/linux/netfilter/xt_nfacct.h net/netfilter/xt_nfacct.h

至此,移植空间完成,Makefile的内容为:

obj-m   += nfnetlink_acct.o
obj-m   += nfnetlink.o
obj-m   += xt_nfacct.o

进入net/netfilter目录,通过下面的命令编译:

make -C /lib/modules/`uname -r`/build SUBDIRS=`pwd` modules

然后依次加载nfnetlink.ko,nfnetlink_acct.ko,xt_acct.ko
如此,再次执行nfacct命令试一下吧:

nfacct add test
iptables -A INPUT -s 192.168.0.0/24 -m nfacct --nfacct-name test -j ACCEPT

停顿片刻,保持网络传输,查看流量计数器:

nfacct get test
{ pkts = 00000000000000188016, bytes = 00000000000250825515 } = aa;

OK了!
当然,你也可以将结果保存为xml文件的格式,在必要时也可以reset计数器的数值为0。
       你相信吗?旋转升降座椅真的会爆炸。

时间: 2024-10-07 08:05:23

Linux-2.6.32内核编译流量计数器nfacct的相关文章

Linux入门之CentOS7内核编译三部曲(1)

Linux入门之CentOS7内核编译三部曲(1) 我们知道,一个Linux系统的主要组成是由liunx内核核心和一些支持模块组合而成的.但是在某些场合中,需要某项功能,而当前内核的核心或者模块不支持此功能,那么就需要对内核进行一个升级或者重新编译内核添加相应的功能,以此提供了对此功能的支持. 编译前的准备 认识kernel 所为kernel,就是一种操作系统的核心,当然也是一个文件,而这种核心提供了对一些硬件的支持,一般来说其中包含了一些对常见硬件核心驱动的核心代码.启动系统时会通过加载MBR

Linux入门之CentOS7内核编译三部曲(2)

Linux入门之CentOS7内核编译三部曲(2) 在linux系统中,编译完了内核,得到了所需的功能,并不能表示就已经能完美完成我们的所需.因为内核只是做一个核心的硬件及核心代码的支持,而注意的模块支持任然是对应版本的内核模块文件.这些文件决定着平时能否使用哪些功能.这次不会介绍如果添加给上次编译的新内核模块功能,主要介绍模块的功能和作用以及其加载和卸载. 查看当前系统以及加载的内核模块命令:lsmod  modinfo lsmod 命令 lsmod - program to show the

Linux入门之CentOS7内核编译三部曲(3)

Linux入门之CentOS7内核编译三部曲(3) 在上篇通过一些简单的例子和使用介绍了linux系统中模块的功能和作用.那么每次系统启动完成之后,又是怎么去自动加载所需要的模块,那么回过头来看还是要连续模块加载具体在系统启动中的哪个阶段开始触发的.同时模块的加载是依据内核本身的预定程序,还是linux文件系统中的相应配置文件呢? 默认安装的模块文件路径:/lib/modules/$(uname -r)/kernel,如: #查看内核模块列表目录 [[email protected] ~]# l

Linux系统启动流程及内核编译(2)

1.内核设计:有单内核和微内核之分 linux属于单内核的模块化设计 系统内核核心路径:/boot/vmlinuz-版本号 内核模块路径: /lib/modules/版本号/ linux分为内核空间和用户空间 而用户空间通过访问和监控内核:路径在/proc/和/sys/两个伪文件系统 2.伪文件系统/proc/sys和/sys/有些目录中文件是可读或可写的 设定内核参数值的方法: 2.1.能立即生效,但重启系统设定无效 2.1.1.echo 值  > /proc/sys/TO/SOMEFILE

linux内核编译与开发

一.Linux内核简介linux kernel map: linux 系统体系结构: linux kernel体系结构: arm有7种工作模式,x86也实现了4个不同级别RING0-RING3,RING0级别最高, 这样linux用户代码运行在RING3下,内核运行在RING0,这样系统本身就得到了 充分的保护 用户空间(用户模式)转到内核空间(系统模式)方法: ·系统调用 ·硬件中断 linux kernel 体系结构: 虚拟文件系统VFS: VFS(虚拟文件系统)隐藏各种文件系统的具体细节,

于Linux-2.6.32内核上编译ipset-6.23的坎坷经历

新版本的ipset 上周在儿童医院给小小看病等待叫号的间隙,收到了Netfilter邮件列表的推送消息,一览了ipset最新的6.23版本的新特性,很多正是我目前所需要的,特别是timeout和skbinfo参数的支持,具体的详情请自行查看manual,如果不想看那么多,我这里简单的贴一下:    timeout       All  set  types  supports the optional timeout parameter when creating a set and addin

【转】Linux CentOS内核编译:下载CentOS源码、编译2.6.32-220的错误(apic.c:819 error 'numi_watchdog' undeclared)

一.下载CentOS源码 1.1 查看CentOS版本 cat /etc/issue 1.2 查看Linux内核版本 uname -r 1.3 下载 文件名:kernel-2.6.32-220.el6.src.rpm 下载地址:http://vault.centos.org/6.2/os/Source/SPackages/ 官网:http://vault.centos.org/ 1.4 从kernel-2.6.32-220.el6.src.rpm获取源码 1. rpm -i kernel-2.6

linux内核编译,配置本机驱动

1.前言  编译linux内核失败的原因很多时候就是驱动选错,适合自己本机的驱动没编译进去.面对特殊平台(或者有些洁癖者,我就是^_^),要编译精简内核,只要本机驱动,其他都不需要.面对内核里面这么多驱动,不懂硬件的我们,看到都头大.本人第一次安装gentoo的时候,内核编译了5次,前4次主要失败原因是以太网卡驱动.无线网卡驱动.显卡驱动.声卡驱动都没一次性配置正确.虽然gentoo提供了genkernel命令,可以自动帮你编译内核,但还是想自己手工尝试下. 2.获取本机驱动信息 既然跟内核挂钩

Linux下的内核编译与模块操作

Linux下的内核编译与模块操作 一:实验环境 1):虚拟机 2):linux系统 3):linux系统的硬盘的空余空间要大于7G 4):虚拟机的内存要大于2.5G以上 二:实验目标 1):源码编译Linux内核 2):使用Linux内核模块 3):实战-编译一个NTFS内核模块,实现linux挂载NTFS文件系统并实现读写功能 三:实验脚本 第一块 --源码编译Linux内核 linux系统与windows系统是两种截然不同的系统,windows系统中的软件都是需要付费的,而linux系统中的