UCloud基于Linux內(nèi)核新特性的下一代外網(wǎng)網(wǎng)關(guān)設(shè)計(jì)及相關(guān)開(kāi)源工作

UCloud外網(wǎng)網(wǎng)關(guān)是為了承載外網(wǎng)IP、負(fù)載均衡等產(chǎn)品的外網(wǎng)出入向流量,當(dāng)前基于Linux內(nèi)核的OVS/GRE tunnel/netns/iptables等實(shí)現(xiàn),很好地支撐了現(xiàn)有業(yè)務(wù)。同時(shí),我們也在不斷跟蹤開(kāi)源社區(qū)的新技術(shù)發(fā)展,并將之用于下一代外網(wǎng)網(wǎng)關(guān)的設(shè)計(jì)。這些新特性可將系統(tǒng)性能和管理能力再提上一檔,滿(mǎn)足未來(lái)幾年的需求。在方案設(shè)計(jì)研發(fā)過(guò)程中發(fā)現(xiàn),新特性存在不少缺陷和Bug,為此我們向開(kāi)源社區(qū)回饋了10多個(gè)patch,并融入到kernel 5.0版本中,幫助完善kernel功能并提升穩(wěn)定性。

當(dāng)前業(yè)界的多租戶(hù)外網(wǎng)網(wǎng)關(guān)很多都是基于OpenFlow的OpenvSwitch(OVS)方案,然而隨著內(nèi)核路由轉(zhuǎn)發(fā)功能的不斷完善,利用內(nèi)核原生路由轉(zhuǎn)發(fā)方式進(jìn)行設(shè)計(jì)多租戶(hù)外網(wǎng)網(wǎng)關(guān)系統(tǒng)成為一種可能。在這種方式下能有效的使用傳統(tǒng)iproute2路由工具以及iptables、nftables等Firewall工具,并且隨著SwitchDev技術(shù)的興起,未來(lái)將網(wǎng)關(guān)系統(tǒng)遷移到Linux Switch上也成為一種可能。

現(xiàn)有kernel 3.x的不足

當(dāng)前廣泛使用的內(nèi)核版本為3.x系列,例如CentOS 7全系列標(biāo)準(zhǔn)支持的內(nèi)核為3.10版本,F(xiàn)edora/Ubuntu等Linux發(fā)行版也有大量使用。在3.x系列內(nèi)核下存在著IP tunnel管理復(fù)雜、租戶(hù)隔離性能損耗等問(wèn)題。

1. IP tunnel管理復(fù)雜

Linux內(nèi)核創(chuàng)建IP tunnel設(shè)備來(lái)建立點(diǎn)對(duì)點(diǎn)的隧道連接,創(chuàng)建時(shí)需指定tunnel dst和 tunnel key。因?yàn)樗拗鳈C(jī)之間兩兩建立連接,面向宿主機(jī)的目的地址眾多,這樣就會(huì)導(dǎo)致網(wǎng)關(guān)節(jié)點(diǎn)上需要?jiǎng)?chuàng)建成千上萬(wàn)的tunnel設(shè)備,在大規(guī)模業(yè)務(wù)環(huán)境下,tunnel的管理將變得及其復(fù)雜。

2. 多租戶(hù)隔離導(dǎo)致的性能下降

a. 公有云需要實(shí)現(xiàn)多租戶(hù)隔離以確保用戶(hù)間的安全和隱私。由于VPC網(wǎng)絡(luò)下不同租戶(hù)的內(nèi)網(wǎng)地址可以重合,導(dǎo)致路由也有重合的可能性,此時(shí)需要通過(guò)大量的策略路由去隔離租戶(hù)的路由規(guī)則,由于策略路由的鏈表屬性,性能會(huì)隨著鏈表長(zhǎng)度的增加而急劇下降。

b. 由于Firewall和NAT的實(shí)現(xiàn)基于同樣鏈?zhǔn)降膇ptables,性能損耗同樣可觀。

