伺服器架設篇 - RedHat 9

第十五章、簡易 NFS 伺服器設定

NFS 伺服器的安裝與設定!

最近更新時間: 2003/09/10

本文資料主要針對 RedHat 9 的系統進行說明,要注意的是,RedHat 9 與 Red Hat Enterprise Linux (RHEL) 是完全不同的東西!RedHat 9 在 2003 年推出,在 2004 年就不再維護了!這部份網站更新到 2005 年,也沒有再維護過! 因此,建議您前往本站查詢最新版本的 Linux distribution 文章來閱讀,比較不會浪費時間。那為何還需要編輯 RedHat 9 的資料呢? 鳥哥只想要做個自己曾經撰寫過的文件內容保存而已囉! ^_^!最新文章請前往鳥站首頁查閱囉!
NFS為 Network FileSystem 的簡稱,最早之前是由 Sun 這家公司所發展出來的,他的目的就是想讓不同的機器、不同的作業系統可以彼此分享個別的檔案啦!目前在 Unix Like 當中用來做為 file server 是相當不錯的一個方案喔!基本上, Unix Like 主機連接到另一部 Unix Like 主機來分享彼此的檔案時,使用 NFS 要比 SAMBA 快速且方便的多了!此外, NFS 的設定真的很簡單,幾乎只要記得啟動 Remote Procedure Call 這個咚咚 ( 就是 portmap 這個套件啦! ) 就一定可以架設的起來!真是不錯啊!不過,如果要達成 Windows 與 Linux 之間的溝通,那麼還是以 SAMBA 比較容易啊!無論如何, NFS 還是可以做為小公司或學校單位內部 Unix Like 機器共享 file 的一個 Server 喔!

NFS 的由來與其功能


    什麼是 NFS ( Network FileSystem )
     
    在開始進行 NFS 的設定之前,我們得先來瞭解一下,什麼是 NFS 呢?不然講了一堆也沒有用,對吧! ^_^!所謂的 NFS 就是 Network FileSystem 的縮寫,最早之前是由 Sun 這家公司所發展出來的。他最大的功能就是可以透過網路,讓不同的機器、不同的作業系統、可以彼此分享個別的檔案 ( share file ),所以,您也可以簡單的將他看做是一個 file server 呢!這個 NFS Server 可以讓您的 PC 來將網路遠端的 NFS 主機分享的目錄,掛載到本地端的機器當中,所以,在本地端的機器看起來,那個遠端主機的目錄就好像是自己的一個磁碟分割槽一樣 ( partition )!使用上面相當的便利!
     

    圖一、NFS 主機分享目錄與 Client 掛載示意圖
     
    就如同上面的圖示一般,當我們的 NFS Server 設定好了分享出來的 /home/sharefile 這個目錄後,其他的 Client 端就可以將這個目錄掛載到自己系統上面的某個掛載點(掛載點可以自訂!),例如前面圖示中的 Personal Computer 1 與 Personal Computer 2 掛載的目錄就不相同。我只要在 Personal Computer 1 系統中進入 /home/data/sharefile 內,就可以看到 NFS Server 系統內的 /home/sharefile 目錄下的所有資料了 (當然,權限要足夠啊!^_^)!這個 /home/data/sharefile 就好像我自己 Personal Computer 1 裡面的一個 partition 喔!只要權限對了,那麼您可以使用 cp, cd, mv, rm... 等等磁碟或檔案相關的指令!真是他X的方便吶!
     
    那麼您或許會問啦:『咦!那麼這個 NFS 是藉由什麼樣的協定來進行傳輸的呢?』雖然 NFS 有屬於自己的協定與使用的 port number ,但是在資料傳送或者其他相關訊息傳遞的時候, NFS 使用的則是一個稱為遠端程序呼叫( Remote Procedure Call, RPC )的協定來協助 NFS 本身的運作!
     

    什麼是 RPC ( Remote Procedure Call )
     
    那麼什麼是 RPC 呢?由字面上的意思來看『遠端程序呼叫』不就是一些程式( Program )在執行遠端連線時,需要用到的程序嗎?呵呵!是這樣沒錯啦!簡單的來說,當我們在使用某些服務來進行遠端連線的時候,有些資訊,例如主機的 IP、服務的 port number、與對應到的服務之 PID 等等,都需要管理與對應!這些管理 port 的對應與服務相關性的工作,就是這個 Remote Procedure Call, RPC 的任務了!
     
    好了,如果我們將 NFS 與 RPC 兩者的相關性連接起來的話,那麼您應該就可以知道: NFS 本身的服務並沒有提供資料傳遞的協定,但是 NFS 卻能讓我們進行檔案的分享,這其中的原因,就是 NFS 使用到一些其他相關的傳輸協定!而這些傳輸的協定,就是使用到這個所謂的 RPC 的功能囉!這也就是說, NFS 本身就是使用 RPC 的一個 program 就是了!說的更白話一點, NFS 也可以視作是一個 RPC server 啦!同時要注意到的是,在某些狀況中,不但跑 NFS 的 Server 需要啟動 RPC 的服務,連帶的,要掛載 NFS partition 的 Client 機器,也需要同步啟動 RPC 才行!這樣 Server 端與 Client 端才能藉由 RPC 的協定來進行 program port 的對應喔!
     
    OK!簡單的說, NFS 也可以看做是 RPC server 的一種,因為他是使用這種協定的 program 呀! ^_^ !那麼為什麼 NFS 要使用 RPC 執行呢?這是因為 NFS 本身可以被看做是一個檔案系統,那麼一來的話,您的使用者連線常常變化,而且您的檔案內容啦、分享的目錄啦,還有其他檔案相關的資訊等等,也都會常常在變化,這個時候,使用類似這種可以對應 program number 與 port number 的 RPC 就相當的方便了!也就是說,NFS 主要在管理分享出來的目錄,而至於資料的傳遞,就直接將他丟給 RPC 的協定來運作就是了!
     
    更多關於 NFS 協定的資訊您可以參考底下的網頁:
       

    NFS 啟動的 RPC daemons
     
    NFS server 總共需要啟用到至少兩個 daemons ,一個管理 Client 是否可以登入的問題,另一個管理登入主機後的 Client 能夠使用的檔案權限!如果您還要管理 quota 的話,那麼 NFS 還會自動的再載入其他相關的 RPC program 呢!我們這裡以最簡單的方式來設定 NFS,說明如下:
    • rpc.nfsd:這個 daemon 主要的功能就是在管理 Client 是否能夠登入主機的權限啦,其中還包含這個登入者的 ID 的判別喔!
    • rpc.mountd:這個 daemon 主要的功能,則是在管理 NFS 的檔案系統哩!當 Client 端順利的通過 rpc.nfsd 而登入主機之後,在他可以使用 NFS server 提供的檔案之前,還會經過檔案使用權限 ( 就是那個 -rwxrwxrwx 與 owner, group 那幾個權限啦 ) 的認證程序!他會去讀 NFS 的設定檔 /etc/exports來比對 Client 的權限,當通過這一關之後, Client 就可以取得使用 NFS 檔案的權限啦!(註:這個也是我們用來管理 NFS 分享之目錄的使用權限與安全設定的地方哩!)

