【NFS】NFS客户端挂载目录后无写入权限的解决方案
NFS 的权限本身没有用户密码和账户验证登录过程 。
你可以回忆下,我们前面访问远程共享目录的时候,是没有输入账户,密码啥的,是没有这个步骤的。
客户端登录到服务器后,会把客户端的账户身份映射到服务器端 ,NFS 要访问成功,不仅与服务器端配置有关,还与操作系统的目录文件权限有关 。
当你用root用户去访问共享目录时,其实你已经变成了服务器端的匿名用户nfsnobodoy了,这样你还有权限访问nfsnobody没有权限的文件吗?当然是不行的。
NFS配置的权限在 文件本身的权限 面前是不起作用的,最终是取决于 文件它自己本身的权限的。
当然解决的方法是有的:通过建立UID和文件所有者UID相同的用户去访问,也就是伪造文件所有者UID去欺骗NFS服务器。
对于 root 用户,默认转换成 nobody 账号,也就是说客户端不管你是以什么账号访问到 nfs 的挂载路径,在服务端都是识别类似为 nobody@<clinet ip> ,实际访问到服务端上面的共享目录时,是以 nobody 账号的身份访问。
对于非 root 用户,则使用其账号访问,即如果 root 用户挂载,但是使用 user1 用户(假设 uid 为1000)访问,则在 nfs 服务端也是识别为 uid 为 1000 的用户访问,如果本地有对应的 uid ,则映射为对应的用户,即:如果服务端 uid 1000 对应为 testuser1,则最后客户端 user1 所对应的权限实际为服务端 testuser1 的权限。
对于 root 账号,可以在 exports 配置文件中添加 no_root_squash 选项即可,这样在客户端访问时,root 账号权限不会被冲刷成 nobody / nfsnobody ,直接映射为服务端 root 账号权限。
但是这样的配置权限太大,存在安全风险,实际生产中比较少这么配置。
nfs 并没有类似 no_root_squash 这种针对非 root 普通用户的配置选项,所以需要使用其他的方式配置。
如果只允许个别非 root 普通用户,则可使用 anonuid 和 anongid 配置项,然后对共享目录配置 acl 权限,根据所授权的 uid 或 gid 配置。
如果使用 anonuid ,则客户端需要授权的用户账号的 uid 需要跟 anonuid 一致。
如果使用 anongid ,则客户端需要授权的用户账号的 groups 中需要有对应的 gid 。
一般需要挂载的客户端比较多,为了便于后续的配置管理,不需要经常调整配置,建议使用 anongid (如501)来配置,然后在客户端创建用户组,其 gid 跟服务端 anongid 一致,对于需要授权的用户账号,将新创建的用户组添加至用户的附属组中。
在linux系统中,判别用户的时候是通过用户的UID来判断的,并不是用户名,所以在我们建立用户的时候只需要将用户的UID和服务器上文件拥有着相同即可!
# vim /etc/exports
/opt/public 192.168.1.104(rw,sync,anonuid=2019,anongid=2019)
image.png
image.png
nfs身份映射
NFS的目的是导出目录给各客户端,因此导出目录中的文件在服务端和客户端上必然有两套属性、权限集。
例如,服务端导出目录中某a文件的所有者和所属组都为A,但在客户端上不存在A,那么在客户端上如何显示a文件的所有者等属性。再例如,在客户端上,以用户B在导出目录中创建了一个文件b,如果服务端上没有用户B,在服务端上该如何决定文件b的所有者等属性。
所以,NFS采用uid/gid <==> username/groupname映射的方式解决客户端和服务端两套属性问题。由于服务端只能控制它自己一端的身份映射,所以客户端也同样需要身份映射组件。也就是说,服务端和客户端两端都需要对导出的所有文件的所有者和所属组进行映射。
但要注意,服务端的身份映射组件为rpc.idmapd,它以守护进程方式工作。而客户端使用nfsidmap工具进行身份映射。
服务端映射时以uid/gid为基准,意味着客户端以身份B(假设对应uid=Xb,gid=Yb)创建的文件或修改了文件的所有者属性时,在服务端将从/etc/passwd(此处不考虑其他用户验证方式)文件中搜索uid=Xb,gid=Yb的用户,如果能搜索到,则设置该文件的所有者和所属组为此uid/gid对应的username/groupname,如果搜索不到,则文件所有者和所属组直接显示为uid/gid的值。
客户端映射时以username/groupname为基准,意味着服务端上文件所有者为A时,则在客户端上搜索A用户名,如果搜索到,则文件所有者显示为A,否则都将显示为nobody。注意,客户端不涉及任何uid/gid转换翻译过程,即使客户端上A用户的uid和服务端上A用户的uid不同,也仍显示为用户A。也就是说,客户端上文件所有者只有两种结果,要么和服务端用户同名,要么显示为nobody。
因此考虑一种特殊情况,客户端上以用户B(其uid=B1)创建文件,假如服务端上没有uid=B1的用户,那么创建文件时提交给服务端后,在服务端上该文件所有者将显示为B1(注意它是一个数值)。再返回到客户端上看,客户端映射时只简单映射username,不涉及uid的转换,因此它认为该文件的所有者为B1(不是uid,而是username),但客户端上必然没有用户名为B1的用户(尽管有uid=B1对应的用户B),因此在客户端,此文件所有者将诡异地将显示为nobody,其诡异之处在于,客户端上以身份B创建的文件,结果在客户端上却显示为nobody。
综上考虑,强烈建议客户端和服务端的用户身份要统一,且尽量让各uid、gid能对应上。
参考
NFS基本应用
https://www.cnblogs.com/f-ck-need-u/p/7305755.htm
文件服务器之一:NFS 服务器
http://cn.linux.vbird.org/linux_server/0330nfs_1.php
推荐的 NFS 装载选项
https://docs.amazonaws.cn/efs/latest/ug/mounting-fs-nfs-mount-settings.html
NFS文件系统-挂载和优化
https://cloud.tencent.com/developer/article/1902098
Linux中常见的NFS挂载选项
https://gamedebug.github.io/Common-NFS-mount-options-in-Linux
Linux系统挂载NFS文件系统
https://help.aliyun.com/zh/nas/user-guide/mount-an-nfs-file-system-on-a-linux-ecs-instance