3. 设置 NFS 服务器

3.1. 服务器设置简介

本文假设您将同时设置服务器和客户端。如果您只是设置客户端以使用其他人的服务器(例如在您的部门中),您可以跳到 第 4 节。但是,每个设置好的客户端都需要在服务器上进行修改以授权该客户端(除非服务器设置是以一种非常不安全的方式完成的),因此即使您没有设置服务器,您也可能希望阅读本节以了解要留意哪些类型的授权问题。

设置服务器将分两步完成:设置 NFS 的配置文件,然后启动 NFS 服务。

3.2. 设置配置文件

您需要编辑三个主要的配置文件来设置 NFS 服务器:/etc/exports/etc/hosts.allow/etc/hosts.deny。 严格来说,您只需要编辑 /etc/exports 就可以使 NFS 工作,但您会留下一个极其不安全的设置。 您可能还需要编辑您的启动脚本;有关更多信息,请参见 第 3.3.3 节

3.2.1. /etc/exports

此文件包含一个条目列表;每个条目指示一个共享的卷以及它的共享方式。查看手册页 (man exports) 以获取该文件的所有设置选项的完整描述,尽管这里的描述可能满足大多数人的需求。

中的一个条目/etc/exports通常看起来像这样
 directory machine1(option11,option12) machine2(option21,option22)

其中

directory

您要共享的目录。它可以是整个卷,但不必是。如果您共享一个目录,则同一文件系统中的所有子目录也将被共享。

machine1 和 machine2

将有权访问该目录的客户端机器。机器可以通过其 DNS 地址或 IP 地址列出(例如,machine.company.com192.168.0.8)。使用 IP 地址更可靠,更安全。如果您需要使用 DNS 地址,并且它们似乎没有解析到正确的机器,请参见 第 7.3 节

optionxx

每台机器的选项列表将描述该机器将具有的访问类型。重要选项是

  • ro:目录以只读方式共享;客户端机器将无法写入该目录。这是默认设置。

  • rw:客户端机器将具有对目录的读写访问权限。

  • no_root_squash:默认情况下,用户root在客户端机器上发出的任何文件请求都被视为由用户nobody在服务器上发出的请求。(请求映射到的确切 UID 取决于服务器上用户“nobody”的 UID,而不是客户端。)如果no_root_squash被选中,则客户端机器上的 root 将对系统上的文件具有与服务器上的 root 相同的访问级别。这可能具有严重的安全性影响,但如果您想在涉及导出目录的客户端机器上执行任何管理工作,则可能是必要的。如果没有充分的理由,您不应指定此选项。

  • no_subtree_check:如果仅导出了卷的一部分,则名为子树检查的例程会验证从客户端请求的文件是否在卷的适当部分中。如果导出了整个卷,则禁用此检查将加快传输速度。

  • sync:默认情况下,除了最新版本(版本 1.11)之外的所有 exportfs 命令都将使用async行为,告诉客户端机器文件写入已完成 - 也就是说,已写入稳定存储 - 当 NFS 完成将写入交给文件系统时。如果服务器重新启动,并且sync选项可以防止这种情况,此行为可能会导致数据损坏。有关syncasync行为的完整讨论,请参见第 5.9 节

假设我们有两台客户端机器,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 写入它可能没有好处,因此超过了安全方面的考虑。 另一方面,如果用户要在其上保存工作,则需要以读写方式导出主目录。

如果您安装了大量计算机,您可能会发现您有很多计算机都在同一个本地网络上,需要访问您的服务器。 有几种简化对大量机器的引用的方法。 首先,您可以通过指定网络和网络掩码一次授予对一系列机器的访问权限。 例如,如果您想允许访问 IP 地址介于 192.168.0.0192.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,您可能还希望查看手册页inithosts.allow.

其次,您可以在您的条目中使用 NIS 网络组。 要在 exports 文件中指定一个网络组,只需在网络组名称前加上一个“@”。 有关网络组如何工作的详细信息,请参见 NIS HOWTO

第三,您可以使用通配符,如 *.foo.com192.168. 代替主机名。 2.2 内核系列中存在通配符实现的问题,这些问题已在内核 2.2.19 中修复。

但是,您应该记住,如果您的网络组或本地网络中存在您不完全信任的机器,则这些简化中的任何一个都可能导致安全风险。

关于什么不能(或不应该)导出,有几点需要注意。 首先,如果导出了一个目录,则如果父目录和子目录在同一文件系统中,则不能导出它们。 但是,导出两者应该不是必要的,因为在/etc/exports文件中列出父目录将导致导出该文件系统中的所有底层目录。

其次,使用 NFS 导出 FAT 或 VFAT(即 MS-DOS 或 Windows 95/98)文件系统是一个糟糕的主意。 FAT 不是为在多用户机器上使用而设计的,因此,依赖于权限的操作将无法很好地工作。 此外,据报道,一些底层文件系统设计在使用 NFS 的期望方面效果不佳。

第三,设备或其他特殊文件可能无法正确导出到非 Linux 客户端。有关特定操作系统的详细信息,请参见 第 8 节

3.2.2. /etc/hosts.allow 和 /etc/hosts.deny

这两个文件指定了网络上的哪些计算机可以使用您机器上的服务。文件的每一行都包含一个单独的条目,列出了一个服务和一组机器。当服务器收到来自机器的请求时,它会执行以下操作