需要的套件

    要啟動 NFS 我們必須要有兩個套件才行,分別是:
    • nfs-utils 與 nfs-utils-clients (有時後僅有一個)
    • portmap
  • portmap

  • 就如同剛剛提的到,我們的 NFS 其實可以被視為一個 RPC server program,而要啟動任何一個 RPC server program 之前,我們都需要做好 port 的對應 ( mapping ) 的工作才行,這個工作其實就是『 portmap 』這個服務所負責的!也就是說,在啟動任何一個 RPC server 之前,我們都需要啟動 portmap 才行呢!那麼這個 portmap 到底在幹嘛呢?就如同這個服務的名稱,哈哈!就是作 port 的 mapping 啊!舉個例子來說:當 Client 端嘗試來使用 RPC server 所提供的服務時,由於 Client 需要取得一個可以連接的 port 才能夠使用 RPC server 所提供的服務,因此, Client 首先就會去跟 portmap 講『喂!可不可以通知一下,給我個 port number ,好讓我可以跟 RPC 聯絡吧!』這個時候 portmap 就自動的將自己管理的 port mapping 告知 Client ,好讓他可以連接上來 server 呢!所以囉:『啟動 NFS 之前,請先啟動 portmap !
  • nfs-utils:

  • 就是提供 rpc.nfsd 及 rpc.mountd 這兩個 NFS daemons 與其他相關 documents 與說明文件、執行檔等的套件!這個就是 NFS 的主要套件啦!一定要有喔!
    好了,知道我們需要這兩個套件之後,現在幹嘛?!趕快去您的系統先用 RPM 看一下有沒有這兩個套件啦!沒有的話趕快用 RPM 去安裝喔!不然就玩不下去了!
     
    例題:
    請問我的主機是以 RPM 為套件管理的 Linux distribution ,例如 Red Hat, Mandrake 與 OpenLinux 等版本,那麼我要如何知道我的主機裡面是否已經安裝了 portmap 與 nfs 相關的套件呢?
    答:
    簡單的使用 rpm -qa | grep nfs 與 rpm -qa | grep portmap 即可知道啦!

