巧用 all_squash 解决 NFS 服务权限问题

前言

NFS 是一种分布式文件系统,允许客户端主机可以像访问本地存储一样通过网络访问服务器端文件。同时,NFS 协议也是开放的,基于 ONC RPC 协议的一个标准 RFC 协议。凡是实现 NFS 标准的软件(客户端或者服务端)都可以互相兼容。

使用

Linux 内置的 mount 命令就支持 NFS,仅仅运行:

mount -t nfs ${server_ip}:${server_nfs_dir} ${local_dir}

即可将远程的网络目录挂载到本地,就如同操作本地文件一样。并且一般来讲,应用程序对 NFS 挂载点的访问及使用和本地目录没有区别。
当然,这篇文章的重点不是 NFS 怎么搭建和使用,而是 NFS 会造成麻烦的权限系统。

NFS 权限

假如你当前登录在系统上的用户 UID 为 1000,那么你对 NFS 文件的操作权限就对应 NFS 服务器的 UID:1000 用户的权限。因为客户端用户对应服务端用户,变相的相当于“你在用服务器上你的身份操作服务器的文件”。因为这个原因,对于系统管理员和客户端使用人员而言,可能对 NFS 的权限配置就省了很大的一笔功夫了。

但是在某些时候,服务器上可能只有一个 root 管理员用户在操作,服务器上存在的文件都是 root 用户所属的,包括你配置的 NFS 目录。
如果你想设置下 NFS 目录的服务器文件权限就完事,好像也没那么简单。因为你不能保证管理员不会操作 NFS 目录,以 root 身份运行的应用程序不会往 NFS 目录写入内容。
以导致在你的客户端出现无法写入的目录和无法更改删除的文件。因为客户端特别是桌面用户,一般来讲不会直接用 root 。

假设我们抛弃安全问题,客户端用户 UID 是 1000 ,那么我在服务器上将 UID:1000 这个用户添加到 root 组,不就完事了吗?永远不可能再有文件权限问题。
不是什么事情都要强行安全的不是吗?假设我只是搭建一个自己用的 NAS 服务器。

嗯,对,这就是抛弃安全解决权限问题的最简单方式。

但是,某些情况下,服务器是不能添加新用户的。就例如 DD-WRT 系统。你无法在 DD-WRT 上添加一个新用户,它默认只有 root 用户给你使用。你无法添加一个对应客户端 UID 的用户,更别提把该用户丢进 root 组了。

这就造成了天生的权限问题。

权限问题的终极解决方式

在 NFS 的配置文件 exports 中,有一个配置项叫 all_squash,它的作用是将客户端的所有用户映射成一个指定的用户。 不管你是 UID 为 0 的 root 用户,还是一个普通用户,在服务端眼里你都是以指定的那个用户身份在操作文件。所有的客户端都是平等的。
它需要配合 anonuid 和 anongid 来指定服务器用户,通常用作公共目录的权限配置。并且默认情况下 NFS 是其相反配置项 no_all_squash 启用的状态。所以启用它必须完整的添加三个配置项。

基于 all_squash 的这个策略,我们就可以解决 DD-WRT 的权限问题了。因为我们只需要将所有客户端映射成 root 即可!要知道我们客户端用户在服务端不仅没有特殊权限的配置方式,甚至连个身份都没有!
所以,我们只能将自己的用户“包装”成 root 用户来操作服务器上的文件了!并且客户端随意用什么身份,在服务端看来,谁都是管理员!

/opt/data   192.168.2.222(rw,anonuid=0,anongid=0,all_squash,sync)

配置如上,所有客户端用户操作 NFS 目录文件,有服务端 uid$gid 为 0 即 root 用户的权限。即使是 DD-WRT 这样系统也能完美当作 NAS 服务器。

最后

其实有两个东西,没有 NFS 处理权限这么固执。一个是 SSHFS 另一个是 CURLFTPFS。它们也可以将服务端上的目录挂载到本地,达到和 NFS 一样的效果。
但是从专业网络存储方面来讲,NFS 比它们更适合:性能更强(体现在网络协议、缓存策略等地方)、更加成熟(配置更合理)、兼容更广(支持三大平台、以及手机设备)等。所以,这里我只是提一下,并不推荐大家使用它们!

我的路由器现在已经是一个 NAS 服务器,内网共享资源我都会往路由器上扔,手机、PC 都开机自动挂载到本地,好用到不行。