3. NFS サーバの設定

3.1. サーバ設定の概略

ここではサーバとクライアントの両方を設定することを考えます。 クライアントだけを設定して、誰か別の人のサーバ (例えば部門のサーバなど) につなぎたい場合は、 Section 4 に進んでください。 しかし、クライアントを設定するたびに、 サーバはそのクライアントからの接続を許すよう修正する必要があります (サーバの設定が非常に危険な場合を除けば)。 従って自分でサーバを設定しない場合でも、 このセクションは読んでおいたほうがいいでしょう。 そうすれば認証関連の問題があった場合にどこを調べれば良いかわかるでしょうから。

サーバの設定は 2 つのステップからなります。 まず NFS の設定ファイルを編集し、 次に NFS サービスを実際に起動します。

3.2. 設定ファイルの編集

NFS サーバの設置にあたって編集しなければならない 主要な設定ファイルは 3 つあります。 /etc/exports, /etc/hosts.allow, /etc/hosts.deny です。 本当のところを言うと、実際に NFS を動作させるには /etc/exports だけで良いのですが、 これだと NFS は非常に危険な状態に置かれます。 さらに、これらに加えて起動スクリプトを編集する必要もあるかもしれません。 これについては Section 3.3.3 を見てください。

3.2.1. /etc/exports

このファイルにはエントリのリストが書かれており、 各エントリは共有するボリュームと、 それがどの様に共有されるかを記述します。 このファイルにおける設定オプションのすべてを知るには man ページ (man exports) を見る必要がありますが、 ここにある記述でも大抵の人の用途には足りるでしょう。

/etc/exports のエントリは、 以下のような形式になっています:
 directory machine1(option11,option12) machine2(option21,option22)

各要素の意味は以下の通りです:

directory

共有させたいディレクトリです。ボリューム全体でも良いですし、 そうでなくてもかまいません。あるディレクトリを共有させると、 それ以下のすべてのディレクトリも (同じファイルシステムにある限り) 同様に共有されます。

machine1 and machine2

そのディレクトリにアクセスするクライアントマシンです。 マシンは DNS アドレスまたは IP アドレスで指定できます (例: machine.company.com とか 192.168.0.8)。 IP アドレスを使うほうがより信頼性が高く安全です。 DNS アドレスを使う必要があって、 その際に正しいマシンを発見できない場合には、 Section 7.3 を見てください。

optionxx

各マシンのオプションのリストで、 そのマシンがどのようにアクセスできるかを記述します。 重要なオプションをいくつか挙げます:

  • ro: このディレクトリは読み出し専用で共有されます。 クライアントは書き込むことはできません。これがデフォルトです。

  • rw: クライアントマシンは読み出しと 書き込み両方のアクセスをこのディレクトリに行います。

  • no_root_squash: デフォルトでは、 root ユーザによるファイル要求は、 すべてサーバ上では nobody ユーザによってなされたものとして扱われます。 (正確に言うと、要求の UID のマップ先はサーバにおける ユーザ "nobody" の UID に依存します。クライアントの ものではありません。) no_root_squash を選ぶと、 クライアントマシンの root は、 サーバシステムでも root としての同じレベルのアクセスを サーバのファイルに行うことになります。 これはセキュリティに多大な影響を及ぼす可能性がありますが、 クライアントで行う管理作業にエクスポートされたディレクトリを 含めたいような場合には、これが必要になるでしょう。 適切な理由がなければ、このオプションは指定すべきではありません。

  • no_subtree_check: ボリュームの一部だけをエクスポートする場合、 subtree checking と呼ばれるルーチンが、 クライアントから要求されたファイルが そのボリュームの適切な場所にあるかどうかを調べます。 ボリューム全体をエクスポートする場合は、 このチェックを無効にしておくと転送が高速になります。

  • sync: 最新の版 (version 1.11) を除き、 exportfs コマンドは デフォルトでは async 動作をします。 つまり、NFS が書き込み処理をファイルシステムに渡した段階で、 クライアントマシンに書き込みが完了した (つまりストレージデバイスへの書き込みが完了した) と伝えます。 この動作ではサーバがリブートするとデータが壊れる可能性があり、 sync を指定すればこれを防げます。 syncasync の動作に関する詳細な議論は Section 5.9 を見てください。

