概述
連接跟蹤是很多網(wǎng)絡(luò)服務(wù)和應(yīng)用的基礎(chǔ)。例如,kubernetes的service,ServiceMesh sidecar,4層負(fù)載均衡軟件LVS/IPVS,容器網(wǎng)絡(luò),OpenvSwitch,OpenStack安全組等等都是依賴連接跟蹤。
概念
顧名思義,連接跟蹤就是跟蹤或維護(hù)網(wǎng)絡(luò)連接及其狀態(tài)的。

上圖中,Linux主機(jī)的IP地址是10.1.1.2,包含3個(gè)連接:
1、10.1.1.2:55667 <-> 10.2.2.2.:80:本地發(fā)起的連接,用于訪問(wèn)外部HTTP/TCP服務(wù)。
2、10.3.3.3:23456 <-> 10.3.3.2.:21:外部連接訪問(wèn)該節(jié)點(diǎn)的FTP/TCP服務(wù)。
3、10.1.1.2:33987 <-> 10.4.4.4.:53:本地發(fā)起的連接,用于訪問(wèn)外部DNS/UDP服務(wù)。
Conntrack模塊負(fù)責(zé)發(fā)現(xiàn)和記錄這些連接及其狀態(tài),包括:
- 提取數(shù)據(jù)包的五元組,區(qū)分?jǐn)?shù)據(jù)包和相關(guān)連接。
- 為所有連接維護(hù)一個(gè)“數(shù)據(jù)庫(kù)”(連接跟蹤表),存儲(chǔ)連接的創(chuàng)建時(shí)間、發(fā)送的數(shù)據(jù)包、發(fā)送的字節(jié)信息等。
- 回收陳舊的連接信息(GC)。
- 為上層功能服務(wù),例如NAT。
但是請(qǐng)注意,“連接跟蹤”中的術(shù)語(yǔ)“連接”不同于我們常在TCP/IP棧中所指的“連接”概念。簡(jiǎn)而言之:
- 在TCP/IP協(xié)議棧中,“連接”是4層概念。TCP是一種面向連接的協(xié)議,所有的報(bào)文都需要得到確認(rèn)(ACK),并且有重傳機(jī)制。UDP是一種無(wú)連接協(xié)議,不需要確認(rèn)(ACK),也不需要重傳。
- 在連接跟蹤中,五元組唯一地定義數(shù)據(jù)流,數(shù)據(jù)流表示連接。
后面我們將看到即使ICMP(3層協(xié)議)也有連接數(shù)據(jù)。但并不是所有的協(xié)議都有連接跟蹤。
我們所說(shuō)的“連接”,在大多數(shù)情況下是指后者,即“連接跟蹤”上下文中的“連接”。
理論
有了上述概念,讓我們來(lái)分析連接跟蹤的基本理論。要跟蹤一個(gè)節(jié)點(diǎn)上所有連接的狀態(tài),我們需要:
1、讀取(或過(guò)濾)通過(guò)該節(jié)點(diǎn)的每個(gè)數(shù)據(jù)包,并分析數(shù)據(jù)包。
2、設(shè)置一個(gè)“數(shù)據(jù)庫(kù)”記錄這些連接的狀態(tài)。
3、根據(jù)數(shù)據(jù)包提取信息,及時(shí)更新連接狀態(tài)到數(shù)據(jù)庫(kù)(連接跟蹤表)。
例如:
1、當(dāng)讀取一個(gè)TCP SYC數(shù)據(jù)包時(shí),我們將確認(rèn)這是在嘗試新的連接,我們需要?jiǎng)?chuàng)建一個(gè)新的連接跟蹤記錄。
2、當(dāng)?shù)玫揭粋€(gè)屬于現(xiàn)有連接的數(shù)據(jù)包時(shí),我們需要更新連接跟蹤的統(tǒng)計(jì)信息,例如發(fā)送的字節(jié)數(shù)、發(fā)送的數(shù)據(jù)包數(shù)、超時(shí)值等。
3、當(dāng)超過(guò)30分鐘沒(méi)有包匹配conntrack條目時(shí),我們考慮從數(shù)據(jù)庫(kù)中刪除該條目。
除了上述功能外,性能也是值得我們關(guān)注的,因?yàn)閏onntrack模塊會(huì)對(duì)每一個(gè)數(shù)據(jù)包進(jìn)行過(guò)濾和分析。性能是相當(dāng)重要的,但它們超出了本文的范圍。在稍后介紹內(nèi)核conntrack實(shí)現(xiàn)時(shí),我們將再次回到性能問(wèn)題。
另外,最好有一些管理工具,方便使用conntrack。
Netfilter
Linux內(nèi)核中的連接跟蹤是在Netfilter框架中作為一個(gè)模塊實(shí)現(xiàn)的。