Server 端的設定:


    NFS 的套件結構
     
    NFS 這個咚咚真的是很簡單,上面我們提到的 NFS 套件中,設定檔只有一個,執行檔也不多,記錄檔也三三兩兩而已吶!趕緊先來看一看吧! ^_^
     
    • /etc/exports:這個檔案就是 NFS 的主要設定檔了!不過,系統並沒有預設值,所以這個檔案『不一定會存在』,所以您必須要使用 vi 主動的建立起這個檔案喔!我們等一下要談的設定也僅只是這個檔案而已吶!

    •  
    • /usr/sbin/exportfs:這個是維護 NFS 分享資源的指令,我們可以利用這個指令重新分享 /etc/exports 變更的目錄資源、將 NFS Server 分享的目錄卸載或重新分享等等,這個指令是 NFS 系統裡面相當重要的一個喔!至於指令的用法我們在底下會再介紹。

    •  
    • /usr/sbin/showmount:這是另一個重要的 NFS 指令。exportfs 是用在 NFS Server 端,而 showmount 則主要用在 Client 端。這個 showmount 可以用來察看 NFS 分享出來的目錄資源喔!

    •  
    • /var/lib/nfs/xtab:這個檔案則是主要的 NFS 的紀錄檔咯!當我們的 NFS 分享出目錄資源後,到底有哪些 Client 端曾經連接上我們的 NFS 主機呢?呵呵!就是看這個檔案的內容即可囉! ^_^
     
    就說不難吧!主要就是這幾個囉!
     

    主機的規劃技巧建議
     
    如果您的工作環境中,具有多部的 Linux 主機,並且預計彼此分享出目錄時,那麼在安裝 Linux distribution 的時候,最好可以規劃出一塊 partition 作為預留之用。因為『 NFS 可以針對目錄來分享』,因此,您可以將預留的 partition 掛載在任何一個掛載點,再將該掛載點(就是目錄啦!)由 /etc/exports 的設定中分享出去,那麼整個工作環境中的其他 Linux 主機就可以使用該 NFS 主機的那塊預留的 partition 了!所以,在主機的規劃上面,主要需要留意的只有 partition 而已。此外,由於分享的 partition 可能較容易被入侵,最好可以針對該 partition 設定比較嚴格的參數在 /etc/fstab 當中喔
     

    設定流程(/etc/exports)
     
    我們在原理的部分對於 NFS 稍微解釋了一下,哇!怎麼看起來好像粉難喔!其實一點也不!為什麼呢?因為 portmap 只要一支 scripts 就可以啟動, NFS 只要設定一個檔案就可以順利運作!那麼怎麼能說不簡單呢!呵呵!這個 NFS 真是他 X 的太太太.....簡單了~在開始 NFS 之前,讓我們先以 Windows 的系統當中的『資源分享』來說明一下整個流程吧:
     
    1. 在 Windows Server 上面,開啟檔案總管,在某個目錄上面按右鍵選擇啟動資源分享;
    2. 在資源分享的內容當中,需要設定『使用者權限』( 以 Windows 2000 為例 );
    3. 在 Client 端需要登入 Windows server 時,需要啟動『網路上的芳鄰』來尋找可用的網路上面分享的目錄,然後點選該目錄,若可以登入該 Windows server 時,則可以依據步驟一的權限使用該目錄下的檔案!
     
    呵呵!沒錯! NFS 的整個流程也差不多是這樣:
     
    • 首先,需要確認一下您的 Linux 主機是否可以支援 NFS 這項服務,然後再設定一下使用者的來源IP或主機名稱以及分享出去的目錄的權限,之後呢,啟動 NFS 即可將剛剛設定的目錄給他分享出去了!
    • 那麼在 Client 端怎麼使用這個分享出來的目錄?就是先以 showmount 這支程式檢查 Linux Server 是否有可以使用的 NFS 目錄,如果有的話,就將他 mount 在本機上面,如果可以 mount ,那麼就可以使用 NFS 主機提供的資源了!
     
    哈哈!果然很簡單吧!所以底下我們就來一個一個步驟的說明一下 NFS 怎麼設定囉:
     
    1. 系統需求
    2. /etc/exports
    3. 關於權限問題
    4. 啟動服務 portmap, nfsd
    5. exportfs
    6. 檢驗目錄 /var/lib/nfs/xtab
    7. showmount
    8. 觀察啟動的 port number
     
    OK!每個咚咚的細部項目就來談一談吧:
    • 系統需求

    • 嗄!NFS 有最低硬體需求嗎?呵呵!您誤會了!這裡的需求其實指的是『軟體需求』啦!需要的是:
      1. 除了剛剛我們已經提到的兩個套件『 portmap 與 nfs-utils 』必需要存在之外;
      2. 您的核心版本最好能夠高於 2.2.xx 以後比較好!
      3. 此外,如果重新編譯過核心,您必需『一定要選擇』NFS 支援才行!
      目前,如果您使用的是安裝時候的 Linux distribution 預設核心時,那麼您都不用太擔心,因為系統已經預設有支援 NFS 囉!所以底下的咚咚您都可以玩!但是,如果您已經重新編譯過核心,並且不知道您是怎麼編譯的 ( 例如道聽途說啦、試試看新鮮玩意啦等等的來編譯您的核心時,所以沒有注意到這個項目的選擇 ) ,這個時候請拿出『鳥哥的 Linux 私房菜 -- 基礎學習篇』好好的再次的讀一遍『核心編譯』!
    • /etc/exports:

    • 好了,已經確認『一切OK』之後,我們就真的要來玩弄 NFS 啦!這個東西真的很簡單的啦,只要一個檔案就可以搞定了!那就是編輯 /etc/exports 這個檔案,請注意,這個檔案如果不存在,請自行建立!並且,檔名不要寫錯了喔!這個檔案的內容很簡單啦,我們列出他的規則:
       
      [root@test root]# vi /etc/exports
      [欲分享的目錄]  [主機名稱1或IP1(參數1,參數2)] [主機名稱2或IP2(參數3,參數4)]
       
      上面的規則是這樣的:[欲分享的目錄]主要是要分享給[主機名稱1]及[主機名稱2],但是提供給這兩者的權限並不一樣,其中,給主機名稱1的權限是參數1與參數2,至於給主機名稱2的 Client 權限則是參數3與參數4。好了,那麼那個『權限』也就是『參數』主要有哪些呢?
      • rw:可讀寫的權限;
      • ro:唯讀的權限;
      • no_root_squash:登入 NFS 主機使用分享目錄的使用者,如果是 root 的話,那麼對於這個分享的目錄來說,他就具有 root 的權限!這個項目『極不安全』,不建議使用!
      • root_squash:在登入 NFS 主機使用分享之目錄的使用者如果是 root 時,那麼這個使用者的權限將被壓縮成為匿名使用者,通常他的 UID 與 GID 都會變成 nobody 那個系統帳號的身份;
      • all_squash:不論登入 NFS 的使用者身份為何,他的身份都會被壓縮成為匿名使用者,通常也就是 nobody 啦!
      • anonuid:前面關於 *_squash 提到的匿名使用者的 UID 設定值,通常為 nobody,但是您可以自行設定這個 UID 的值!當然,這個 UID 必需要存在於您的 /etc/passwd 當中!
      • anongid:同 anonuid ,但是變成 group ID 就是了!
      • sync:資料同步寫入到記憶體與硬碟當中;
      • async:資料會先暫存於記憶體當中,而非直接寫入硬碟!
      大致的參數就是這幾樣囉!那麼我們來假設幾個例子好了:
      • 思考一:我要將 /tmp 分享出去給大家使用,由於這個目錄本來就是大家都可以讀寫的,因此我要讓所有的人都可以存取。此外,我要讓 root 寫入的檔案還是具有 root 的權限!那麼您可以這麼寫喔!
      • [root@test root]# vi /etc/exports
        /tmp  *(rw,no_root_squash)
        這樣一來,無論來自哪裡(*萬用字元!表示萬事OK!)都可以使用我的 /tmp 這個目錄。請注意,那個 *(rw,no_root_squash) 中間沒有空白字元喔!而 /tmp 與 *(rw,no_root_squash) 則是有空白字元來隔開的!特別注意到那個 no_root_squash 的功能!在這個例子中,如果您是 client 端,而且您是以 root 的身份登入您的 Linux 主機,那麼當您 mount 上我這部主機的 /tmp 之後,您在該 mount 的目錄當中,將具有『root 的權限!』
         
      • 思考二:我要將一個公共的目錄 /home/public 公開出去,但是只有限定我的區域網路內 192.168.0.0/24 這個網域可以讀寫,其他人則只能讀取:
      • [root@test root]# vi /etc/exports
        /tmp     *(rw,no_root_squash)
        /home/public 192.168.0.*(rw)   *(ro)
        /home/public 192.168.0.0/24(rw) *(ro)
        請注意,在上面的例子中,倒數兩行的格式都可以適用!所以只要寫一行即可!上面的例子說的是,當我的 IP 是在 192.168.0.0/24 這個網段的時候,那麼當我在 Client 端掛載了 Server 端的 /home/public 後,針對這個被我掛載的目錄我就具有可以讀寫的權限~至於如果我不是在這個網段之內,那麼這個目錄的資料我就僅能讀取而已,亦即為唯讀的屬性啦!
         
      • 思考三:我要將一個私人的目錄 /home/test 開放給 192.168.0.100 這個 Client 端的機器來使用,那麼我就必需這麼寫:
      • [root@test root]# vi /etc/exports
        /tmp     *(rw,no_root_squash)
        /home/public 192.168.0.*(rw)   *(ro)
        /home/test  192.168.0.100(rw)
        這樣就設定完成了!而且,只有 192.168.0.100 這部機器才能對 /home/test 這個目錄進行存取喔!
         
      • 思考四:我要讓 *.linux.org 網域的主機,登入我的 NFS 主機時,可以存取 /home/linux ,但是他們存資料的時候,我希望他們的 UID 與 GID 都變成 40 這個身份的使用者:
      • [root@test root]# vi /etc/exports
        /tmp     *(rw,no_root_squash)
        /home/public 192.168.0.*(rw)   *(ro)
        /home/test  192.168.0.100(rw)
        /home/linux  *.linux.org(rw,all_squash,anonuid=40,anongid=40)
        特別注意到那個 all_squash 與 anonuid, anongid 的功能!如此一來,當 test.linux.org 登入這部 NFS 主機,並且在 /home/linux 寫入檔案時,該檔案的所有人與所有群組,就會變成 /etc/passwd 裡面對應的 UID 為 40 的那個身份的使用者了!
    • 關於權限問題:

    • 無論任何時候,權限的問題都是需要考慮到的!讓我們來看看剛剛建立的 /etc/exports 檔案的內容:
      [root@test root]# vi /etc/exports
      /tmp     *(rw,no_root_squash)
      /home/public 192.168.0.*(rw)   *(ro)
      /home/test  192.168.0.100(rw)
      /home/linux  *.linux.org(rw,all_squash,anonuid=40,anongid=40)
      假設我在 192.168.0.100 登入這部 NFS ( IP 假設為 192.168.0.2 ) 主機,並且我在 192.168.0.100 的帳號為 test 這個身份,同時,在這部 NFS 上面也有 test 這個帳號,果真如此的話,那麼:
      1. 由於 192.168.0.2 這部 NFS 主機的 /tmp 權限為 -rwxrwxrwt ,所以我 ( test 在 192.168.0.100 上面 ) 在 /tmp 底下具有存取的權限,並且寫入的檔案所有人為 test ;
      2. 在 /home/public 當中,由於我有讀寫的權限,所以如果在 /home/public 這個目錄的權限對於 test 有開放寫入的話,那麼我就可以讀寫,並且我寫入的檔案所有人是 test 。但是萬一 /home/public 對於 test 這個使用者並沒有開放可以寫入的權限時,那麼我還是沒有辦法寫入檔案喔!這點請特別留意!
      3. 在 /home/test 當中,我的權限與 /home/public 相同的狀態!還需要 NFS 主機的 /home/test 對於 test 有開放權限;
      4. 在 /home/linux 當中就比較麻煩!因為不論您是何種 user ,您的身份一定會被變成 UID=40 這個帳號!所以,這個目錄就必需要針對 UID = 40 的那個帳號名稱,修改他的權限才行!
       
      那麼假如我在 192.168.0.100 的身份為 test2 ,但是 192.168.0.2 這部 NFS 主機卻沒有 test2 這個帳號時,情況會變成怎樣呢?
      1. 我在 /tmp 底下還是可以寫入,但是寫入的檔案所有人變成 nobody 了;
      2. 我在 /home/public 裡面是否可以寫入,還需要視 /home/public 的權限而定,不過,反正我的身份就被變成 nobody 了就是;
      3. /home/test 的觀點與 /home/public 相同!
      4. /home/linux 底下,我的身份就被變成 UID = 40 那個使用者就是了!
       
      那麼假如我在 192.168.0.100 的身份為 root 呢? root 這個帳號每個系統都會有呀!呵呵!權限變成怎樣呢?
      1. 我在 /tmp 裡面可以寫入,並且由於 no_root_squash 的參數,改變了預設的 root_squash 設定值,所以在 /tmp 寫入的檔案所有人為 root 喔!
      2. 我在 /home/public 底下的身份還是被壓縮成為 nobody 了!因為預設屬性裡面都具有 root_squash 呢!所以,如果 /home/public 有針對 nobody 開放寫入權限時,那麼我就可以寫入,但是檔案所有人變成 nobody 就是了!
      3. /home/test 與 /home/public 相同;
      4. /home/linux 的情況中,我 root 的身份也被壓縮成為 UID = 40 的那個使用者了!
       
      這樣的權限講解之後,您可以瞭解了嗎?這裡是最重要的地方,如果這一關通過了,底下的咚咚就沒有問題啦! ^_^
    • 啟動服務 portmap, nfsd

    • 好了,設定OK也沒有權限的問題之後 ( 有問題也沒關係,可以事後在好好的檢視與修改一番!) ,再來自然就是啟動他囉!如何啟動呢?簡單的很,直接給他OK下去!
      [root@test root]# /etc/rc.d/init.d/portmap start<==啟動 portmap !
      [root@test root]# /etc/rc.d/init.d/nfs start   <==啟動 NFS
      那個 portmap 根本就不需要設定!只要直接啟動他就可以啦!啟動之後,會出現一個 port 111 的 sunrpc 的服務!那就是 portmap 啦!至於 nfs 則會啟動至少兩個以上的 daemon 出現!然後就開始在監聽 Client 端的需求啦!啟動之後,請趕快到 /var/log/messages 裡面看看有沒有被正確的啟動呢?
      [root@test root]# vi /var/log/messages
      Nov 16 15:04:45 test portmap: portmap startup succeeded
      Nov 16 15:04:53 test nfs: Starting NFS services:  succeeded
      Nov 16 15:04:54 test nfs: rpc.rquotad startup succeeded
      Nov 16 15:04:54 test nfs: rpc.mountd startup succeeded
      Nov 16 15:04:54 test nfs: rpc.nfsd startup succeeded
      要正常的出現上面的字樣之後,才算是正確的啟動喔!
    • exportfs:

    • 好了,那麼如果我們修改了 /etc/exports 這個檔案之後,是否需要重新啟動 nfs 呢?呵呵,並不需要,只要使用 exportfs 重新掃瞄一次 /etc/exports 這的檔案,並且重新將設定載入即可!因此,就要來瞭解一下 exportfs 的用法了:
      語法:
      [root@test root]# exportfs [-aruv]
      參數說明:
      -a :全部掛載(或卸載) /etc/exports 檔案內的設定
      -r :重新掛載 /etc/exports 裡面的設定,此外,亦同步更新 /etc/exports
         及 /var/lib/nfs/xtab 的內容!
      -u :卸載某一目錄
      -v :在 export 的時候,將分享的目錄顯示到螢幕上!
      範例:
      [root@test root]# exportfs -rv  <==全部重新 export 一次!
      exporting 192.168.0.100:/home/test
      exporting 192.168.0.*:/home/public
      exporting *.linux.org:/home/linux
      exporting *:/home/public
      exporting *:/tmp
      reexporting 192.168.0.100:/home/test to kernel

      [root@test root]# exportfs -au <==全部都卸載了!

      要熟悉一下這個指令的用法喔!這樣一來,就可以直接重新 export 我們的記錄在 /etc/exports 的目錄資料囉!
    • 檢驗目錄 /var/lib/nfs/xtab

    •  好了,當您順利的將您的目錄都分享出去之後,您怎麼知道每個目錄的分享權限呢?不要忘記了,因為我們有相當多的預設屬性呢!因此,這個時候就得需要檢驗一下您所分享的目錄內容囉!看一下 /var/lib/nfs/xtab 這個檔案吧!他有點像這樣:
      [root@test root]# vi /var/lib/nfs/xtab
      /home/test  192.168.0.100(rw,sync,wdelay,hide,secure,root_squash,
      no_all_squash,subtree_check,secure_locks,mapping=identity,anonuid=-2,
      anongid=-2)
      看到沒?這個就是 /home/test 這個分享出去的目錄的預設 NFS 裡面的屬性啦!這個屬性狀態裡頭有個比較奇怪的,那就是 anonuid=-2 這個,怎麼有 uid=-2 的呢?呵呵!其實它說的是將 65536 - 2 的值,也就是 65534 的那個 UID 啦!對照一下 /etc/passwd ,您就會發現,哇!原來那就是 nobody 的啦!
    • showmount:

    • showmount 顧名思義,就是看看有沒有可以 mount 的指令嘛!怎麼用呢?
      語法:
      [root@test root]# showmount [-ae] hostname
      -a :在螢幕上顯示目前主機與 Client 所連上來的使用目錄狀態
      -e :顯示 hostname 這部機器的 /etc/exports 裡面的分享目錄!
      範例:
      [root@test root]# showmount -e localhost
      Export list for localhost:
      /tmp         *
      /home/linux  *.linux.org
      /home/public (everyone)
      /home/test   192.168.0.100
      很簡單吧!所以,當您要掃瞄某一部主機他提供的 NFS 分享的目錄時,就使用 showmount -e IP(或hostname)即可!非常的方便吧!
    • 觀察啟動的 port number:

    • OK!來看看我們啟動 NFS 之後,到底啟動了多少的 port 呢?要注意的是,我們有啟動 portmap 與 nfs 兩支 scripts 喔!
      [root@test root]# netstat -utln 
      Active Internet connections (only servers)
      Proto Recv-Q Send-Q Local Address           Foreign Address         State
      tcp        0      0 0.0.0.0:111             0.0.0.0:*               LISTEN <==來自 portmap
      tcp        0      0 0.0.0.0:817             0.0.0.0:*               LISTEN <==來自 rpc.xxxx 
      tcp        0      0 0.0.0.0:1266            0.0.0.0:*               LISTEN <==來自 rpc.xxxx
      udp        0      0 0.0.0.0:2049            0.0.0.0:*           <==就是 nfs 的 port
      udp        0      0 0.0.0.0:814             0.0.0.0:*           <==來自 rpc.xxxx
      udp        0      0 0.0.0.0:1327            0.0.0.0:*           <==來自 rpc.xxxx
      udp        0      0 0.0.0.0:111             0.0.0.0:*           <==來自 portmap 
      注意看到上面喔!總共產生了好多的 port 喔!真是可怕!先注意到 nfs 自己所開啟的 port ,就是那個 2049 的 port 啦!那個就是 NFS 主要產生的 port 囉。那麼其他的 rpc.xxxx 的 port 又是從何而來? NFS server 在前面我們就提過了,他是 RPC server 的一種,而 NFS 由於提供了多個 program ( 例如 rpc.mountd, rpc.rquotad, rpc.nfsd... ) ,因此就需要啟動多個 port 了!而且這些 port 是『隨機產生的』,也就是那個 port number 不會是固定的啦!每次 restart nfs 都會得到不一樣的 port number 呢!那麼 Client 端怎麼知道要連接上那個 port 來呼叫需要的 program 呢?呵呵!那就是 sunrpc ( port 111 ) 那個 portmap 服務所產生的 port number 的功用啦!Client 會先連接到 sunrpc 那個 port 去知道應該到那個 port 去呼叫所需要的程式!所以囉, rpc.xxxx 等之類的 daemon 自然就不需要有固定的 port number 囉!
    OK!這樣一來, Server 端的設定就 OK 啦!
     

    RPC server 的相關指令:
     
    好了,既然我們知道這個 NFS 其實使用的是 RPC 這個咚咚,所以當然要知道 RPC 的每個 port 在幹什麼呀!這個時候,就不能不知道 rpcinfo 這個指令了!先來談一談這個指令的用法吧!
     
    語法:
    [root@test root]# rpcinfo [-p] hostname(orIP)
    -p :顯示所有的 port 與 program 的資訊!
    範例:
    [root@test root]# rpcinfo -p test.linux.org
       program vers proto   port
        100000    2   tcp    111  portmapper
        100000    2   udp    111  portmapper
        100011    1   udp   1014  rquotad
        100011    2   udp   1014  rquotad
        100011    1   tcp   1017  rquotad
        100011    2   tcp   1017  rquotad
        100003    2   udp   2049  nfs
        100003    3   udp   2049  nfs
        100021    1   udp   1339  nlockmgr
        100021    3   udp   1339  nlockmgr
        100021    4   udp   1339  nlockmgr
        100005    1   udp   1340  mountd
        100005    1   tcp   1271  mountd
        100005    2   udp   1340  mountd
        100005    2   tcp   1271  mountd
        100005    3   udp   1340  mountd
        100005    3   tcp   1271  mountd
     
    這樣就可以知道每個 port number 所對應的 program 囉!您也就知道這個 RPC server 提供給您的 program 是什麼了!當然了,要讓這個 rpcinfo 可以正確的動作,您的 portmap 得真的動起來才行吶!加油囉!