いま 2 台のクライアントマシン、 slave1slave2 があり、 それぞれの IP アドレスはそれぞれ 192.168.0.1192.168.0.2 であるとしましょう。 これらのマシンに、自分たちで作ったソフトウェアバイナリのディレクトリと、 ホームディレクトリを共有させたいとします。 このような場合の /etc/exports は 次のようになるでしょう:
  /usr/local   192.168.0.1(ro) 192.168.0.2(ro)
  /home        192.168.0.1(rw) 192.168.0.2(rw)
 

ここでは /usr/local の共有は slave1 slave2 ともに読み出し専用としています。 ここには自分たちで開発したソフトウェアが入るので、 slave1 や slave2 に書き込み権限を与えることに、 それがもたらすセキュリティ上のリスクを越えるメリットはないでしょうから。 一方ホームディレクトリは、そこにユーザが作業をセーブするのであれば、 読み書き可能でエクスポートしなければなりません。

もし大きなシステムを使っている場合には、 たくさんのコンピュータが同じローカルネットワークにつながっていて、 それらすべてからサーバへのアクセスを行わせたいかもしれません。 多くのマシンへの参照を簡単に行うには、いくつかの方法があります。 最初のものは、ネットワークとネットマスクを用いて、 アクセスを許すマシンの範囲を指定する方法です。 例えば 192.168.0.0 から 192.168.0.255 にあるすべてのマシンにアクセスを許すには、 次のようなエントリを用意します:
  /usr/local 192.168.0.0/255.255.255.0(ro)
  /home      192.168.0.0/255.255.255.0(rw)
 

ネットマスクの詳しい動作原理については Networking-Overview HOWTO (JF による日本語訳) を見てください。また init および hosts.allow の各 man ページも見ておくといいでしょう。

二番目の方法は、エントリに NIS のネットグループを用いるやり方です。 exports ファイルにネットグループを指定するには、 ネットグループ名の前に "@" をつければ良いだけです。 ネットグループの詳しい動作原理については NIS HOWTO (JF による日本語訳) を見てください。

三番目の方法は、ホスト名の代わりに *.foo.com192.168. のようなワイルドカードを使う方法です。2.2 系カーネルには ワイルドカードの実装に問題があったのですが、これは カーネル 2.2.19 で修正されました。

しかしこれらの単純化を行うと、ネットグループやローカルネットワークに あるすべてのマシンを完全には信頼できていない場合には、 セキュリティ上のリスクが加わることになります。

エクスポートできない (あるいはすべきでない) 内容について、 いくつか順番に注意しておきます。 まず第一に、あるディレクトリをエクスポートすると、 その親ディレクトリと子ディレクトリは (同じファイルシステムにある場合は) エクスポートできません。しかしこれらをエクスポートする必要はないはずです。 なぜなら親ディレクトリを /etc/exports にかけば、同じファイルシステムにある それ以下のディレクトリはすべてエクスポートされるからです。

第二に、FAT や VFAT ファイルシステム (MS-DOS や Windows 95/98 の領域) を NFS でエクスポートするのはよい考えではありません。 FAT はマルチユーザのマシンで利用することを考慮されていませんから、 権限という概念に基づいた操作が行えません。 さらに、これらのファイルシステムの下層システムは、設計上の理由から NFS の期待通りには動作しないとも報告されています。

第三に、デバイスファイルや特殊ファイルは、 Linux 以外のクライアントには正しくエクスポートされないことがあります。 各 OS それぞれに関する詳細は Section 8 を見てください。

3.2.2. /etc/hosts.allow と /etc/hosts.deny

この 2 つのファイルは、 あなたのマシンのサービスを利用できるのは、 ネットワーク上のどのコンピュータなのかを指定するものです。 このファイルの各行は、サービスとマシンの一覧をリストした ひとつのエントリになっています。サーバがあるマシンから要求を受けると、 サーバは次のように動作します:

このファイルによるアクセス制御は、inetd で扱われるサービス (telnet や FTP など) だけでなく、 NFS にも適用できます。 NFS サービスを提供するデーモンへの接続を制限できるのです。 制限はサービスごとに行えます。

