NFS.png

 

 

NFSの歴史的背景


■ NFSとは何か

NFS とは Network File System の略称で、サンマイクロシステムズが1985年にSUNワークステーションに導入したファイル共有システムである。一般にUNIXではデバイスファイルをマウントすることによってファイルシステムを拡張して行くが、NFSではこの概念がネットワークに応用された。すなわち、ネットワーク越しにファイルシステムをマウントし、UNIXにとって「自然な」ファイル共有を目指したもので、Samba のようにSMBプロトコルを使った共有とは本質的な相違がある。なおNFSは単体のデーモンで構成されるものではなく、 rpc.mountd と nfsd および rpc.portmapper が連携してサーバ動作をする。

NFSはもともとSUNマイクロシステムズの技術だが、SUNがリモートプロシージャコールの
仕様を公開したために広く利用されるようになった。先頃WindowsがMS-blast ウィルスによってRPCのバグを衝かれたことはまだ記憶に新しいが、WindowsのRPCもSUNRPCの拡張版のひとつである。このようにNFSは各社が独自に仕様を改定したためそれぞれの実装系にはかなり違いがあり、オプションひとつをとってもその使い方に戸惑うことがある。たとえばretryオプションがそれで、LinuxのNFSでは時間(分)で指定するのに対し、HP-UXのmountコマンドでは回数だったりするので、異なる実装系では注意が必要である。また、異なるNFSバージョンでは問題が発生することもしばしば耳にする。

また、NFSはUNIXの専売ではないことにも注意しておきたい。近年まで有料であったためそれほど普及はしていないが、実はWindowsにもフリーとなったNFSソフト<SFU3.5>がある。使い勝手に一癖あるため賛否両論あるのだが、評価してみたい向きにはマイクロソフトのHPからダウンロードできるので、ここでは深く触れないことにする。いずれにせよNFSがプラットフォームを問わない共有システムとして広く利用されていることのみ留意されたい。


NFSマウント

NFSプロトコルではアプリケーション層でNFS、プレゼンテーション層ではXDR (eXternal Data Representation)、セッション層ではRPC( Remote Procedure Call )がそれぞれ対応して通信する。さらに下位のトランスポート層ではUDPが対応しネットワーク層でIPが対応するのは、通常のTCP/IPネットワークと変わらない。もちろんデータリンク層・物理層ではイーサネットが対応する。



NFS の設定


■ 基本設定項目

NFSはカーネル機能の一部分でもあるので、インストールを意識する必要はない。RedHat ではインストール時にサーバインストールを選択し、NFS にチェックを入れておけば自動的にインストールされる。ただし、NFSはポートマップ→マウント→ファイル共有という流れの複合型サービスであるため、起動には複数のデーモンを動かす必要がある(後述)。
サーバ設定の流れは次のようになる。

     1.サーバ側公開ディレクトリの作成
     2.exports ファイルを編集してNFSサーバの設定をする
     3.NFS用ユーザの設定
     4.NFSクライアントの設定をする(ユーザ設定とファイル設定)
     5.起動



■ exports ファイル

exports は公開ディレクトを設定するファイルで、インストール直後は中身が空である。先に例示したとおり、
サーバ名が nfs_server で公開するディレクトリが /public であるとき、exports ファイルには以下の様式で記述を行う。(/etc/exportsの記述はホスト形式となっており、まず第一フィールドにディレクトリ、第二フィールドにアクセスを許可するホストの名前とパーミッションを設定し、その後にオプションを記述する。)

           /public   192.168.1.0/255.255.255.0(rw)    192.168.1.0 のサブネット上の全ユーザに /public の読み書き許可

このとき前もって /public 公開ディレクトリを mkdir しておくこと。当たり前の話だが、このディレクトリが存在しないことには共有のしようがない。また、exports ファイルの許可とOSのファイルパーミッションは別に機能するため、このディレクトリに対するパーミッションも設計しておく必要がある。仮に上記のサブネットのユーザにすべての許可を与えるなら、次のように chmod すればよい。

     # chmod 777 /public

(※ もちろん、この設定ではセキュリティ上通用しない。また、/etc/exports 自身にもパーミッションの指定が必要である。詳細は用例を参照せよ。)

オプション項目一覧

オプション項目

内  容

rw、ro エクスポートするディレクトリの読み書き可能、または読み取り専用の指定。
secure、insecure NFS クライアントからのリクエストを受け付けるポート番号を、1024 未満に制限するかどうかを指定。デフォルトはsecure で制限される。