Client 端的設定:

    掛載遠端主機
    好了, Server 端已經設定完畢,接著下來自然就是要使用 Client 端連接上 Server 端囉!那麼連接上 Server 的步驟是怎樣呢?
    1. 掃瞄可以使用的 Server 目錄;
    2. 在 Client 本地端建立 mount point;
    3. 使用 mount 將遠端主機分享的目錄掛載進來;
    4. 可能發生的問題解決(被防火牆擋掉了!?)。
OK啦!所以我們得先知道一下我們的主機裡面有什麼?假設我的主機名稱是 test.linux.org ,那麼我要知道裡頭有些什麼藉由 NFS 分享出來的目錄,就給他 showmount 一下囉!
 
[root@test root]# showmount -e test.linux.org
Export list for localhost:
/tmp         *
/home/linux  *.linux.org
/home/public (everyone)
/home/test   192.168.0.100
 
然後呢?假設我要將 /home/public 掛載在我的 /home/nfs/public 底下,那麼我就得先有這個目錄才行呀!然後再利用 mount 這個指令來掛載 /home/public 這個目錄!有點像這樣:
 
[root@test root]# mkdir -p /home/nfs/public <==建立 public 這個目錄,加 -p 可以持續增加目錄
[root@test root]# mount -t nfs test.linux.org:/home/public /home/nfs/public
掛載的格式:
[root@test root]# mount -t nfs hostname(orIP):/directory /mount/point
[root@test root]# df
Filesystem           1K-blocks      Used Available Use% Mounted on
/dev/hda1              1904920   1235380    572776  69% /
/dev/hdb1               976344    115212    810736  13% /backup
test.linux.org:/home/public
                       1904920   1235376    572776  69% /home/nfs/public <==這個是遠端主機的容量
 