Netfilter是內(nèi)核內(nèi)部的一個(gè)包操作和過(guò)濾框架。它在內(nèi)核中提供了幾個(gè)掛鉤點(diǎn)hook,因此可以完成包讀取、過(guò)濾和許多其他處理。
更清楚地說(shuō),鉤子(hook)是一種在包的遍歷路徑上放置多個(gè)檢查點(diǎn)的機(jī)制。當(dāng)一個(gè)包到達(dá)一個(gè)鉤子時(shí),首先檢查規(guī)則,檢查結(jié)果可能是:
1、通過(guò):對(duì)數(shù)據(jù)包不做任何處理,把它推回到原來(lái)的路徑,讓它通過(guò)。
2、修改:替換網(wǎng)絡(luò)地址(NAT),然后推回到原來(lái)的路徑,繼續(xù)通過(guò)。
3、丟棄:例如,通過(guò)在這個(gè)檢查(掛鉤)點(diǎn)配置的防火墻規(guī)則。
注意,conntrack模塊只提取連接信息并維護(hù)其數(shù)據(jù)庫(kù),它不會(huì)修改或丟棄數(shù)據(jù)包。修改和刪除是由其他模塊完成的,例如NAT。
Netfilter是Linux內(nèi)核中最早的網(wǎng)絡(luò)框架之一,它最初于1998年開(kāi)發(fā),2000年合并到內(nèi)核2.4.x主線中。經(jīng)過(guò)20多年的發(fā)展,它變得非常復(fù)雜,以至于在某些場(chǎng)景中導(dǎo)致性能下降,我們稍后將對(duì)此進(jìn)行更多討論。
進(jìn)一步考慮
根據(jù)我們?cè)谏弦还?jié)的討論,連接跟蹤的概念獨(dú)立于Netfilter,而后者只是連接跟蹤的一種實(shí)現(xiàn)。
換句話說(shuō),只要具備了鉤子(hook)功能——能鉤住經(jīng)過(guò)系統(tǒng)的每一個(gè)數(shù)據(jù)包——我們就可以實(shí)現(xiàn)自己的連接跟蹤。

Cilium是Kubernetes的一個(gè)云原生網(wǎng)絡(luò)解決方案,實(shí)現(xiàn)了這樣的連接跟蹤和NAT機(jī)制。實(shí)現(xiàn)的基礎(chǔ):
1、基于BPF鉤子來(lái)勾住數(shù)據(jù)包(BPF類似于Netfilter的Hook)。
2、基于BPF鉤子實(shí)現(xiàn)一個(gè)全新的連接跟蹤和NAT模塊。內(nèi)核版本4.19+。
因此,可以完全移除整個(gè)Netfilter模塊,Cilium還可以為Kubernetes提供網(wǎng)絡(luò)功能例如ClusterIP,NodePort,ExternalIP和負(fù)載均衡。
因?yàn)樗倪B接跟蹤實(shí)現(xiàn)獨(dú)立于Netfilter,Cilium的連接跟蹤和NAT信息不是存儲(chǔ)在系統(tǒng)的連接跟蹤表和NAT表中。因此,通常使用的網(wǎng)絡(luò)工具conntrack/netstats/ss/lsof無(wú)法查詢到相關(guān)信息,你必須使用Cilium的方式,例如;
$ cilium bpf nat list
$ cilium bpf ct list global
而且,配置也是獨(dú)立的,你需要指定Cilium的參數(shù),例如命令行參數(shù)-bpf-ct-tcp-max。
我們澄清了conntrack的概念是獨(dú)立于NAT模塊的,但是出于性能考慮,代碼可能是耦合的。例如,當(dāng)對(duì)conntrack表執(zhí)行GC時(shí),它將有效地刪除NAT表中的相關(guān)條目,而不是為NAT表維護(hù)一個(gè)單獨(dú)的GC循環(huán)。
使用場(chǎng)景
我們來(lái)看看一些基于conntrack的具體網(wǎng)絡(luò)應(yīng)用程序/函數(shù)。
NAT網(wǎng)絡(luò)地址轉(zhuǎn)換
顧名思義,NAT轉(zhuǎn)換(數(shù)據(jù)包)網(wǎng)絡(luò)地址(IP+端口)。

