一、简介


   NFS(Network File System/网络文件系统):



      1)、设置Linux系统之间的文件共享(Linux与Windows中间文件共享采用SAMBA服务);

2)、NFS只是一种文件系统,本身没有传输功能,是基于RPC协议实现的,才能达到两个Linux系统之间的文件目录共享;

3)、NFS为C/S架构;



二、依赖的服务和软件包



1、检查下列两个包是否已经安装(默认安装完RHEL或者CentOS系统,就已经安装了这两个软件包)


[root@Mylinux ~]# rpm -qa | grep 'portmap\|nfs-utils'


2、如果没有安装,现在就安装它们

[root@Mylinux ~]# yum install -y portmap nfs-utils


说明如下:

(1)nfs-utils套件

该套件提供 rpc.nfsd 及 rpc.mountd 这两个 NFS daemons 与其它相关 documents 与说明文件、执行档等的套件!所以它是 NFS 的主要套件

(2)portmap套件

NFS 其实可以被视为一个 RPC server program,而要激活任何一个 RPC server program 之前,我们都需要做好 port 的对应 (mapping)的工作才行,这个工作其实就是portmap这个服务所负责的!也就是说,在激活任何一个 RPC server 之前,需要激活 portmap ,那么 portmap 就是作 port 的 mapping 

例如:当 Client 端尝试来使用 RPC server 所提供的服务时,由于 Client 需要取得一个可以连接的 port 才能够使用 RPC server 所提供的服务,因此, Client 首先就会去跟 portmap 联系一个port number ,好让Client可以跟 RPC 联络,这个时候 portmap 就自动的将自己管理的 port mapping 告知 Client ,好让他可以连接上来 server!所以说:在激活 NFS 之前,要先激活portmap


既然nfs依赖于RPC,那么我们使用rpcinfo指令来查看一下本地rpc信息

[root@Mylinux ~]# service portmap start;   service nfs start;   rpcinfo -p localhost

rpc.nfsd---管理clinet是否有权限登录,以及判别登录者的uid等

rpc.mountd---读取/etc/exports的权限,对文件访问权限进行控制

rpc.lockd---文件的互斥锁,保证文件在同一时间只有一个人访问,需要nfslockd服务



rpc.statd---检查文件的一致性,需要nfslockd服务



三、服务端配置方法





1)配置服务器端的主配置文件/etc/exports


[root@Mylinux ~]# vim   /etc/exports


(1)语法格式

/etc/exports文件中每一行提供了一个共享目录的设置,其格式为如下:

+ 空格 + [hostname1或IP1(参数1,参数2.....)] + 空格 + [ hostname2或IP2(参数3,参数4....)]


(2)主要参数如下



rw

可读可写

ro

只读

sync

数据同步写入内存缓冲区与磁盘中,虽然这样做效率较低,但可以保证数据的一致性(适合于小文件传输)

async

数据先暂时放于内存,而非直接写入硬盘,等到必要时才写入磁盘(适合于大文件传输)

no_root_squash

使用nfs时,如果用户是root,不进行权限压缩,即root用户在nfs上创建的文件   属组和属主仍然是root(不安全,不建议使用)

root_squash

使用nfs时,如果用户是root,则进行权限压缩,即把root用户在nfs上创建的文件   属组和属主修改为nfsnobody

all_squash

所有的普通用户使用nfs都将使用权限压缩,即:将远程访问的所有普通用户及所属用户组都映射为匿名用户或者用户组(一般均为nfsnobody)

no_all_squash

所有的普通用户使用nfs都不使用权限压缩,即:不将远程访问的所有普通用户及所属用户组都映射为匿名用户或者用户组(默认设置)

anonuid=XXX

anon即anonymous(匿名者),前面关于*_squash提到的匿名用户的uid的设置值,通常为nobody或者nfsnobody,使用这个参数可以自行设定这个uid值,这个uid必须存在  于/etc/passwd

anongid=XXX

将远程访问的所有用户组都映身为匿名用户组账户,并指定该匿名用户组账户为本地用户组账户(GID=XXX)

insecure

允许客户端从大于1024的TCP/IP端口连NFS服务器

secure

