Fork me on GitHub

Linux NFS配置

简介

NFS(Network File System)即网络文件系统。主要功能是通过局域网络让不同的主机系统之间可以共享文件或目录。NFS在文件传送或信息传送过程中依赖于RPC协议。NFS存储文件系统简单易用、方便部署、数据可靠、服务稳定;存放的数据都在文件系统之上,所有数据都是能看得见。但存在单点故障, 构建高可用维护麻烦;且客户端挂载无账号密码设置及数据明文,导致安全性一般。

RPC协议介绍

RPC(Remote Procedure Call)远程过程调用,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。其工作在TCP/UDP的111端口。建立在Socket之上的,主要是简化编程的工作在底层提供网络之间的通信。当客户端尝试使用RPC Server所提供的服务时,由于Client需要取得一个可以连接的端口(port)才能够使用RPC Server所提供的服务,因此,客户端首先去请求rpcbind,然后rpcbind将自己管理的端口映射告知客户端,好让客户端可以连接上服务,因此启动NFS之前,一定要先启动rpcbind。
NFS系统守护进程(rpc.nfsd和rpc.mountd):
rpc.nfsd∶
这个 daemon 主要的功能即管理客户端是否能够登入主机的权限
rpc.mountd
这个 daemon 主要的功能即管理 NFS 的档案系统。当客户端顺利通过 rpc.nfsd 而登入主机之后,在他可以使用 NFS 服务器提供的档案之前,还要经过档案使用权限 (即-rwxrwxrwx 与 owner/group等权限) 的认证程序!除此之外还要根据NFS的设定档 /etc/exports 来比对 Client 的权限,当都通过这些权限设置之后客户端即可取得使用NFS档案的权限

环境准备

NFS服务端 CentOS7.4 192.168.1.60
NFS客户端 CentOS7.4 192.168.1.76 

安装NFS与配置

NFS的常用目录:

/etc/exports        #NFS服务的主要配置文件
/usr/sbin/exportfs  #NFS服务的管理命令
/usr/sbin/showmount #客户端的查看命令
/var/lib/nfs/etab   #记录NFS分享出来的目录的完整权限设定值
/var/lib/nfs/xtab   #记录曾经登录过的客户端信息

服务端

安装服务端

检查下本地是否已经安装,如果安装则无需重复安装包:

rpm -qa | grep rpcbind
rpm -qa | grep nfs

CentOS系统:

#CentOS系统服务端
yum -y install nfs-utils
yum -y install rpcbind 

Ubuntu系统:

#Ubuntu服务端
apt-get install nfs-kernel-server

将服务加入开机自启动,并启动服务:

systemctl enable rpcbind nfs-server
systemctl start rpcbind nfs-server

查看nfs服务向rpc注册的端口信息(当前nfs-server未启动,所有没有注册端口):

[root@localhost ~]# rpcinfo -p
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

如果此时启动nfs,可以发现nfs随机注册的端口如下(对于此种情况下,如果未开启防火墙,随机端口是没有问题的,一旦开启就需要将端口固定下来了):

[root@localhost ~]# rpcinfo -p
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  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
100003    4   tcp   2049  nfs
100227    3   tcp   2049  nfs_acl
100003    3   udp   2049  nfs
100003    4   udp   2049  nfs
100227    3   udp   2049  nfs_acl
100021    1   udp  37045  nlockmgr
100021    3   udp  37045  nlockmgr
100021    4   udp  37045  nlockmgr
100021    1   tcp  39375  nlockmgr
100021    3   tcp  39375  nlockmgr
100021    4   tcp  39375  nlockmgr

防火墙配置

NFS的防火墙很难设定规则,除了固定的nfs2049、portmapper111之外, 还有很多不固定的端口是由rpc.mountd, rpc.rquotad等服务所开启的。因此我们需要在/etc/sysconfig/nfs指定特定的端口,这样每次启动nfs时,相关服务启动的端口就会固定,如此即可设置防护墙!

固定nfs服务端口

固定端口nfs 2049、portmapper 111,另外3个服务端口可设置为mountd 892、rpc.statd 662、 nlockmgr 32803、32769

