Chinaunix首页 | 论坛 | 博客
  • 博客访问: 233138
  • 博文数量: 63
  • 博客积分: 2465
  • 博客等级: 大尉
  • 技术积分: 471
  • 用 户 组: 普通用户
  • 注册时间: 2008-10-08 17:25
文章分类

全部博文(63)

文章存档

2011年(5)

2010年(41)

2009年(17)

我的朋友

分类: LINUX

2010-08-30 10:02:10

1. 准备工作
2. NFS的由来与其功能
  2.1 什么是NFS ( Network FileSystem )
  2.2 什么是RPC ( Remote Procedure Call )
  2.3 NFS启动的RPC daemons
  2.4 NFS的文件存取权限
3. NFS Server 端的设定
  3.1 所需要的套件
  3.2 NFS的套件结构
  3.3 /etc/exports 配置文件的语法与参数
  3.4 NFS服务的启动:rpcinfo
  3.5 NFS的连接观察: showmount, /var/lib/nfs/etab, exportfs
  3.6 NFS的安全性
4. NFS 客户端的设定
  4.1 远端NFS服务器的挂载
  4.2 客户端可处理的挂载参数与开机挂载
  4.3 无法挂载的原因分析
  4.4 自动挂载 autofs 的使用
5. 案例演练
6. 参考资料
1、准备工作
  NFS 这个借由网路分享文件系统的服务在架设的时候是很简单的,不过,他最大的问题在于『权限』方面的概念!因为在客户端与服务器端可能必须要具备相同的帐号才 能够存取某些目录或档案。 另外,NFS的启动需要透过所谓的远端程序呼叫 (RPC),也就是说,我们并不是只要启动NFS就好了,还需要启动RPC这个服务才行!
2、 NFS的由来与其功能
2.1 什么是 NFS (Network FileSystem)
  NFS(Network File System)是一种分布式文件系统,允许网络中的安装不同操作系统的计算机间共享文件和外设,所以它的通讯协定设计与主机及操作系统无关. 它是由SUN公司于1984年推出,使得可以本地机一样的使用另一台联网计算机的文件和外设。NFS在文件传送或信息传送过程中依赖于RPC协议。
            





  图一、NFS 主机分享目录与 Client 挂载示意图
  就如同上面的图示一般,当我们的NFS Server设定好共享出来的/home/sharefile这个目录后,其他的NFS Client端就可以将这个目录挂载到自己系统上面的某个挂载点(挂载点可以自定义),例如前面图示中的NFS client 1与NFS client 2挂载的目录就不相同。我只要在 NFS client 1系统中进入/home/data/sharefile内,就可以看到 NFS Server系统内的/home/sharefile目录下的所有资料了 (当然,权限要足够)。这个 /home/data/sharefile 就好像 NFS client 1自己机器里面的一个 partition。只要权限对了,那么您可以使用 cp, cd, mv, rm... 等等磁盘或文件相关的命令。
  好的,既然NFS是通过网络来进行文件的传输,那么经由socket pair的概念你会知道NFS应该会使用一些port吧?那么NFS使用哪个 port来进行传输呢?答案是....不知道?因为NFS用来传输的port是随机选择小于1024以下的端口来使用的。那客户端怎么知道你服务器端使用 那个port呢?此时就得要远程过程调用(Remote Procedure Call, RPC)的协议来辅助,下面我们就来谈谈什么是 RPC?
2.2 什么是 RPC (Remote Procedure Call)
  RPC, 远程过程调用 (remote procedure call)是能使客户端执行其他系统中程序的一种机制。由于使用 RPC 的程序不必了解支持通信的网络协议的情况,因此 RPC 提高了程序的互操作性。常用于分布式客户端/服务器模型,发出请求的程序是客户程序,而提供服务的程序是服务器。
  因为NFS支持的功能相当的多,而不同的功能都会使用不同的程序来启动,每启动一个功能就会启用一些 port 来传输文件,因此, NFS 的功能所对应的 port 才没有固定, 而是采用随机取用一些未被使用的小于 1024 的端口来作为传输之用。但如此一来又造成客户端想要连上服务器时的困拢, 因为客户端得要知道服务器端的相关端口才能够连接!
  此时我们就得需要远程过程调用(RPC) 的服务,RPC 最主要的功能就是在指定每个 NFS 功能所对应的 port number ,并且返回给客户端,让客户端可以连结到正确的端口上去。 那 RPC 又是如何知道每个 NFS 的端口呢?这是因为当服务器在启动 NFS 时会随机取用数个端口,并主动的向 RPC 注册,因此 RPC 可以知道每个端口对应的 NFS 功能,然后 RPC 又是固定使用 port 111 来监听客户端的需求并返回客户端正确的端口。
  注:在启动 NFS 之前,RPC 就要先启动了,否则NFS会无法向 RPC 注册。 另外,RPC若重新启动时,原来注册的资料会不见,因此RPC重新启动后,它管理的所有程序都需要重新启动以重新向RPC注册。
               

  图二、NFS 与 RPC 服务及文件系统操作的相关性
            
  如上图所示,当客户端有NFS文件存取需求时,它会如何向服务器端请求文件呢?
  1)、客户端会向服务器端的RPC(port 111)发出NFS档案存取功能的询问要求;
  2)、服务器端找到对应的已注册的NFS daemon端口后,会返回给客户端;
  3)、客户端了解正确的端口后,就可以直接与NFS daemon来建立连接;
  由于 NFS 的各项功能都必须要向RPC来注册,如此一来RPC就能了解NFS这个服务的各项功能之port number, PID, NFS 在主机所监听的IP等等,而客户端才能够通过RPC的询问找到正确对应的端口。 也就是说,NFS 必须要有RPC存在时才能成功的提供服务,因此我们称NFS为RPC server的一种。事实上,有很多这样的服务器都是向RPC注册的,举例来说,NIS (Network Information Service)也是RPC server 的一种。 此外,由图二你也会知道,不论是客户端还是服务器端,要使用 NFS 时,两者都需要启动 RPC 才行。
  更多的 NFS 相关协议信息你可以参考下面网页:
     
     
