NFS是干嘛的?

Network File System的缩写,主要是通过网络,让不同的计算机、不同的操作系统可以比较方便地共享文件。

NFS通信

NFS服务器的端口开在2049(TCP和UDP),但是由于文件系统的复杂性,NFS还有其他程序启动额外的端口来传输数据,通常是小于1024的随机端口。

随机端口的话,客户端如何知道使用哪个端口连接呢?

这就需要远程过程调用(Remote Procedure Call,RPC)协议来实现 RPC 服务。这个名称看字面意思比较难懂,实质上可能是 portmap 或者 rpcbind 服务(CentOS7)。主要功能就是指定每个NFS功能所对应的端口号( port number),并且通知到客户端,让客户端可以连接到正确的Port上。

RPC(rpcbind)服务监听的端口是111(TCP和UDP)。

RPC如何知道每个NFS功能的端口呢?

NFS Server启动之前,RPC服务会先(作为依赖服务)启动。然后NFS启动会向RPC去注册这些随机端口。客户端通过111端口和RPC通信来获取NFS服务器注册的端口信息。最终客户端会通过获取到的NFS端口信息和NFS Server进行实际的数据传输。

NFS工作流程

NFS工作流程.png

NFS安装

CentOS7中支持NFSv4,相对于NFSv3,它扩展了对更大文件尺寸、Windows类型的访问控制列表的支持。内置了文件锁定功能,不再需要NLM,和rpmbind程序包。

安装命令

安装“文件和存储服务器”组,这将包括Samba、CIFS和iSCSI目标的程序包。
yum group install “File and Storage Server”

如果仅安装客户端,则是:
yum install nfs-utils

安装完成之后,查看和启动 rpcbind 和 NFS 服务:
systemctl status/start/enable rpcbind.service
systemctl status/start/enable nfs.service

PS:nfs.service 等同于 nfs-server.service,都是基于守护进程 nfsd 的服务。

查看nfs状态

nfsstat -s 查看服务端状态
nfsstat -c 查看客户端状态
nfsstat —help 查看更多选项帮助信息

NFS导出(exports 共享目录配置)

有的时候看到NFS导出比较费解,而实质上是通过 /etc/exports 文件的配置来定义哪些目录将通过NFS来共享给网络上的客户端主机,以及定义主机或网络对目录的访问权限

除了 /etc/exports 文件,还接受将名为 *.exports 的文件添加到 /etc/exports.d/ 目录下实现同样的配置。
下面是一些 exports 常用条目的举例:

  1. # 针对目标域名的共享(假设共享目录为 /myshare)
  2. /myshare server0.example.com
  3. /myshare *.example.com
  4. /myshare server[0-10].example.com
  5. # 针对目标IP地址的共享
  6. /myshare 172.25.11.11
  7. /myshare 172.25.0.0/24
  8. # 一个目录可以共享给多个目标,中间用空格隔开
  9. /myshare *.example.com 172.25.0.0/24
  10. # 可以为共享的目标主机指定权限,ro表示只读,rw表示读写
  11. /myshare *.example.com(ro) 172.25.0.0/24(rw)
  12. # 所有主机可读
  13. /myshare *(ro)
  14. # 对客户端 root 用户的权限处理
  15. # no_root_squash:登入 NFS 主机使用分享目录的使用者,如果是 root 的话,
  16. # 那么对于这个分享的目录来说,他就具有 root 的权限!(可能不安全)
  17. # 一般不建议使用!多用于无盘工作站
  18. # root_squash:默认值,在登入NFS的使用者如果是 root 时,将被视为nfsnobody
  19. /myshare diskless.example.com(rw, no_root_squash)
  20. /myshare server0.example.com(rw, root_squash)
  21. # sync(同步) 和 async(异步)
  22. # sync 适用于实时性要求高的场合,在1.0.0版本之后是默认值。
  23. # async 适用于远程挂载点处大批量数据生成,如解压较大的压缩包,可以适当提升性能。
  24. # NFS服务器可能会在写入磁盘前就响应客户端请求,在系统异常时,可能产生数据丢失的情况。
  25. /myshare *(ro,async)