配置:
1.修改/etc/sysconfig/nfs文件,将下列内容的注释去掉,如果没有则添加:

# TCP port rpc.lockd should listen on.
LOCKD_TCPPORT=32803
# UDP port rpc.lockd should listen on.
LOCKD_UDPPORT=32769

# Port rpc.mountd should listen on.
MOUNTD_PORT=892

# Port rpc.statd should listen on.
STATD_PORT=662
# Outgoing port statd should used. The default is port
# is random
STATD_OUTGOING_PORT=2020

端口配置完成后查看(注意重启nfs与服务器):

[root@localhost ~]# rpcinfo -p
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    892  mountd
100024    1   udp    662  status
100005    1   tcp    892  mountd
100024    1   tcp    662  status
100005    2   udp    892  mountd
100005    2   tcp    892  mountd
100005    3   udp    892  mountd
100005    3   tcp    892  mountd
100003    3   tcp   2049  nfs
100003    4   tcp   2049  nfs
100227    3   tcp   2049  nfs_acl
100003    3   udp   2049  nfs
100003    4   udp   2049  nfs
100227    3   udp   2049  nfs_acl
100021    1   udp  32769  nlockmgr
100021    3   udp  32769  nlockmgr
100021    4   udp  32769  nlockmgr
100021    1   tcp  32803  nlockmgr
100021    3   tcp  32803  nlockmgr
100021    4   tcp  32803  nlockmgr
CentOS7下配置

编辑文件 /etc/firewalld/zones/public.xml:

#vim /etc/firewalld/zones/public.xml
<?xml version="1.0" encoding="utf-8"?>
<zone>
  <short>Public</short>
  <description>For use in public areas. You do not trust the other computers on networks to not harm your computer. Only selected incoming connections are accepted.</description>
  <service name="ssh"/>
  <service name="http"/> 
  <service name="https"/> 
  <port protocol="tcp" port="8080"/>
  <port protocol="tcp" port="22"/>
  <port protocol="tcp" port="111"/>
  <port protocol="tcp" port="662"/>
  <port protocol="tcp" port="892"/>
  <port protocol="tcp" port="2049"/>
  <port protocol="tcp" port="32803"/>
  <port protocol="udp" port="111"/>
  <port protocol="udp" port="662"/>
  <port protocol="udp" port="892"/>
  <port protocol="udp" port="2049"/>
  <port protocol="udp" port="32769"/>
</zone>

注意重启防火墙

创建共享目录

创建服务端共享目录,例如:

mkdir /data   

NFS共享目录文件配置

/etc/exports文件内容:

#vi /etc/exports
/data     192.168.1.76(rw,sync,secure,no_root_squash,no_all_squash)

以上配置分为三个部分:

第一部分就是本地要共享出去的目录。
第二部分为允许访问的主机(可以是一个IP,一个IP段如192.168.0.0/24、192.168.0.0/255.255.255.0,指定域名的主机 www.example.com ,指定域中的所有主机 .example.com ,所有主机)。
第三部分小括号里面的,为一些权限选项。权限说明:

rw :读写;
ro :只读;
sync :同步模式,内存中数据时时写入磁盘
async :不同步,把内存中数据定期写入磁盘中
secure :nfs通过1024以下的安全TCP/IP端口发送
insecure :nfs通过1024以上的端口发送
no_root_squash:NFS客户端连接服务端时如果使用的是root的话,那么对服务端分享的目录来说,
            也拥有root权限。 显然开启这项是不安全的
root_squash:当客户端登陆NFS的身份为root用户时,将客户端的root用户及所属组都映射为匿名用户
            或用户组(默认设置), 通常使用nobody或nfsnobody身份
subtree:若输出目录是一个子目录,则nfs服务器将检查其父目录的权限(默认设置)。
no_subtree:即使输出目录是一个子目录,nfs服务器也不检查其父目录的权限,这样可以提高效率
no_all_squash :无论客户端登陆NFS的身份为何,都将映射为root用户(默认设置)
all_squash :不论NFS客户端连接服务端时使用什么用户,对服务端分享的目录来说都是拥有匿名用户权限;
anonuid:匿名用户的UID值,通常是nobody或nfsnobody,可以在此处自行设定
anongid:匿名用户的GID值