noaccess

ディレクトリへのアクセスを禁止。ただし、ファイル名やディレクトリ名の一覧は参照可能。
link_absolute、link_relative エクスポートするディレクトリ以下に存在するシンボリック・リンクを、そのままエクスポートするかどうか指定。デフォルトは、link_absolute でそのままエクスポートする。

注意:link_relative を指定すると、絶対パス形式のシンボリック・リンクを相対パス形式のリンクに変換する。 "/"で始まる絶対パスを、"../"などを含む相対パスに変換するため、場合によってはルート・ディレクトリを越えてしまう恐れがある。この場合の動作は予想がつかないので、使用には注意が必要である。
root_squash、no_root_squash NFS クライアントからのルート権限でのアクセス要求を有効または無効にする。デフォルトは、root_squashで、ユーザーIDとグループIDが共に 0 の要求がされるとユーザIDとグループIDを nobody に置き換える。
 no_root_squash を指定すると、ルート権限での要求をそのまま受け入れる。これはセキュリティ面で問題があるので、基本的には使用すべきでない。 root_squash の場合でも、bin などのユーザーには適用されないので注意が必要である。
squash_uids、squash_gids nobody に置き換えるユーザーIDやグループIDを指定する。

no_all_squash、all_squash

すべてのユーザーIDとグループIDを nobody に置き換えるかどうかを指定。デフォルトは、no_all_squash で置き換えをしない。 このオプションは公開 FTP ディレクトリやNews のスプール・ディレクトリなどをエクスポートする場合などに使用される。
map_identity、map_daemon 動的なユーザーID/グループIDのマッピングを有効にするかどうかを指定。デフォルトは、map_identity で、すべてのユーザーIDとグループIDをそのまま NFS サーバに渡す。
map_static 静的なマッピングを可能にする。このオプションでは、ユーザーID/グループIDの置き換えを記述したファイルの名前を指定する。
map_nis NIS ベースのユーザーID/グループIDの置き換えを可能にする。
anonuid、anongid nobody のユーザーIDとグループIDを別のIDに置き換える。

nosuid

suid 属性を持つプログラムがNFS クライアントで実行できなくなる。

noexec

NFS サーバー上のすべてのプログラムがNFS クライアントで実行できなくなる。


なお、/etc/exports ファイルを編集した場合は、次のコマンドでnfsdに通知する必要がある。

     /usr/sbin/exportfs -a


これを実行しないと設定の変更が反映されないので注意すること。また、NFSのバージョンは日々進歩しているので、仕様が変わることがある。例えばつい先頃までのNFSではディスク I/O は非同期がデフォルトだったが、現在では同期( async → sync )がデフォルトになっている。このような変更は特に断りなく行われるので、オプションを適用するときは現行バージョンの仕様を十分に調査すること。
 


■ exports ファイルでのアクセス制御

NFSでは exports ファイル上でユーザのアクセス権限を設定することができる。/
etc/exports ファイルは、NFS クライアントに公開(export)してもよいファイル・システムのアクセス制御リストを与える。これは NFS マウント・デーモンである mountd (8) と NFS ファイル・サーバー・デーモンである nfsd (8) の両方で使用される。最も基本的なアクセス制御は次のオプションで行う。

      (ro)       read only    読み込みのみ許可
             (rw)       read write   読み書きの許可

これらは第二フィールドのユーザの直後に付記し、省略した場合はデフォルトで読み取りのみとなる。ここで注意するべき点はブランク文字の取り方である。次の2例ではブランクひとつによって意味が全く異なるのでよく考えていただきたい。

      
/public user.domain.co.jp(rw)
      /public user.domain.co.jp (rw)

者はユーザのドメイン名の直後に(rw)が記述されていることから、このユーザだけが /public に対する読み書き権限を持っている、という意味になる。しかし、後者はドメイン名と(rw)の間に1つブランクがあることから、このユーザの権限が省略されたことによってデフォルトの読み取り専用として解釈され、その他の全世界のユーザが読み書きできる設定になってしまう。すなわち、ブランクを一つ入れた記述は次のような意味になるので、セキュリティ上特に注意を要する。

      /public user.domain.co.jp(ro)  others_all(rw)

一方、NFSはリモート root 権限でのアクセスをオプションで制約することができる。その他の詳細はオプション一覧表を参照のこと。

root_squash

