Linux - NFS存储服务器

1.什么是NFS?

NFS: Network File System网络文件共享服务,最大的功能就是让不同的机器、不同的操作系统、可以彼此分享个别的档案,也可以看成一个文件服务器。

由于NFS支持的功能相当多,而不同的功能都会使用不同的程序来启动,而启动一个功能就会启动一个端口来传输数据,因此NFS的功能所对应的端口口才没有固定住,而是随机开启小于1024的端口作为传输之用,但如此又造成客户端想要联机服务器时的困扰,因为客户端要知道服务器的端口才能联机。

2.什么是RCP?

RPC(Remote Procedure Call)协议辅助,指定每个NFS功能所对应的port number,并且回报给客户端,让客户端可以连接到正确的端口。
RPC是一种不同的网络程序设计方法,客户程序编写时只是调用了服务器程序提供的函数。

  1. 当客户程序调用远程的过程时,它实际调用了本机上的、由RPC程序包生成的函数,这个函数称为残桩,客户残桩将过程的参数封装成一个网络报文,将报文发送到服务器程序。
  2. 服务器主机上的一个服务器残桩负责接收这个网络报文,它从网络报文中提取参数,然后调用应用程序员编写的服务器过程。
  3. 当服务器函数返回时,它返回到服务器残桩,服务器残桩提取返回值,把返回值封装成一个网络报文,并发送给客户残桩。
  4. 客户残桩接收到网络报文后取出返回值,返回给客户程序。

网络程序设计是通过残桩和API的RPC库来实现的,但用户程序–客户程序与被客户程序调用的服务器过程–不会与API打交道。客户应用程序只是调用服务器的过程。

RPC有两个版本:1.建立在API基础上,与TCP、UDP打交道。2.TI-RPC独立于运输层。

在这里插入图片描述

在这里插入图片描述
图1是RPC过程调用报文作为一个UDP数据报的格式,图2是RPC应答报文作为一个UDP数据报的格式

  • XID:事务标识符,由客户程序设置,由服务器程序返回。客户收到一个应答,它将服务器返回的XID与它发送的请求XID进行比较,不同则放弃。
  • call:调用变量,调用报文中设置为0,在应答报文中设置为1
  • RPC版本:当前版本为2
  • 程序号、版本号、过程号:标识服务器上被调用的特定过程
  • 证书:标识客户
  • 验证:DES加密安全的RPC
  • 过程参数:参数的格式依赖于远程过程的定义
  • XDR:外部数据表示,是一个标准。用来对RPC调用报文与应答报文中的值进行编码。

端口映射器:
包含远程过程的RPC服务器程序使用的是临时端口,需要某种形式的“注册” 程序来跟踪哪一个RPC程序使用了哪一个临时端口,这个注册的过程称为端口映射器。

端口映射器有一个知名端口:UDP111和TCP111。端口映射器也是一个RPC服务器程序,它有一个程序号、一个版本号、一个TCP端口号、一个UDP端口号。服务器程序使用RPC调用向端口号映射器注册自身,客户程序使用RPC调用向端口映射器查询,端口映射器提供4个服务过程:

  1. PMAPPROC_SET,一个RPC服务器启动时调用这个过程,注册一个程序号、一个版本号和带一个端口号的协议
  2. PMAPPROC_UNSET,RPC服务器调用此过程来删除一个已经被注册的映射
  3. PMAPPROC_GETPORT,一个RPC客户启动时调用此过程,根据一个给定的程序号、版本号、协议来获取注册的端口号。
  4. PMAPPROC_DUMP,返回端口映射器数据库中所有的记录

一个RPC服务器启动,一个RPC客户启动时调用此过程,有以下步骤:

  1. 端口映射器先启动,创建一个TCP端点,主动打开TCP111端口,创建一个UDP端点,主动打开UDP111端口;
  2. 当RPC服务器程序启动时,它为它所支持的程序的每一个版本创建一个TCP端点和UDP端点,两个端点都绑定一个端口,服务器通过调用端口映射器的PAMAPPROC_SET过程,注册每一个程序、版本、协议和端口号。
  3. 当RPC客户程序启动时,它调用端口映射器的PAMAPPROC_GETPORT过程获得一个指定程序、版本和端口号。
  4. 客户发送一个RPC调用报文给第3步返回的端口号,如果使用UDP,客户只是发送一个包含RPC调用报文的UDP数据报到服务器相应的UDP端口,服务器发送一个包含RPC应答报文的UDP数据报到客户作为响应。

