歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

Linux-2.6.32內核編譯流量計數器nfacct

把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。

Ubuntu 13.10 (Saucy Salamander) 內核已升級至 Linux Kernel 3.10 RC5 http://www.linuxidc.com/Linux/2013-06/86110.htm

Linux Kernel 3.4.62 LTS 現已經提供下載 http://www.linuxidc.com/Linux/2013-09/90368.htm

如何在Ubuntu 13.10上安裝Linux內核 3.12 http://www.linuxidc.com/Linux/2013-11/92930.htm

Linux Kernel 的詳細介紹:請點這裡
Linux Kernel 的下載地址:請點這裡

Copyright © Linux教程網 All Rights Reserved