エクスポートファイルシステムにクライアントマシンのrootユーザーとしてアクセスした場合、nobodyユーザーIDに変更する。これはリモートrootユーザーの能力を最低のローカルユーザーにまで格下げして、リモートrootユーザーがサーバ上のrootユーザーとして振舞うのを禁止するもの。

no_root_squash

リモートrootユーザをサーバ上のrootとして振舞うことを許す。

all_squash

rootを含めてすべてのリモートユーザをnobodyに格下げする。



■ クライアント側の設定(ファイルシステムのマウント/アンマウント)

クライアント側の設定を行う前に名前解決ができることを確認する。内部にDNSサーバがあれば問題はないが、そうでない場合は /etc/hosts ファイルでクライアントの名前とIPアドレスを定義しておく。クライアントが20〜30台程度までなら hosts ファイルをFDにコピーしてインストールすればそう面倒でもなく、また名前解決もDNSより高速である。なお、名前解決ができない場合は直接サーバのIPアドレスを指定する。

クライアント側ではマウントポイントを作っておく必要がある。ここではマウントポイントを /mnt/nfs とする。

           # mkdir /mnt/nfs

NFSではサーバ上のファイルシステムをネットワーク越しにクライアントにマウントする。これによってクライアントからは共有ファイルシステムが、あたかもFDやCD-ROMのように自分のファイルシステムに連結して見える。サーバ名が nfs_server で、公開するディレクトリが /public であるとき、ファイルシステムをローカルの /mnt/nfs にマウントするには次のコマンドを投入すればよい。( mount -t nfs はファイルシステムのタイプを nfs に指定するという意味。もちろん、前もってマウントポイント /mnt/nfs を mkdir しておくことが前提である。)

     mount -t nfs nfs_server:/public /mnt/nfs


さらにファイルシステムのマウントはクライアント側で自動化することができ、その意味でもユーザは共有を意識する必要がない。Autoマウントするには /etc/fstab に以下のような一行を追加する。サーバ名とマウントポイントの名称はそれぞれの環境に合わせること。

     nfs_server:/public    /mnt/nfs   nfs   defaults 0 0

アンマウントには次のコマンドで対応する。(クライアントのシャットダウン時には必ずアンマウントする。)

     umount /mnt/nfs

アンマウントはどうしても忘れがちなので、たとえば shutdown2 のような名前のショートスクリプトを書いて、停止時にはそれで停止するようにしてもよい。以下にシェルスクリプト例を示す。

---- script shutdown2 ----

           #! /bin/bash
           umount /mnt/nfs
           shutdown -h 10

これをコマンドパスの通ったディレクトリに設置し、実行可能パーミッションに chmod しておく。(
なお、NFSの原理はサーバのファイルシステムをローカルにマウントするということである。したがってサーバが先に起動していないと当然ローカル側ではファイルシステムをマウントできない。サーバのメンテナンス時など、前もってユーザに知らせておかないとちょっとしたパニックになるのでご注意を。)


■ showmount コマンド


NFSマウント情報を知りたいときは showmount コマンドを使用する。以下にオプションごとの用例を示す。

1.-v オプション

バージョンを示して終了する。nfs-utils のユーティリティであることに注意。

[root@server root]# showmount -v
showmount for nfs-utils 1.0.1

2.-d オプション

あるクライアントからマウントされているディレクトリだけを表示する。

[root@server root]# showmount -d
Directories on server:
/home/sharednfs

3.-e オプション

クライアント側からサーバのエクスポートディレクトリ(公開ディレクトリ)情報を要求する。

[root@client root]# showmount -e server
Export list for server:
/home/sharednfs 192.168.2.0/255.255.255.0

4.-a オプション

クライアントに対するすべてのマウントポイントをホスト:ディレクトリの形で帰す。

[root@server root]# showmount -a
All mount points on server:
192.168.2.107:/home/sharednfs
192.168.2.200:/home/sharednfs
192.168.2.209:/home/sharednfs
192.168.2.219:/home/sharednfs
192.168.2.21:/home/sharednfs



■ NFSの起動

先に述べたように
NFSサーバでは最低限 nfsd、mountd、portmap が動作している必要がある。これらのデーモンは、/etc/rc.d/rc[n].d (nはランレベルを示す数字)に記述された順番で起動される。RedHatでのNFSシステムは起動順が確立しているが、起動された nfsd は /etc/exports を参照して、NFSクライアントからのアクセスが正当であるかを判断する。
サーバ側でNFSを起動のためのコマンドは次のとおり。

     
# /etc/rc.d/init.d/nfs restart