アクセスを制限すべき最初のデーモンはポートマッパ (portmapper) です。 このデーモンの仕事は、基本的には要求をよこしたクライアントに、 システム上の様々な NFS サービスへの接続先を伝えることだけです。 ポートマッパへのアクセス制限は、 NFS 経由でシステムへ侵入しようとする者に対する最適な防御となります。 なぜなら全く認証されていないクライアントは、 どこに NFS デーモンがいるかを知るすべがないからです。 しかしここで 2 つの点に気をつけなければなりません。 一つ目は、ポートマッパを制限するだけでは十分ではないということです。 侵入者はなんらかの理由で、 これらのデーモンへの接続先を知っているかもしれません。 二つ目は、NIS を動かしている場合には、ポートマッパを制限すると NIS への要求も制限されるということです。 通常は NFS も NIS も同様に制限したいでしょうから、 これが問題になることは少ないでしょうが、 しかし気には留めておいてください。 (NFS を動作させるなら、 NIS もいっしょに動作させると良いでしょう。 クライアントマシンには、 エクスポートされたボリュームにあるファイルの所有者を 知る方法が必要だからです。 もちろんパスワードファイルを同期させる方法は他にもありますが。 NIS の設定については NIS HOWTO (JF による日本語訳) を見てください。

一般には、NFS (を含めほとんどのインターネットサービス) への アクセスは、許可する必要のない IP アドレスに対しては 明示的に拒否しておくのが良いでしょう。

こうするには、まず次のようなエントリを /etc/hosts.deny に追加します:

   portmap:ALL
  

nfs-utils 0.2.0 からは、 それぞれのデーモンのアクセス制御も行うことができ、 よりシステムを堅固にできます。 侵入者はポートマッパを回避できることも多いので、 この用心をしておくのはよいことです。 最近版の nfs-utils を用いているのなら、 NFS 関連のデーモンそれぞれについて エントリを一行ずつ追加しておきましょう (これらのデーモンがそれぞれ何であるかは次の節を見てください。 いまは単にこれらのエントリを hosts.deny に加えてください):

    lockd:ALL
    mountd:ALL
    rquotad:ALL
    statd:ALL
  

古い版の nfs-utils を使っている場合でも、 少なくともこれらのエントリを追加して問題が起きることはありません (単に無視されます)。そしてアップグレードしたときに、 システムをトラブルから救ってくれるかもしれないわけです。 /etc/hosts.deny ファイルに ALL:ALL というエントリを追加する方を選ぶ システム管理者もいます。こうすると、これらのファイルを参照する すべてのサービスは、明示的に許可されたホスト以外からのアクセスを すべて拒否します。 これはとても安全な動作ですが、 新しいサービスをインストールした際にトラブルの原因となるかもしれません。 このエントリを置いたことを忘れていると、 なぜ新しいサービスが動かないのか、 一生かかってもわからないかもしれません。

次にエントリを hosts.allow に追加し、 アクセスを許可するホストを指定します。 (上記のように hosts.deny に追加しただけだと、 誰も NFS にアクセスできません。) hosts.allow のエントリは次のような形式です:

ここで host はクライアントになれるホストの IP アドレスです。 ホストの DNS 名を利用できるシステムもありますが、 DNS 名の利用は避けるよう強くおすすめします。

以前に行ったような設定で、 slave1.foo.comslave2.foo.com にアクセスを許可したい場合を考えましょう。 これらのマシンの IP アドレスをそれぞれ 192.168.0.1192.168.0.2 とします。この場合は次のようなエントリを /etc/hosts.allow に追加します:

最近の版の nfs-utils では、次の内容も追加しましょう (同じくサポートされていなくても無害です):

NFS をローカルなネットワークにつながった多数のマシンに対して 動作させる場合は、 /etc/hosts.allow にも「ネットワーク/ネットマスク」 形式のエントリを指定することもできます。 やり方は先に /etc/exports の部分で説明したのと同じです。

3.3. サービスを開始する

3.3.1. 事前の準備

これで NFS サーバの設定ができましたので、動作させてみましょう。 まず、適切なパッケージをインストールしましょう。 要するに十分新しいカーネルと、十分新しい版の nfs-utils パッケージです。 よく分からなければ Section 2.4 を見ましょう。

続いて、NFS を開始する前に、TCP/IP ネットワークの機能が そのマシンで正しく動作しているか確認しましょう。 telnet, FTP などが使えれば、おそらく TCP ネットワークは ちゃんと動いていると思います。

じつは、最近の Linux ディストリビューションのほとんどでは、 NFS を起動して動作させるには、マシンをリブートするだけですみます。 こうすると起動スクリプトは、あなたが /etc/exports に対して行った設定を検知して、NFS を正しく起動してくれます。 こちらを試してみるなら、Section 3.4 を読んで、 NFS が動作しているかどうか調べてください。 うまく行かなかった場合や、マシンをリブートできない場合には、 次の節を読めば NFS サービスに必要なデーモンがどれかわかります。 なんらかの理由で、先に設定ファイルを編集していた時点で nfsd が動作していた場合は、 行った設定を反映させる必要があります。 これを行うには Section 3.5 を見てください。

3.3.3. それぞれのデーモン

NFS のサービスは、5 つのデーモンによって処理されます: rpc.nfsd は作業の大部分を行います。 rpc.lockdrpc.statd はファイルロックを扱います。 rpc.mountd は接続開始時のマウント要求を扱います。 rpc.quotad はエクスポートされたボリュームにおける ユーザファイルクォータを扱います。 2.2.18 以降では、lockdnfsd から必要に応じて呼び出されますので、 手動で起動する必要はありません。 statd は別に起動しておく必要があります。 最近の Linux ディストリビューションのほとんどには、 これらのデーモンの起動スクリプトがあるはずです。

これらのデーモンはすべて nfs-utils パッケージに入っており、 /sbin または /usr/sbin のいずれかのディレクトリにあると思います。

使っているディストリビューションの起動スクリプトにこれらがない場合は、 次の順に起動するよう設定を追加しなければなりません:

rpc.portmap
rpc.mountd, rpc.nfsd
rpc.statd, rpc.lockd (必要なら), rpc.rquotad

nfs-utils パッケージには、RedHat と Debian 向けの起動スクリプトの例が 入っています。これら以外のディストリビューションを使っている場合でも、 大抵は RedHat のスクリプトをコピーすればすむと思いますが、
    . ../init.d/functions
   
という行を削除しないとエラーメッセージが表示されるかもしれません。

3.4. NFS が動作しているか確認する

これを行うには、 rpcinfo -p コマンドを用いてポートマッパに問い合わせ、 どんなサービスが提供されているかを調べます。 次のような出力が得られるはずです。
    program vers proto   port
    100000    2   tcp    111  portmapper
    100000    2   udp    111  portmapper
    100011    1   udp    749  rquotad
    100011    2   udp    749  rquotad
    100005    1   udp    759  mountd
    100005    1   tcp    761  mountd
    100005    2   udp    764  mountd
    100005    2   tcp    766  mountd
    100005    3   udp    769  mountd
    100005    3   tcp    771  mountd
    100003    2   udp   2049  nfs
    100003    3   udp   2049  nfs
    300019    1   tcp    830  amd
    300019    1   udp    831  amd
    100024    1   udp    944  status
    100024    1   tcp    946  status
    100021    1   udp   1042  nlockmgr
    100021    3   udp   1042  nlockmgr
    100021    4   udp   1042  nlockmgr
    100021    1   tcp   1629  nlockmgr
    100021    3   tcp   1629  nlockmgr
    100021    4   tcp   1629  nlockmgr
  

ここでは NFS version 2 と 3、rpc.statd version 1、 network lock manager (rpc.lockd のサービス名) version 1, 3, 4 があります。また NFS が TCP を使うか UDP を使うかによって、 別々のサービスとしてリストされています。 Linux システムは、特に TCP を使うべく指定されない限り、 UDP をデフォルトで用います。しかし Solaris のような他の OS では、 デフォルトは TCP になっています。

もし portmapper の行、 nfs の行、 mountd の行のどれかがなければ、 戻ってデーモンを起動しなおす必要があります (もしそれでも動かなければ、Section 7 トラブルシュートを見てください)。

これらのサービスが表示されていたら、NFS クライアントを用意して、 サーバのファイルにアクセスさせるための準備が整ったことになります。

3.5. /etc/exports をあとから変更する

先ほどやった /etc/exports ファイルの変更を再び行なった場合、 その変更はすぐには反映されません。nfsd/etc/exports ファイルを読み直させるには、 exportfs -ra コマンドを実行しなければなりません。  exportfs コマンドが見つからない場合は、 -HUP フラグを指定して nfsd を kill します (詳細は kill の man ページを見てください)。

これでもうまくいかない場合は、 hosts.allow を調べ、 新しいクライアントマシンをリストし忘れていないか確認してください。 またファイアウォールを設定している場合は、 そのホストリストもチェックしてください (ファイアウォールと NFS の関係については Section 7Section 6 とを見てください)。