日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

如何扩展Linux的ip_conntrack

發布時間:2025/4/16 linux 13 豆豆
生活随笔 收集整理的這篇文章主要介紹了 如何扩展Linux的ip_conntrack 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Linux中有一個基于Netfilter的連接跟蹤機制,即ip_conntrack,每一個conntrack表示的就是一個流,該流里面保存了大量的信息字段,這些字段本地有效,指導著數據包的轉發策略,但是我覺得這些字段信息還不夠詳細,試想,一個nfmark字段好像就可以做到一切了,但是我如果想為一個數據流綁定一個字符串怎么辦呢?也許你會說使用iptables+ipset+nfmark可以完成一切,這也是UNIX/Linux哲學的風格,一種后現代主義的風格,但是最近我上了不歸路,非要在ip_conntrack里面擴充一個字段,為我們產品加入一個基于用戶名字符串的訪問控制和審計功能,于是我有了以下看似可以的方案,順便鄙視一下紙上談兵的人:
1.完全學ipmark的樣子,在sk_buff和nf_conn里面均加一個mark字段,分別代表數據包的mark和數據流的mark
作罷的原因:需要重新編譯內核,而我不希望為了一個小小的功能重新編譯內核,背后的思想是我比較崇尚熱插拔。
2.不動sk_buff,只在nf_conn里面加一個字段,skb僅僅作為一個中轉,在iptables的target通過skb找到nf_conn,設置nf_conn的info字段
作罷的原因:Linux嚴格控制內核模塊的版本,模塊依賴的頭文件一點都不能動,如果我改變了net/netfilter/nf_conntrack.h,那么新編譯的所有的依賴nf_conntrack.ko的模塊中的符號CRC碼都會變化從而無法通過內核的驗證,我不得不學Netfilter的一個項目xtables-addons中compat-xtables的樣子,把所有的會改變CRC碼的導出函數全部再重新實現一遍,然而,天啊,我起初的想法太天真了,沒完美了的循環依賴,以至于我想罵兩句:
第一:
ip_conntrack為何不讓人擴展?雖然它有一個extend機制,但是MD簡直就是自說自話,全部都是預定義好的,就下面的枚舉里面的幾類:

enum nf_ct_ext_id {NF_CT_EXT_HELPER,NF_CT_EXT_NAT,NF_CT_EXT_ACCT,NF_CT_EXT_ECACHE,NF_CT_EXT_NUM, };
你加一個新的類型,就會改變內核頭文件,既然不讓擴展,為何還叫extend呢?你干脆直接放進nf_conn就可以了,搞成extend感覺上好像多么的模塊化,多么的可插拔,實際上你能擴展的東西只能是邏輯,而不能是數據結構!

第二:

Linux為何把extend寫的那么死呢?當我突然感到這是合理的時候,我就三緘其口了,后面我會說到,數據結構需要可以自解釋,即自己解釋自己。雖然人可以看到一個結構體馬上說出它的含義,但是程序卻很難將一堆數據對應到一個結構體!自解釋,如果不知道自解釋,那就說明你根本就TM就不懂計算機!雖然你可能很精通編程...

思路

既然不能擴展nf_conn的extend,也不能在nf_conn本身加新的字段,那么只能重新編譯內核了,在重新編譯內核的時候,加入且僅僅加入一個extend類型,作為一個中間層,在這個extend中實現一個可插拔的注冊機制,以后再想加入新的擴展就可以直接在這個extend的機制上進行了。然而,我還是不想編譯內核,這是一個思想!我希望做最小的改動。萬事都難不倒偏執的人,我采用了一個常規卻不常用的方法,那就是默默地擴展結構體的大小,這也正是在《JAVA編程思想》里面學到的一個思想。

思想