配置完成后,重新加载nfs配置(exportfs -rv)或重启nfs服务。

exportfs [-aruv]
参数说明:
-a  全部挂载(或卸载)/etc/exports文件内的设定
-r  重新挂载/etc/exports中的设置,此外同步更新/etc/exports及/var/lib/nfs/xtab中的内容
-u  卸载某一目录
-v  在export时将共享的目录显示在屏幕上

例如:

[root@localhost /]# exportfs -rv
exporting 192.168.1.76:/data

服务端验证

通过showmount -e命令如果正常显示共享目录,表示安装正常:

[root@localhost ~]# showmount -e localhost
Export list for localhost:
/data 192.168.1.76

如果客户端已经挂载了目录,在服务端通过showmount -a命令可显示NFS客户端信息和共享目录(包含历史信息)

[root@localhost ~]# showmount -a localhost
All mount points on localhost.localdomain:
192.168.1.76:/data

注意:挂载时如果未指定nfsvers版本,默认使用nfs支持的最新版本,目前为ver=4,如果使用此版本, showmount -a将不会显示NFS客户端信息和共享目录

客户端

安装客户端NFS

检查下本地是否已经安装,如果安装则无需重复安装包:

rpm -qa | grep nfs

CentOS系统:

#CentOS系统客户端
yum -y install nfs-utils

Ubuntu系统:

#Ubuntu客户端
apt-get install nfs-common

启动rpcbind,无需启动nfs:

systemctl start rpcbind 

挂载NFS共享目录

1、查看showmount -e IP来查看NFS共享状态:

[root@localhost /]# showmount -e 192.168.1.60
Export list for 192.168.1.60:
/data 192.168.1.76

2、挂载NFS共享目录

1)创建服务端共享目录,例如:

mkdir /test

2)挂载目录

#临时挂载,即时生效
mount -t nfs -o nfsvers=3 192.168.1.60:/data /test

#配置永久挂载nfs文件系统,保存后重启服务器即可生效
$ vim /etc/fstab
$ 192.168.1.60:/data /test nfs defaults,nfsvers=3 0 0  

客户端执行nfsstat -m命令,查看当前所使用的nfs版本:

[root@localhost ~]# nfsstat -m
/data from 192.168.1.60:/data
 Flags:    rw,relatime,vers=3,rsize=262144,wsize=262144,namlen=255,hard,
 proto=tcp,timeo=600,retrans=2,sec=sys,mountaddr=192.168.1.60,mountvers=3,
 mountport=892,mountproto=udp,local_lock=none,addr=192.168.1.60

3)查看挂载是否成功:

[root@localhost /]# df -h
Filesystem               Size  Used Avail Use% Mounted on
devtmpfs                 994M     0  994M   0% /dev
tmpfs                   1000M  8.4M  992M   1% /run
/dev/mapper/centos-root  6.7G  3.5G  3.2G  53% /
/dev/sda1                497M  118M  380M  24% /boot
192.168.1.60:/data       6.2G  4.5G  1.8G  72% /test

常用命令

nfsstat

查看NFS的运行状态,对于调整NFS的运行有很大帮助:

nfsstat -s #查看服务端的情况
nfsstat -c #查看客户端的情况

exportfs

启动了NFS之后又修改了/etc/exports,使用exportfs命令来使改动立刻生效

rpcinfo

查看rpc执行信息,可以用于检测rpc运行情况的工具

实例

实例一

服务端NFS配置:

#vi /etc/exports
/data  192.168.1.76(rw,sync,secure,no_root_squash,no_all_squash)

客户端创建文件:touch a,客户端显示如下:

[root@localhost test]# touch a
[root@localhost test]# ls -al 
total 4
drwxr-xr-x.  2 root root   15 Feb 24 20:52 .
dr-xr-xr-x. 19 root root 4096 Feb 24 20:51 ..
-rw-r--r--.  1 root root    0 Feb 24 20:52 a