下面还有一些其他选项:

  1. all_squash:将远程访问的所有普通用户及所属组都映射为匿名用户或用户组(nfsnobody);
  2. no_all_squash:与all_squash取反(默认设置);
  3. root_squash:将root用户及所属组都映射为匿名用户或用户组(默认设置);
  4. no_root_squash:与rootsquash取反;如果是本地root登录,nfs也给root权限,不安全,无盘工作站用
  5. # 英文单词squash有抑制的意思
  6. anonuid=xxx:将远程访问的所有用户都映射为匿名用户,并指定该用户为本地用户(UID=xxx);
  7. anongid=xxx:将远程访问的所有用户组都映射为匿名用户组账户,并指定该匿名用户组账户为本地用户组账户(GID=xxx);
  8. secure:限制客户端只能从小于1024tcp/ip端口连接nfs服务器(默认设置);
  9. insecure:允许客户端从大于1024tcp/ip端口连接服务器;
  10. sync:将数据同步写入内存缓冲区与磁盘中,效率低,但可以保证数据的一致性;
  11. async:将数据先保存在内存缓冲区中,必要时才写入磁盘;
  12. wdelay:检查是否有相关的写操作,如果有则将这些写操作一起执行,这样可以提高效率(默认设置);
  13. no_wdelay:若有写操作则立即执行,应与sync配合使用;
  14. subtree:若输出目录是一个子目录,则nfs服务器将检查其父目录的权限(默认设置);
  15. no_subtree:即使输出目录是一个子目录,nfs服务器也不检查其父目录的权限,这样可以提高效率。

编辑 exports 文件之后,需要运行 exportfs -r 命令来应用更改。

防火墙配置参考

对NFSv4来说,需要使用的是TCP/2049端口,这样防火墙配置比较简单:
firewall-cmd —add-service=nfs —permanent
firewall-cmd —reload

但一般安装NFS时默认也支持NFSv3,在客户端不支持NFSv4时会使用NFSv3连接,这样的情况下还须通过动态端口号使用RPC服务,而RPC服务还须监听TCP/UDP 111端口。而且还要授予mountd服务的访问权,所以NFSv3需要允许如下的服务:
firewall-cmd —add-service=nfs —add-service=rpc-bind —add-service=mountd —permanent
firewall-cmd —reload

客户端挂载

Linux上挂载NFS

mount -t nfs -o async 172.25.11.10:/myshare /mnt

可能会遇到报错:
mount.nfs: Operation not permitted
最终在加入 insecure 参数后成功挂载
/myshare 172.25.11.11(rw,insecure)

挂载完成后通过showmount命令可以查看
showmount -e
Export list for test1:
/myshare 172.25.11.11

此时对挂载目录内的文件进行写入,发现没有写入权限(nfsnobody)
最终在加入 no_root_squash 参数后成功写入
/myshare 172.25.11.11rw,insecure,no_root_squash)

而且查看写入数据的用户:
-rw-r—r— 1 root root 58 May 1 23:22 date.txt
果然是本地 root 会被映射为服务器的 root 用户,稍微有点不安全。

不过非root用户就无法写入了(sudo 也不行)。
更高级别的安全可能需要搭配 Kerberos 身份验证配置才可以了。

Windows上挂载NFS

Windows上挂载NFS时首先要在:控制面板>程序>启用或关闭Windows功能 页面中将NFS客户端启用。
image.png

然后使用mount命令挂载:
C:\Users\fly12>mount 172.25.11.10:/myshare g:
g: 现已成功连接到 172.25.11.10:/myshare

或者还可以通过图形界面来映射网络驱动器:
image.png
image.png
有时候可能遇到报错:
网络错误 - 53
主要是服务端或网络通信的问题,一般为网络防火墙或者 NFS 服务器没有 insecure 配置。这两点修正后问题解决。

NFS安全参考

https://tldp.org/HOWTO/NFS-HOWTO/security.html