3.NFS协议

NFS是一个使用sun RPC构造的客户服务器应用程序,NFS客户通过向一个NFS服务器发送RPC请求来访问其上的文件。

文件句柄:用来引用服务器上的文件或目录,服务器创建文件句柄,把它传给客户,然后客户访问文件,使用文件句柄。

文件句柄存储:文件系统标识符、i-node号、i-node生成码。

安装协议:挂载,客户必须在访问服务器上一个文件系统中的文件时,使用安装协议安装那个文件系统。在客户主机上完成此过程,最后的结果是客户获得服务器文件系统的一个文件句柄。

使用mount命令的安装协议,如下图:

在这里插入图片描述
步骤:

  1. 服务器上的端口映射器一般在服务器启动时被启动
  2. 安装守护程序mountd在端口映射器之后被启动,它创建一个TCP端点和UDP端点,并分配一个端口,在端口映射器中注册这些端口
  3. 在客户端执行mount命令,它向服务器上端口映射器发出一个RPC调用获取服务器上安装守护程序的端口号
  4. 端口映射器应答以安装程序的端口号
  5. mount命令向安装程序发送一个RPC调用来安装服务器上的一个文件系统
  6. 安装守护程序应答以指定文件系统的文件句柄
  7. 客户机上的mount命令发出mount系统调用将第5步返回的文件句柄与客户机上的一个本地安装点联系起来。文件句柄被存储在NFS客户代码中,从现在开始,用户进程对于那个服务器文件系统的任何引用都将从使用这个文件句柄开始。

当NFS服务启动时,会随机启动数个port,并主动想RPC注册,因此RPC知道每个port对应的NFS的功能,然后RPC又是固定port11来监听客户端的需求并回报客户端正确的端口,这样NFS就正常的工作了。

  1. 当客户端向服务器RPC发出NFS存取功能询问后
  2. 服务器找到已经注册的NFS服务端口后,会回报给客户端
  3. 客户端了解正确的端口后,直接连接NFS服务器

NFS客户端:一般是web服务器,通过挂载的方式将NFS服务器上的某个共享服务器挂载到客户端,看起来就像是客户端下的一个目录。

NFS服务器用于共享存储。

先启动RPC服务,再启动NFS服务,向RPC进行注册,RPC就知道每个port对应的NFS的功能。而RPC固定port111来监听客户端的请求并回报客户端正确的端口。

搭建NFS存储服务器

NFS服务器所需软件

  1. RPC主程序:rpcbind
  2. NFS主程序:nfs-utils
[root@www1 ~]# cat /etc/redhat-release   #查看当前系统发行版
CentOS release 6.5 (Final)
[root@www1 ~]# uname  -a    #查看系统内核信息
Linux www1 2.6.32-431.el6.x86_64 #1 SMP Fri Nov 22 03:15:09 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux

[root@www1 ~]#  yum install nfs-utils rpcbind -y  #安装rpcbind nfs
[root@www1 ~]# rpm -qa | grep nfs
nfs4-acl-tools-0.3.3-8.el6.x86_64
nfs-utils-lib-1.1.5-13.el6.x86_64
nfs-utils-lib-devel-1.1.5-13.el6.x86_64
nfs-utils-1.2.3-75.el6.x86_64
[root@www1 ~]# rpm -qa | grep rpcbind
rpcbind-0.2.0-13.el6_9.1.x86_64
[root@www ~]#
[root@www11 ~]# /etc/init.d/rpcbind start            #启动rpc
正在启动 rpcbind:                                         [确定]
[root@www1 ~]# netstat -lantup | grep rpcbind                                        #查看rpc的主端口111
tcp        0      0 0.0.0.0:111                 0.0.0.0:*                   LISTEN      2599/rpcbind
tcp        0      0 :::111                      :::*                        LISTEN      2599/rpcbind
udp        0      0 0.0.0.0:111                 0.0.0.0:*                               2599/rpcbind
udp        0      0 0.0.0.0:654                 0.0.0.0:*                               2599/rpcbind
udp        0      0 :::111                      :::*                                    2599/rpcbind
udp        0      0 :::654                      :::*                                    2599/rpcbind
[root@www1 ~]# rpcinfo -p    #查看rpc启动的端口,都是主程序的端口,因为nfs还未向rpcbind进行注册
   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