這其實是一種OO的思想,找到一個基類,然后擴展它,在擴展繼承的過程中實現你自己的邏輯,我擴展的是內核的nf_conn_counter結構體:
struct nf_conn_counter {u_int64_t packets;u_int64_t bytes; };我希望它成為下面的樣子:
struct nf_conn_counter {u_int64_t packets;u_int64_t bytes;unsigned char *info; }; 但是我又不能改變結構體的定義,所以我采用下面等價的辦法:
struct conn_info_extends_nf_conn_counter {struct nf_conn_counter base;char *info; }info是最關鍵的。我需要做的僅僅就是在為nf_conn_counter分配空間的時候為其多加一個指針的空間即可,至于這個指針指向什么,自有調用者解釋。在我的需求中,它可能就是一個字符串,存在info信息。acct_extend原始定義為(之所以選擇對acct開刀,是因為它足夠簡單,在字面上里面,其表示統計信息,加入一個info也無可厚非):
static struct nf_ct_ext_type acct_extend __read_mostly = {.len = sizeof(struct nf_conn_counter[IP_CT_DIR_MAX]),.align = __alignof__(struct nf_conn_counter[IP_CT_DIR_MAX]),.id = NF_CT_EXT_ACCT, };
將其修改為:
struct info_compat {struct nf_conn_counter nc[IP_CT_DIR_MAX];unsigned char * info; };static struct nf_ct_ext_type acct_extend __read_mostly = {.len = sizeof(struct info_compat),.align = __alignof__(struct info_compat),.id = NF_CT_EXT_ACCT, };
到此為止,我沒有修改任何內核頭文件,接下來我來寫一個測試模塊來進行測試:
#include <linux/ip.h> #include <linux/module.h> #include <linux/skbuff.h> #include <linux/version.h> #include <net/netfilter/nf_conntrack.h> #include <net/netfilter/nf_conntrack_acct.h>MODULE_AUTHOR("xtt"); MODULE_DESCRIPTION("gll"); MODULE_LICENSE("GPL"); MODULE_ALIAS("XTT and GLL");struct nf_info {struct nf_conn_counter nc[IP_CT_DIR_MAX];char *info; };static unsigned int ipv4_conntrack_info (unsigned int hooknum,struct sk_buff *skb,const struct net_device *in,const struct net_device *out,int (*okfn)(struct sk_buff *)) {u32 addr = ip_hdr(skb)->daddr;// 測試我家的路由器的地址192.168.1.1if (addr == 0x0101a8c0) {struct nf_conn *ct;enum ip_conntrack_info ctinfo;struct nf_conn_counter *acct;struct nf_info *info;unsigned char *cn = NULL;ct = nf_ct_get(skb, &ctinfo);if (!ct || ct == &nf_conntrack_untracked)return NF_ACCEPT;acct = nf_conn_acct_find(ct);if (acct) {info = (struct nf_info *)acct;info->info = (unsigned char*) kzalloc(32, GFP_ATOMIC);if (!info->info) {return NF_ACCEPT;} // 測試將1234567890作為字符串設置到conntrackmemcpy(info->info, "1234567890", min(32, strlen("1234567890")));}}return NF_ACCEPT; }static struct nf_hook_ops ipv4_conn_info __read_mostly = {.hook = ipv4_conntrack_info,.owner = THIS_MODULE,.pf = NFPROTO_IPV4,.hooknum = NF_INET_LOCAL_OUT,.priority = NF_IP_PRI_CONNTRACK + 1, };static int __init test_info_init(void) {int err;err = nf_register_hook(&ipv4_conn_info);if (err) {return err;}return err; }static void __exit test_info_exit(void) {nf_unregister_hook(&ipv4_conn_info); }module_init(test_info_init); module_exit(test_info_exit);

到底成功了沒有呢?我需要將這一切展示在/proc/net/nf_conntrack里面,但是由于我使用了acct機制,所以我需要打開內核的acct選項:
sysctl -w net.netfilter.nf_conntrack_acct=1
真正修改的地方在/net/netfilter/nf_conntrack_standalone.c的ct_seq_show函數:
if (seq_printf(s, "use=%u ", atomic_read(&ct->ct_general.use)))goto release;{struct nf_info {struct nf_conn_counter acct[2];char *info;};struct nf_conn_counter *acct;struct nf_info *info;acct = nf_conn_acct_find(ct);if (acct) {info = (struct nf_info *)acct;if (info->info) {if (seq_printf(s, "info=%s\n", info->info)) {goto release;}}} }
在測試的時候,/proc/net/nf_conntrack中擁有了一個信息:
ipv4 ? ? 2 tcp ? ? ?6 431985 ESTABLISHED src=192.168.1.109 dst=192.168.1.1 sport=33591 dport=50 packets=2 bytes=112 src=192.168.1.1dst=192.168.1.109 sport=50 dport=33591 packets=1 bytes=60 [ASSURED] mark=0 zone=0 use=2 ?info=1234567890
這就說明這種方法是可行的,改動的地方并不多,關鍵是你要找到一個危險性最少的開刀部位,然后按照OO的思想擴展它,給它它所有沒有的行為。曾經,我對nat的extend進行了偷梁換柱,但那是不對的,正確的做法是在原有結構體的地址后面緊跟著進行擴展,類似0長度數組那種。
? ? ? 我需要解釋一下程序的自解釋了。Linux在實現nf_conntrack的extend的時候,為何將類型數值以及定義的順序用一個枚舉寫死呢?換句話說那就是為何不允許用戶隨意定義extend呢?答案是:那很難!Why?試想,如果我把一個結構體給了一個extend type。請問我把這個type存在哪?除了事先自定義一個type序列,僅存的辦法就是把這個type序列存在extend本身了,這就遇到了一個循環定義的問題,我們對此是沒有辦法的,一個程序很難看到一對數字后,然后就可以把它們看作一個結構體,起碼的字段分界就無法解決。雖然可以用OO的思想之外,剩下的解決方案就是尋求一種自解釋的數據格式。我能想到的就是ASN.1了。實際上,ASN.1也是一種事先定義的類型格式序列,只不過該序列是經過標準化的而已,一個ASN.1序列是不需要解釋的,它可以自己解釋自己,需要的僅僅是文檔。一個ASN.1序列可以將一段數據解釋為一個結構體,或者反過來也可以。OpenSSL里面的d2i/i2d就是做這個的。難道不是嗎?
? ? ? 清明時節雨紛紛,就這樣在沒有雨的一整天過去了,沒有從《JAVA編程思想》中看到什么思想,依然沒有感悟到JAVA的思想,依然沒有。