2.3 NFS启动的RPC daemons
  我们现在知道NFS服务器在启动的时候就得要向RPC注册,所以NFS服务器也被称为RPC server之一。那么NFS服务器主要的任务是进行文件系统的共享,文件系统的共享则与权限有关。 所以 NFS 服务器启动时至少需要两个 daemons ,一个管理client端是否能够登入的问题,一个管理client端能够取得的权限。如果你还想要管理quota的话,那么NFS还得要再载入其他的 RPC程序。我们以较单纯的NFS主机来说:
  rpc.nfsd:
  这个 daemon 主要的功能就是在管理 Client 是否能够登入主机的权限,其中还包含这个登入者的 ID 的判别。
  rpc.mountd
  这个daemon主要的功能,则是在管理NFS的文件系统,当Client端顺利的通过rpc.nfsd而登入主机之后,在他可以使用NFS服务器提 供的文件之前,还会经过文件使用权限 (就是那个-rwxrwxrwx与owner, group那几个权限)的认证程序!它会去读NFS的配置文件/etc/exports 来比对Client的权限,当通过这一关之后Client就可以取得使用NFS文件的权限(注:这个也是我们用来管理NFS共享之目录的使用权限与安全设 定的地方)
  rpc.lockd (非必要)
  这个玩意儿可以用在管理文件的锁定(lock)用途。为何文件需要『锁定』呢?因为既然分享的NFS文件可以让客户端使用,那么当多个客户端同时尝试 写入某个文件时,就可能对于该文件造成一些问题啦!这个rpc.lockd则可以用来克服这个问题。 但rpc.lockd必须要同时在客户端与服务器端都开启才行,此外,rpc.lockd也常与rpc.statd 同时启用。
  rpc.statd (非必要)
  可以用来检查文件的一致性,与rpc.lockd有关!若发生因为客户端同时使用同一文件造成文件可能有所损毁时, rpc.statd 可以用来检测并尝试回复该文件。与 rpc.lockd同样的,这个功能必须要在服务器端与客户端都启动才会生效。
2.4 NFS的文件存取权限
  不知道你有没有想过这个问题,在图一的环境下,假如我在NFS client 1上面以dmtsai这个使用者身份想要去存取 /home/data/sharefile/这个来自NFS server所提供的文件系统时,请问NFS server所提供的文件系统会让我以什么身份去存取?是 dmtsai 还是?
  为什么会这么问呢?这是因为NFS本身的服务并没有进行身份登入的识别,所以说,当你在客户端以dmtsai的身份想要存取服务器端的文件系统时,服 务器端会以客户端的使用者UID与GID等身份来尝试读取服务器端的文件系统。这时有个有趣的问题就产生啦!那就是如果客户端与服务器端的使用者身份并不 一致怎么办?
  我们以下面这个图示来说明一下:
                    

         
  图三、NFS 的服务器端与客户端的使用者身份确认机制
  当我以dmtsai这个一般身份使用者要去存取来自服务器端的文件时,你要先注意到的是:文件系统的inode所记录的属性为UID,GID而非帐号 与群组名。那一般Linux主机会主动的以自己的/etc/passwd,/etc/group来查询对应的使用者、群组名称。所以当dmtsai进入到 该目录后,会参照NFS client 1的使用者与群组名称。 但是由于该目录的文件主要来自NFS server,所以可能就会发现几个情况:
  NFS server/NFS client刚好有相同的帐号与群组
  则此时使用者可以直接以dmtsai的身份进行服务器所提供的文件系统之存取。
  NFS server的501这个UID帐号对应为vbird
  若 NFS 服务器上的/etc/passwd里面UID 501的使用者名称为vbird时,则客户端的dmtsai可以存取服务器端的vbird这个使用者的文件!只因为两者具有相同的UID而已。这就造成很 大的问题了!因为没有人可以保证客户端的UID所对应的帐号会与服务器端相同, 那服务器所提供的资料就可能会被错误的使用者修改?
  NFS server并没有501这个UID
  另一个极端的情况是,在服务器端并没有501这个UID的存在,则此时dmtsai的身份在该目录下会被压缩成匿名者,一般NFS的匿名者会以UID 为 65534为其使用者,早期的Linux distributions这个65534的帐号名称通常是nobody ,我们的RHEL4则取名为nfsnobody 。
  如果使用者身份是root时
  有个比较特殊的使用者,那就是每个 Linux 主机都有的UID为0的root。想一想,如果客户端可以用root的身份去存取服务器端的文件系统时,那服务器端的资料哪有什么保护性?所以在预设的情况下, root的身份会被主动的压缩成为匿名者。
  总之,客户端使用者能做的事情是与UID及其GID有关的,那当客户端与服务器端的UID及帐号的对应不一致时,可能就会造成文件系统使用上的困扰, 这个就是NFS文件系统在使用上面的一个很重要的地方!而在了解使用者帐号与UID及文件系统的关系之后,要实际在客户端以NFS取用服务器端的文件系统 时, 你还得需要具有:
  NFS服务器有开放可写入的权限(与/etc/exports设定有关);
  实际的文件权限具有可写入(w)的权限。
  当你满足了(1)使用者帐号,亦即UID的相关身份;(2)NFS服务器允许有写入的权限;(3)文件系统确实具有w的权限时,你才具有该文件的可写 入权限!尤其是身份(UID)确认的环节部分,最容易搞错!也因为如此,所以NFS通常需要与NIS这一个可以确认客户端与服务器端身份一致的服务搭配使 用,以避免身份的错乱