[root@www1 ~]# /etc/init.d/nfs start            #启动nfs
启动 NFS 服务:                                            [确定]
启动 NFS mountd:                                          [确定]
启动 NFS 守护进程:                                        [确定]
正在启动 RPC idmapd:                                      [确定]
[root@www1 ~]# rpcinfo -p                        #再看rpcbind管理的端口
   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
    100005    1   udp  37383  mountd
    100005    1   tcp  59846  mountd
    100005    2   udp  54635  mountd
    100005    2   tcp  48766  mountd
    100005    3   udp  58293  mountd
    100005    3   tcp  40313  mountd
    100003    2   tcp   2049  nfs
    100003    3   tcp   2049  nfs
    100003    4   tcp   2049  nfs
    100227    2   tcp   2049  nfs_acl
    100227    3   tcp   2049  nfs_acl
    100003    2   udp   2049  nfs
    100003    3   udp   2049  nfs
    100003    4   udp   2049  nfs
    100227    2   udp   2049  nfs_acl
    100227    3   udp   2049  nfs_acl
    100021    1   udp  34573  nlockmgr
    100021    3   udp  34573  nlockmgr
    100021    4   udp  34573  nlockmgr
    100021    1   tcp  54386  nlockmgr
    100021    3   tcp  54386  nlockmgr
    100021    4   tcp  54386  nlockmgr
[root@www1 ~]# 
[root@www1 ~]# ps aux | grep -E "nfs|rpcbind"        #查看启动的进程有哪些?
rpc       2599  0.0  0.0  18976   904 ?        Ss   16:40   0:00 rpcbind
root      2648  0.0  0.0      0     0 ?        S    16:43   0:00 [nfsd4]
root      2649  0.0  0.0      0     0 ?        S    16:43   0:00 [nfsd4_callbacks]
root      2650  0.0  0.0      0     0 ?        S    16:43   0:00 [nfsd]
root      2651  0.0  0.0      0     0 ?        S    16:43   0:00 [nfsd]
root      2652  0.0  0.0      0     0 ?        S    16:43   0:00 [nfsd]
root      2653  0.0  0.0      0     0 ?        S    16:43   0:00 [nfsd]
root      2654  0.0  0.0      0     0 ?        S    16:43   0:00 [nfsd]
root      2655  0.0  0.0      0     0 ?        S    16:43   0:00 [nfsd]
root      2656  0.0  0.0      0     0 ?        S    16:43   0:00 [nfsd]
root      2657  0.0  0.0      0     0 ?        S    16:43   0:00 [nfsd]