先注意一下掛載 NFS 檔案的格式範例喔!呵呵!這樣就可以將資料掛載進來啦!請注意喔!以後,只要您進入您的目錄 /home/nfs/public 就等於到了 test.linux.org 那部遠端主機的 /home/public 那個目錄中囉!很不錯吧!那麼如何將掛載的 NFS 目錄卸載呢?就使用 umount 啊!
 
[root@test root]# umount /home/nfs/public
 
可能發生的問題
通常無法掛載的原因有底下這幾個:
  1. 使用者的權限不符:以上面的例子來說明,我的 /home/test 只能提供 192.168.0.0/24 這個網域,所以,如果我在 test.linux.org 這部機器中,以 localhost 來掛載時,就會無法掛載上,這個權限概念沒問題吧!那麼您可以試試看:
  2. [root @test root]# mount -t nfs localhost:/home/test /home/nfs
    mount: localhost:/home/test failed, reason given by server: Permission denied
    所以囉!如果您發現上面的顯示的訊息時,就表示您的主機權限不能夠進入該目錄囉!如果確定您的 IP 沒有錯誤,那麼請回到 /etc/exports 這個檔案中,針對您自己的 IP 來進行修正吧!
     
  3. 忘記啟動 portmap :

  4. 這個最容易被忘記了!就是忘記了啟動 portmap 這個服務啦!如果您發現您的 mount 的訊息是這樣:
    [root@test root]# mount -t nfs localhost:/home/test /home/nfs
    mount: RPC: Port mapper failure - RPC: Unable to receive
    或者是:
    [root@test root]# mount -t nfs localhost:/home/test /home/nfs
    mount: RPC: Program not registered
    那麼就趕緊將 portmap 啟動吧!!並且也需要將 nfs 重新啟動喔!
    [root@test root]# /etc/rc.d/init.d/portmap start
    [root@test root]# /etc/rc.d/init.d/nfs restart
     
  5. 被防火牆擋掉了

  6. 這個也很容易忘記了!那就是重新設定一下您的防火牆,這包含了兩部份,包括 iptables 與 TCP_Wrappers !因為我們啟動了 portmap ,這個東西有兩個資料需要分享出來,一個是 port 111 需要提供出去,因此您的 iptables 規則當中,需要開放這個 port 喔!有點像這樣的幾行字要加入您的 iptables rules 當中:
    iptables -A INPUT -p TCP --dport 111 -j ACCEPT
    iptables -A INPUT -p UDP --dport 111 -j ACCEPT
    如果您已經開放了這個 port 的連接權限,卻還是無法連接成功,那麼應該就是 TCP_Wrappers 的問題了!檢查一下您的 /etc/hosts.deny 裡頭是否有這行:
    [root@test root]# vi /etc/hosts.deny
    ALL: ALL
    果真如此的話,由於 portmap 是由 portmap 這個 daemon 所啟動的,所以您就必須要在 /etc/hosts.allow 裡面加入這一行:
    [root@test root]# vi /etc/hosts.allow
    portmap: ALL 
    或者是將 ALL 改成您所想要讓他使用 NFS 的網域即可!這樣說可以瞭解了嗎?若想進一步瞭解一下防火牆,請參考前面章節提過的:簡易防火牆建置

