iptables中ULOG和NFLOG實現分析【轉】

原文地址:http://blog.csdn.net/eydwyz/article/details/52456335

----------原文以下----------------------------------------

iptables中ULOG和NFLOG實現分析

轉載 2016年09月07日 09:00:41

目錄(?)[-]網絡

本文檔的Copyleft歸wwwlkk全部,使用GPL發佈,能夠自由拷貝、轉載,轉載時請保持文檔的完整性,嚴禁用於任何商業用途。數據結構

E-mail: wwwlkk@126.com併發

來源: http://blog.csdn.net/wwwlkksocket

ULOG和NFLOG特色比較

1.都是使用netlink進行通訊,ULOG使用NETLINK_NFLOG通訊協議,而NFLOG使用NETLINK_NETFILTER通訊協議。函數

2. ULOG只能從內核發送消息到用戶空間,而NFLOG用戶空間能夠發送消息到內核。post

3. NFLOG用戶空間有libnfnetlink庫的支持,而ULOG沒有性能

4. ULOG消息編碼固定,NFLOG消息編碼使用屬性,相對比較靈活。編碼

5. ULOG的消息池的個數和屬性都是固定,而NFLOG消息池是動態添加和撤銷,而且屬性能夠設置。spa

6. 兩個都是使用netlink進行通訊,從性能方面看,二者應該差很少。.net

7. 可是NFLOG有一個特色,就是,消息池是動態創建和撤銷的,若是nflog target指定的消息池不存在,則不會去建立消息,也不會去寫入消息,避免作無用功。

8. NFLOG消息池是用戶空間經過發送配置消息建立,用戶空間若是關閉netlink socket,對應的消息池也會隨之撤銷。

9.NFLOG數據包是經過單播來發送數據包,也就是,只有建立消息池的進程才能夠接收到數據包,

而ULOG是經過廣播來發送數據包,一個消息池對應一個廣播組,全部加入到某個廣播組的接收進程均可以接收到這個廣播中的數據包。

 

總的來講:ULOG通訊是單向的,用戶空間不能發送一些配置命令到內核,而NFLOG彌補了ULOG的不足,使得通訊是雙向的。

 

NFLOG特色及實現機制

1.      可使用libnfnetlink提供的接口來發送和接收數據

2.      一個分組對應一個消息池,能夠創建多個消息池,並能夠設置消息池的屬性,比較有用的屬性有3個:

       NFULA_CFG_NLBUFSIZ  能夠設置消息池的大小

       NFULA_CFG_TIMEOUT     設置消息池的刷新定時器時間間隔

       NFULA_CFG_QTHRESH  設置消息池容許存儲的最大消息個數

說明:內核向用戶空間發送數據有3個時機

(1)   消息池已滿,先發送全部舊的消息,再寫入新消息。

(2)   刷新定時器到期,發送全部消息。

(3)   消息池的消息個數大於容許的最大消息個數,發送全部舊消息,再寫入新消息。

3.      消息的建立和撤銷是由用戶空間程序控制,用戶空間經過發送配置消息到netlink子系統,建立消息池,並設置消息池的屬性。

4.      用戶空間關閉NFLOG子系統,對應的消息池也隨之撤銷,內核將再也不寫消息。

也就是說,用戶空間的讀取程序控制消息池的建立,撤銷以及消息池的屬性。

 

iptables中的NFLOG有如下4個屬性:

--nflog-group NUM          標識消息寫入哪一個消息池,若是消息池不存在將不會寫消息

--nflog-range NUM          消息中包含網絡層數據最大長度,0表示將寫入全部網絡層數據

--nflog-threshold NUM    消息池消息個數等於大於NUM,刷新消息池。

--nflog-prefix STRING    本條消息的前綴

說明:消息池也有一個threshold屬性,target中也有一個threshold屬性,每次寫入消息前,取二者最小的,而後判斷是否刷新消息池。

注意:這裏的group是選擇消息池,nflog netlink消息是發送給建立這個消息池的進程,不是用廣播包來發送,而ULOG是用廣播包來發送消息。

 