限制客户端只能从小于1024的TCP/IP端口连接NFS服务器(默认设置)

wdelay

检查是否有相关的写操作,如果有则将这些写操作一起执行,这样可提高效率(默认设置)

no_wdelay

若有写操作则立即执行(应与sync配置)

subtree_check

若输出目录是一个子目录,则NFSW:务器将检查其父目录的权限(默认设置)

no_subtree_check

即使输出目录是一个子目录,NFS服务器也不检查其父目录的权限,这样做可提高效率



(3)设置实例

/tmp *(rw,no_root_squash)

在所有的IP(主机)上登录的用户都可对NFS服务器上的共享目录/tmp拥有rw操作权限,同时如果是root用户访问该共享目录,那么不将root用户及所属用户组都映射为匿名用户或用户组(*表示所有的主机或者IP)

/tmp *(rw)

在所有的IP(主机)登录的用户都可对NFS服务器上的共享目录/tmp拥有rw操作权限

/home/public 192.168.0.*(rw)   *(ro) 
/home/public 192.168.0.0/24(rw) *(ro)

除了在192. 168. 0.0/24这个网段内的主机上登录的用户,可对NFS服务器共享目录/home/public进行rw操作权限,而其它网段的主机上登录的用户,对NFS服务器共享目录/home/public只能进行r操作

/home/test 192.168.0.100(rw)

只对192.168.0.100该台主机设置权限,即:使在该台主机登录的用户都可对NFS服务器上的共享目录/home/test拥有读与写的操作

/home/linux *.linux.org(rw,all_squash,anonuid=40,anongid=40)

当*.linux.org(加入域linux.org的所有主机) 登陆此NFS主机,并且在/home/linux下面写入档案时,该档案的所有人与所有组,就会变成NFS服务器上的/etc/passwd文件里面对应的UID为40的那个身份的使用者了(因为指定了参数:all_squash,anonuid=40,anongid=40)



(4)权限问题

NFS服务器(192.168.0.2)上的/etc/exports配置文件设置如下
/tmp *(rw,no_root_squash)
/home/public 192.168.0.*(rw) *(ro)
/home/test 192.168.0.100(rw)
/home/linux *.linux.org(rw,all_squash,anonuid=40,anongid=40)

例如:我们在192.168.0.100这个client端登陆此NFS主机(192.168.0.2),那么会怎么样呢?

情况一: 在192.168.0.100的帐号为test这个身份,同时NFS主机上也有test这个帐号

(1)由于NFS主机的/tmp权限为-rwxrwxrwt,所以我(test在192.168.0.100上)在/tmp下面具有存取的权限,并且写入档案的所有人为test

(2)在/home/public中,由于我有读写的权限,如果NFS主机在/home/public这个目录的权限对于test开放写入的话,那么就可 以读写,并且写入档案的所有人是test。如果NFS主机的/home/public对于test这个使用者并没有开放写入权限时,那就无法写入,虽然 /etc/exports里面是rw,也不起作用

(3)在/home/test中,权限与/home/public有相同的状态,需要NFS主机的/home/test对于test有开放的权限

(4)在/home/linux当中,不论是何种的user,身份都会被变成UID=40的这个帐号

情况二: 如果我们在192.168.0.100的身份为test2,但是NFS主机却没有test2这个帐号时

(1)在/tmp下还是可以写入,但是写入的档案所有人变成nobody

(2)在/home/public与/home/test里面是否可以写入,还需要看/home/public的权限而定,不过身份就被变成nobody

(3)/home/linux下的身份还是变成UID=40的帐号

情况三:在192.168.0.100的身份为root     

(1)在/tmp里面可以写入,但是由于no_root_squash的参数,改变了预设的root_squash的设定值,所以在/tmp写入档案的所有人为root了

(2)在/home/public底下的身份被压缩成了nobody,因为预设的属性都具有root_squash,所以档案所有人就变成了nobody

(3)/home/test情况与/home/public相同

(4)/home/linux中,root的身份也被压缩成UID=40的那个使用者了

(5)启动nfslock、portmap、nfs服务,并查看日志是否正常的激活
[root@Mylinux ~]# service portmap start
[root@Mylinux ~]# service nfs   start
[root@Mylinux ~]# service nfslock start
[root@Mylinux ~]# tail -10 /var/log/messages
注意:启动这些服务的顺序