3. netns帶來(lái)性能開(kāi)銷(xiāo)

通過(guò)netns實(shí)現(xiàn)租戶(hù)路由和Firewall規(guī)則的隔離,但是netns會(huì)引入虛擬網(wǎng)卡和協(xié)議棧重入開(kāi)銷(xiāo),使整體性能下降20%左右。

三項(xiàng)內(nèi)核新技術(shù)

為了解決原有方案存在的困擾,我們調(diào)研了大量行業(yè)主流方案和內(nèi)核上游的新動(dòng)向,發(fā)現(xiàn)Lightweight tunneling(輕量級(jí)隧道,簡(jiǎn)稱(chēng)lwtunnel)、Virtual Routing Forwarding(虛擬路由轉(zhuǎn)發(fā),簡(jiǎn)稱(chēng)VRF)以及nftable & netfilter flow offload(流卸載)三項(xiàng)內(nèi)核新技術(shù)的特性,可以幫助規(guī)避原方案存在的缺陷。

1. Lightweight tunneling

Linux內(nèi)核在4.3版本中引入了輕量級(jí)隧道Lightweight tunneling,它提供了通過(guò)route方式設(shè)置tunnel屬性的方法,這樣可以避免管理大量的tunnel設(shè)備。

創(chuàng)建隧道設(shè)備時(shí)指定external模式,利用路由設(shè)置的輕量級(jí)隧道通過(guò)tun設(shè)備發(fā)送報(bào)文。

UCloud基于Linux內(nèi)核新特性的下一代外網(wǎng)網(wǎng)關(guān)設(shè)計(jì)及相關(guān)開(kāi)源工作

2. Virtual Routing Forwarding

Linux內(nèi)核在4.3版本中引入了VRF的初步支持,并在4.8版本形成完備版本。Virtual Routing Forwarding虛擬路由轉(zhuǎn)發(fā),可以將一臺(tái)Linux Box的物理路由器當(dāng)多臺(tái)虛擬路由器使用,能很好的解決租戶(hù)路由隔離問(wèn)題,避免直接使用策略路由。因此,可以將不同租戶(hù)的網(wǎng)卡加入租戶(hù)所屬的虛擬路由器中來(lái)實(shí)現(xiàn)多租戶(hù)的虛擬路由。

UCloud基于Linux內(nèi)核新特性的下一代外網(wǎng)網(wǎng)關(guān)設(shè)計(jì)及相關(guān)開(kāi)源工作

UCloud基于Linux內(nèi)核新特性的下一代外網(wǎng)網(wǎng)關(guān)設(shè)計(jì)及相關(guān)開(kāi)源工作

3. flow offload

Nftables是一種新的數(shù)據(jù)包分類(lèi)框架,旨在替代現(xiàn)存的{ip,ip6,arp,eb}_tables。在nftables中,大部分工作是在用戶(hù)態(tài)完成的,內(nèi)核只知道一些基本指令(過(guò)濾是用偽狀態(tài)機(jī)實(shí)現(xiàn)的)。nftables的一個(gè)高級(jí)特性就是映射,可以使用不同類(lèi)型的數(shù)據(jù)并映射它們。例如,我們可以映射iif device到專(zhuān)用的規(guī)則集合(之前創(chuàng)建的存儲(chǔ)在一個(gè)鏈中)。由于是hash映射的方式,可以完美的避免鏈?zhǔn)揭?guī)則跳轉(zhuǎn)的性能開(kāi)銷(xiāo)。

Linux內(nèi)核在版本4.16引入了flow offload功能,它為IP forward提供了基于流的卸載功能。當(dāng)一條新建連接完成首回合原方向和反方向的報(bào)文時(shí),完成路由,F(xiàn)irewall和NAT工作后,在處理反方向首報(bào)文的forward hook,根據(jù)報(bào)文路由、NAT等信息創(chuàng)建可卸載flow到接收網(wǎng)卡ingress hook上。后續(xù)的報(bào)文可以在接收ingress hook上直接轉(zhuǎn)發(fā),不需要再進(jìn)入IP stack處理。此外,將來(lái)flow offload還將支持hardware offload模式,這將極大提高系統(tǒng)轉(zhuǎn)發(fā)性能。