服务端”/data”显示如下:

[root@localhost /]# ls -al /data
total 0
drwxr-xr-x.  2 root root  15 Feb 24 20:52 .
dr-xr-xr-x. 18 root root 236 Feb 19 00:43 ..
-rw-r--r--.  1 root root   0 Feb 24 20:52 a

实例二

服务端NFS配置:

#vi /etc/exports
/data  192.168.1.76(rw,sync,secure,root_squash)

此时服务端”/data”的权限:

[root@localhost /]# ls -al | grep data
drwxr-xr-x.   2 root root   15 Feb 24 20:52 data    

客户端创建文件:touch b,客户端显示如下:

[root@localhost test]# touch b
touch: cannot touch 'b': Permission denied

此时客户端是不能创建,主要是因”/data”的权限:所在组group和其他用户other的权限不能写,需要修改权限:

[root@localhost /]# chmod go+w /data
[root@localhost /]# ls -al | grep data
drwxrwxrwx.   2 root root   15 Feb 24 20:52 data

客户端再次创建文件:touch b,客户端显示如下:

[root@localhost test]# touch b
[root@localhost test]# ls -al 
total 4
drwxrwxrwx.  2 root      root        24 Feb 24 21:03 .
dr-xr-xr-x. 19 root      root      4096 Feb 24 20:51 ..
-rw-r--r--.  1 root      root         0 Feb 24 20:52 a
-rw-r--r--.  1 nfsnobody nfsnobody    0 Feb 24 21:03 b

服务端”/data”显示如下:

[root@bogon /]# ls -al /data
total 0
drwxrwxrwx.  2 root      root       24 Feb 24 21:03 .
dr-xr-xr-x. 18 root      root      236 Feb 19 00:43 ..
-rw-r--r--.  1 root      root        0 Feb 24 20:52 a
-rw-r--r--.  1 nfsnobody nfsnobody   0 Feb 24 21:03 b

实例三

服务端NFS配置:

创建group和user 
# groupadd -g 1000 jason
# useradd -u 1000 -g jason -M -s /bin/bash jason
设置共享目录权限
setfacl -m u:jason:rwx /data

#vi /etc/exports
/data  192.168.1.76(rw,sync,secure,all_squash,,anonuid=1000,anongid=1000))

此时服务端”/data”的权限:

[root@localhost /]# ls -al | grep data
drwxr-xr-x.   2 root root   15 Feb 25 12:41 data
[root@localhost /]# getfacl /data
getfacl: Removing leading '/' from absolute path names
# file: data
# owner: root
# group: root
user::rwx
group::r-x
other::r-x

[root@localhost /]# setfacl -m u:jason:rwx  /data
[root@localhost /]# getfacl /data
getfacl: Removing leading '/' from absolute path names
# file: data
# owner: root
# group: root
user::rwx
user:jason:rwx #多出来一个用户jason的权限rwx
group::r-x
mask::rwx
other::r-x

备注: ACL(Access Control List),主要的目的是在提供传统的 owner,group,others 的 read,write,execute 权限之外的细部权限配置
1)、setfacl可以更精确的控制权限的分配
2)、getfacl取得某个文件/目录的 ACL 配置项目

客户端创建文件:touch a,客户端显示如下:

[root@localhost test]# touch a
[root@localhost test]# ls -al
total 4
drwxrwxr-x.  2 root  root    15 Feb 25 12:39 .
dr-xr-xr-x. 19 root  root  4096 Feb 24 20:51 ..
#因客户端也存在uid和gid为1000的jason,所以用户和组都显示为jason,否则显示1000
-rw-r--r--.  1 jason jason    0 Feb 25 12:39 a 

服务端”/data”显示如下:

[root@localhost data]# ls -al
total 0
drwxrwxr-x+  2 root  root   15 Feb 25 12:41 .
dr-xr-xr-x. 18 root  root  236 Feb 19 00:43 ..
-rw-r--r--.  1 jason jason   0 Feb 25 12:41 a        
轻轻的我走了,正如我轻轻的来