もちろん RedHat では service nfs start の様式で /sbin/service コマンドを利用できる。サーバでNFSが起動したらファイルシステムをマウントする。クライアント側で /public ディレクトリをマウントするためのコマンドは次のとおり。

           # mount -t nfs nfs_server:/public /mnt/nfs

なお、DNSやhosts ファイルを使わない(名前解決を求めない)場合は、直接サーバのIPアドレスを指定する。

     # mount -t nfs 192.168.1.1:/public /mnt/nfs


■ デーモンの確認

NFSの起動を確認するには rpcinfo コマンドを使う。これは rpc 関連のプログラムのバージョンと利用ポートをレポートするもので、NFSのトラブルシューティングの基本となるものである。また、システムのポート使用状況は netstat コマンドでも確認できるので、起動後に必ずチェックしておく。
以下に RedHat9 で実行した rpcinfo  -p のアクションを示す。()内はデーモン名。

    [root@sakuyahime root]# rpcinfo -p
       プログラム バージョン プロトコル ポート
        100000    2   tcp    111  portmapper   (
    portmap )
        100000    2   udp    111  portmapper
        100024    1   udp  32768  status     (
    rpc.statd )
        100024    1   tcp  32768  status
        391002    2   tcp  32769  sgi_fam     (
    sgi_fam → xinetd 経由)
        100011    1   udp    916  rquotad     (
    rpc.quotad )
        100011    2   udp    916  rquotad
        100011    1   tcp    919  rquotad
        100011    2   tcp    919  rquotad
        100003    2   udp   2049  nfs                 (
    nfsd )
        100003    3   udp   2049  nfs
        100021    1   udp  32770  nlockmgr        (
    nfslock )
        100021    3   udp  32770  nlockmgr
        100021    4   udp  32770  nlockmgr
        100005    1   udp  32771  mountd          (
    rpc.mountd )
        100005    1   tcp  32770  mountd
        100005    2   udp  32771  mountd
        100005    2   tcp  32770  mountd
        100005    3   udp  32771  mountd
        100005    3   tcp  32770  mountd


このほかに netstat -ant, netstat -anu, fuser -vn PROTOCOL PORT_NUM等のコマンドを使って利用ポートを調べておくこと。なお、外部からのNFS要求をファイアウォール上でブロックするには最低限 tcp/udp 111 (portmapper) を塞げばよい。




exportsファイル の設定例


■ etc/exportsでできること


exports ファイルの設定例を JM-project のマニュアル掲載例をもとにいくつか示す。この項目については、このようなことができる、という意味で読んでいただきたい。まずはもっとも大胆かつ危険な設定から紹介する。

         
/                         master(rw) trust(rw,no_root_squash)

master と trust に対して、/ 以下のすべてのファイルシステムのマウント許可を出している。書き込みの許可に加え、さらに trust に対しては uid squashing も無効にしている。つまり、すべてのファイルシステムを丸ごとマウントさせ、リモート root ですべてができる、という意味の設定である。上位ホストから特殊なメンテナンスを行う場合などに設定する可能性はあるが、通常はまかり間違ってもやらないこと。

         /projects
              proj*.local.domain(rw)

ワイルドカードを使う設定はしばしば見かける。この例ではあるプロジェクトに関わっているユーザに proj* というユーザ名を割り振られるものとし、 /projects というディレクトリを公開する。ここに開発用のファイルを置き、それぞれのユーザがワークステーションにマウントして使う。したがって、このディレクトリは読み書きができるように設定してある。

         /usr
                     *.local.domain(ro) @trusted(rw)

これもワイルドカードを使ったもの。この例では /usr ディレクトリをアカウントユーザに読み取り専用で公開するものである。また、後半の @trusted はNISによるネットグループにエントリを用意したもので、読み書き可能に指定されている。

         /home/taro
          pc001(rw,all_squash,anonuid=150,anongid=100)

これはNISベースで入ってくるユーザpc001に /home/taro を読み書き可能なかたちで公開するものである。すべてのユーザを いったん nobody に変換し、さらに uid を150、gid を100に変換する。

         /public
                 (ro,insecure,all_squash)

これは /public ディレクトリを世界中のあらゆるホストに向けて(ユーザ名がないことに注目すること。
うっかりユーザ名を落としてしまうとこの設定になります!)読み取り専用にエクスポートするものである。すべてのリクエストは nobody アカウントで実行されるが、エントリ中の insecure オプションによって、NFS用ポートを使わないように実装されたNFSクライアントからのアクセスも許可する。

         /public/private
      (noaccess)