(6)客户端连接使用nfs
[root@Mylinux ~]# /etc/init.d/portmap start
[root@Mylinux ~]# /etc/init.d/nfslock    start
[root@Mylinux ~]# showmount -e 192.168.0.2

(7)exportfs与showmount指令的用法 

exportfs指令作用

用来维护NFS服务的共享目录列表的输出

exportfs指令语法
(exportfs [-aruv])

-a

全部mount或者unmount /etc/exports中内容(即:要被共享出来的目录)

-r

重新读取/etc/exports文件的设置,并使得设置立即生效,而不需要重新启动nfs服务

-u

停止输出某一个目录

-v

在输出目录时,将详细的信息输出到屏幕上

注意:当修改了/etc/exports配置文件,可以使用参数-r重新读取/etc/exports配置文件,使得设置立即生效,而不需要重启nfs服务

exportfs指令例子

#exportfs -rv //重新export一次
#exportfs -au //全部卸载
exporting 192.168.0.100:/home/test
exporting 192.168.0.*:/home/public
exporting *.the9.com:/home/linux
exporting *:/home/public
exporting *:/tmp
reexporting 192.168.0.100:/home/test to kerne

格式:showmount [-ae] hostname(IP)

-a

显示指定的NFS服务器的所有客户端主机及其所连接的目录(一般在NFS Server上使用该参数)

-e
-d

显示指定的NFS服务器上所有export出来的目录
显示指定的NFS服务器中已被客户端连接的所有export出来的目录

/var/lib/nfs/etab里面可以查看每个目录的分享权,例如:
/nfs *rw,sync,wdelay,hide,nocrossmnt,secure,root_squash,no_all_squash,no_subtree_check,secure_locks,acl,mapping=identity,anonuid=65534,anongid=65534)
对照一下 /etc/passwd ,你就会发现,65534这个UID的用户是nfsnobody

(9)启动和停止NFS服务
Section 1:启动NFS服务
[root@Mylinux ~]# service portmap start
[root@Mylinux ~]# service nfs start
[root@Mylinux ~]# service nfslock start
注意:它们的启动顺序,因为nfs服务是依赖于RPC服务的,而RPC服务又依赖于portmap服务,所以要先启动portmap,而最后一个nfslock服务是对nfs共享的文件的读定锁定,所以在启动nfs服务后再启动
Section 2:停止NFS服务
[root@Mylinux ~]# service nfslock start
[root@Mylinux ~]# service nfs start
[root@Mylinux ~]# service portmap start
Section 3:检测与重启NFS服务
[root@Mylinux ~]# /etc/init.d/nfs restart
[root@Mylinux ~]# /etc/init.d/nfs status
[root@Mylinux ~]# /etc/init.d/portmap status
Section 4:设置自动启动NFS服务
[root@Mylinux ~]# chkconfig --level 345 portmap on
[root@Mylinux ~]# chkconfig --level 345 nfs on









四、客户端配置方法



1、手动挂载NFS服务器的共享目录到NFS客户端



[root@Mylinux ~]# mount -t nfs hostname(orIP):/directory /mountpoint 
注意:为了担心会不小心将 NFS 端挂进来的具有 SUID 权限档案的程序执行,root可以将NFS 所分享的目录以较为安全的情况挂载进来,即:“ mount -t nfs -o nosuid,ro hostname:/directory /mountponit ”

挂载NFS系统文件的可选参数如下

soft

当服务器端没回应时,会在timeout后重新连接,传回错误信息

hard

当服务器端没回应时持续在后台尝试连接

intr

当正在进行 NFS 请求时,允许用键盘中断

nointr

当正在进行 NFS 请求时,不允许用键盘中断

timeo

请求过期时间,单位为秒

bg

当第一次请求不成功,第二次的mount将放到后台执行

fg

一直在前台发送请求

proto=tcp|udp

修改使用TCP协议还是UDP协议来传输nfs的数据

default

hard和nointr

rsize

读操作的块大小,这个设置影响服务器和客户端的nfs缓存大小,如果有充足的内存和网络带宽,可以设置高些,如32768(bytes)