關機或結束時的注意事項:

需要注意的是,由於 NFS 使用的這個 RPC 在 client 端連上主機時,那麼您的主機想要關機,那可就會成為『不可能的任務』!如果您的 Server 上面還有 Client 在連線,那麼您要關機,可能得要等到數個鐘頭才能夠正常的關機成功!嗄!真的假的!不相信嗎?不然您自個兒試試看! ^_^!所以囉,建議您的 NFS Server 想要關機之前,能先『關掉 portmap 與 nfs 』這兩個東西!如果無法正確的將這兩個 daemons 關掉,那麼先以 netstat -utlp 找出 PID ,然後以 kill 將他關掉先!這樣才有辦法正常的關機成功喔!這個請特別特別的注意呢!

安全設定(被防火牆擋掉了):

好了!一些注意事項講完了之後,再來呢?對了!又是最重要的安全設定方面的問題了!那麼 NFS 可以設定安全的地方有哪裡呢?其實還不少呢?由外而內可以這樣看:
  1. iptables 防火牆設定;
  2. TCP_Wrappers 防火牆設定;
  3. /etc/exports 權限設定。
防火牆的基本概念請參考『簡易防火牆建置』一文,最好能將該篇文章給他看完,否則還真難瞭解底下在幹嘛~嗯!假設您已經看完該篇短文了,接著下來我們就得要一步一步的接著建立防火牆囉!
  • 使用 iptables 限制大範圍連線:

  • 假設我們的 NFS 主要是針對內部網路開放而已,而對於外部網路只有對學術網路開放,亦即是 140.0.0.0/8 ,那麼您可以使用這樣的語法:
    iptables -A INPUT -i eth0 -p TCP -s 192.168.0.0/24 --dport 111 -j ACCEPT
    iptables -A INPUT -i eth0 -p UDP -s 192.168.0.0/24 --dport 111 -j ACCEPT
    iptables -A INPUT -i eth0 -p TCP -s 140.0.0.0/8    --dport 111 -j ACCEPT
    iptables -A INPUT -i eth0 -p UDP -s 140.0.0.0/8    --dport 111 -j ACCEPT
    這樣大致上就可以讓 192.168.0.0/24 這個 C Class 的網域與 140.0.0.0/8 這個 A Class 的網域到您的主機裡面來,而其他的連線就視您的原本的 iptables 的狀態而定喔!
     
  • 使用 TCP_Wrappers 限制更細的範圍:

  • 事實上,如果您不懂得如何設定 iptables 的話,那也沒關係,我們可以使用 TCP_Wrappers 阿!因為要使用 NFS 就必須要通過 portmap 這一關( 因為要使用 RPC 啦! ),而這個 portmap 可以藉由 TCP_Wrappers 來管理!呵呵!太好了!那麼就將他連線的範圍限制的更小囉!我們可以在 /etc/hosts.allow 裡面規定連上 NFS 主機的主機 IP 與名稱,假設限制中的主機只有 192.168.0.0/24 這個 C class 及 140.116.44.125 這個主機,以及後面接的是 ncku.edu.tw 的網域可以連上我的 NFS 主機,那麼我可以寫成這樣:
    [root@test root]# vi /etc/hosts.allow
    portmap: 192.168.0.0/255.255.255.0 
    portmap: 140.116.44.125 
    portmap: .ncku.edu.tw 

    [root@test root]# vi /etc/hosts.deny
    portmap: ALL

    呵呵!這樣可就設定好囉!很簡單的吧!
     
  • 使用 /etc/exports 設定更安全的權限:

  • 這就牽涉到您的邏輯思考了!怎麼設定都沒有關係,但是在『便利』與『安全』之間,要找到您的平衡點吶!善用 root_squash 及 all_squash 等功能,再利用 anonuid 等等的設定來規範登入您主機的使用者身份!應該還是有辦法提供一個較為安全的 NFS 主機的!
  • Client 端掛載的問題:

  • 基本上,在 Client 端掛載的時候,為了擔心會不小心剛 NFS 端掛進來的具有 SUID 權限檔案的程式執行!這個很可能會危害到系統的安全呢!因為 SUID 本來就不是很安全的嘛!所以呢,您這個 root 也可以將 NFS 所分享的目錄以較為安全的情況掛載進來!例如:
    [root@test root]# mount -t nfs -o nosuid,ro hostname:/directory /mount/point
    選擇 nosuid 也是一個很不錯的抉擇喔!