ちょっとおかしな状況設定であるが、/public の中にある /private
ディレクトリへのアクセスをすべてのクライアントに対して拒否するようにしている。公開ディレクトリの中にちょっと見せたくないディレクトリがあった、などというとき、緊急回避的にこの手を使うことがある。


■ その他 の設定ファイル

/etc/hosts.allow および /etc/hosts.deny ファイルは tcpd(TCP_Wrappers) の設定ファイルとして知られているが、portmap もこのファイルを参照してアクセス制御を行う。hosts.allow には接続を許可するホストを記述し、hosts.deny は接続を拒否するホストを記述する。この二つのファイルには allow 側に読み込みの優先権があり、デーモンはまず hosts.allow を読みに行き、条件がクライアントからの要求と一致すれば承認する。この時点で承認されなかった要求は /etc/hosts.deny と照合され、 deny ファイルに記述された条件と一致した要求は拒否される。したがってまず allow 側で許可するホストを定義し、そののち読み込まれる deny 側ですべてのホストを拒否する条件を設定しておく。

hosts.allow および hosts.deny によるアクセス許可フロー

flow.png

両ファイルの記述書式は次のとおり。サービス:ホストの形式となる。

---- /etc/hosts.allow ----

           portmap:192.168.1.

---- /etc/hosts.deny ----

          portmap:ALL



コラム:共有システムのクライアントセキュリティ

共有システムを構築するとき、サーバのセキュリティは厳重に設計されることが多いが、その割に貧弱になりがちなのがクライアントのセキュリティである。共有システムでは文字通り情報を共有するので、クライアント側から「合法」的にアクセスされると、いくらサーバ側のセキュリティが強固であっても意味がない。サーバでディレクトリに対するアクセス制御を厳重に行っていても、アクセスさせる以上は読み出せることが前提だからである。

では共有ファイルをro属性でしか許可しなければOKかと言えば、そうではない。たとえばTeraTermなどにはロギングモードがあるため、リモートアクセスさえできればcatでファイルをログに落とすことが可能だ。しかもこの手はサーバの異常系ログに残らない(!)ので、管理者がいかに目を光らせていようと情報漏洩の発見はきわめて難しい。この意味において、共有システムのクライアントのセキュリティはサーバと同等以上に設計しなければならない。

ならばパスワードの更新頻度を早めたりしてガチガチにセキュリティを固めればいいのかといえば、もちろんそうではない。このような手法は下策でユーザの利便性を大幅に損なうばかりか、ファイル共有のメリットを放棄することにもなりかねないからだ。これはNFSやSambaに限らず、共有システムの本質に関わる問題であり、だからこそ共有に関する基本ポリシーが必要になる。

通常、システム設計に先立って、共有ポリシーとして次のようなことが検討される(…少なくとも、されていて欲しい)。もちろんこれは情報の機密性・重要性について階層的な分類ができていることが前提である。

1.誰にアクセスさせるのか(アクセスグループの特定)
2.どこからアクセスさせるのか(ファシリティの特定)
3.どのようにアクセスさせるのか(書き込み・読み出し許可の特定)

よく考えると、これらはサーバに対するポリシーではなく、実はクライアントに対するポリシーそのものである。すなわち、共有システムの導入にあたってはよくクライアントに対するポリシー設計こそが重要なのである。

しかし実際にはなかなかこうはいかないのが現実である。特にヤバイよなあ、と思うことがあるのは2のファシリティだ。経験上、構築基本設計書には「どこから」に対してネットワーク範囲が書いてある場合がほとんどである。しかし、設計書にある「経理セグメント」や「開発室セグメント」のファシリティが実際にはどのようになっているのか、我々には知る由がない。いざ構築となって現場を訪れてみれば、外部からの入室がノーチェックにもかかわらず、ユーザはクライアントマシンにログオンしたまま24時間点けっぱなし、などという環境だったりする。かと思うと、ファイアウォール越しに共有にアクセス可能とする仕様だったり…。

といって我々はお客さんに物申す立場じゃないもんなあ。結局、喉元まで上がってくる言葉をため息にすりかえるしかないのかなあ…。



 

 

Copyright(c) 2003 My Company. All rights reserved. www.suzu841.com / mrs.suzu841.com