李臣
摘要:網(wǎng)絡(luò)安全問題在現(xiàn)實生活中變的愈發(fā)重要,而研究利用操作系統(tǒng)自帶的防火墻系統(tǒng)來阻斷異常流量是解決網(wǎng)絡(luò)安全問題最常使用且高效的手段。Linux操作系統(tǒng)作為一個開源的操作系統(tǒng)廣泛應(yīng)用于服務(wù)器和嵌入式領(lǐng)域,而這些領(lǐng)域往往是網(wǎng)絡(luò)安全問題的重災(zāi)區(qū),研究Linux下的防火墻具有重要意義?,F(xiàn)有的防火墻系統(tǒng)中的配置規(guī)則一般是基于IP配置的,但是對于多個域名對應(yīng)一個IP的場景這種配置便不再適用,文章在Netfilter框架的基礎(chǔ)上設(shè)計實現(xiàn)了一個基于域名進行配置的內(nèi)核模塊來解決上述問題。
關(guān)鍵詞: 網(wǎng)絡(luò)安全; 異常流量;Linux操作系統(tǒng); 防火墻規(guī)則; Netfilter框架
中圖分類號:TP311? ? ? 文獻標識碼:A
文章編號:1009-3044(2023)06-0066-03
開放科學(資源服務(wù))標識碼(OSID)
隨著虛擬主機的廣泛應(yīng)用,一個IP經(jīng)常會對應(yīng)多個域名[1]。這樣導致我們在使用防火墻進行單個或多個IP流量阻斷時會發(fā)生錯誤域名的阻斷。為了解決這一難題,本文基于Netfilter框架的可擴展性開發(fā)了一個Linux內(nèi)核模塊使得防火墻可以針對具體的域名或者域名集進行流量的阻斷。
1? Netfilter/Iptables框架
Netfilter/Iptables 由三部分組成,分別是Netfilter框架,Iptables(內(nèi)核空間)和Iptables 命令行工具(用戶空間)[2]。
1.1? Netfilter框架
Netfilter是Linux內(nèi)核提供的一個框架[3],它允許以自定義處理程序的形式實現(xiàn)各種與網(wǎng)絡(luò)相關(guān)的操作。Netfilter 在 Linux內(nèi)核中表現(xiàn)為一系列的hook, 并允許Linux 內(nèi)核模塊注冊為回調(diào)函數(shù),Linux內(nèi)核模塊通過回調(diào)函數(shù)操作網(wǎng)絡(luò)報文。Netfilter框架一共提供了5個hook,分別位于linux 網(wǎng)絡(luò)棧中的各個處理節(jié)點,如圖1所示:
Netfilter Hook的意義:
NF_IP_PRE_ROUTING: 位于路由之前,報文一致性檢查之后(報文一致性檢查包括: 報文版本、報文長度和checksum)。
NF_IP_LOCAL_IN: 位于報文經(jīng)過路由之后,并且目的是本機的。
NF_IP_FORWARD:位于在報文路由之后,目的地非本機的。
NF_IP_LOCAL_OUT: 由本機發(fā)出去的報文,并且在路由之前。
NF_IP_POST_ROUTING: 所有即將離開本機的報文。
Linux 內(nèi)核模塊可以注冊到任何的hook,注冊的回調(diào)函數(shù)也必須指定優(yōu)先級。當一個報文通過hook的時候,hook將會依據(jù)優(yōu)先級調(diào)用回調(diào)函數(shù)。注冊的回調(diào)函數(shù),可以有五種返回,每種返回代表對報文不同的操作:
NF_ACCEPT: 繼續(xù)正常處理此報文,即允許報文通過。
NF_DROP: 丟棄此報文,不再進行繼續(xù)處理,即拒絕此報文。
NF_STOLEN: 取走這個報文,不再繼續(xù)處理。
NF_QUEUE: 報文進行重新排隊,可以將報文發(fā)到用戶空間的程序,進行修改或者決定是拒絕或者允許。
NF_REPEAT: 報文重新調(diào)用hook。
1.2 Iptables內(nèi)核空間
Iptables 是基于Netfilter框架實現(xiàn)的報文選擇系統(tǒng)[4],其可以用于報文的過濾、網(wǎng)絡(luò)地址轉(zhuǎn)換和報文修改等功能。Iptables 本質(zhì)上是包含了5個規(guī)則表,而規(guī)則表則包含了一些列的報文的匹配規(guī)則以及操作目標。以下對每個規(guī)則表進行了簡單說明:
Filter Table: 是一個默認的規(guī)則表,用于報文的過濾,注冊了三個鏈: INPUT、FORWARD和OUTPUT。
NAT Table: 主要用于NAT轉(zhuǎn)換,注冊了四個鏈:PREROUTING、INPUT、OUTPUT和POSTROUTING。
Mangle Table: 主要用于報文的修改,一共注冊了五個鏈: PREROUTING、OUTPUT、INPUT、FORWARD和POSTROUTING。
Raw Table: 可以對報文不進行鏈路跟蹤,其優(yōu)先級在hook中注冊很高,注冊了兩個鏈: PREROUTING和OUTPUT。
Security Table: 用于強制網(wǎng)絡(luò)接入控制,注冊了三個鏈:INPUT、OUTPUT 和 FORWARD。
1.3 Iptables命令行工具(用戶空間)
Iptables命令行工具是工作在用戶空間的操作工具,用于修改內(nèi)核空間的規(guī)則表[5]。
2 SNI(服務(wù)器名稱指示)
SNI 是 TLS 協(xié)議(以前稱為 SSL 協(xié)議)的擴展[6],該協(xié)議在 HTTPS 中使用,它的出現(xiàn)是為了解決多個服務(wù)器域名對應(yīng)同一個IP而產(chǎn)生客戶端不知道鏈接哪個服務(wù)端的問題。它包含在 TLS/SSL 握手流程中,以確??蛻舳嗽O(shè)備能夠看到他們嘗試訪問的網(wǎng)站的正確 SSL 證書。該擴展使得可以在 TLS 握手期間指定網(wǎng)站的主機名或域名 ,而不是在握手之后打開 HTTP 連接時指定。
3 SNI防火墻實現(xiàn)
基于Netfilter框架很好的擴展性,用戶可以開發(fā)編寫自定義的Linux內(nèi)核模塊并在Netfilter上注冊為回調(diào)函數(shù)來實現(xiàn)自定義的防火墻功能。
3.1? 匹配模塊的實現(xiàn)
每一條iptables配置的規(guī)則中都包含了匹配條件(match)和動作(target),要定義一個新的匹配條件就要實現(xiàn)一個匹配條件模塊[7]。匹配模塊的職責是檢測每一個數(shù)據(jù)包確定是否滿足匹配條件。首先要定義一個xt_match結(jié)構(gòu)體類型的變量,模塊初始化的時候調(diào)用xt_register_match函數(shù)將其注冊到netfilter框架中,xt_match結(jié)構(gòu)體的定義如下:
struct xt_match {
const char name[XT_EXTENSION_MAXNAMELEN];
unsigned short family;
bool (*match) (const struct sk_buff *sbk, struct xt_action_param *);
int (*checkentry) (const struct xt_mtchk_param *);
void (*destroy) (const struct xt_mtdtor_param *);
}
3.1.1 自定義結(jié)構(gòu)體
我們在iptables命令中支持的匹配條件包括域名精確匹配、域名模糊匹配和域名集匹配。域名集的匹配借鑒了ipsets[8]。為了支持這些功能自定義了一個結(jié)構(gòu)體xt_tls_info和host_set
struct xt_tls_info {
char host_or_set_name[MAX_HOSTNAME_LEN + 1]; //匹配條件中的單個域名和域名集
__s32 hostset_index; //域名集存儲在域名表中的位置
}
3.1.2 域名集數(shù)據(jù)的存入與查詢
域名集中的數(shù)據(jù)集合的存入使用Linux系統(tǒng)中的proc文件系統(tǒng),每一個域名集對應(yīng)proc文件系統(tǒng)中的一個目錄。
host_set hs;
hs->proc_file = proc_create_data(name, 0644, proc_fs_hostset_dir, &proc_fops, hs);
在做查詢的時候我們使用紅黑樹來做高性能查詢。
3.1.3 tls_mt_init函數(shù)
原型為:static int __init tls_mt_init (void)
主要完成xt_register_matches函數(shù)將xt_match類型的變量tls_mt_regs[]注冊到netfilter框架中及host_set表的初始化:
static struct host_set *host_set_table;
host_set_table = kmalloc(sizeof (struct host_set) * max_host_sets, GFP_KERNEL);
3.1.4 tls_mt_check函數(shù)
原型為:static int tls_mt_check (const struct xt_mtchk_param *par)
首先得到iptable命令中的匹配信息,對應(yīng)到代碼中的xt_tls_info類型的變量match_info,判斷規(guī)則中的匹配信息是不是域名集,如果是則把該域名集信息存入到host_set_table中。存入到表中的索引位置也要放入match_info變量的hostset_index中。
3.1.5 tls_mt函數(shù)
原型為:static bool tls_mt(const struct sk_buff *skb, struct xt_action_param *par)
首先我們會根據(jù)HTTPS協(xié)議的格式從skb->data中解析出SNI中的域名,然后從par->mathchinfo中取出我們在iptables中創(chuàng)建的匹配信息,從而進行規(guī)則匹配。根據(jù)標準以太網(wǎng)數(shù)據(jù)格式RFC6066[],SNI字段的位置和多個字段有關(guān)。具體處理流程為:
在整個TCP報文中截取TCP報文頭之后的有效TLS協(xié)議負載報文數(shù)據(jù)data
檢測data數(shù)組的第一個元素Content Type判斷是否為0x16(Handshake)
檢測data數(shù)組的第六個元素Handshake協(xié)議判斷是否為0x01(Client Hello)
依次檢測Session ID長度、ciphers長度、compression types長度是否小于報文頭長度
檢測通過后得到所有擴展數(shù)據(jù)項,依次遍歷這些擴展數(shù)據(jù)得到SNI的數(shù)據(jù)
得到域名的信息之后我們再與規(guī)則中的域名或者域名集信息進行匹配。若是域名信息則直接使用glob_match函數(shù)進行精確或者模糊匹配。若是域名集信息則根據(jù)match_info的索引信息精確定位到host_set_table表中的位置再進行匹配。
3.1.6 tls_mt_destroy函數(shù)
原型為:static void tls_mt_destroy(const struct xt_mtdtor_param *par)
在iptables命令中刪除規(guī)則時根據(jù)par中的match_info信息刪除相應(yīng)的域名或者域名集信息。
3.2 用戶態(tài)功能實現(xiàn)
首先定義一個xtables_match類型的變量:
static struct xtables_match tls_match = {
.name = "tls",? ? // 擴展名稱與匹配模塊中的名稱一致
.size = XT_ALIGN(sizeof(struct xt_tls_info)),
.userspacesize = XT_ALIGN(sizeof(struct xt_tls_info)),
.help = tls_help,? // 輸入iptables -m tls -h調(diào)用
.save = tls_save,
.x6_parse = tls_parse, // 解析命令行參數(shù)
};
使用iptables的示例如下:
1)阻止去往facebook的流量:
sudo iptables -A OUTPUT -p tcp --dport 443 -m tls --tls-host "www.facebook.com" -j DROP
2)模糊匹配:
sudo iptables -A OUTPUT -p tcp --dport 443 -m tls --tls-host "*.googlevideo.com" -j DROP
3)域名集匹配:
sudo iptables -A OUTPUT -p tcp --dport 443 -m tls --tls-hostset blacklist -j DROP
域名集中添加域名:
sudo echo +facebook.com > /proc/net/xt_tls/hostset/blacklist
sudo echo +googlevideo.com > /proc/net/xt_tls/hostset/blacklist
域名集中刪減域名:
sudo echo -facebook.com > /proc/net/xt_tls/hostset/blacklist
4 結(jié)論
針對一個IP經(jīng)常會對應(yīng)多個域名在使用Linux系統(tǒng)自帶的防火前進行IP阻斷會發(fā)生誤阻斷的問題,基于Netfilter/Iptables框架開發(fā)了一個Linux內(nèi)核模塊進行基于域名或者域名集的阻斷,具體原理是使用HTTPS協(xié)議中的SNI標示。實驗表明,在配置了基于域名的相關(guān)規(guī)則后對應(yīng)的流量被正常阻斷,而且規(guī)則支持精準匹配和模糊匹配。
參考文獻:
[1] 賴雋文,張煥杰,楊壽保.大規(guī)模WWW虛擬主機設(shè)計[J].小型微型計算機系統(tǒng),2001,22(3):373-375.
[2] 姚曉宇,趙晨.Linux內(nèi)核防火墻Netfilter實現(xiàn)與應(yīng)用研究[J].計算機工程,2003,29(8):112-113,163.
[3] 王一平,韋衛(wèi).網(wǎng)絡(luò)安全框架Netfilter在Linux中的實現(xiàn)[J].計算機工程與設(shè)計,2006,27(3):439-442,468.
[4] (美)Robert Love.Linux內(nèi)核設(shè)計與實現(xiàn)[M].2版.陳莉君,康華,張波.北京:機械工業(yè)出版社,2006.
[5] Daniel P.Bovet,Marco Cesati.深入理解LINUX內(nèi)核[M].陳莉君,張瓊聲,張宏偉,譯.北京:中國電力出版社,2007.
[6] 毛偉杰,李永忠.基于SNI的加密流量檢測在蜜罐中的研究與應(yīng)用[J].信息技術(shù),2021,45(8):97-101.
[7] 毛新宇.Linux內(nèi)核防火墻netfilter的原理和應(yīng)用[J].微型機與應(yīng)用,2004,23(4):35-37.
[8] 岳新.Linux2.4內(nèi)核下基于Netfilter框架可擴展性研究與實現(xiàn)[D].哈爾濱:哈爾濱理工大學,2005.
【通聯(lián)編輯:光文玲】