UCloud基于Linux內(nèi)核新特性的下一代外網(wǎng)網(wǎng)關(guān)設(shè)計(jì)及相關(guān)開(kāi)源工作

UCloud基于Linux內(nèi)核新特性的下一代外網(wǎng)網(wǎng)關(guān)設(shè)計(jì)及相關(guān)開(kāi)源工作

方案設(shè)計(jì)與優(yōu)化實(shí)踐

通過(guò)對(duì)上述三項(xiàng)新技術(shù)的研究,我們發(fā)現(xiàn)可以嘗試設(shè)計(jì)一套基于路由的方式,實(shí)現(xiàn)多租戶(hù)overlay網(wǎng)絡(luò)的外網(wǎng)網(wǎng)關(guān)。在方案設(shè)計(jì)過(guò)程中,我們也碰到了諸如lwtunnel和flow offload功能不足,以及VRF和flow offload不能一起有效的工作等問(wèn)題。最終我們都設(shè)法解決了,并針對(duì)這些內(nèi)核的不足提交patch給Linux開(kāi)源社區(qū)。

1. lwtunnel發(fā)送報(bào)文tunnel_key丟失

問(wèn)題描述:我們利用lwtunnel路由方式發(fā)送報(bào)文時(shí),創(chuàng)建了一個(gè)external類(lèi)型的gretap tunnel,我們將命令設(shè)置了id為1000,但是發(fā)送成功報(bào)文中沒(méi)有tunnel_key字段。

UCloud基于Linux內(nèi)核新特性的下一代外網(wǎng)網(wǎng)關(guān)設(shè)計(jì)及相關(guān)開(kāi)源工作

問(wèn)題定位:我們研究iproute2代碼,發(fā)現(xiàn)由于TUNNEL_KEY flag并沒(méi)有開(kāi)放給用戶(hù)態(tài),所以iproute2工具并沒(méi)有對(duì)lwtunnel路由設(shè)置TUNNEL_KEY,導(dǎo)致報(bào)文不會(huì)創(chuàng)建tunnel_key字段。

提交patch:我們給內(nèi)核和用戶(hù)態(tài)iproute2分別提交patch來(lái)解決這一問(wèn)題:

iptunnel: make TUNNEL_FLAGS available in uapi

https://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next.git/commit/?

id=1875a9ab01dfa96b06cb6649cb1ce56efa86c7cb

iproute: Set ip/ip6 lwtunnel flags

https://git.kernel.org/pub/scm/network/iproute2/iproute2.git/commit/?id=3d65cefbefc86a53877f1e6461a9461e5b8fd7b3

提交patch后,可以通過(guò)以下方式設(shè)置路由。

ip r r 2.2.2.11 via 1.1.1.11 dev tun encap ip id 1000 dst 172.168.0.1 key

2. lwtunnel對(duì)指定key的IP tunnel無(wú)效

問(wèn)題發(fā)現(xiàn):為了能有效隔離租戶(hù)路由,我們給每個(gè)租戶(hù)創(chuàng)建一個(gè)基于tunnel_key的gretap tunnel設(shè)備。如下圖,創(chuàng)建一個(gè)tunnel_key 1000的gretap tunnel設(shè)備,把tunnel設(shè)備加入租戶(hù)所屬VRF,tunnel設(shè)備能有效地接收?qǐng)?bào)文,但并不能發(fā)送報(bào)文。

UCloud基于Linux內(nèi)核新特性的下一代外網(wǎng)網(wǎng)關(guān)設(shè)計(jì)及相關(guān)開(kāi)源工作

問(wèn)題定位:研究?jī)?nèi)核發(fā)現(xiàn),IP tunnel在非external模式下即使指定了輕量級(jí)隧道路由,發(fā)送報(bào)文也沒(méi)有使用它,導(dǎo)致報(bào)文路由錯(cuò)誤被丟棄。