3、NFS Server 端的设定
  既然要使用NFS的话,就得要安装NFS所需要的套件,下面让我们查询一下系统有无安装所需要的套件, NFS套件的架构以及如何设定 NFS主机。^
3.1 所需要的套件
  以RHEL 4为例的话,要设定好NFS服务器我们必须要有两个套件才行,分别是:
  NFS 主程序:nfs-utils
  RPC 主程序:portmap
  portmap
  就如同刚刚提的到,我们的NFS其实可以被视为一个RPC程序,而要启动任何一个RPC程序之前,我们都需要做好port的对应 (mapping) 的工作才行,这个工作其实就是『portmap』这个服务所负责的!也就是说, 在启动任何一个RPC server之前,我们都需要启动portmap才行!
  nfs-utils
  就是提供 rpc.nfsd 及 rpc.mountd 这两个 NFS daemons 与其他相关 documents 与说明文件、执行档等的套件!这个就是 NFS 的主要套件。
  判断系统中是否已安装NFS相关包
  RHEL4 系统的情况;其它版本的Redhat及Fedora的系统和这相似;
#rpm -qa | grep nfs
nfs-utils-1.0.6-65.EL4
#rpm -qa | grep portmap
portmap-4.0-63
3.2 NFS的套件结构
  /etc/exports
  这个文件就是NFS的主要配置文件。系统可能没有预设,所以这个文件不一定会存在,您可能必须要使用 vi 主动的建立这个文件。
  /usr/sbin/exportfs
  这个是维护NFS共享资源的命令,我们可以利用这个命令重新共享 /etc/exports 变更的目录资源、将NFS Server分享的目录卸载或重新分享等等,这个指令是NFS系统里面相当重要的。至于指令的用法我们在下面会再介绍。
  /usr/sbin/showmount
  这是另一个重要的NFS命令。exportfs是用在NFS Server端,而showmount则主要用在Client端。这个showmount可以用来察看NFS共享出来的目录资源。
  /var/lib/nfs/*tab
  在NFS服务器的登录档都放置到/var/lib/nfs/目录里面,在该目录下有两个比较重要的登录档,一个是etab ,主要记录了 NFS 所分享出来的目录的完整权限设定值;另一个xtab则记录曾经连结到此NFS主机的相关客户端资料。
  /var/lib/nfs/rmtab
  状态文件,列出了挂接导出文件的远程客户机清单。
  
3.3 /etc/exports配置文件的语法与参数
  在开始NFS服务器的设置之前,您必须要了解的是,NFS会直接使用到内核功能,所以你的内核必须要有支持NFS才行。 万一如果你的内核版本小于2.2版,或者重新自行编译过内核的话,那么就得要很注意, 因为你可能会忘记选择NFS的核心支持。
  还好,我们RHEL4或者是其他版本的Linux ,预设内核通常是支援NFS功能的, 所以你只要确认你的内核版本是目前新的2.6.x版,并且使用你的distribution所提供的核心,那应该就不会有问题。
  至于NFS服务器的架设实在很简单,你只要编辑好主要配置文件/etc/exports之后, 先启动portmap ,然后再启动nfs ,你的NFS就成功了!不过这样的设定能否对客户端生效?那就得要考虑你权限方面的设定能力了。 我们就直接来看看/etc/exports 应该如何配置,某些 distributions并不会主动提供 /etc/exports 文件,所以请您自行手动建立。
  例如:
# vi /etc/exports
/tmp         192.168.1.0/24(ro)   localhost(rw)   *.ev.ncku.edu.tw(ro,sync)
[分享目录]  [第一个主机(权限)]   [可用主机名]    [可用域名]
  这个文件的内容非常简单,每一行由共享路径,客户端列表以及每个客户端后紧跟的访问选项构成:
[共享的目录] [主机名或IP(参数,参数)]
  其中参数是可选的,当不指定参数时,nfs将使用默认选项。默认的共享选项是 sync,ro,root_squash,no_delay。
  当主机名或IP地址为空时,则代表共享给任意客户机提供服务。
  当将同一目录共享给多个客户机,但对每个客户机提供的权限不同时,可以这样:
[共享的目录] [主机名1或IP1(参数1,参数2)] [主机名2或IP2(参数3,参数4)]
  下面是一些NFS共享的常用参数:
    
ro: read-only,只读访问权限
rw: read-write,可读写的权限
sync: 资料同步写入到内存与硬盘中
async: 资料会先暂存于内存中,而非直接写入硬盘
secure: NFS通过1024以下的安全TCP/IP端口发送
insecure: NFS通过1024以上的端口发送
wdelay: 如果多个客户要写入NFS目录,则归组写入(默认)
no_wdelay: 如果多个客户要写入NFS目录,则立即写入,当使用async时,无需此设置。
hide: 在NFS共享目录中不共享其子目录
no_hide: 共享NFS目录的子目录
subtree_check: 如果共享/usr/bin之类的子目录时,强制NFS检查父目录的权限(默认)
no_subtree_check: 和上面相对,不检查父目录权限
no_all_squash: 保留共享文件的UID和GID(默认)
   
all_squash
  不论登入 NFS 的使用者身份为何, 他的UID和GID映射匿名客户anonymous(通常也就是 nobody(nfsnobody)),适合公用目录。
      
root_squash  
  在登入NFS主机使用共享之目录的使用者如果是root时,那么这个使用者的权限将被映射成为匿名使用者,通常他的 UID 与 GID 都会变成nobody(nfsnobody) 那个系统帐号的身份的权限;(默认)
      
no_root_squas         
  登入NFS主机使用共享目录的使用者,如果是root的话,那么对于这个共享的目录来说,他就具有root的权限!这个项目『极不安全』,不建议使用!
      
anonuid=xxx: 指定NFS服务器/etc/passwd文件中匿名客户的UID
      
anongid=xxx: 指定NFS服务器/etc/passwd文件中匿名客户的GID
/etc/exports 中client的书写规则
  (1)单个主机
  可以用短名及完全限定名,或者用IP地址,例如student01、student01.flying.com.cn或者192.168.10.1都是合法的主机名。
  (2)Net-Group
  可以列出/etc/netgroup文件中或NFS网组映射中定义的整组主机。网组名以@开头。
  (3)通配符主机
  .discuz.net *.*.comsenz.com
  (4)掩码
  192.168.1.0/255.255.255.0
  接下来我们利用上述的几个参数来实际思考一下几个有趣的小习题:
  思考一:让root保有root的权限
  我想将/tmp共享出去给大家使用,由于这个目录本来就是大家都可以读写的,因此想让所有的人都可以存取。 此外,我要让root写入的文件还是具有root的权限,那如何设计配置文件?
# vi /etc/exports
# 任何人都可以用我的 /tmp ,用通配字符(*)来处理主机名称,重点在no_root_squash
/tmp  *(rw,no_root_squash)
  参考前面的主机名称设定说明,我们可以利用通配字符(*)。这表示无论来自哪里都可以使用我的/tmp这个目录。 再次提醒,『 *(rw,no_root_squash)』这一串设定值中间是没有空格的,而/tmp与*(rw,no_root_squash)则是有空格来隔开的。 特别注意到 no_root_squash的功能!在这个例子中,如果你是客户端,而且您是以 root 的身份登入您的Linux主机,那么当您mount上我这部主机的 /tmp 之后,您在该mount的目录当中,将具有『root 的权限』
  思考二:同一目录针对不同范围开放不同权限
  我要将一个公共的目录/home/public公开出去,但是只有限定我的局域网内192.168.0.0/24这个网段可以读写,其他人则只能读取:
# vi /etc/exports
/tmp          *(rw,no_root_squash)
/home/public  192.168.0.0/24(rw)    *(ro)
# 继续加在后面,注意,我有将主机与网域分为两段(用空格隔开)
  上面的例子说的是,当我的IP是在192.168.0.0/24 这个网段的时候,那么当我在Client端挂载了Server 端的/home/public后,针对这个被我挂载的目录我就具有可以读写的权限,至于如果我不是在这个网段之内,那么这个目录的文件我就只能读取而已, 亦即为只读的属性。
  需要注意的是,通配字符仅能用在主机名称的分辨上面,IP或网段就只能用192.168.0.0/24的状况,不可以使用192.168.0.*
  思考三:仅给某个单一主机使用的目录设置
  我要将一个私人的目录 /home/test 开放给192.168.0.100这个Client端的机器来使用,那么我就必需这么写:
# vi /etc/exports
/tmp          *(rw,no_root_squash)
/home/public  192.168.0.0/24(rw)    *(ro)
/home/test    192.168.0.100(rw) # 只要设定 IP 正确即可!
  这样就设定完成了!而且,只有192.168.0.100这部机器才能对/home/test这个目录进行存取。
  思考四:开放匿名登入的情况
  我要让*.linux.org网域的主机,登入我的NFS主机时,可以存取 /home/linux,但是他们存资料的时候,我希望他们的UID与GID 都变成40这个身份的使用者, 假设我NFS服务器上的UID 40已经有设定妥当:
# vi /etc/exports
/tmp          *(rw,no_root_squash)
/home/public  192.168.0.0/24(rw)    *(ro)
/home/test    192.168.0.100(rw)
/home/linux   *.linux.org(rw,all_squash,anonuid=40,anongid=40)
# 如果要开放匿名,那么重点是all_squash,并且要配合anonuid
  特别注意到那个all_squash与anonuid,anongid 的功能!如此一来,当 test.linux.org 登入这部 NFS 主机,并且在 /home/linux 写入文件时,该文件的所有人与所有群组,就会变成/etc/passwd 里面对应的UID为40的那个身份的使用者。
  上面四个案例的权限如果依照前一小节的存取设定权限来思考的话,那么权限会是什么情况呢?让我们来检查一下:
  客户端与主机端具有相同的UID与帐号:
  假设我在192.168.0.100登入这个NFS(IP假设为192.168.0.2)主机,并且我在192.168.0.100的帐号为dmtsai这个身份,同时,在这个NFS上面也有dmtsai这个帐号,并具有相同的UID,果真如此的话,那么:
  a) 由于192.168.0.2这个NFS主机的/tmp权限为-rwxrwxrwt,所以我 (dmtsai在192.168.0.100上面)在/tmp底下具有存取的权限,并且写入的文件所有人为dmtsai;
  b) 在/home/public当中,由于我有读写的权限,所以如果在/home/public这个目录的权限对于dmtsai有开放写入的话,那么我就可以 读写,并且我写入的文件所有人是dmtsai。但是万一/home/public对于dmtsai这个使用者并没有开放可以写入的权限时,那么我还是没有 办法写入文件(这点请特别留意);
  c) 在/home/test当中,我的权限与/home/public相同的状态,还需要NFS主机的/home/test对于dmtsai有开放权限;
  d) 在/home/linux当中就比较麻烦,因为不论您是何种user ,您的身份一定会被变成UID=40这个帐号!所以,这个目录就必需要针对UID = 40的那个帐号名称,修改他的权限才行。
  客户端与主机端的帐号并未相同时:
  假如我在192.168.0.100的身份为vbird ,但是192.168.0.2这部NFS主机却没有vbird这个帐号时,情况会变成怎样呢?
  a) 我在/tmp 底下还是可以写入,但是写入的文件所有人变成 nobody 了;
  b) 我在/home/public里面是否可以写入,还需要视/home/public的权限而定,不过,反正我的身份就被变成nobody了就是;
  c) /home/test 的观点与/home/public相同!
  d) /home/linux 底下,我的身份就被变成 UID=40那个使用者呢!
  当客户端的身份为 root 时:
  假如我在192.168.0.100的身份为root,root这个帐号每个系统都会有,权限变成怎样呢?
  a) 我在/tmp里面可以写入,并且由于no_root_squash的参数,改变了预设的root_squash设定值,所以在/tmp写入的文件所有者为 root
  b) 我在/home/public底下的身份还是被压缩成为nobody,因为预设属性里面都具有root_squash,所以,如果/home/public 有针对 nobody开放写入权限时,那么我就可以写入,但是文件所有者变成nobody
  c) /home/test与/home/public相同;
  d) /home/linux 的情况中,我root的身份也被压缩成为UID=40的那个使用者
  这样的权限讲解之后,您可以了解了吗?这里是最重要的地方,如果这一关通过了,下面的就没有问题啦! 当然,您还是得要回到前一小节NFS 的文件存取权限好好的瞧一瞧, 才能解决NFS的问题。
3.4 NFS服务的启动
  
  NFS的启动还需要portmap的协助,所以需先启动。
# /etc/init.d/portmap start
# 如果 portmap 本来就已经在执行了,那就不需要启动啊!
# /etc/init.d/nfs start
# 有时候可能会出现如下的警告讯息:
exportfs: /etc/exports [3]: No 'sync' or 'async' option specified
for export "192.168.0.100:/home/test".
Assuming default behaviour ('sync').
# 上面的警告讯息仅是在告知因为我们没有指定 sync 或 async 的参数,
# 则NFS将预设会使用sync的资讯而已。你可以不理他,也可以加入/etc/exports。
# vi /etc/exports
/tmp          *(rw,no_root_squash,sync)
/home/public  192.168.0.0/24(rw,sync)    *(ro,sync)
/home/test    192.168.0.100(rw,sync)
/home/linux   *.linux.org(rw,all_squash,anonuid=40,anongid=40,sync)
# /etc/init.d/nfs restart
  portmap不需要设定,只要直接启动就行,启动之后,会出现一个port 111的sunrpc的服务,那就是portmap啦!至于nfs则会启动至少两个以上的daemon出现!然后就开始在监听Client端的请求。你必 须要很注意屏幕上面的输出资讯, 因为如果配置文件写错的话,屏幕上会显示出错误。
  此外,如果你想要增加一些NFS服务器的文件一致性功能时,可能需要用到rpc.lockd及rpc.statd等RPC服务, 那么或许你可以增加一个服务,那就是nfslock
# /etc/init.d/nfslock start
  启动之后,请赶快到 /var/log/messages 里面看看有没有被正确的启动呢?
# vi /var/log/messages
Sep 22 00:01:37 linux nfs: Starting NFS services:  succeeded
Sep 22 00:01:37 linux nfs: rpc.rquotad startup succeeded
Sep 22 00:01:37 linux nfsd[1050]: nfssvc_versbits: +2 +3 +4
Sep 22 00:01:37 linux nfs: rpc.nfsd startup succeeded
Sep 22 00:01:37 linux nfs: rpc.mountd startup succeeded
Sep 22 00:01:37 linux rpcidmapd: rpc.idmapd -SIGHUP succeeded
  在确认没有问题之后,接下来我们来看一看NFS到底开了哪些端口?
# netstat -ultn
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address   State   PID/Program name
tcp        0      0 0.0.0.0:2049    LISTEN  -
tcp        0      0 0.0.0.0:803     LISTEN  1047/rpc.rquotad
tcp        0      0 0.0.0.0:111     LISTEN  32503/portmap
tcp        0      0 0.0.0.0:819     LISTEN  1064/rpc.mountd
udp        0      0 0.0.0.0:2049            -
udp        0      0 0.0.0.0:800             1047/rpc.rquotad
udp        0      0 0.0.0.0:816             1064/rpc.mountd
udp        0      0 0.0.0.0:111             32503/portmap
  注意看到上面,总共产生了好多的port,真是可怕!不过主要的端口是:
  portmap启动的 port 在 111;
  NFS启动的port在2049;
  其它rpc.daemons启动的port则是随机产生的,因此需向port 111注册。
  
  好了,那我怎么知道每个RPC服务的注册状况?你可以使用 rpcinfo 来处理的。
# rpcinfo [-p] [IP|hostname]
参数:
-p :显示出所有的 port 与 porgram 的信息;
  范例一:显示出目前这部主机的 RPC 状态
# rpcinfo -p localhost
program vers proto   port
  100000    2   tcp    111  portmapper
  100000    2   udp    111  portmapper
  100011    1   udp    800  rquotad
  100011    2   udp    800  rquotad
  100011    1   tcp    803  rquotad
  100011    2   tcp    803  rquotad
  100003    2   udp   2049  nfs
  100003    3   udp   2049  nfs
  100003    2   tcp   2049  nfs
  100003    3   tcp   2049  nfs
  100005    1   udp    816  mountd
  100005    1   tcp    819  mountd
  100005    2   udp    816  mountd
  100005    2   tcp    819  mountd
  100005    3   udp    816  mountd
  100005    3   tcp    819  mountd
#         NFS版本       端口  服务名称
  上面出现的信息当中除了程序名称与端口的对应可以与netstat -tlunp输出的结果作比对之外,还需要注意到NFS版本支持!新的NFS 版本传输速度较快,由上表看起来,我们的NFS至少支持到第3版,应该还算合理,如果你的rpcinfo无法输出,那就表示注册的资料有问题,可能需要重 新启动portmap与nfs。
3.5 NFS的连接观察
  在你的NFS服务器设定好之后,我们可以先自我测试一下是否可以连接?
showmount [-ae] [hostname|IP]
参数:
-a :这个参数是一般在NFS SERVER上使用,是用来显示已经mount上本机nfs目录的cline机器
-e :显示主机的 /etc/exports 所共享的目录。
  范例一:请显示出刚刚我们所设定好的相关exports信息
# showmount -e localhost
Export list for localhost:
/tmp         *
/home/linux  *.linux.org
/home/public (everyone)
/home/test   192.168.0.100
  很简单吧!所以,当您要查看某一台主机提供的NFS共享的目录时,就使用 showmount -e IP (或hostname)即可!非常的方便吧!这也是 NFS client 端最常用的指令。
  事实上NFS关于目录权限设定的资料非常之多!我们可以检查一下/var/lib/nfs/etab就知道了!
# tail /var/lib/nfs/etab
/home/public    *(ro,sync,wdelay,hide,nocrossmnt,secure,root_squash,no_all_squash,
subtree_check,secure_locks,mapping=identity,anonuid=-2,anongid=-2)
# 上面是同一行,可以看出除了 ro, sync, root_squash 等等,
# 其实还有 anonuid 及 anongid 等等的设定!
/tmp    *(rw,sync,wdelay,hide,nocrossmnt,secure,no_root_squash,no_all_squash,subtr
ee_check,secure_locks,mapping=identity,anonuid=-2,anongid=-2)
# 同样的,在/tmp也有很多的权限相关的参数
  上面仅仅是一个小范例,只是....怎么anonuid会是-2?其实那个数值是65536-2,所以得到65534,比对/etc/passwd, 会发现RHEL4出现的是nfsnobody,这个帐号在不同的版本都可能会不一样。 另外,如果有其他客户端挂载了你的NFS文件系统时,那么该客户端与文件系统信息就会被记录到/var/lib/nfs/xtab。
  另外,如果你想要重新处理/etc/exports文件,是不是我们每次修改了配置文件都需要重启nfs服务呢?这个时候我们就可以用exportfs命令重新扫描/etc/exports文件,来使改动立刻生效。
exportfs [-aruv]
参数:
-a :全部挂载(或卸载)/etc/exports文件内的设置
-r :重新挂载/etc/exports里面的设置,此外,亦同步更新/etc/exports及/var/lib/nfs/xtab 的内容!
-u :卸载某一目录
-v :在export的时候,将分享的目录显示到屏幕上!
  范例一:重新挂载一次 /etc/exports的设置
# exportfs -arv
exporting 192.168.0.100:/home/test
exporting 192.168.0.0/24:/home/public
exporting *.linux.org:/home/linux
exporting *:/home/public
exporting *:/tmp
  范例二:全部卸载
# exportfs -auv
3.6 NFS的安全性
  在NFS的安全性上面,有些地方是你必须知道的!下面我们分别来看一看:
  a) 利用iptables做大范围连接的限制:
  假设我们的NFS主要是针对内部网路开放而已,而对于外部网路只有对140.116.0.0/16这个网段 ,那么你可以在iptables.allow内增加如下的语法:
# vi /usr/local/virus/iptables/iptables.allow
iptables -A INPUT -i $EXTIF -p TCP -s 192.168.0.0/24 --dport 111 -j ACCEPT
iptables -A INPUT -i $EXTIF -p UDP -s 192.168.0.0/24 --dport 111 -j ACCEPT
iptables -A INPUT -i $EXTIF -p TCP -s 140.116.0.0/16 --dport 111 -j ACCEPT
iptables -A INPUT -i $EXTIF -p UDP -s 140.116.0.0/16 --dport 111 -j ACCEPT
  这样大致上就可以让 192.168.0.0/24 这个C Class的网域与140.116.0.0/16这个 B Class的网段到您的主机里面来,而其它的连接就视您的原本的iptables的状态而定。
  那为什么是限制port 111而不是每个RPC server所开启的端口呢?因为RPC server所开启的端口都是随机产生的,要对他开放实在是... 而且客户端想要连上NFS服务器之前,都是透过port 111来向NFS服务器询问连接的端口的,所以当然先就port 111来进行限制。
b) 利用 TCP Wrappers 限制
  但是不同的 RPC 毕竟提供的服务不一样,如果你想要针对某些服务来阻止的话,那可以透过TCP Wrappers这个根据 program name来阻止网路包,还记得我们刚刚使用过rpcinfo这个指令,不是会输出很多的RPC program name吗?没错!你可以这样做:
# vi /etc/hosts.allow
# 让来自 140.116.44.0/255.255.255.0 的主机可以使用 mountd
mountd: 140.116.44.0/255.255.255.0
# vi /etc/hosts.deny
# 让所有人都不能使用 mountd
mountd: ALL
  为什么使用的是mountd呢?去到前一小节的rpcinfo指令处看一下, 你就会知道为何需要使用到mountd。
  c) 使用/etc/exports 设定更安全的权限
  这就牵涉到您的逻辑思考了!怎么设置都没有关系,但是在『便利』与『安全』之间,要找到您的平衡点。善用root_squash 及 all_squash 等功能,再利用anonuid等等的设定来规范登入您主机的使用者身份!应该还是有办法提供一个较为安全的NFS主机的!
  另外,当然啦,你的NFS服务器的文件系统之权限设定也需要很留意!不要随便设定成为-rwxrwxrwx ,这样会造成你的系统『很大的困扰』。
  d) 更安全的 partition 规划:
  如果您的工作环境中,具有多部的 Linux 主机,并且预计彼此共享出目录时,那么在安装 Linux 的时候,最好就可以规划出一块 partition作为预留之用。因为『NFS可以针对目录来分享』,因此,您可以将预留的partition挂载在任何一个挂载点,再将该挂载点 (就是目录)由/etc/exports的设定中分享出去,那么整个工作环境中的其他Linux主机就可以使用该NFS主机的那块预留的 partition。所以,在主机的规划上面,主要需要留意的只有partition而已。此外,由于共享的partition可能较容易被入侵,最好可 以针对该partition设定比较严格的参数在/etc/fstab当中。
  e) NFS服务器关机前的注意事项:
  需要注意的是,由于NFS使用的这个RPC在client端连上服务器时,那么您的服务器想要关机,那可就会成为『不可能的任务』!如果您的 Server上面还有Client在连接,那么您要关机,可能得要等到数个钟头才能够正常的关机成功!真的假的?不相信吗?不然您自已试试看!
  所以,建议您的NFS Server想要关机之前,能先『关掉portmap与nfs』。如果无法正确的将这两个daemons关掉,那么先以netstat -utlp找出PID ,然后以kill将他杀掉先,这样才有办法正常的关机成功。请特别的注意!
  当然,你也可以利用showmount -a localhost查出来那个客户端还在连接,或者是查阅/var/lib/nfs/rmtab或xtab等文件来检查亦可。找到这些客户端后,可以直接call他们啊!让他们能够帮帮忙先!
  事实上,客户端以NFS连接到服务器端时,如果他们可以下达一些比较不那么『硬』的挂载参数时,就能够减少这方面的问题。相关的安全性可以参考下一小节的客户端可处理的挂载参数与开机挂载。
4、NFS 客户端的设定
  既然NFS服务器最主要的工作就是共享文件系统给网路上其他的客户端,所以客户端当然得要挂载这个玩意儿!此外,主机端可以加设防火墙来保护自己的文件系统,那么客户端挂载该文件系统后,难道不需要保护自己? 所以下面我们要来谈一谈几个NFS客户端。
4.1 远端NFS服务器的挂载
  你要如何挂载NFS服务器所提供的文件系统?基本上,可以这样做:
  a) 确认本地端已经启动了portmap服务!  
  b) 查看NFS服务器共享的目录有哪些,并了解我们是否可以使用(showmount);
  c) 在本地端建立预计要挂载的挂载点目录(mkdir);
  d) 利用mount将远端主机直接挂载到相关目录。
  好,现在假设客户端在192.168.0.100这部机器上,而服务器是192.168.0.2,那么赶紧来检查一下我们是否已经有portmap的启动,另外远端主机有什么可用的目录!
# /etc/init.d/portmap start
# /etc/init.d/nfslock start
# 一般来说,系统预设会启动 portmap
# 另外,如果服务器端有启动nfslock的话,客户端也要启动才能生效!
# showmount -e 192.168.0.2
Export list for 192.168.0.2:
/tmp         *
/home/linux  *.linux.org
/home/public (everyone)   

         
  图四、自动挂载的设定档内容
  如上图所示,我们的autofs主要设定档为 /etc/auto.master,这个文件的内容很简单, 如上所示,我只要定义出最上层目录 (/home/nfs) 即可,至于后续的文件则是该目录底下各次目录的对应。 在etc/auto.nfs (这个文件的文件名可自定义) 里面则可以定义出每个次目录所欲挂载的远端服务器目录。 然后:『当我们在客户端要使用 /home/nfs/public 的资料时,此时 autofs 才会去 192.168.0.2 挂载/home/public』且『当隔了5分钟没有使用该目录下的文件后,则/home/nfs/public 将会主动的卸载』。
  建立主要配置文件 /etc/auto.master
  这个主要配置文件的内容很简单,只要有预设目录及『资料对应文件』即可。 那个资料对应文件的文件名是可以自行定义的,在这个例子当中我使用 /etc/auto.nfs 来命名。
# vi /etc/auto.master
/home/nfs  /etc/auto.nfs
# mkdir /home/nfs
# 注意!此时 /home/nfs 内并没有其他的目录存在
  建立资料对应文件内的挂载资讯
  刚刚我们所指定的/etc/auto.nfs是自行设定的,所以这个文件是不存在的。该文件的格式:
[本地端目录] [-挂载参数] [服务器所提供的目录]
参数:
本地端目录:指的就是在 /etc/auto.master 内指定的目录之次目录
-挂载参数 :就是前一小节提到的 rw,bg,soft 等等的参数;
服务器所提供的目录 :例如 192.168.0.2:/home/public 等
# vi /etc/auto.nfs
public  -rw,bg,soft,rsize=8192,wsize=8192 192.168.0.2:/home/public
testing -rw,bg,soft,rsize=8192,wsize=8192 192.168.0.2:/home/test
temp    -rw,bg,soft,rsize=8192,wsize=8192 192.168.0.2:/tmp
# 参数部分,只要最前面加个 - 符号即可!
  这样就可以建立对应了!要注意的是,那些 /home/nfs/public 是不需要事先建立的。(public目录是由 automount 动态地创建的,它不应该在客户机器上实际存在。)
  实际运作与观察
  配置文件配置好后,启动autofs
# /etc/init.d/autofs start
  假设你目前并没有挂载任何来自192.168.0.2这个NFS服务器的目录, 让我们实际来看看,如果我要进入 /home/nfs/public 时,文件系统会如何变化呢?
# mount; df
# 你不会看到任何跟192.168.0.2这个主机有关的NFS挂载信息。
# cd /home/nfs/public
# mount; df
192.168.0.2:/home/public on /home/nfs/public type nfs (rw,bg,soft,rsize=8192,wsize=8192,addr=140.116.44.179)
# 上面的输出是同一行
Filesystem 1K-blocks     Used Available Use% Mounted on
192.168.0.2:/home/public
          10080488  2144288   7424136  23% /home/nfs/public
# 文件的挂载也出现没错!
# pwd
/home/nfs/public
# 应当注意public目录是由 automount 动态地创建的,它不应该在客户机器上实际存在。
4.4 无法挂载的原因分析
  
  使用者或客户端身份权限不符:
  以上面的例子来说明,我的/home/test只能提供 192.168.0.0/24 这个网域,所以如果我在 192.168.0.2 这部服务器中,以 localhost (127.0.0.1) 来挂载时,就会无法挂载上,这个权限概念没问题吧! 那么您可以试试看:
# mount -t nfs localhost:/home/test /home/nfs
mount: localhost:/home/test failed, reason given by server: Permission denied
  服务器或客户端某些服务未启动:
  如果您发现您的mount的讯息是这样,说明未启动portmap或服务器nfs这个服务。
# mount -t nfs localhost:/home/test /home/nfs
mount: RPC: Port mapper failure - RPC: Unable to receive
# mount -t nfs localhost:/home/test /home/nfs
mount: RPC: Program not registered
  被防火墙阻挡
  这个原因很多人都忽视了,在有严格要求的网络环境中,我们一般会关闭linux上的所有端口,当需要使用哪个端口的时候才会去打开。而NFS默认是使用111端口,所以我们先要检测是否打开了这个端口,另外也要检查TCP_Wrappers的设定。
5、案例演练
  假设环境:
  假设我的 Linux 主机为 192.168.0.100 这一台;
  预计将 /tmp 以可读写,并且不限制使用者身份的方式分享给所有 192.168.0.0/24 这个网域中的所有 Linux 工作站;
  预计开放 /home/nfs 这个目录,使用的属性为唯读,可提供除了网域内的工作站外,向外亦提供资料内容;
  预计开放 /home/upload 做为 192.168.0.0/24 这个网域的资料上传目录,其中,这个 /home/upload 的使用者及所属群组为 nfs-upload 这个名字,他的 UID 与 GID 均为 210;
  预计将 /home/andy 这个目录仅分享给 192.168.0.50 这部 Linux 主机,以提供该主机上面 andy 这个使用者来使用,也就是说, andy 在 192.168.0.50 及 192.168.0.100 均有帐号,且帐号均为 andy ,所以预计开放 /home/andy 给 andy 使用他的家目录啦!
  实地演练:
  
  (1)、首先,就是要建立/etc/exports这个文件的内容,您可以这样写:
# vi /etc/exports
/tmp         192.168.0.*(rw,no_root_squash)
/home/nfs    192.168.0.*(ro)  *(ro,all_squash)
/home/upload 192.168.0.*(rw,all_squash,anonuid=210,anongid=210)
/home/andy   192.168.0.50(rw)
  (2)、再来,就是要建立每个对应的目录的实际Linux权限:
  a. /tmp
# ll -d /tmp
drwxrwxrwt  5 root root 20480 Sep 22 22:52 /tmp
  b. /home/nfs
# mkdir -p /home/nfs
# chmod 755 -R /home/nfs
# 修改较为严格的文件权限将目录与文件设定成只读!不能写入的状态,会更保险一点!
  c. /home/upload
# groupadd -g 210 nfs-upload
# useradd -g 210 -u 210 -M nfs-upload
# 先建立对应的帐号与群组名称及UID
# mkdir -p /home/upload
# chown -R nfs-upload:nfs-upload /home/upload
# 修改拥有者!如此,则使用者与目录的权限都设定妥当!
 (3)、启动 portmap 与 nfs 服务:
# /etc/init.d/portmap start
# /etc/init.d/nfs start
# /etc/init.d/nfslock start
  (4)、在 192.168.0.50 这部机器上面测试一下:
  a. 确认远端服务器的可用目录:
# /etc/init.d/portmap start
# /etc/init.d/nfslock start
# showmount -e 192.168.0.100
Export list for 192.168.0.100:
/tmp         192.168.0.*
/home/nfs    (everyone)
/home/upload 192.168.0.*
/home/andy   192.168.0.50
  b. 建立挂载点:
# mkdir -p /home/zzz/tmp
# mkdir -p /home/zzz/nfs
# mkdir -p /home/zzz/upload
# mkdir -p /home/zzz/andy
  c. 实际挂载:
# mount -t nfs 192.168.0.100:/tmp         /home/zzz/tmp
# mount -t nfs 192.168.0.100:/home/nfs    /home/zzz/nfs
# mount -t nfs 192.168.0.100:/home/upload /home/zzz/upload
# mount -t nfs 192.168.0.100:/home/andy   /home/zzz/andy
  整个步骤大致上就是这样。
6、参考资料
  
  
  
  
  http://x.discuz.net/65438/viewspace_19518.html
  
阅读(1291) | 评论(1) | 转发(0) |
给主人留下些什么吧!~~

chinaunix网友2010-08-30 21:48:58

Download More than 1000 free IT eBooks: http://free-ebooks.appspot.com