通常我們都會約略的建議,不要啟動 NFS Server ,即使要啟動,最好也是針對某個範圍來進行目錄的分享!並且,『要分使用者層級來管理』會比較好一些喔!底下我們就來實際的在您的機器上面搞一個簡單的 NFS server 吧!

實際演練:

假設環境:
  1. 假設我的 Linux 主機為 192.168.0.100 這一部;
  2. 預計將 /tmp 以可讀寫,並且不限制使用者身份的方式分享給所有 192.168.0.0/24 這個網域中的所有 Linux 工作站;
  3. 預計開放 /home/nfs 這個目錄,使用的屬性為唯讀,可提供除了網域內的工作站外,向外亦提供資料內容;
  4. 預計開放 /home/upload 做為 192.168.0.0/24 這個網域的資料上傳目錄,其中,這個 /home/upload 的使用者及所屬群組為 nfs-upload 這個名字,他的 UID 與 GID 均為 210;
  5. 預計將 /home/andy 這個目錄僅分享給 192.168.0.50 這部 Linux 主機,以提供該主機上面 andy 這個使用者來使用,也就是說, andy 在 192.168.0.50 及 192.168.0.100 均有帳號,且帳號均為 andy ,所以預計開放 /home/andy 給 andy 使用他的家目錄啦!