提交patch:

ip_tunnel: Make none-tunnel-dst tunnel port work with lwtunnel

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=d71b57532d70c03f4671dd04e84157ac6bf021b0

提交patch后,在未指定tunnel_dst的非external模式IP tunnel下,能使用輕量級(jí)隧道路由進(jìn)行發(fā)送報(bào)文。

3. external IP tunnel ARP無(wú)法正常運(yùn)行

問(wèn)題描述:鄰居IP tunnel進(jìn)行了ARP請(qǐng)求,但是本端的ARP回應(yīng)報(bào)文的隧道頭中并沒(méi)帶tunnel_key字段。

UCloud基于Linux內(nèi)核新特性的下一代外網(wǎng)網(wǎng)關(guān)設(shè)計(jì)及相關(guān)開(kāi)源工作

問(wèn)題定位:研究代碼發(fā)現(xiàn),tunnel收到了對(duì)端的ARP 請(qǐng)求,在發(fā)送報(bào)文ARP回復(fù)的時(shí)候會(huì)復(fù)制請(qǐng)求報(bào)文的tunnel信息,但是遺漏了所有tun_flags。

提交patch:

iptunnel: Set tun_flags in the iptunnel_metadata_reply from src

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=7bdca378b2301b1fc6a95c60d6d428408ae4e39e

4. Flow offload不能與DNAT有效工作

問(wèn)題描述:Firewall創(chuàng)建規(guī)則從eth0收到目的地址2.2.2.11的報(bào)文,DNAT為10.0.0.7, flow offload無(wú)法工作。

UCloud基于Linux內(nèi)核新特性的下一代外網(wǎng)網(wǎng)關(guān)設(shè)計(jì)及相關(guān)開(kāi)源工作

問(wèn)題定位:分析發(fā)現(xiàn),客戶(hù)端1.1.1.7 —> 2.2.2.7 DNAT到server 10.0.0.7,第一個(gè)reply反向報(bào)文(syc+ack)使用了錯(cuò)的目的地址獲取反向路由

daddr = ct->tuplehash[!dir].tuple.dst.u3.ip

此時(shí)dir為反方向,所以daddr獲取為原方向的目的地址,這個(gè)值是2.2.2.7, 但是由于被DNAT過(guò),真正的路由不應(yīng)該通過(guò)2.2.2.7去獲取,而是應(yīng)該根據(jù)10.0.0.7這個(gè)值去獲取

addr = ct->tuplehash[dir].tuple.src.u3.ip

提交patch:

netfilter: nft_flow_offload: Fix reverse route lookup

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=a799aea0988ea0d1b1f263e996fdad2f6133c680

5. Flow offload不能與VRF有效工作

問(wèn)題描述:將網(wǎng)卡eth0和eth1加入VFR后,flow offload不起作用。

UCloud基于Linux內(nèi)核新特性的下一代外網(wǎng)網(wǎng)關(guān)設(shè)計(jì)及相關(guān)開(kāi)源工作

問(wèn)題定位:查看代碼發(fā)現(xiàn),原方向和反方向首報(bào)文進(jìn)入?yún)f(xié)議堆棧后skb->dev會(huì)設(shè)置為vrf device user1,創(chuàng)建flow offload規(guī)則的iif就是user1。但是offload規(guī)則下發(fā)在eth0和eth1的ingress hook上,所以后續(xù)報(bào)文在eth0和eth1的ingress hook上不能匹配flow規(guī)則。

提交patch:

netfilter: nft_flow_offload: fix interaction with vrf slave device

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=10f4e765879e514e1ce7f52ed26603047af196e2

最終,我們根據(jù)兩個(gè)方向查找路由的結(jié)果,設(shè)置flow offload規(guī)則的iif和oif信息來(lái)解決此問(wèn)題。

6. VRF PREROUTING hook重入問(wèn)題

