和滿哥抓包學(xué)NFSv3 (RFC1813)

Network File System(NFS)協(xié)議是SUN公司設(shè)計(jì)的,NFS就是網(wǎng)絡(luò)上的文件系統(tǒng)。NFS自1984年面世以來(lái),已經(jīng)流行30年。理論上它適用于任何操作系統(tǒng),不過(guò)因?yàn)榉N種原因,一般只在 Linux/UNIX 環(huán)境中存在。

無(wú)論SUN的命運(yùn)如何多舛,NFS始終處亂不驚,這么多年來(lái)只出過(guò)3個(gè)版本,即1984年的NFSv2、1995年的NFSv3和2000年的NFSv4。目前,大多數(shù)NFS環(huán)境都還是NFSv3,本文介紹的也是這個(gè)版本。NFSv2還在極少數(shù)環(huán)境中運(yùn)行(只在日本見(jiàn)到過(guò)),可以想象這些環(huán)境有多老了。而NFSv4因?yàn)樯钍蹸IFS影響,實(shí)施過(guò)程相對(duì)復(fù)雜,所以普及速度較慢。

如何深入學(xué)習(xí)NFS協(xié)議呢?其實(shí)所有權(quán)威資料都可以在RFC 1813中找到,不過(guò)這些文檔讀起來(lái)就像面對(duì)一張冷冰冰的面孔,令人望而卻步。《鳥(niǎo)哥的Linux私房菜》中對(duì)NFS的介紹雖稱得上友好,但美中不足的是不夠深入,出了問(wèn)題也不知道如何排查。

ps:不是所有問(wèn)題都要抓包,如何定位問(wèn)題的方法很多,本文僅介紹抓包方式。

抓包實(shí)踐

NFS客戶端和文件服務(wù)器的IP分別是10.32.106.159和10.32.106.62。在運(yùn)行掛載命令(mount)時(shí)抓了包,然后用“portmap||mount||nfs”進(jìn)行過(guò)濾。

# mount 10.32.106.62:/code /tmp/code

從上圖中的Info一欄可以看到,Wireshark已經(jīng)提供了詳細(xì)的解析。

包號(hào)112和113:

客戶端:“我想連接你的NFS進(jìn)程,應(yīng)該用哪個(gè)端口呀?”

服務(wù)器:“我的NFS端口是2049?!?/p>

包號(hào)123和124:

客戶端:“那我試一下NFS進(jìn)程能否連上。”

服務(wù)器:“收到了,能連上。”

包號(hào)128和129:

客戶端:“我想連接你的mount服務(wù),應(yīng)該用哪個(gè)端口呀?”

服務(wù)器:“我的mount的端口號(hào)是1234。”

包號(hào)132和133:

客戶端:“那我試一下mount進(jìn)程能否連上?!?br>

服務(wù)器:“收到了,能連上。”

包號(hào)134和135:

客戶端:“我要掛載/code共享目錄。”

服務(wù)器:“你的請(qǐng)求被批準(zhǔn)了。以后請(qǐng)用file handle 0x2cc9be18 來(lái)訪問(wèn)本目錄?!?/p>

包號(hào)140和141:

客戶端:“我試一下NFS進(jìn)程能否連上?!?br>

服務(wù)器:“收到了,能連上?!?/p>

包號(hào)143和144:

客戶端:“我想看看這個(gè)文件系統(tǒng)的屬性?!?/p>

服務(wù)器:“給,都在這里?!?/p>

包號(hào)145和146:

客戶端:“我想看看這個(gè)文件系統(tǒng)的屬性。”

服務(wù)器:“給,都在這里?!?/p>

以上便是NFS掛載的全過(guò)程。細(xì)節(jié)之處很多,所以在沒(méi)有Wireshark的情況下很難排錯(cuò),經(jīng)常不得不盲目地檢查每一個(gè)環(huán)節(jié),比如先用rpcinfo命令獲得服務(wù)器上的端口列表,再用 Telnet命令逐個(gè)試探。即使這樣也只能檢查幾個(gè)關(guān)鍵進(jìn)程能否連上,排查范圍非常有限。

看到portmap請(qǐng)求沒(méi)有得到回復(fù),可以考慮防火墻對(duì)111端口的攔截;如果發(fā)現(xiàn)mount請(qǐng)求被服務(wù)器拒絕了,就應(yīng)該檢查該共享目錄的訪問(wèn)控制。

既然說(shuō)到訪問(wèn)控制,我們就來(lái)看看NFS在安全方面的機(jī)制,包括對(duì)客戶端的訪問(wèn)控制和對(duì)用戶的權(quán)限控制。NFS對(duì)客戶端的訪問(wèn)控制是通過(guò)IP地址實(shí)現(xiàn)的。創(chuàng)建共享目錄時(shí)可以指定哪些IP允許讀寫(xiě),哪些IP只允許讀,還有哪些IP連掛載都不允許。

問(wèn)題1:客戶端A上的用戶admin在/code目錄里新建一個(gè)文件,該文件的owner正常顯示為admin。但是在客戶端B上查看該文件時(shí),owner卻變成nasadmin。