wsize

写操作的块大小,这个设置影响服务器和客户端的nfs缓存大小,如果有充足的内存和网络带宽,可以设置高些,如32768(bytes)

查看帮助文件:man fstab、man -a mount



注意:如果要自动挂NFS共享目录,那么可以在/etc/fstab文件中进行配置

2、使用autofs来实现自动挂载NFS服务器的共享目录到NFS客户端

1)为什么要使用autofs
autofs 能够自动挂载卸载nfs和文件系统,并且在空闲的时候能够关闭nfs连接,降低系统负载。使用autofs要先关闭netfs服务,并注释掉/etc/fstab里关于nfs的内容

2)如何使用autofs实现NFS服务
[root@Mylinux ~]# chkconfig --level 35 autofs on
[root@Mylinux ~]# /etc/init.d/autofs start
[root@Mylinux ~]# vi /etc/auto.master
/nfs    /etc/auto.nfs   --timeout=60
[root@Mylinux ~]# vi /etc/auto.nfs
public          -ro,soft,intr           192.168.0.228:/data
[root@Mylinux ~]# reboot
[root@Mylinux ~]# cd /nfs
[root@Mylinux ~]# ls
[root@Mylinux ~]# mount
/dev/hda1 on / type ext3 (rw)
proc on /proc type proc (rw)
sysfs on /sys type sysfs (rw)
devpts on /dev/pts type devpts (rw,gid=5,mode=620)
tmpfs on /dev/shm type tmpfs (rw)
/dev/hda2 on /web type ext3 (rw)
none on /proc/sys/fs/binfmt_misc type binfmt_misc (rw)
sunrpc on /var/lib/nfs/rpc_pipefs type rpc_pipefs (rw)
[root@Mylinux ~]# cd public
[root@Mylinux ~]# mount
/dev/hda1 on / type ext3 (rw)
proc on /proc type proc (rw)
sysfs on /sys type sysfs (rw)
devpts on /dev/pts type devpts (rw,gid=5,mode=620)
tmpfs on /dev/shm type tmpfs (rw)
/dev/hda2 on /web type ext3 (rw)
none on /proc/sys/fs/binfmt_misc type binfmt_misc (rw)
sunrpc on /var/lib/nfs/rpc_pipefs type rpc_pipefs (rw)
192.168.0.228:/data on /nfs/public type nfs (ro,soft,intr,addr=192.168.0.228)

同时使用多个参数的方法:mount -t nfs -o timeo=3,udp,hard 192.168.0.30:/tmp /nfs
注意:NFS客户机和服务器的选项并不一定完全相同,而且有的时候会有冲突。比如说服务器以只读的方式导出,客户端却以可写的方式mount,虽然可以成功mount上,但尝试写入的时候就会发生错误。一般服务器和客户端配置冲突的时候,会以服务器的配置为准

3、配置/etc/fstab文件来实现开机自动挂载NFS服务器的共享目录到NFS客户端
注意: 要开机挂载nfs文件系统还需要开启netfs服务,并且把挂载项写入到/etc/fstab

/etc/fstab文件的语法格式

格式: fs_spec   fs_file   fs_type   fs_options  fs_dump fs_pass

fs_spec

该字段定义希望加载的文件系统所在的设备或远程文件系统, 对于nfs这个参数一般设置为这样:192.168.0.1:/NFS

fs_file

本地的挂载点

fs_type

对于NFS来说这个字段只要设置成nfs

fs_options

挂载的参数,可以使用的参数可以参考上面的mount参数

fs_dump

该选项被" dump " 命令使用来检查一个文件系统应该以多快频率进行转储,若不需要转储就设置该字段为:0

fs_pass

该字段被fsck命令用来决定在启动时需要被扫描的文件系统的顺序,根文件系统"/"对应该字段的值应该为:1,其他文件系统应该为:2。若该文件系统无需在启动时扫描则设置该字段为:0

查看帮助文件:man fstab、man -a mount

4、与NFS有关一些其它指令
nfsstat: 查看NFS的运行状态,对于调整NFS的运行有很大帮助
rpcinfo -p hostname(orIP): 查看rpc执行信息,可以用于检测rpc运行情况的工具