iptables的默認屬性: -j NFLOG –nflog-group 0 –nflog-threshold 1

圖 1  nflog消息編碼

圖1說明:nflog是使用屬性的名值對應來傳遞消息,能夠經過添加屬性來傳遞更多的消息,下圖是2.6.33.2內核中nflog已有的屬性:

圖2 nflog屬性列表

圖2說明:其中nfulnl_attr_type是數據包的信息屬性列表

nfulnl_attr_config是用於配置nflog消息池的屬性列表

 

NFLOG消息發送流程:

當一個數據包知足了匹配條件,並開始執行NFLOG target時,須要根據nflog target的私有數據struct xt_nflog_info來構造要發送的消息,並使用xt_nflog_info中消息池編號指定的消息池發送消息,使用單播把數據包發送給建立本消息池的進程。

注意:若是消息池還未創建,將不會寫入消息,也不會構造消息。

圖3是消息池和xt_nflog_info結構

圖3 消息池 和 NFLOG target私有數據結構

圖3說明:若是指定的消息池不存在(使用分組編號定位一個消息池),將不寫入消息,也不構造消息。消息池的創建和配置不是經過iptables進行,而是經過netlink傳遞配置消息到內核的nfnetlink子系統,nfnetlink子系統會根據消息的信息,來初始化一個消息池,圖2中的nfulnl_attr_config屬性列表就是用來創建和配置一個消息池。

 