上圖的Credentials信息可知,用戶在創(chuàng)建文件時(shí)并沒(méi)有使用admin這個(gè)用戶名,而是用了admin的UID501來(lái)代表自己的身份(用戶名與UID的對(duì)應(yīng)關(guān)系是由客戶端的 /etc/passwd決定的)。也就是說(shuō)NFS協(xié)議是只認(rèn)UID不認(rèn)用戶名的。當(dāng)admin通過(guò)客戶端A創(chuàng)建了一個(gè)文件,其UID 501就會(huì)被寫(xiě)到文件里,成為owner信息。

而當(dāng)客戶端B上的用戶查看該文件屬性時(shí),看到的其實(shí)也是“UID:501”。但是因?yàn)榭蛻舳薆上的/etc/passwd文件和客戶端A上的不一樣,其UID501對(duì)應(yīng)的用戶名叫nasadmin,所以文件的owner就顯示為nasadmin了。

為了防止這類問(wèn)題,建議用戶名和UID的關(guān)系在每臺(tái)客戶端上都保持一致。

問(wèn)題2: NFS 是如何讀寫(xiě)文件的?不同mount參數(shù)有什么作用?如何針對(duì)性地進(jìn)行性能調(diào)優(yōu)?

以讀取文件abc.txt的過(guò)程為例

# cat /tmp/code/abc.txt

包號(hào)2和3:

客戶端:“我可以進(jìn)入0x2cc9be18(也就是/code的file handle)嗎?”

服務(wù)器:“你的請(qǐng)求被接受了,進(jìn)來(lái)吧。”

包號(hào)5和6:

客戶端:“我想看看這個(gè)目錄里的文件及其file handle。”

服務(wù)器:“文件名及file handle的信息在這里。其中abc.txt的file handle是0x531352e1?!?/p>

包號(hào)8和9:

客戶端:“0x531352e1(也就是abc.txt)的文件屬性是什么?“

服務(wù)器:“權(quán)限、uid、gid, 文件大小等信息都給你?!?/p>

包號(hào)11和12:

客戶端:“我可以打開(kāi)0x531352e1(也就是abc.txt)嗎?”

服務(wù)器:“你的請(qǐng)求被允許了。你有讀、寫(xiě)、執(zhí)行等權(quán)限?!?/p>

包號(hào)13、14、152、292:

客戶端:“從0x531352e1的偏移量為0處(即從abc.txt的開(kāi)頭位置)讀131072字節(jié)?!?br>

客戶端:“從0x531352e1的偏移量為131072處(即接著上一個(gè)請(qǐng)求讀完的位置)再讀131072字節(jié)?!?/p>

服務(wù)器:“給你131072字節(jié)?!?/p>

服務(wù)器:“再給你131072字節(jié)?!保ɡ^續(xù)讀,直到讀完整個(gè)文件。)

NFS完成了文件的讀取過(guò)程。從最后幾個(gè)包可見(jiàn),Linux客戶端讀NFS共享文件時(shí)是多個(gè) READ Call 連續(xù)發(fā)出去的(本例中是連續(xù)兩個(gè))。這個(gè)方式跟Windows XP讀CIFS共享文件有所不同。Windows XP不會(huì)連續(xù)發(fā)READ Call,而是先發(fā)一個(gè)Call,等收到Reply后再發(fā)下一個(gè)。

除了讀文件的方式,每個(gè)READ Call請(qǐng)求多少數(shù)據(jù)也會(huì)影響性能。這臺(tái)Linux默認(rèn)每次讀131072字節(jié),實(shí)驗(yàn)室里還有默認(rèn)每次讀32768字節(jié)的客戶端。在高性能環(huán)境中,要手動(dòng)指定一個(gè)比較大的值。我的Isilon實(shí)驗(yàn)室中,常常要調(diào)到512KB。這個(gè)值可以在mount時(shí)通過(guò)rsize參數(shù)來(lái)定義,比如 “mount -o? rsize=524288 10.32.106.62:/code/tmp/code”。

問(wèn)題3:NFS 是如何寫(xiě)寫(xiě)文件的?不同mount參數(shù)有什么作用?如何針對(duì)性地進(jìn)行性能調(diào)優(yōu)?

# cp abc.txt code/abc.txt

包號(hào)1和2:

客戶端:“我可以進(jìn)入0x2cc9be18(即/code目錄)嗎?”

服務(wù)器:“你的請(qǐng)求被接受了,進(jìn)來(lái)吧?!?/p>

包號(hào)4和5

客戶端:“請(qǐng)問(wèn)這里有叫abc.txt的文件么?”

服務(wù)器:“沒(méi)有?!?/p>

包號(hào)6和7

客戶端:“那我想創(chuàng)建一個(gè)叫abc.txt的文件。”

服務(wù)器:“沒(méi)問(wèn)題,這個(gè)文件的file handle是0x531352e1?!?/p>

包號(hào)69、104、130、190