實地演練:
好了,那麼請您先不要看底下的答案,先自己動筆或者直接在自己的機器上面動手作作看,等到得到您要的答案之後,在看底下的說明吧!
  • 首先,就是要建立 /etc/exports 這個檔案的內容囉,您可以這樣寫吧!
  • [root @test root]# vi /etc/exports
    /tmp     192.168.0.*(rw,no_root_squash)
    /home/nfs   192.168.0.*(ro)  *(ro,all_squash)
    /home/upload 192.168.0.*(rw,all_squash,anonuid=210,anongid=210)
    /home/andy  192.168.0.50(rw)
    大概就是這樣子吧!您可以自行測試看看!
     
  • 再來,就是要建立每個對應的目錄的實際 Linux 權限了!我們一個一個來看:
  • 1. /tmp
    [root @test root]# ll / 
    drwxrwxrwt    6 root     root         4096 Nov 16 09:07 tmp

    2. /home/nfs
    [root @test root]# mkdir -p /home/nfs            <==建立所需要的目錄
    [root @test root]# chmod 755 -R /home/nfs      <==修改較為嚴格的檔案權限
    將目錄與檔案設定成唯讀!不能寫入的狀態,會更保險一點!

    3. /home/upload
    [root @test root]# groupadd -g 210 nfs-upload  <==先建立所需要的 210 這個群組
    [root @test root]# useradd -g 210 -u 210 -M nfs-upload <==建立需要的使用者名稱
    [root @test root]# mkdir -p /home/upload       <==建立起目錄了!
    [root @test root]# chown -R nfs-upload:nfs-upload /home/upload <==修改擁有者!
    如此,則使用者與目錄的權限都設定妥當囉!

    4. /home/andy
    [root @test root]# ll /home
    drwx------    3 andy     andy         4096 Oct 28 13:37 andy

    這樣子一來,權限的問題大概就可以解決囉!
     
  • 啟動 portmap 與 nfs 服務:
  • [root @test root]# /etc/rc.d/init.d/portmap start
    [root @test root]# /etc/rc.d/init.d/nfs start
     
  • 在 192.168.0.50 這部機器上面演練一下:
  • 1. 確認可用目錄
    [andy @linux50 andy]$ showmount -e 192.168.0.100
    Export list for 192.168.0.100:
    /tmp         192.168.0.*
    /home/nfs    (everyone)
    /home/upload 192.168.0.*
    /home/andy   192.168.0.50

    2. 建立掛載點:
    [andy @linux50 andy]$ mkdir -p /home/zzz/tmp
    [andy @linux50 andy]$ mkdir -p /home/zzz/nfs
    [andy @linux50 andy]$ mkdir -p /home/zzz/upload
    [andy @linux50 andy]$ mkdir -p /home/zzz/andy

    3. 實際掛載:
    [andy @linux50 andy]$ su   <==通常 Linux 只允許 root 來掛載!
    [root @linux50 andy]# mount -t nfs 192.168.0.100:/tmp /home/zzz/tmp
    [root @linux50 andy]# mount -t nfs 192.168.0.100:/home/nfs /home/zzz/nfs
    [root @linux50 andy]# mount -t nfs 192.168.0.100:/home/upload /home/zzz/upload
    [root @linux50 andy]# mount -t nfs 192.168.0.100:/home/andy /home/zzz/andy
    [root @linux50 andy]# exit

整個步驟大致上就是這樣吶!加油喔!

重點回顧

  • Network FileSystem (NFS) 可以讓主機之間透過網路分享彼此的檔案與目錄;
  • NFS 主要是透過 RPC 來進行 file share 的目的,所以 Server 與 Client 的 RPC 一定要啟動才行!
  • NFS 主機可以控制連線的 Client 端的登入與權限;
  • NFS 的設定檔就是 /etc/exports 這個檔案;
  • NFS 的重要登錄檔可以參考 /var/lib/nfs/xtab 這個檔案,還包含相當多有用的資訊在其中!
  • NFS 主機要關機之前,請務必先關閉 portmap 與 nfs server ,否則關機無法順利成功;
  • NFS 主機在更動 /etc/exports 這個檔案之後,可以透過 exportfs 這個指令來重新掛載分享的目錄!
  • 可以使用 rpcinfo 來觀察 RPC program 之間的關係!!!
  • NFS 主機在設定之初,就必須要考慮到 client 端登入的權限問題,很多時候無法寫入或者無法進行分享,主要是 Linux 實體檔案的權限設定問題所致!
  • NFS 的防火牆設定可以透過控制 RPC 的主要 port ,亦即是 111 這個 port 來管理!此外,亦可透過 TCP_Wrappers 來管理!
  • NFS 用戶端只要成功 mount NFS 主機分享的目錄之後,使用上面就好像自己的 partition 一般;
  • NFS 用戶端可以透過使用 showmount, mount 與 umount 來使用 NFS 主機提供的分享的目錄!

本章與 LPI 的關係

在 LPI 網站 http://www.lpi.org 裡面提到的,關於 NFS 的考試題庫的地方,只有在 LPI level 1 的 102 ,裡面的 topic 113 Networking Services ,第四點當中,簡易的 NFS 設定。強調的是『應試者需瞭解 NFS 的設定、啟動與關閉的關係』至於會考的檔案與指令可能有這些:
  • /etc/exports
  • /etc/fstab
  • mount
  • umount

參考資源:


本章習題練習

  • NFS 的主要設定檔為何?而在該檔案內主要設定項目為何?
  • 在 NFS 主要的設定檔當中僅有少許的參數說明,至於預設的參數說明則沒有在該檔案當中出現,請問,如果要查閱更詳細的分享出來的檔案的屬性,要看那個檔案?
  • 如果已經啟動了 nfs 這個伺服器,但是卻又修改過主要設定檔,請問可以使用那個指令來重新掛載分享出來的目錄與 client 端權限的設定值?
  • 在 client 端如果要掛載 NFS 所提供分享的檔案,可以使用那個指令?
  • 在 NFS 主要設定檔當中,可以透過那個參數來控制不讓 client 端以 root 的身份使用您所分享出來的目錄與檔案?
  • 我在 client 端掛載了 NFS Server 的某個目錄在我的 /home/data 底下,當我執行其中某個程式時,卻發現我的系統被破壞了?您認為可能的原因為何?該如何克服這樣的問題,尤其是當我的 Client 端主機其實是多人共用的環境,怕其他的使用者也同樣發生類似的問題呢?!

  • 前往參考解答
修改歷史:
2002/11/17:第一次完成
2003/03/09:修改部分內容,並且新增 LPI 相關性與重點整理部分!
2003/09/10:又重新修改版面,以及新增主機的規劃等部分。
其他連結
環境工程模式篇
鳥園討論區
鳥哥舊站

今日 人數統計
昨日 人數統計
本月 人數統計
上月 人數統計