NFS软件结构:

  1. 主要配置文件:/etc/exports,配置方法语法及参数
  • 需要共享的目录 单个主机/主机名/IP地址
  • 需要共享的目录 使用通配符指定机器系列
  • 需要共享的目录 IP网络 192.168.1.1/24
  • /tmp 172.16.4.5(rw)小括号内是权限
  1. NFS文件系统维护指令:/usr/sbin/exportfs
  • 维护NFS分享资源的指令,可以用这个指令重新分享/etc/exports变更的目录资源
  1. 分享资源的登录档:/var/lib/nfs/*tab
  • etab 记录NFS所分享出来的目录的完整权限设定值
  • xtab 记录曾经连接到此NFS服务器的相关客户端数据,centos6已经没有了
[root@www1 ~]# cat /var/lib/nfs/etab
/nfs_share      192.168.146.133(rw,sync,wdelay,hide,nocrossmnt,secure,root_squash,no_all_squash,no_subtree_check,secure_locks,acl,anonuid=65534,anongid=65534)
/nfs_share      192.168.146.134(rw,sync,wdelay,hide,nocrossmnt,secure,root_squash,no_all_squash,no_subtree_check,secure_locks,acl,anonuid=65534,anongid=65534)
  1. 客户端查询服务器分享资源的指令:/usr/sbin/showmount
[root@www1 ~]# vim /etc/exports
#share
/nfs_share 192.168.146.133(rw,sync) 192.168.146.134(rw,sync)
[root@www1 ~]# /etc/init.d/nfs reload    #需要平滑重启已加载配置文件exports

#NFS服务器www1使用showmount
[root@www1 ~]# showmount -e        #在nfs服务器看可挂载的目录
Export list for www1:
/nfs_share 192.168.146.134,192.168.146.133

#NFS客户端web1使用showmount
[root@web1 ~]# showmount -e 192.168.146.132
Export list for 192.168.146.132:
/nfs_share 192.168.146.134,192.168.146.133

启动NFS

[root@www1 ~]/etc/init.d/nfs start

设置开机自启动

[root@www1 ~]# systemctl enable nfs
[root@www1 ~]# systemctl enable rpcbind 

手动挂载NFS服务器分享的资源

  1. 确定客户端开启了rpcbind服务
  2. 扫描NFS服务器分享的的目录有哪些?并了解我们是否可以使用showmount -e nfs-ip命令
  3. 在客户端建立预计要挂载的挂载点或目录
  4. 利用mount将nfs服务器的直接挂载到相关目录
netstat -tulp | grep -E '(rpc|nfs)'
showmount -e 192.168.146.132
mount -t nfs 192.168.146.132:/nfs_share /data/nfs
  1. 自动挂载设置
  • 放在rc.local中
[root@www1 ~]# cat /etc/rc.local
#!/bin/sh
#
# This script will be executed *after* all the other init scripts.
# You can put your own initialization stuff in here if you don't
# want to do the full Sys V style init stuff.

mount -t nfs 192.168.146.132:/nfs_share /data/nfs
  • 在/etc/fstab中设置,但是由于linux开机是先挂载/etc/fstab中设备,再开启网卡。所以会无法自动挂载,但我们可以启动netfs服务,也可以实现。
[root@web2 ~]# tail -1 /etc/fstab
192.168.146.132:/nfs_share /data/nfs            nfs     defaults        0 0

nfs服务器配置文件中权限介绍:【即/etc/exports文件配置格式中小括号()里的参数集】

  • rw(readwrite):可读可写
  • ro(readonly):只读
  • sync:请求或写入数据时,数据同步到nfs服务器的硬盘才返回。优点数据不丢失,安全,性能差
  • async:先写入数据缓冲区,硬盘有空档才会写入,从而提供效率。但要保持服务器不当机不断电
  • no_root_squash:登陆到NFS主机,使用共享目录的用户,如果是root,那么对于这个目录他就具有root的权限了
  • root_squash:登陆到NFS主机,使用共享目录的用户如果是root,那么这个用户就被贬为匿名使用者,他的uid,gid都会变成nobody
  • all_squash:不管访问共享目录的身份如何,都是用nfsnobody
  • anonuid:指定匿名用户的uid
  • anongid:指定匿名组的gid

查看客户端的挂载参数(mount -t nfs的额外参数)

[root@web1 nfs]# cat /proc/mounts
192.168.146.132:/nfs_share/ /data/nfs nfs4 rw,relatime,vers=4,rsize=131072,wsize=131072,namlen=255,hard,proto=tcp,port=0,timeo=600,retrans=2,sec=sys,clientaddr=192.168.146.133,minorversion=0,local_lock=none,addr=192.168.146.132 0 0
  • hard:客户端会一直尝试与NFS服务器连接,直到挂载成功。在后台不给出任何提示。
  • soft: 会在前台尝试与NFS服务器的连接,当收到错误信息后终止mount尝试,并给出相关信息。
  • rsize/wsize: 文件传输尺寸设定:V3没有限定传输尺寸,V2最多只能设定为8k,可以使用-rsize and -wsize 来进行设定。这两个参数的设定对于NFS的执行效能有较大的影响
  • bg:在执行mount时如果无法顺利mount上时,系统会将mount的操作转移到后台并继续尝试mount,直到mount成功为止。(通常在设定/etc/fstab文件时都应该使用bg,以避免可能的mount不上而影响启动速度)
  • fg:和bg正好相反,是默认的参数
  • port:根据server端export出的端口设定,例如如果server使用5555端口输出NFS,那客户端就需要使用这个参数进行同样的设定
  • timeo=n:设置超时时间,当数据传输遇到问题时,会根据这个参数尝试进行重新传输。如果网络连接不是很稳定的话就要加大这个数值,并且推荐使用HARD MOUNT方式,同时最好也加上INTR参数,这样你就可以终止任何挂起的文件访问。
  • intr : 允许通知中断一个NFS调用。当服务器没有应答需要放弃的时候有用处。
  • udp:使用udp作为nfs的传输协议(NFS V2只支持UDP)
  • tcp:使用tcp作为nfs的传输协议
  • vers=n:设定要使用的NFS版本
  • mountport:设定mount的端口
  • namlen=n:设定远程服务器所允许的最长文件名。这个值的默认是255
  • acregmin=n:设定最小的在文件更新之前cache时间,默认是3
  • acregmax=n:设定最大的在文件更新之前cache时间,默认是60
  • acdirmin=n:设定最小的在目录更新之前cache时间,默认是30
  • acdirmax=n:设定最大的在目录更新之前cache时间,默认是60
  • actimeo=n:将acregmin、acregmax、acdirmin、acdirmax设定为同一个数值,默认是没有启用。
  • retry=n:设定当网络传输出现故障的时候,尝试重新连接多少时间后不再尝试。默认的数值是10000 minutes
  • noac:关闭cache机制

当然也可以有mount命令的额外参数哦~

  • -o options:(挂载文件系统的选项)
  • async:异步模式(提高性能,但数据安全有所降低,生产环境不建议使用)
  • sync:同步模式(数据安全又保障)
  • atime/noatime:每次访问数据时,会同步更新 访问文件的inode时间戳,会减低性能。高并发时建议使用noatime
  • diratime/nodiratime:目录的访问时间戳
  • auto/noauto:是否支持自动挂载
  • exec/noexec:是否支持文件系统执行二进制文件
  • dev/nodev:是否支持在此文件系统上使用设备文件
  • suid/nosuid:是否支持在此文件系统上使用特殊权限
  • remount:重新挂载
  • ro:只读
  • rw:可读写
  • user/nouser:是否允许普通用户挂载此设备
  • acl:启用此文件系统上的acl功能

注:每次修改完配置文件/etc/exports后要使用平滑重启nfs.或使用命令exportsfs -rv。

细节

NFS服务的用户身份映射

1.NFS的基本配置

NFS服务在CentOS7系统中默认已经安装,但并未运行,因而首先需要在虚拟机Server中执行“systemctl start nfs”命令启动服务,然后再执行“systemctl enable nfs”命令将服务设置为开机自动运行。
在服务器端新建一个/var/share目录,并在其中创建一个测试文件test.txt。

[root@server ~]# mkdir /var/share
[root@server ~]# echo 'hello,world!' > /var/share/test.txt

下面将/var/share目录设置为NFS共享,并允许所有客户端访问。
NFS服务的主配置文件是/etc/exports,在/etc/exports文件中,每一行定义一个共享目录。利用vi编辑器打开配置文件/etc/exports,在其中增加下面的一行:

[root@server ~]# vim /etc/exports
/var/share  *(ro,sync)

在设置项中,“/var/share”表示要共享的目录,“”表示所有客户端都可以访问该共享目录,选项“ro”用于定义客户端的权限为read-only(只读),选项“sync”表示启用同步模式,可以将内存中的数据实时写入到磁盘中。
修改完配置文件之后,重启NFS服务生效。

[root@server ~]# systemctl restart nfs

然后在客户端就可以将共享目录挂载到本地使用。

[root@client ~]# mkdir /mnt/nfs                                 #创建挂载点目录
[root@client ~]# mount -t nfs 192.168.80.10:/common /mnt/nfs        #挂载共享目录
[root@client ~]# ls /mnt/nfs                                    #查看共享目录中的文件
test.txt

由于NFS服务本身并不具备用户身份验证的功能,而仅支持基于客户端IP进行认证。也就是说,我们在对NFS服务进行权限设置时,不能针对用户来分配权限,而只能针对客户端IP进行权限分配。所以如果希望IP地址为192.168.80.101的客户端可以对共享目录执行写入操作,那么可以在服务器端对配置文件进行如下修改,添加客户端的IP,并设置权限选项为“rw(read-write)”:

[root@server ~]# vim /etc/exports
/var/share  *(ro,sync)   192.168.80.101(rw,sync)

修改完成后,需要重启NFS服务生效。但是如果NFS共享正在被某些服务器使用的话,那么NFS服务是不允许随便重启的,所以在CentOS系统中提供了exportfs命令,可以在不重启NFS服务的情况下,重新加载/etc/exports文件,使得新的设置项生效。exportfs命令的常用选项有:-a(全部挂载或全部卸载)、-r(重新挂载)、-v(显示详细信息),通常都是将这三个选项组合使用。下面通过exportfs命令使得我们刚才所做的设置生效。

[root@server ~]# exportfs -arv
exporting 192.168.80.101:/var/share
exporting *:/var/share

在客户端先将共享目录卸载,然后再重新挂载,以使得服务器端的设置生效。但在对共享目录进行写入测试时失败。

[root@Client ~]# umount /mnt/share                          #卸载共享目录
[root@Client ~]# mount 192.168.80.10:/var/share /mnt/share      #重新挂载共享目录
[root@Client ~]# touch /mnt/share/a.txt                     #写入测试失败
touch: 无法创建"/mnt/share/a.txt": 只读文件系统

这是由于虽然在服务器端的配置文件/etc/exports中设置了允许用户对/var/share目录具有读写权限,但在操作系统层面,用户对/var/share目录却不具备写入权限。因而要实现对共享目录的写入操作,必须要保证在NFS服务和操作系统两个层面全部都具有写入权限才可以。
如何使得客户端可以在操作系统层面对共享目录具有写入权限,这就要涉及到用户身份映射问题。

2.用户身份映射的原理

NFS服务虽然不具备用户身份验证的功能,但是NFS提供了一种身份映射的机制来对用户身份进行管理。当客户端访问NFS服务时,服务器会根据情况将客户端用户的身份映射成NFS匿名用户nfsnobody。nfsnobody是由NFS服务在系统中自动创建的一个程序用户账号,该账号不能用于登录系统,专门用作NFS服务的匿名用户账号。

[root@Server ~]# grep nfsnobody /etc/passwd        #查看nfsnobody用户的信息。
nfsnobody:x:65534:65534:Anonymous NFS User:/var/lib/nfs:/sbin/nologin

所谓用户身份映射,是指当客户端访问NFS服务器时,会自动被视作服务器中的nfsnobody用户,并按照该用户的权限设置去执行操作。但是并非所有的客户端都会被映射为nfsnobody用户,在/etc/exports配置文件中提供了以下选项,以决定是否将NFS客户端映射为nfsnobody用户:

  • root_squash,当NFS客户端以root用户身份访问时,映射为NFS服务器的nfsnobody用户。
  • no_root_squash,当NFS客户端以root身份访问时,映射为NFS服务器的root用户,也就是要为超级用户保留权限。这个选项会留下严重的安全隐患,一般不建议采用。
  • all_squash,无论NFS客户端以哪种用户身份访问,均映射为NFS服务器的nfsnobody用户。
    其中默认值是root_squash,即当客户端以root用户的身份访问NFS共享时,在服务器端会自动被映射为匿名账号nfsnobody。
    下面将分几种情况分别予以说明。
root用户的身份映射

我们之前之所以无法在客户端执行写入操作,是因为还没有在系统层面赋予nfsnobody用户对共享目录/var/share具有写入权限。这里通过设置ACL规则赋予nfsnobody用户rwx权限。

[root@Server ~]# setfacl -m u:nfsnobody:rwx /var/share

然后在客户端重新挂载共享目录,并测试能否写入。

[root@Client ~]# umount /mnt/share
[root@Client ~]# mount -t nfs 192.168.80.10:/var/share /mnt/share
[root@Client ~]# touch /mnt/share/b.txt

可以看到此时客户端可以写入,并且所创建文件的所有者正是nfsnobody。

[root@Client ~]# ll /mnt/share/b.txt
-rw-r--r--. 1 nfsnobody nfsnobody 0 3月  21 07:39 /mnt/share/b.txt

由于客户端当前所使用的用户身份是root,默认情况下,当客户端访问NFS服务器时,在服务器端会将其用户身份映射为nfsnobody,所以在服务器端只要赋予nfsnobody用户对共享目录具有写入权限,那么客户端自然就可以写入了。
下面我们再验证一下no_root_squash设置项,即root用户不进行身份映射。
首先在服务器端修改配置文件/etc/exports,为/var/share共享目录添加no_root_squash选项。

[root@server ~]# vim /etc/exports           #修改配置文件
/var/share *(rw,no_root_squash,sync)
[root@Server ~]# exportfs  -arv             #重新加载服务
exporting *:/var/share

然后去掉对共享目录/var/share所设置的ACL规则,取消nfsnobody用户对该目录的写入权限。

[root@Server ~]# setfacl -b /var/share

最后在客户端重新挂载共享目录,并测试能否写入。

[root@Client ~]# umount /mnt/share
[root@Client ~]# mount -t nfs 192.168.80.10:/var/share /mnt/share
[root@Client ~]# touch /mnt/share/c.txt
[root@Client ~]# ll /mnt/share/c.txt 
-rw-r--r--. 1 root root 0 4月  14 17:08 /mnt/share/c.txt

可以发现,此时客户端仍然是可以写入的。因为对于NFS服务器而言,访问共享目录的客户端就是服务器中的root用户,对共享目录具有完全权限。所以no_root_squash选项会产生很大的安全隐患,一般情况下都不建议采用。

普通用户的身份映射

如果客户端所使用的用户身份不是root,而是一个普通用户,那么默认情况下在服务器端会将其视作其它用户(other)。下面在客户端以普通用户的身份继续进行测试。
首先在服务器端修改配置文件/etc/exports,将共享目录/var/share中的no_root_squash选项去掉,重新加载服务之后,再次通过设置ACL规则的方式赋予nfsnobody用户读写执行权限。

[root@server ~]# vim /etc/exports       #修改配置文件
/var/share *(rw,sync)
[root@Server ~]# exportfs  -arv         #重新加载服务
exporting *:/var/share
#通过设置ACL赋予nfsnobody用户rwx权限
[root@Server ~]# setfacl -m u:nfsnobody:rwx /var/share

在客户端重新挂载共享,并测试以root用户身份可以正常写入。

[root@Client ~]# umount /mnt/share
[root@Client ~]# mount 192.168.80.10:/var/share /mnt/share
[root@Client ~]# touch /mnt/share/d.txt
[root@Client ~]# ll /mnt/share/d.txt 
-rw-r--r--. 1 nfsnobody nfsnobody 0 4月  14 17:29 /mnt/share/d.txt

下面在客户端创建一个admin用户,并设置密码。

[root@Client ~]# useradd admin
[root@Client ~]# echo 123 | passwd --stdin admin

切换到admin用户身份,尝试向共享目录中写入文件,写入失败,但是可以读取目录中的内容。因而如果客户端是以普通用户的身份访问NFS共享,那么默认情况下在服务器端并不将其映射为nfsnobody,而是视作其他用户(other)。

[root@Client ~]# su - admin
[admin@Client ~]$ touch /mnt/share/e.txt
touch: 无法创建"/mnt/share/e.txt": 权限不够
[admin@Client ~]$ cat /mnt/share/e.txt

下面在服务器端继续修改配置文件/etc/exports,在共享设置中添加“all_squash”选项,将所有客户端用户均映射为nfsnobody。

[root@server ~]# vim /etc/exports           #修改配置文件
/var/share *(rw,sync,all_squash)
[root@Server ~]# exportfs  -arv             #重新加载服务
exporting *:/var/share

然后在客户端再次重新挂载共享(具体操作从略),此时以admin用户身份就可以写入了,并且可以发现所创建文件的所有者同样是nfsnobody。

[admin@Client ~]$ touch /mnt/share/e.txt
[admin@Client ~]$ ll /mnt/share/e.txt 
-rw-rw-r--. 1 nfsnobody nfsnobody 0 4月  14 17:37 /mnt/share/e.txt
用户身份重叠

在使用NFS共享的过程中,有时还可能会遇到用户身份重叠的问题。所谓用户身份重叠,是指在NFS服务采用默认设置(用户身份映射选项为root_squash)时,如果在服务器端赋予某个用户对共享目录具有相应权限,而且在客户端恰好也有一个具有相同uid的用户,那么当在客户端以该用户身份访问共享时,将自动具有服务器端对应用户的权限。下面举例予以说明。

首先在服务器端将/var/share共享还原为默认设置,并且取消/var/share目录针对nfsnobody用户的ACL规则,具体操作从略。
假设服务器端存在一个名为teacher的用户账号,uid为1246,将该用户设置为共享目录的所有者。

[root@Server ~]# id teacher                 #查看teacher用户的身份信息`
uid=1246(teacher) gid=1246(teacher)=1246(teacher
#将teacher用户设置为/var/share目录的所有者
[root@Server ~]# chown teacher /var/share
[root@Server ~]# ll -d /var/share
drwxr-xr-x. 2 teacher root 45 4月  14 17:37 /var/share

下面在客户端进行操作。首先仍是重新挂载共享目录,然后将原先admin用户的uid也改为1246。

[root@Client ~]# usermod -u 1246 admin
[root@Client ~]# id admin
uid=1246(admin) gid=1002(admin)=1002(admin)

然后以admin用户身份测试能否对共享目录执行写入操作,发现可以正常写入,并且所创建文件的所有者是admin。

[root@Client ~]# su - admin
[admin@Client ~]$ touch /mnt/share/f.txt
[admin@Client ~]$ ll /mnt/share/f.txt
-rw-rw-r--. 1 admin admin 0 4月  14 17:47 /mnt/share/f.txt

在服务器端查看admin用户所创建的文件,发现所有者则是teacher。

[root@Server ~]# ll /var/share/f.txt 
-rw-rw-r--. 1 teacher 1002 0 4月  14 17:47 /var/share/f.txt

这是因为对于Linux系统而言,区分不同用户的唯一标识就是uid,至于用户名只是为了方便人类理解。所以在系统层面,无论是teacher用户还是admin用户,只要他们的uid一样,就认为是同一个用户。但也正是因为这个原因,才会导致出现用户身份重叠的问题,对于NFS服务而言,这也是一个比较严重的安全隐患。

如何避免用户身份重叠呢?可以从以下两个方面着手:

  • 一是在设置NFS共享时,建议采用“all_squash”选项,将所有客户端用户均映射为nfsnobody。这样就可以有效避免用户身份重叠的问题。
  • 二是应严格控制NFS共享目录的系统权限,尽量不用为普通用户赋予权限。

无法实现网路存储服务自动挂载原因

无法实现自动挂载与服务的启动顺序有关。nfs依赖于网络,如果网卡服务还未启动,而nfs先于网络服务启动,就会导致挂载失败。
Centos6:
每个服务的串行启动的。
根据系统服务启动顺序
按照顺序依次启动 network服务— sshd服务— crond服务— rsync服务— rpcbind服务— nfs服务
所以Centos6 要实现自动挂载,需要依赖autofs 或 netfs服务
先加载/etc/fstab — network服务 — autofs服务

Centos7:每个服务是并行启动的。最长时间由启动最慢的哪个服务决定。
要像实现自动挂载,需要安装 remote-fs.target

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值