客戶端:“從0x531352e1的偏移量為0處(即 abc.txt的文件開(kāi)頭)寫(xiě)131072字節(jié)?!?/p>

服務(wù)器:“第/個(gè)131072字節(jié)寫(xiě)好了?!?/p>

客戶端:“從0x531352e1的偏移量為131072處(即接著上一個(gè)寫(xiě)完的位置)再寫(xiě)131072字節(jié)?!?/p>

客戶端:“從0x531352e1的偏移量為262144處(即接著上一個(gè)寫(xiě)完的位置)再寫(xiě)131072字節(jié)?!?/p>

(繼續(xù)寫(xiě),直到寫(xiě)完整個(gè)文件。)

包號(hào)306和307

客戶端:“我剛才往0x531352e1(也就是abc.txt)寫(xiě)的數(shù)據(jù)都存盤(pán)了嗎?”

服務(wù)器:“都存好了?!?/p>

包號(hào)308和309:

客戶端:“那我看看0x531352e1(也就是abc.txt)的文件屬性。”

服務(wù)器:“文件的權(quán)限、uid、gid、文件大小等信息都給你?!?/p>

這個(gè)例子的寫(xiě)操作也是多個(gè)WRITE Call連續(xù)發(fā)出去的,這是因?yàn)槲覀冊(cè)趻燧d時(shí)沒(méi)有指定任何參數(shù),所以使用了默認(rèn)的async寫(xiě)方式。和async相對(duì)應(yīng)的是sync方式。假如mount時(shí)使用了sync參數(shù)(見(jiàn)圖29),客戶端會(huì)先發(fā)送一個(gè)WRITE Call,等收到Reply后再發(fā)下一個(gè)Call,也就是說(shuō)WRITE Call和WRITE Reply是交替出現(xiàn)的。除此之外,還有什么辦法在包里看出一個(gè)寫(xiě)操作是async還是sync呢?答案就是每個(gè)WRITE Call上的“UNSTABLE”和“FILE_SYNC”標(biāo)志,前者表示async,后者表示sync。下圖顯示了用sync參數(shù)后的網(wǎng)絡(luò)包。

從上圖中不僅可以看到FILE_SYNC標(biāo)志,還可以看到WRITE Call和WRITE Reply 是交替出現(xiàn)的(也就是說(shuō)沒(méi)有連續(xù)的 Call)。不難想象,每個(gè) WRITE Call寫(xiě)多少數(shù)據(jù)也是影響寫(xiě)性能的重要因素,我們可以在mount時(shí)用wsize參數(shù)來(lái)指定每次應(yīng)該寫(xiě)多少。不過(guò)在有些客戶端上啟用sync參數(shù)之后,無(wú)論wsize定義成多少都會(huì)被強(qiáng)制為 4KB,從而導(dǎo)致寫(xiě)性能非常差。那為什么還有人用 sync 方式呢?答案是有些特殊的應(yīng)用要求服務(wù)器收到sync的寫(xiě)請(qǐng)求之后,一定要等到存盤(pán)才能回復(fù) WRITE Reply,sync 操作正符合了這個(gè)需求。由此我們也可以推出COMMIT對(duì)于sync寫(xiě)操作是沒(méi)有必要的。

非常值得一提的是,經(jīng)常有人在mount時(shí)使用noac參數(shù),然后發(fā)現(xiàn)讀寫(xiě)性能都有問(wèn)題。而根據(jù)RFC的說(shuō)明,noac只是讓客戶端不緩存文件屬性而已,為什么會(huì)影響性能呢?光看文檔也許永遠(yuǎn)發(fā)現(xiàn)不了原因。抓個(gè)包吧,Wireshark會(huì)告訴我們答案。


本章讀書(shū)筆記來(lái)自林沛滿的《Wireshark網(wǎng)絡(luò)分析就這么簡(jiǎn)單》

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(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)容

  • Linux習(xí)慣問(wèn)題: 在vim編輯時(shí),按了ctrl + s后,再按ctrl + q就可以繼續(xù)執(zhí)行了。ctrl + ...
    光著腳的鞋閱讀 4,710評(píng)論 0 16
  • 為什么fstab無(wú)法實(shí)現(xiàn)nfs掛載?回顧:開(kāi)機(jī)啟動(dòng)流程:1、磁盤(pán)先啟動(dòng)/etc/fstab2、防火墻在前。3、網(wǎng)卡...
    Linux_淡忘閱讀 259評(píng)論 0 1
  • DAY32 rsync 復(fù)制軟件應(yīng)用和實(shí)踐 1、什么是rsync Remote synchronization 開(kāi)...
    chloepang閱讀 379評(píng)論 0 0
  • 4.15 1、什么是rsync?rsync,Rsync英文全稱為Remote synchronization ...
    dereinsameFnger閱讀 344評(píng)論 0 0
  • rsync復(fù)制軟件應(yīng)用與實(shí)踐 1、什么是rsync? rsync,Rsync英文全稱為Remote synchro...
    路邊大呲花閱讀 306評(píng)論 0 0

友情鏈接更多精彩內(nèi)容