NFS为Network File System 的简称,它的目的就算想让不同的机器、不同的操作系统可以彼此共享数据文件。
NFS这个通过网络共享文件的服务在搭建的时候是很简单的,不过,它最大的问题在于"权限"。因为在客户端与服务器端必须具备相同的账号才能够访问某些目录或文件。
另外,NFS的启动需要通过所谓的远程调用(RPC),也就是说,我们并不是只要启动NFS就可以了,还需要启动RPC这个服务才可以。
NFS就是 Network File System 的缩写,意思就是网络文件系统,最初是由 Sun 这家公司发展出来的,他最大的功能就是可以通过网络,让不同的机器、不同的操作系统可以共享彼此的文件
。所以,也可以简单地将它看做是一个文件服务器。这个NFS服务器可以让PC将网络中的NFS服务器共享的目录挂载到本地端的文件系统中,而在本地端的系统中看来,那个远程主机的目录就好像是自己的一个磁盘分区一样
,在使用上相当便利。
如上图,当NFS服务器配置好共享出来的 /home/sharefile 这个目录后,其他的NFS客户端就可以将这个目录挂载到自己的文件系统的某个挂载点(挂载点可以自定义)上。例如上图 NFS Client1 与 NFS Client2 挂载的目录就不相同。我只要在NFS Client 1 系统中进入 /home/data/sharefile 内,就可以看到NFS 服务器系统内的 /home/sharefile 目录下的所有数据了 (只要权限足够)。这个/home/data/sharefile 就好像NFS Client 1自己机器里面的一个分区,只要权限足够,就可以使用他。
NFS是一种用来共享文件的服务,它需要在服务器上开启一个特定的端口,一般是2049端口。但是因为文件系统很复杂,有时候NFS还需要启动其他的端口来传输数据,这些端口的号码是不确定的,可能是小于1024的任意一个端口。为了让客户端知道服务器端使用的是哪个端口,NFS会使用远程过程调用(RPC)协议来辅助。
NFS支持的功能相当多,而不同的功能都会使用不同程序来启动,每启动一个功能就会启用一些端口来传输数据,因此,NFS的功能所对应的端口并不固定,而是随机取用一些未被使用的小于1024的端口用于传输。但如此一来会产生客户端连接服务器的同题,因此客户端需要知道服务器端的相关端口才能够连接。
RPC最主要的功能就是指定每个NFS功能所对应的 port number ,并且通知给客户端,让客户端可以连接到正确的端口上去。那RPC又是如何知道每个NFS的端口呢?这是因为当服务器在启动NFS时会随机选取数个端口,并主动向RPC注册,因此RPC可以知道每个端口对应的NFS功能。然后RPC又是固定使用port 111来监听客户端的需求,并向客户端响应正确的端口,因此使NFS的启动更为快捷了
启动NFS之前,RPC就要先启动了,否则NFS会无法向RPC注册,另外,RPC若重新启动,原来注册的数据会不见,因此RPC重新启动后,它管理的所有服务都需要重新启动以重新向RPC注册
如上图所示,客户端有NFS文件访问需求时,它会如何向服务器端请求数据呢?
(1)客户端会向服务器端的RPC(port 111)发出NFS文件访问功能的查询要求
(2)服务器端找到对应的已注册的NFS daemon 端口后,会通知给客户端
(3)客户端了解正确的端口后,就可以直接与NFS daemon 连接
NFS服务器正在启动的时候需要向RPC注册,所以NFS服务器也称为RPC Server之一。那么NFS服务器主要的任务是进行文件系统的共享,而文件系统的共享是与权限有关的。所以NFS服务器启动时至少需要两个daemons,一个管理客户端是否能够登录的问题,一个管理客户端能够取得的权限。如果还想管理quota的话,那么NFS还需要再加载其他的RPC程序。
以功能单纯的NFS服务器来说,需要启动以下daemon
最主要的NFS服务提供程序。这个daemon 主要的功能就是管理客户端是否能够使用服务器文件系统挂载信息等
,其中还包含判断这个登录用户的ID
这个daemon主要的功能,则是在于管理NFS的文件系统。当客户端顺利地通过rpc.nfsd登录服务器后,再它可以使用NFS服务器提供的文件之前,还会经过文件权限(就是-rwxrwxrwx与owner,group 那几个权限)的认证程序。它会去读NFS的配置文件 /etc/exports来比对客户端的权限,当通过这一关之后客户端就可以取得使用NFS文件的权限了。(这个daemon也是我们用来管理NFS共享目录的权限与安全设置的地方)
这个daemon 可以用于管理文件的锁定(lock)方面。为何文件需要锁定呢?因为既然共享的NFS文件可以让客户端使用,那么当多各客户端同时尝试写入某个文件时,就可能对该文件造成一些问题。rpc.lockd则可以用来克服这些问题。但rpc.lockd必须要同时再客户端于服务器端都开启才行。此外,rpc.lockd也常与rpc.statd同时启动。
这个daemon 可以用来检查文件的一致性,于rpc.lockd有关。若发生因为客户端同时使用同一文件造成文件可能有所损毁时,rpc.statd 可以用来检测并尝试恢复该文件。与rpc.lockd一样,这个功能必须要在服务器端与客户端都启动才会生效。
既然要使用NFS,就需要安装NFS所需要的软件。下面查询以下是否安装了所需要的软件
NFS其实可以视为一个RPC服务,而要启动任何一个RPC服务之前,都需要做好port的对应工作才行,这个工作其实就是rpcbind服务负责的。也就是说,在启动任何一个RPC服务之前,我们都需要启动rpcbind才行
就是提供rpc.nfsd及rpc.mountd 这两个NFS daemons 与其他相关文件与说明文件、可执行文件等的软件。这个是NFS服务所需要的主要软件
我们只需要执行一条命令即可安装两个软件
[root@localhost ~]# yum install -y nfs-utils
查看是否安装了
[root@localhost ~]# rpm -qa |grep nfs
nfs-utils-1.3.0-0.68.el7.2.x86_64
[root@localhost ~]# rpm -qa |grep rpcbind
rpcbind-0.2.0-49.el7.x86_64
这个文件就是NFS的主要配置文件。
这个是维护NFS共享资源的命令,我们可以利用这个命令重新共享/etc/exports 更新的目录资源、将NFS Server 共享的目录卸载或重新共享等,这是NFS系统里面相当重要的一个命令
在NFS服务器中,日志文件都放置到 /var/lib/nfs/ 目录中,在该目录下有两个比较重要的日志文件,一个etab,主要记录了NFS所共享出来的目录的完整权限设置值,另一个是xtab,则记录了曾经连接到此NFS服务器的相关客户端的数据。
这是另一个重要的NFS命令。exportfs用在NFS Server 端,而showmount 则主要用在Client端。这个showmount可以用来查看NFS共享出来的目录资源。
至于NFS服务器的搭建很简单,你只要编辑好主要配置文件/etc/exports 之后,先启动rpcbind(若已经启动了,就不要重新启动),然后再启动NFS,NFS就成功了。
[root@localhost ~]# vim /etc/exports
/tmp 192.168.200.0/24(ro)localhost(rw) *.ev.ncku.edu.tw(ro,sync)
[共享目录] [第一台主机(权限)] [可用主机名表示] [可用通配符表示]
每一行最前面是要共享出来的目录,是以目录为单位的,然后这个目录可以依照不同的权限共享给不同的主机。
例如上面的例子,要将 /tmp 分别共享给 3 个不同的主机或网络。记得主机后面以小括号"()“定义权限参数,若权限参数不止一个时,则以逗号”,“分开,并且主机名与小括号是连载一起的。在这个文件内也可以利用”#"来进行注释。
至于主机名的设置主要有以下几种方式:
/etc/exports配置文件的权限参数
rw:可读写方式共享
ro:只读方式共享
sync:表示同步方式共享,服务器将写操作同步到硬盘之后再返回成功信息给客户端,可靠性更高,但效率较低。
async:表示异步方式共享,服务器将写操作放入缓存之后就返回成功信息给客户端,效率更高,但可靠性较低。
no_root_squash:表示客户端以root身份访问时,也具有root权限
root_squash:表示客户端以root身份访问时,root权限被限制为匿名用户权限
all_squash:不论登录NFS的用户身份为何,它的身份都会被压缩成为匿名用户。
anonuid:anon指的是"anonymous"(匿名用户)前面关于*_squash提到的匿名用户的UID设置值,你可以自行设置这个UID的值。当然这个UID必须存在于/etc/passwd当中
anongid:anonuid指定是UID而anongid则是组的GID
还有其他参数请查看man exports
例题
让root保留root的权限
假如想将 /tmp 共享出去给大家使用,由于这个目录本来就是大家都可以读写的,因此想让所有的人都可以访问。此外,要让root写入的文件还具有root的权限,那应该如何设置配置文件?
[root@localhost ~]# vim /etc/exports
/tmp *(rw,no_root_squash)
同一目录针对不同范围开放不同权限
假如要将一个公共的目录/home/public开放,但是需要限定在局域网 192.168.200.0/24这个网络且加入csqgroup的用户才能够读写,其他来源的用户则只能读取
[root@localhost ~]# mkdir /home/public
[root@localhost ~]# setfacl -m g:csqgroup:rwx /home/public
[root@localhost ~]# vim /etc/exports
/home/public 192.168.200.0/24(rw) *(ro)
仅给某个单一主机使用的目录设置
加入要将一个私人的目录/home/test开放给192.168.100.10 这个Client 端的机器来使用,该如何设置?假设具有完整的权限的用户是csq
[root@localhost ~]# mkdir /home/test
[root@localhost ~]# setfacl -m u:csq:rwx /home/test/
[root@localhost ~]# vim /etc/exports
/home/test 192.168.100.10(rw)
开放匿名访问的情况
假如要让 *.centos.csq 网络的主机,登录到NFS主机时,可以访问 /home/linux,但是在写入数据时,希望它们的UID与GID都变成45这个身份的用户,假设NFS服务器上的UID 45与GID 45的用户/组名为 nfsanon
[root@localhost ~]# groupadd -g 45 nfsanon
[root@localhost ~]# useradd -u 45 -g nfsanon nfsanon
[root@localhost ~]# mkdir /home/linux
[root@localhost ~]# setfacl -m u:nfsanon:rwx /home/linux/
[root@localhost ~]# vim /etc/exports
/home/linux *.centos.csq(rw,all_squash,anonuid=45,anongid=45)
配置文件搞定后,就可以启动NFS了,启动NFS还需要rpcbind的协助
[root@localhost ~]# systemctl start rpcbind.service
[root@localhost ~]# systemctl start nfs.service
启动之后,会出现一个port 111的 那就是rpcbind
接下来看看NFS到底开放了哪些端口
NFS开启了很多port,不过最主要的端口是:
rpcbind启动的port在111,同时启动在UDP与TCP
NFS本身的服务启动在port 2049上
其他rpc.* 服务启动的port 则是随机产生的,因此需向port 111注册
rpcinfo -p [IP|hostname]
rpcinfo -t|-u IP|hostname 程序名称
选项:
-p:针对某IP(未写则默认为本机)显示出所有的port与program的信息
-t:针对某主机的某个程序检查其TCP数据包所在的软件版本
-u:针对某主机的某支程序检查其UDP数据所在的软件版本
显示出目前这台主机的RPC状态
[root@localhost ~]# rpcinfo -p localhost
program vers proto port service
100000 4 tcp 111 portmapper
100000 3 tcp 111 portmapper
100000 2 tcp 111 portmapper
100000 4 udp 111 portmapper
100000 3 udp 111 portmapper
100000 2 udp 111 portmapper
100024 1 udp 60979 status
100024 1 tcp 43043 status
100005 1 udp 20048 mountd
100005 1 tcp 20048 mountd
100005 2 udp 20048 mountd
100005 2 tcp 20048 mountd
100005 3 udp 20048 mountd
100005 3 tcp 20048 mountd
100003 3 tcp 2049 nfs
.....
# 程序代号 NFS版本 数据包类型 端口 服务名称
针对nfs这个程序检查其他相关的软件版本信息(仅查看TCP数据包)
[root@localhost ~]# rpcinfo -t localhost nfs
program 100003 version 3 ready and waiting
program 100003 version 4 ready and waiting
# 可以发现提供NFS的版本共有二种,分别是2、3版
新的版本传输速度较快。如果rpcinfo无法输出,那就表示注册的数据有问题,需要重新启动rpcbind与nfs
在NFS服务器配置妥当之后,我们可以在Server端先自我测试一下是否可以连接。具体做法就是利用showmount这个命令来查看
showmount [-ae] [hostname|IP]
选项:
-a:显示当前主机与客户端的NFS连接共享的状态
-e:显示某台主机的 /etc/exports 所共享的目录数据
1. 显示出刚刚我们所设置号的相关exports共享目录信息
[root@localhost ~]# showmount -e localhost
Export list for localhost:
/home/test 192.168.100.10
NFS关于目录权限设置的数据非常之多,/etc/exports 只是比较特别的权限参数而已,还有很多默认参数,可以查看/var/lib/nfs/etab
[root@localhost ~]# cat /var/lib/nfs/etab
/home/test 192.168.100.10(rw,sync,wdelay,hide,nocrossmnt,secure,root_squash,no_all_squash,no_subtree_check,secure_locks,acl,no_pnfs,anonuid=65534,anongid=65534,sec=sys,rw,secure,root_squash,no_all_squash)
# 可以看到除了 rw、sync、root_squash
# 其实还有 anonuid 及 anongid 等的设置。
如果想要重新处理/etc/export文件,当重新设置完 /etc/exports 后需不需要重新启动NFS?不需要。如果重新启动NFS的话,要得再向RPC注册,很麻烦,这个时候通过exportfs这个命令帮忙
exportfs [-aruv]
选项:
-a:全部挂载(或卸载) /etc/exports 文件中的设置
-r:重新挂载 /etc/exports 里面的设置,此外,同步更新/etc/exports 及/var/lib/nfs/xtab内容
-u:卸载某一目录
-v:在export 的时候将共享的目录显示到屏幕上
重新挂载一次 /etc/exports 的设置
[root@localhost ~]# exportfs -arv
exporting 192.168.100.10:/home/test
将已经共享的NFS目录资源,全部都卸载
[root@localhost ~]# exportfs -auv
# 这时候再使用 showmount -e localhost 就看不到任何资源了
[root@nfs-server ~]# rpm -qa |grep nfs-utils
nfs-utils-1.3.0-0.68.el7.2.x86_64
[root@nfs-server ~]# rpm -qa |grep rpcbind
rpcbind-0.2.0-49.el7.x86_64
# 如果没有查到就要安装 yum install -y nfs-utils
[root@nfs-server ~]# systemctl start rpcbind
[root@nfs-server ~]# systemctl enable rpcbind
[root@nfs-server ~]# systemctl start nfs
[root@nfs-server ~]# systemctl enable nfs
# 一般来说系统默认会启动rpcbind,不过以防自己忘记,所以启动一下
[root@nfs-server ~]# mkdir /opt/linuxshare
[root@localhost ~]# vim /etc/exports
/opt/linuxshare 192.168.200.0/24(rw,sync,no_root_squash)
[root@nfs-server ~]# exportfs -arv
exporting 192.168.200.0/24:/opt/linuxshare
[root@nfs-server ~]# showmount -e 192.168.200.10
Export list for 192.168.200.10:
/opt/linuxshare 192.168.200.0/24 # 这个就是我们等下要挂载的目录!
[root@nfs-server ~]# firewall-cmd --add-service=nfs --permanent
[root@nfs-server ~]# firewall-cmd --reload
[root@nfs-server ~]# firewall-cmd --list-all
public (active)
target: default
icmp-block-inversion: no
interfaces: ens34
sources:
services: dhcpv6-client nfs ssh # 默认是没有放行nfs规则的
ports:
protocols:
masquerade: no
forward-ports:
source-ports:
icmp-blocks:
rich rules:
[root@nfs-client ~]# rpm -qa |grep nfs-utils
nfs-utils-1.3.0-0.68.el7.2.x86_64
[root@nfs-client ~]# rpm -qa |grep rpcbind
rpcbind-0.2.0-49.el7.x86_64
[root@nfs-client ~]# systemctl start rpcbind
[root@nfs-client ~]# systemctl enable rpcbind
[root@nfs-client ~]# systemctl start nfs
[root@nfs-client ~]# systemctl enable nfs
# 如果没有查到就要安装 yum install -y nfs-utils
[root@nfs-client ~]# mkdir /opt/linuxshare
[root@nfs-client ~]# mount -t nfs 192.168.200.10:/opt/linuxshare/ /opt/linuxshare/nfs/
[root@nfs-client ~]# df -h
文件系统 容量 已用 可用 已用% 挂载点
devtmpfs 3.8G 0 3.8G 0% /dev
tmpfs 3.9G 0 3.9G 0% /dev/shm
tmpfs 3.9G 12M 3.8G 1% /run
tmpfs 3.9G 0 3.9G 0% /sys/fs/cgroup
/dev/mapper/centos-root 50G 1.5G 49G 3% /
/dev/mapper/centos-home 42G 33M 42G 1% /home
/dev/sda1 1014M 151M 864M 15% /boot
tmpfs 781M 0 781M 0% /run/user/0
192.168.200.10:/opt/linuxshare 50G 1.5G 49G 3% /opt/linuxshare/nfs
这样就可以将数据挂载进来,需要注意的是NFS文件的格式。以后你进入/opt/linuxshare/nfs/ 目录就相当于进入了 192.168.200.10 远程主机的 /opt/linuxshare 目录。
[root@nfs-client ~]# umount /opt/linuxshare/nfs/
[root@nfs-client ~]# df -h
文件系统 容量 已用 可用 已用% 挂载点
devtmpfs 3.8G 0 3.8G 0% /dev
tmpfs 3.9G 0 3.9G 0% /dev/shm
tmpfs 3.9G 12M 3.8G 1% /run
tmpfs 3.9G 0 3.9G 0% /sys/fs/cgroup
/dev/mapper/centos-root 50G 1.5G 49G 3% /
/dev/mapper/centos-home 42G 33M 42G 1% /home
/dev/sda1 1014M 151M 864M 15% /boot
tmpfs 781M 0 781M 0% /run/user/0
# 挂载点没有了
客户端的挂载很简单,不过有个问题,如果你刚刚挂载到主机/opt/linuxshare/nfs 的文件系统中含有一个 script,而且这个script 的内容为 rm -rf /,文件权限为 555,如果你好奇执行了这个脚本,那就坏了,因为整个系统都会被删除
所以,NFS服务器需要保护之外,使用NFS文件系统也需要自我保护,那么如何自我保护?可以通过 mount 的命令参数实现
参数 | 参数意义 | 系统默认值 |
---|---|---|
suid nosuid |
当挂载的分区上面有任何SUID的二进制脚本程序时,只要使用nosuid就能够取消SUID的功能 | suid |
rw ro |
你可以指定该文件系统是只读或可读可写 | rw |
dev nodev |
是否可以保留设备文件的特殊功能?一般来说只有dev这个目录才会有特殊的设备,可以选择nodev | dev |
exec noexec |
是否具有执行 二进制文件的权限?如果要保护文件系统,最好不要允许用户进行挂载与卸载 | nouser |
user nouser |
是否允许用户进行文件的挂载与卸载操作?如果要保护文件系统,最好不要允许用户进行挂载与卸载。 | nouser |
auto noauto |
这个auto指的是mount -a 时,会不会被挂载到项目。如果不需要这个分区随时被挂载,可以设置为noauto | auto |
一般来说,如果是NFS服务器所提供的只是类似 /home下面的文件,应该不需要可以执行、SUID设备文件,因此在挂载的时候,可以使用这样的命令
[root@nfs-client ~]# mount -t nfs -o nosuid,noexec,nodev,rw 192.168.200.10:/home/data/ /home/data/nfs/
[root@nfs-client ~]# mount |grep addr
192.168.200.10:/home/data on /home/data/nfs type nfs4 (rw,nosuid,nodev,noexec,relatime,vers=4.1,rsize=1048576,wsize=1048576,namlen=255,hard,proto=tcp,timeo=600,retrans=2,sec=sys,clientaddr=192.168.200.20,local_lock=none,addr=192.168.200.10)
除了mount参数之外,其实针对NFS,Linux还提供了不少额外参数
参数 | 参数功能 | 默认参数 |
---|---|---|
fg bg |
当执行挂载时,该挂载的行为会在前台(fg)还是在后台(bg)执行?若在前台执行,则mount会持续尝试挂载,直到成功为止;若为后台执行,则mount会在后台持续多次进行mount,而不会影响到前台的程序允许。如果网络连接不稳定,或是服务器常常需要开关机,那简易使用bg比较妥当 | fg |
soft hard |
如果是hard情况,则当两者之间有任何一台主机脱机。则RPC会持续地呼叫,直到对方恢复连接为止。如果是soft的话,那RPC会在暂停后重复呼叫,非持续呼叫。同上,如果服务器开开关关建议使用soft | hard |
intr | 当使用上面提到的hard方式挂载时,若加上intr这个参数,则当RPC持续呼叫时,该次的呼叫是可以被中断的 | 无 |
更多参数查看man nfs
[root@nfs-client nfs]# mount -t nfs -o nosuid,noexec,nodev,rw -o bg,soft 192.168.200.10:/home/data/ /home/data/nfs/
则当 192.168.200.10 这台服务器因为某些原因脱机时,NFS可以继续在后台重复呼叫,直到NFS服务器再度上线为止。这对于持续性操作还是有用的!
修改 /etc/fstab 配置文件,加入 NFS 共享目录的挂载设置(文件系统类型为nfs)。
挂载参数建议添加_netdev(设备需要网络)
[root@nfs-client ~]# vi /etc/fstab
192.168.200.10:/home/data /home/data/nfs nfs defaults,_netdev 0 0
客户端的主机名或IP网段不被允许
服务器或客户端某些服务器未启动
被防火墙拦截
/etc/exports
这个文件/var/lib/nfs/etab
,至于日志文件可以参考/var/lib/nfs/xtab
:该文件记录了当前NFS服务器上所有活动的文件系统挂载点和客户端的连接信息/etc/exports
这个文件后,可以通过exportfs
这个命令来重新挂载共享目录rpcinfo
来查看RPC 程序之间的关系showmount 、 mount、umount
来使用NFS主机提供的共享目录bg、soft、nosuid、noexec、nodev
等来达到保护自己文件系统的目标_netdev
(设备需要网络)