轉載于:https://blog.51cto.com/dog250/1391022

總結

以上是生活随笔為你收集整理的如何扩展Linux的ip_conntrack的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 久久精品国产99国产精品 | 免费欧美一级视频 | 69色堂| 五月开心播播网 | 影音先锋亚洲天堂 | 久爱精品 | 在线视频一区二区 | 成人乱人乱一区二区三区一级视频 | 超碰69| 亚洲欧洲日本国产 | 国产午夜视频 | 国产精品视频999 | 绿帽视频 | 久久午夜精品 | 97精品视频| 午夜精品久久久久久久四虎美女版 | 91视频xxx| 亚洲人成电影一区二区在线 | 亚洲精品高清无码视频 | 精品无码免费视频 | 国产精品二区三区 | 亚洲天堂免费视频 | 欧av在线| 日本污视频在线观看 | 女人被狂躁c到高潮 | 91在线看黄 | 熟女少妇在线视频播放 | 少妇人妻一区二区 | 国产成人啪精品午夜在线观看 | 日韩激情电影在线 | 国产精品无码av在线播放 | 欧美视频免费在线 | 在线免费精品视频 | 日本91网站| 国产免费黄色网址 | 小柔好湿好紧太爽了国产网址 | 中文字幕一区二区三区视频 | 老太脱裤让老头玩ⅹxxxx | 中文字幕制服丝袜 | 欧美日韩一区二区区 | 亚洲一区三区 | av最新天| 一级啪啪片 | 中文字幕一区二区三区人妻四季 | 国产高清色| 午夜三级在线观看 | 狠狠躁夜夜躁人人爽天天高潮 | 私人网站| 国产精品欧美激情在线 | av天堂永久资源网 | 亚洲玖玖爱 | 亚洲精品久久久中文字幕 | 天天av天天翘 | 欧美黄色三级视频 | av网在线观看 | 男人桶进美女尿囗 | 国产一伦一伦一伦 | av动漫天堂 | 香蕉国产精品视频 | 天天干天天操天天爱 | 久久国产美女 | 用我的手指扰乱你 | 午夜免费网站 | 手机看片国产1024 | 干成人网| 看片地址 | 老司机午夜精品 | 欧美日韩在线影院 | 夜夜爽天天爽 | 天堂在线资源库 | 国产精品乱轮 | 女人喷潮完整视频 | 亚洲区一区二 | 成人精品在线 | 国产精品精品国产 | 午夜影院 | 色涩视频在线观看 | 无码人妻精品一区二区三区在线 | 岛国av免费在线观看 | 欧美激情综合五月色丁香 | 亚洲网址在线观看 | 插插插网站 | 亚洲一级中文字幕 | 国产精品日韩在线 | 西西44rtwww国产精品 | 伊人影视在线 | 三上悠亚久久 | 一级日韩一级欧美 | 国产午夜精品久久久 | 欧美人妻精品一区二区免费看 | 亚洲一区图片 | 手机看片1024国产 | 成人免费看类便视频 | 国精产品一区一区三区免费视频 | 国产自产| 欧美激情黄色 | 亚洲男人的天堂在线 | 九九在线| 成人在线精品视频 |