問(wèn)題描述:配置網(wǎng)卡加入VRF,firewall ingress方向規(guī)則為接收目的地址2.2.2.11 、TCP 目的端口22的報(bào)文,egress方向規(guī)則為丟棄TCP 目的端口 22的報(bào)文。出現(xiàn)異常結(jié)果: 收到目的地址2.2.2.11 TCP 22目的端口的報(bào)文卻被丟棄。

UCloud基于Linux內(nèi)核新特性的下一代外網(wǎng)網(wǎng)關(guān)設(shè)計(jì)及相關(guān)開(kāi)源工作

問(wèn)題定位:研究發(fā)現(xiàn)網(wǎng)卡加入VRF后收到的報(bào)文會(huì)兩次進(jìn)入PREROUTING hook,因?yàn)樵谶M(jìn)入IP stack時(shí)會(huì)進(jìn)第一次PREROUTING hook,然后被VRF設(shè)備接管后會(huì)再次進(jìn)入PREROUTING hook。上述規(guī)則第一次在rule-1000-ingress chain中dst nat為10.0.0.7,第二次由于報(bào)文被DNAT后會(huì)錯(cuò)誤的進(jìn)入rule-1000-egress,導(dǎo)致報(bào)文被丟棄。

提交patch:我們給內(nèi)核加了一個(gè)支持判斷網(wǎng)卡類(lèi)型的match項(xiàng)目,讓用戶(hù)態(tài)避免可知的第二次無(wú)效重入,內(nèi)核態(tài)和用戶(hù)態(tài)nftables分別提交了如下的patch:

netfilter: nft_meta: Add NFT_META_I/OIFKIND meta type

https://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next.git/commit/?id=0fb4d21956f4a9af225594a46857ccf29bd747bc

meta: add iifkind and oifkind support

http://git.netfilter.org/nftables/commit/?id=512795a673f999fb04b84dbbbe41174e9c581430

使用方法:

nft add rule firewall rules-all meta iifkind "vrf" counter accept

原型驗(yàn)證

最終,我們成功地利用lwtunnel、VRF和flow offload實(shí)現(xiàn)多租戶(hù)外網(wǎng)網(wǎng)關(guān)的原型驗(yàn)證。驗(yàn)證過(guò)程如下:

1. 首先創(chuàng)建原型環(huán)境。

a. netns cl模擬外網(wǎng)client, 地址為1.1.1.7,tunnel src 172.168.0.7,配置發(fā)送路由;

b. netns ns1模擬租戶(hù)1,內(nèi)網(wǎng)地址為10.0.0.7,外網(wǎng)地址為 2.2.2.11,tunnel src 172.168.0.11 tunnel_key 1000,配置發(fā)送路由;

c. netns ns2模擬租戶(hù)2,內(nèi)網(wǎng)地址為10.0.0.7,外網(wǎng)地址為 2.2.2.12,tunnel src 172.168.0.12 tunnel_key 2000,配置發(fā)送路由;

d. Host模擬外網(wǎng)網(wǎng)關(guān),tunnel src 172.168.0.1,創(chuàng)建租戶(hù)VRF user1和use2,創(chuàng)建租戶(hù)IP tunnel tun1和tun2,配置轉(zhuǎn)發(fā)路由。

原型環(huán)境圖如下:

UCloud基于Linux內(nèi)核新特性的下一代外網(wǎng)網(wǎng)關(guān)設(shè)計(jì)及相關(guān)開(kāi)源工作

UCloud基于Linux內(nèi)核新特性的下一代外網(wǎng)網(wǎng)關(guān)設(shè)計(jì)及相關(guān)開(kāi)源工作

2. 創(chuàng)建firewall規(guī)則:

a. 租戶(hù)1入向允許TCP目的端口22和ICMP訪問(wèn),出向禁止訪問(wèn)外部TCP 22目的端口;

b. 租戶(hù)2入向允許TCP端口23和ICMP訪問(wèn),出向禁止訪問(wèn)外部TCP 23目的端口;