上圖中,假設(shè)節(jié)點(diǎn)IP 10.1.1.2可以被其他節(jié)點(diǎn)訪問(wèn),但是內(nèi)部網(wǎng)絡(luò)地址范圍在192.168.1.0/24的,外部訪問(wèn)不了,類似節(jié)點(diǎn)上容器地址。這表明:
1、數(shù)據(jù)包原地址在192.168.1.0/24范圍內(nèi)可以被發(fā)送,因?yàn)槌隹诼酚芍灰蕾囉谀康腎P。
2、但是,響應(yīng)數(shù)據(jù)包(目的IP范圍是在192.168.1.0/24內(nèi))就無(wú)法返回了,因?yàn)?92.168.1.0/24在節(jié)點(diǎn)上是不能直接被外界訪問(wèn)的。
這種情況的一種解決方案就是:
1、在發(fā)送原地址范圍在192.168.1.0/24的數(shù)據(jù)包時(shí),將原地址IP替換成節(jié)點(diǎn)IP 10.1.1.2然后再發(fā)送出去。
2、接收到返回?cái)?shù)據(jù)包,做相反的操作,并轉(zhuǎn)發(fā)給原始發(fā)送者。
這只是NAT的底層工作機(jī)制。
容器網(wǎng)絡(luò)默認(rèn)是網(wǎng)橋模式,使用的就是上面的NAT機(jī)制來(lái)實(shí)現(xiàn)容器與外部節(jié)點(diǎn)的通信的。在節(jié)點(diǎn)內(nèi),每個(gè)Docker容器分配一個(gè)本地IP地址。該地址支持節(jié)點(diǎn)內(nèi)容器之間的通信,但當(dāng)與節(jié)點(diǎn)外的服務(wù)通信時(shí),通信將被NAT處理。
NAT也可以替換源端口。這并不難理解:每個(gè)IP地址可以使用完整的端口范圍(例如1~65535)。假設(shè)我們有兩個(gè)連接:
- 192.168.1.2:3333 <–> NAT <–> 10.2.2.2:80
- 192.168.1.3:3333 <–> NAT <–> 10.2.2.2:80
如果NAT只將源IP地址替換為節(jié)點(diǎn)IP地址,則上述兩個(gè)不同連接NAT處理好后是:- 10.1.1.2:3333 <–> 10.2.2.2:80
- 10.1.1.2:3333 <–> 10.2.2.2:80
兩個(gè)連接混在一起無(wú)法區(qū)分,返回?cái)?shù)據(jù)將不能做地址轉(zhuǎn)換操作,因此,如果發(fā)生沖突,NAT也會(huì)替換源端口。
NAT還可以進(jìn)一步分類:
- SNAT:原地址轉(zhuǎn)換。
- DNAT:目的地址轉(zhuǎn)換。
- Full NAT:原地址和目的地址都轉(zhuǎn)換。
上圖中使用的是SNAT轉(zhuǎn)換。NAT依賴于連接跟蹤,并且NAT是連接跟蹤最重要使用場(chǎng)景。
4層負(fù)載均衡(L4LB)
讓我們?cè)龠M(jìn)一步討論,基于NAT模式的4層負(fù)載均衡。L4LB是根據(jù)數(shù)據(jù)包的L3+L4信息來(lái)轉(zhuǎn)發(fā)流量的,例如src/dst ip(原地址/目的地址),src/dst端口。
VIP(虛地址):是實(shí)現(xiàn)4層負(fù)載均衡的一種方式:
- 具有不同真實(shí)IP的多個(gè)后端節(jié)點(diǎn)注冊(cè)到相同的虛IP (VIP)
-
來(lái)自客戶端的流量首先到達(dá)VIP,然后負(fù)載均衡到特定的后端ip。
如果L4LB采用NAT模式(VIP和Real ip之間),L4LB會(huì)對(duì)客戶端和服務(wù)器之間的流量進(jìn)行全NAT轉(zhuǎn)換,數(shù)據(jù)流如下圖所示:
4層負(fù)載均衡:NAT模式
有狀態(tài)防火墻
有狀態(tài)防火墻是相對(duì)于早期的無(wú)狀態(tài)防火墻而言。很明顯,要提供有狀態(tài)防火墻,必須跟蹤數(shù)據(jù)流和狀態(tài)—這正是連接跟蹤所做的事情。
我們來(lái)看一個(gè)具體例子:OpenStack安全組,主機(jī)防火墻解決方案。
OpenStack security group
安全組提供的是虛擬機(jī)級(jí)別的安全隔離,它是通過(guò)在虛擬機(jī)的主機(jī)網(wǎng)絡(luò)設(shè)備上應(yīng)用有狀態(tài)防火墻規(guī)則來(lái)實(shí)現(xiàn)的。在當(dāng)時(shí),最成熟的有狀態(tài)防火墻可能是Netfilter/iptables。
現(xiàn)在回到每個(gè)計(jì)算節(jié)點(diǎn)內(nèi)部的網(wǎng)絡(luò)拓?fù)洌?/p>