除了控制由 inetd 处理的服务(例如 telnet 和 FTP)的访问之外,此文件还可以通过限制与提供 NFS 服务的守护程序的连接来控制对 NFS 的访问。 限制是基于每个服务进行的。

要限制访问的第一个守护程序是端口映射器。 此守护程序本质上只是告诉请求客户端如何在系统上找到所有 NFS 服务。 限制对端口映射器的访问是防止有人通过 NFS 闯入您系统的最佳防御手段,因为完全未经授权的客户端不会知道在哪里可以找到 NFS 守护程序。 但是,有两件事需要注意。 首先,如果入侵者由于某种原因已经知道如何找到这些守护程序,则限制端口映射器是不够的。 其次,如果您正在运行 NIS,则限制端口映射器也会限制对 NIS 的请求。 这通常应该是无害的,因为您通常希望以类似的方式限制 NFS 和 NIS,但请注意。 (如果您正在运行 NFS,那么运行 NIS 通常是一个好主意,因为客户端机器需要一种方法来知道谁拥有导出卷上的哪些文件。 当然,还有其他方法可以做到这一点,例如同步密码文件。 有关设置 NIS 的信息,请参见 NIS HOWTO。)

总的来说,使用 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,添加这些条目充其量是无害的(因为它们将被忽略),并且最好是在升级时为您节省一些麻烦。 一些系统管理员选择将条目ALL:ALL放入文件/etc/hosts.deny中,这会导致任何查看这些文件的服务拒绝访问所有主机,除非它被明确允许。 虽然这是更安全的行为,但当您安装新服务时,也可能会给您带来麻烦,您忘记将其放在那里,并且您无法弄清楚为什么它们无法工作。

接下来,我们需要向hosts.allow允许我们希望允许访问的任何主机进行访问。(如果保留上面的行)hosts.deny那么将没有人能够访问NFS。) /etc/hosts.allow 中的条目hosts.allow遵循以下格式:

这里,host 是潜在客户端的 IP 地址;某些版本可能允许使用主机的 DNS 名称,但不强烈建议这样做。

假设我们有上述设置,并且我们只想允许 *slave1.foo.com* 和 *slave2.foo.com* 访问,并且假设这些机器的 IP 地址分别为 *192.168.0.1* 和 *192.168.0.2*。 我们可以将以下条目添加到/etc/hosts.allow:

对于最新的 nfs-utils 版本,我们还需要添加以下内容(同样,即使不支持这些条目也没有害处):

如果您打算在本地网络中的大量计算机上运行 NFS,/etc/hosts.allow也允许使用网络/子网掩码样式的条目,方式与/etc/exports上面相同。

3.3. 启动服务

3.3.1. 先决条件

NFS 服务器现在应该已经配置完毕,我们可以开始运行它了。 首先,您需要安装适当的软件包。 这主要包括足够新的内核和足够新版本的 nfs-utils 软件包。 如果您有疑问,请参阅 第 2.4 节

接下来,在启动 NFS 之前,您需要在您的机器上正确运行 TCP/IP 网络。 如果您可以使用 telnet、FTP 等等,那么您的 TCP 网络很可能没问题。

也就是说,在大多数最新的 Linux 发行版中,您只需重新启动计算机即可启动并运行 NFS,并且启动脚本应该检测到您已设置/etc/exports/etc/exports 文件,并会正确启动 NFS。 如果您尝试这样做,请参阅第 3.4 节验证 NFS 是否正在运行。 如果这不起作用,或者您无法重新启动计算机,那么以下部分将告诉您哪些守护程序需要启动才能运行 NFS 服务。 如果由于某种原因,在您编辑上面的配置文件时 nfsd 已经在运行,则您必须刷新您的配置;有关详细信息,请参阅第 3.5 节

3.4. 验证 NFS 是否正在运行

为此,请使用命令 rpcinfo -p 查询 portmapper,以找出它正在提供的服务。 您应该得到类似以下内容:
    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 版本 2 和 3,rpc.statd 版本 1,网络锁定管理器(rpc.lockd 的服务名称)版本 1、3 和 4。 还有不同的服务列表,具体取决于 NFS 是通过 TCP 还是 UDP 传输。 除非明确请求 TCP,否则 Linux 系统默认使用 UDP; 但是,其他操作系统(例如 Solaris)默认使用 TCP。

如果您至少没有看到一行显示 portmapper,一行显示 nfs,以及一行显示 mountd,那么您需要返回并再次尝试启动守护程序(如果这仍然不起作用,请参阅 第 7 节,故障排除)。

如果您确实看到列出了这些服务,那么您应该可以设置 NFS 客户端以从您的服务器访问文件。

3.5. 稍后更改 /etc/exports

如果您返回并更改您的/etc/exports/etc/exports 文件,您所做的更改可能不会立即生效。 您应该运行命令 exportfs -ra 以强制 nfsd 重新读取/etc/exports/etc/exports文件。 如果您找不到 exportfs 命令,那么您可以使用-HUP标志来杀死 nfsd(有关详细信息,请参见 kill 的手册页)。

如果这仍然不起作用,请不要忘记检查 hosts.allow 以确保您没有忘记在那里列出任何新的客户端机器。 还要检查您可能设置的任何防火墙上的主机列表(有关防火墙和 NFS 的更多详细信息,请参见 第 7 节第 6 节)。