c. 在租戶(hù)tun1和tun2設(shè)備上支持flow offload。

UCloud基于Linux內(nèi)核新特性的下一代外網(wǎng)網(wǎng)關(guān)設(shè)計(jì)及相關(guān)開(kāi)源工作

最終,client可以通過(guò)2.2.2.11成功訪問(wèn)user1 tcp 22端口服務(wù),user1不能訪問(wèn)client tcp 22端口服務(wù);client可以通過(guò)2.2.2.12成功訪問(wèn)user2 tcp 23端口服務(wù),user1不能訪問(wèn)client tcp 23端口服務(wù)。

待后續(xù)hardware offload功能完善以及網(wǎng)卡廠商支持后,我們會(huì)做進(jìn)一步的開(kāi)發(fā)驗(yàn)證。

寫(xiě)在最后

以上是本項(xiàng)目涉及的部分核心問(wèn)題,這些patch特性都可以在Linux kernel 5.0版本里獲取。我們把這期間為L(zhǎng)inux kernel社區(qū)貢獻(xiàn)的patch整理成了一份列表,希望能為開(kāi)發(fā)者提供幫助,讀者可以在

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/log/?qt=author&q=wenxu%40ucloud.cn地址閱覽完整patch list。

Linux作為成熟的開(kāi)源套件,一直是云廠商使用的主流操作系統(tǒng),但在技術(shù)的更新迭代過(guò)程中,一些新特性在實(shí)際應(yīng)用上也會(huì)存在穩(wěn)定性、兼容性等方面的問(wèn)題。我們?cè)谘芯渴褂蒙嫌渭夹g(shù)的同時(shí),也一直積極探索、豐富開(kāi)源技術(shù)功能,幫助提高開(kāi)源技術(shù)穩(wěn)定性。并將產(chǎn)出持續(xù)回饋給社區(qū),與社區(qū)共同構(gòu)建一個(gè)繁榮的開(kāi)源生態(tài)。

免責(zé)聲明:本網(wǎng)站內(nèi)容主要來(lái)自原創(chuàng)、合作伙伴供稿和第三方自媒體作者投稿,凡在本網(wǎng)站出現(xiàn)的信息,均僅供參考。本網(wǎng)站將盡力確保所提供信息的準(zhǔn)確性及可靠性,但不保證有關(guān)資料的準(zhǔn)確性及可靠性,讀者在使用前請(qǐng)進(jìn)一步核實(shí),并對(duì)任何自主決定的行為負(fù)責(zé)。本網(wǎng)站對(duì)有關(guān)資料所引致的錯(cuò)誤、不確或遺漏,概不負(fù)任何法律責(zé)任。任何單位或個(gè)人認(rèn)為本網(wǎng)站中的網(wǎng)頁(yè)或鏈接內(nèi)容可能涉嫌侵犯其知識(shí)產(chǎn)權(quán)或存在不實(shí)內(nèi)容時(shí),應(yīng)及時(shí)向本網(wǎng)站提出書(shū)面權(quán)利通知或不實(shí)情況說(shuō)明,并提供身份證明、權(quán)屬證明及詳細(xì)侵權(quán)或不實(shí)情況證明。本網(wǎng)站在收到上述法律文件后,將會(huì)依法盡快聯(lián)系相關(guān)文章源頭核實(shí),溝通刪除相關(guān)內(nèi)容或斷開(kāi)相關(guān)鏈接。

2019-03-27
UCloud基于Linux內(nèi)核新特性的下一代外網(wǎng)網(wǎng)關(guān)設(shè)計(jì)及相關(guān)開(kāi)源工作
UCloud外網(wǎng)網(wǎng)關(guān)是為了承載外網(wǎng)IP、負(fù)載均衡等產(chǎn)品的外網(wǎng)出入向流量,當(dāng)前基于Linux內(nèi)核的OVS/GRE tunnel/netns/iptables等實(shí)現(xiàn)

長(zhǎng)按掃碼 閱讀全文