每個(gè)計(jì)算節(jié)點(diǎn)用一個(gè)OVS橋接(br-int)連接(集成)它內(nèi)部的所有虛擬機(jī)vm。如果只考慮網(wǎng)絡(luò)連接,每個(gè)VM應(yīng)該直接連接到br-int。但問(wèn)題來(lái)了:
- OVS早期版本沒(méi)有連接跟蹤模塊conntrack。
- Linux內(nèi)核有conntrack模塊,基于連接跟蹤的防火墻工作在IP層(L3),通過(guò)iptables操作。
- OVS是L2模塊,這意味著它不能利用L3模塊,因此,無(wú)法對(duì)虛擬機(jī)的OVS(節(jié)點(diǎn)側(cè))網(wǎng)絡(luò)設(shè)備設(shè)置防火墻。
OpenStack通過(guò)在每個(gè)VM和br-int之間插入一個(gè)Linux橋來(lái)解決這個(gè)問(wèn)題,如上圖所示。
Linux 網(wǎng)橋也是一個(gè)L2模塊,所以不能使用iptables。但是,它有一種稱為ebtables的L2過(guò)濾機(jī)制,可以跳轉(zhuǎn)到iptables規(guī)則,從而使Netfilter/iptables可行。
但是這種解決方法很難看,并且會(huì)導(dǎo)致嚴(yán)重的性能問(wèn)題。因此,在2016年,RedHat提出了一種OVS連接跟蹤解決方案,可以在具有安全組功能的情況下關(guān)閉Linux橋接。
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
相關(guān)閱讀更多精彩內(nèi)容
- 什么是conntrack 一般conntrack用來(lái)指代“Connection Tracking”,即連接跟蹤,是...
- 原文地址: https://blog.csdn.net/just_shunjian/article/details...
- 1. NAT概述 NAT是(Network Address Translation)的縮寫(xiě)。還有個(gè)名字叫NAPT(...
- 【出處】http://blog.51cto.com/wwdhks/1154032【作者】張?zhí)斐桑?zhangtia...
- 最近有很多Kubernetes的用戶報(bào)告說(shuō)從Pod中查找DNS有時(shí)需要5秒甚至更多的時(shí)間:weave#3287ku...