五、NFS服务的安全

1、NFS不安全体现在以下几个方面

第一点:新手对NFS的访问控制机制难于做到得心应手,控制目标的精确性难以实现

第二点:NFS没有真正的用户验证机制,而只有对RPC/Mount请求的过程验证机制

第三点:较早的NFS可以使未授权用户获得有效的文件句柄

第四点:在RPC远程调用中,一个SUID的程序就具有超级用户权限

2、加强NFS安全的方法如下

第一:合理的设定/etc/exports中共享出去的目录,最好能使用anonuid,anongid以使MOUNT到NFS SERVER的CLIENT仅仅有最小的权限,最好不要使用root_squash

第二:使用IPTABLE防火墙限制能够连接到NFS SERVER的机器范围
iptables -A INPUT -i eth0 -p TCP -s 192.168.0.0/24 --dport 111 -j ACCEPT
iptables -A INPUT -i eth0 -p UDP -s 192.168.0.0/24 --dport 111 -j ACCEPT
iptables -A INPUT -i eth0 -p TCP -s 140.0.0.0/8 --dport 111 -j ACCEPT
iptables -A INPUT -i eth0 -p UDP -s 140.0.0.0/8 --dport 111 -j ACCEPT

第三:为了防止可能的Dos攻击,需要合理设定NFSD 的COPY数目

第四:修改/etc/hosts.allow和/etc/hosts.deny达到限制CLIENT的目的
/etc/hosts.allow
portmap: 192.168.0.0/255.255.255.0 : allow
portmap: 140.116.44.125 : allow
/etc/hosts.deny
portmap: ALL : deny

第五:改变默认的NFS 端口
NFS默认使用的是111端口,但同时你也可以使用port参数来改变这个端口,这样就可以在一定程度上增强安全性

第六:使用Kerberos V5作为登陆验证系统

六、NFS服务的trouble shooting



   



常见错误

(1)权限的设置不符合

 

(2)忘记了激活portmap服务

错误信息

mount: RPC: Port mapper failure - RPC: Unable to receive 或mount: RPC: Program not registered

解决办法

启动portmap,并且重新启动nfs
#service portmap start
#service nfs restart

(3)被防火墙拦截

重新设置防火墙,包括iptables与TCP_Wrappers,因为激活了portmap,所以port 111必须提供出去.因此在iptables rules中,要增加:
iptables -A INPUT -p TCP --dport 111 -j ACCEPT
iptables -A INPUT -p UDP --dport 111 -j ACCEPT

如果还不行,那就是TCP_Wrappers的问题,检查/etc/hosts.deny,如果有一行是:
  ALL: ALL: deny
那就必须在/etc/hosts.allow中增加:
  portmap: ALL: allow

如果我们的NFS针对内部网络开发,对于外部网络只对学术网络开发(140.0.0.0/8),可以:
iptables -A INPUT -i eth0 -p TCP -s 192.168.0.0/24 --dport 111 -j ACCEPT
iptables -A INPUT -i eth0 -p UDP -s 192.168.0.0/24 --dport 111 -j ACCEPT
iptables -A INPUT -i eth0 -p TCP -s 140.0.0.0/8 --dport 111 -j ACCEPT
iptables -A INPUT -i eth0 -p UDP -s 140.0.0.0/8 --dport 111 -j ACCEPT

还可以使用TCP_Wrappers,在/etc/hosts.allow里面规定连上 NFS 主机的主机 IP 与名称,例如
#vi /.etc/hosts.allow
portmap: 192.168.0.0/255.255.255.0 :allow
portmap: 140.113.23.23     :allow

(4)cant contact portmapper: RPC: Remote system error - Connection refused

出现这个错误信息是由于SEVER端的PORTMAP没有启动

(5)mount clntudp_create: RPC: Program not registered

NFS没有启动起来,可以用showmout -e host命令来检查NFS SERVER是否正常启动起来

(6)mount: localhost:/home/test failed, reason given by server: Permission denied

这个提示是当client要mount nfs server时可能出现的提示,意思是说本机没有权限去mount nfs server上的目录。解决方法当然是去修改NFS SERVER