這裏就要涉及到nfnetlink子系統如何根據消息的類型,定位相應的處理函數,如圖4《內核nfnetlink子系統結構》所示,是根據struct nlmsghdr {__u16   nlmsg_type;//前8位爲子系統id號 //後8位爲消息的類型};,找到相應的消息處理函數,最後根據屬性列表執行相應的動做。

 

圖4 內核nfnetlink子系統結構

 

圖4說明的是內核nfnetlink子系統根據消息類型定位相應的處理函數。

內核發送消息到用戶空間,用戶空間能夠經過libnfnetlink庫函數來接收消息,和內核相似libnfnetlink庫也是根據相同的字段來定位處理函數,如圖5《用戶空間libnfnetlink結構》所示。

圖5 用戶空間libnfnetlink結構

圖5說明:一個回調函數對應一個消息類型。

 

這裏說明的是nflog實現機制,事實上conntrack也是nfnetlink子系統的一部分,實現機制是同樣的,libnetfilter_conntrack庫就是在nfnetlink庫的基礎上進行擴展的,是否也有nflog對應的擴展庫呢?若是沒有也能夠仿照libnetfilter_conntrack創建一個擴展庫。

接下來講明ulog的實現機制,最後經過具體的例子程序來作最後的說明。

 

ULOG特色及實現機制

1.內核也是經過消息池來發送消息,可是不能接收消息,消息池是靜態的,也就是說,消息池的個數和相應的屬性是固定的,用戶空間無法進行配置,

2.因爲消息池老是存在的,只要執行ULOG目標,總會建立消息,並將消息寫入消息池。

3.消息的格式是固定的,傳出的是一個結構體,如圖6所示。

4.用戶空間沒有對應的庫函數支持。

 

說明:內核向用戶空間發送數據有3個時機

(1)消息池已滿,先發送全部舊的消息,再寫入新消息。

(2)刷新定時器到期,發送全部消息。

(3)消息池的消息個數大於ipt_ulog_info中的qthreshold,發送全部舊消息,再寫入新消息。

 

iptables中的ULOG有如下4個屬性

--ulog-nlgroup nlgroup     選擇哪一個消息池發送消息,發送給編號和消息池編號相同的分組

--ulog-cprange size    截取網絡層數據的最大長度

--ulog-qthreshold  當消息池中消息個數大於等於qthreshold,刷新消息池,而後再寫入新消息。

--ulog-prefix prefix    消息的前綴

注意:nlgroup是消息池的編號,一樣也是netlink分組編號,接收進城只有加入到這個分組才能夠接收這個分組的廣播包,具體的能夠看ULOG例子程序中的說明。

 

iptables的默認屬性: -j ULOG –ulog-group 1 –ulog-threshold 1

 

 

圖6 ulog消息結構

 

ULOG消息發送流程:

當一個數據包知足了匹配條件,並開始執行ULOG target時,須要根據uflog target的私有數據struct ipt_uflog_info來構造要發送的消息,並使用ipt_uflog_info中消息池編號指定的消息池發送消息,使用和消息池編號相同的廣播組發送廣播包。

注意:消息池老是存在,也總會寫入消息。

消息池的結構如圖7《ulog消息池結構》所示。

圖7 ulog消息池結構

 

 

NFLOG例子程序

1. 首先加載NFLOG target並創建NFLOG規則,以下:

iptables -A OUTPUT -p ICMP -d 192.168.190.2 -j NFLOG --nflog-group 112 --nflog-prefix "nflog-test."

規則說明:使用編號是112的消息池發送消息,消息的前綴是「nflog-test.」

如今消息池還未創建,內核還不會寫入消息。

2. 使用libnfnetlink庫函數提供的接口向內核發送配置命令,程序段以下:

cmd.command = NFULNL_CFG_CMD_BIND;

nfnl_fill_hdr(subh, &u.req.nlh, 0, AF_INET, 112, NFULNL_MSG_CONFIG, NLM_F_REQUEST);

nfnl_addattr_l(&u.req.nlh, sizeof(u), NFULA_CFG_CMD, &cmd, sizeof(cmd));

nfnl_addattr32(&u.req.nlh, sizeof(u), NFULA_CFG_QTHRESH, 10);

nfnl_addattr32(&u.req.nlh, sizeof(u), NFULA_CFG_TIMEOUT, htonl(400));

命令說明:

NFULNL_CFG_CMD_BIND:建立一個消息池

112是建立的消息池的編號

NFULA_CFG_QTHRESH:消息池最大消息個數 10。

NFULA_CFG_TIMEOUT:消息池定時器刷新時間,400*(1/100)=4秒。

 

運行截圖以下:

注意:這裏雖然設置消息的QTHRESH屬性是10,可是NFLOG target的QTHRESH屬性是1,

取其中最小的,因此QTHRESH屬性是1.

 

ULOG例子程序

1. 首先加載ULOG target並創建ULOG規則,以下:

iptables -A OUTPUT -p ICMP -d 192.168.190.2 -j ULOG --ulog-nlgroup 6 --ulog-prefix "ulog-test."

說明:使用編號是6的消息池廣播消息,全部屬於廣播6的接收進程均可以接收到消息,消息前綴是"ulog-test.",使用默認的最大消息個數1

如今只要有規則匹配,內核就會向消息池寫入消息,併發送消息。

2. 其中用戶空間消息接收程序,程序段以下:

group = 6;

sd = socket(AF_NETLINK, SOCK_RAW,NETLINK_NFLOG);

memset(&saddr, 0, sizeof(saddr));

memset(&daddr, 0, sizeof(daddr));

saddr.nl_family = AF_NETLINK;     

saddr.nl_pid = getpid();

saddr.nl_groups = group;

bind(sd, (struct sockaddr*)&saddr, sizeof(saddr));

setsockopt(sd, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP, &group, sizeof(group));

說明:

AF_NETLINK和NETLINK_NFLOG是說接收netlink協議族中協議類型是NETLINK_NFLOG

的數據包。

saddr.nl_pid = getpid()是說,接收發給本進程的數據包。

saddr.nl_groups = 6是說,也接收廣播組6的廣播包。

Setsockopt是因爲內核 2.6.14 對 netlink 套接字有新的實現,它缺省狀況下不容許用戶態應用發送給組號非 1 的netlink 組,所以用戶態應用要想使用非1的組,必須先加入到該組,使用Setsockopt實現。

程序運行截圖:

相關文章
相關標籤/搜索