NFS为 Network FileSystem 的简称,最早之前是由 Sun 这家公司所发展出来的,他的目的就是想让不同的机器、不同的操作系统可以彼此分享个别的档案啦!目前在 Unix Like 当中用来做为 file server 是相当不错的一个方案喔!基本上, Unix Like 主机连接到另一部 Unix Like 主机来分享彼此的档案时,使用 NFS 要比 SAMBA 快速且方便的多了!此外, NFS 的设定真的很简单,几乎只要记得启动 Remote Pocedure Call 这个咚咚 ( 就是 portmap 这个套件啦! ) 就一定可以架设的起来!真是不错啊!不过,如果要达成 Windows 与 Linux 之间的沟通,那么还是以 SAMBA 比较容易啊!无论如何, NFS 还是可以做为小公司或学校单位内部 Unix Like 机器共享 file 的一个 Server 喔! |
例题:
请问我的主机是以 RPM 为套件管理的 Linux distribution ,例如 Red Hat, Mandrake 与 OpenLinux 等版本,那么我要如何知道我的主机里面是否已经安装了 portmap 与 nfs 相关的套件呢? 答: 简单的使用 rpm -qa | grep nfs 与 rpm -qa | grep portmap 即可知道啦! |
[root@test
root]# vi /etc/exports
[欲分享的目录] [主机名称1或IP1(参数1,参数2)] [主机名称2或IP2(参数3,参数4)] |
[root@test
root]# vi /etc/exports
/tmp *(rw,no_root_squash) |
[root@test
root]# vi /etc/exports
/tmp *(rw,no_root_squash) /home/public 192.168.0.*(rw) *(ro) /home/public 192.168.0.0/24(rw) *(ro) |
[root@test
root]# vi /etc/exports
/tmp *(rw,no_root_squash) /home/public 192.168.0.*(rw) *(ro) /home/test 192.168.0.100(rw) |
[root@test
root]# vi /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) |
[root@test
root]# vi /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) |
[root@test
root]# /etc/rc.d/init.d/portmap start<==启动
portmap !
[root@test root]# /etc/rc.d/init.d/nfs start <==启动 NFS |
[root@test
root]# vi /var/log/messages
Nov 16 15:04:45 test portmap: portmap startup succeeded Nov 16 15:04:53 test nfs: Starting NFS services: succeeded Nov 16 15:04:54 test nfs: rpc.rquotad startup succeeded Nov 16 15:04:54 test nfs: rpc.mountd startup succeeded Nov 16 15:04:54 test nfs: rpc.nfsd startup succeeded |
语法:
[root@test root]# exportfs [-aruv] 参数说明: -a :全部挂载(或卸载) /etc/exports 档案内的设定 -r :重新挂载 /etc/exports 里面的设定,此外,亦同步更新 /etc/exports 及 /var/lib/nfs/xtab 的内容! -u :卸载某一目录 -v :在 export 的时候,将分享的目录显示到屏幕上! 范例: [root@test root]# exportfs -rv <==全部重新 export 一次! exporting 192.168.0.100:/home/test exporting 192.168.0.*:/home/public exporting *.linux.org:/home/linux exporting *:/home/public exporting *:/tmp reexporting 192.168.0.100:/home/test to kernel [root@test root]# exportfs -au <==全部都卸载了! |
[root@test
root]# vi /var/lib/nfs/xtab
/home/test 192.168.0.100(rw,sync,wdelay,hide,secure,root_squash, no_all_squash,subtree_check,secure_locks,mapping=identity,anonuid=-2, anongid=-2) |
语法:
[root@test root]# showmount [-ae] hostname -a :在屏幕上显示目前主机与 Client 所连上来的使用目录状态 -e :显示 hostname 这部机器的 /etc/exports 里面的分享目录! 范例: [root@test root]# showmount -e localhost Export list for localhost: /tmp * /home/linux *.linux.org /home/public (everyone) /home/test 192.168.0.100 |
[root@test
root]# netstat -utln
Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State tcp 0 0 0.0.0.0:111 0.0.0.0:* LISTEN <==来自 portmap tcp 0 0 0.0.0.0:817 0.0.0.0:* LISTEN <==来自 rpc.xxxx tcp 0 0 0.0.0.0:1266 0.0.0.0:* LISTEN <==来自 rpc.xxxx udp 0 0 0.0.0.0:2049 0.0.0.0:* <==就是 nfs 的 port udp 0 0 0.0.0.0:814 0.0.0.0:* <==来自 rpc.xxxx udp 0 0 0.0.0.0:1327 0.0.0.0:* <==来自 rpc.xxxx udp 0 0 0.0.0.0:111 0.0.0.0:* <==来自 portmap |
语法:
[root@test root]# rpcinfo [-p] hostname(orIP) -p :显示所有的 port 与 program 的信息! 范例: [root@test root]# rpcinfo -p test.linux.org program vers proto port 100000 2 tcp 111 portmapper 100000 2 udp 111 portmapper 100011 1 udp 1014 rquotad 100011 2 udp 1014 rquotad 100011 1 tcp 1017 rquotad 100011 2 tcp 1017 rquotad 100003 2 udp 2049 nfs 100003 3 udp 2049 nfs 100021 1 udp 1339 nlockmgr 100021 3 udp 1339 nlockmgr 100021 4 udp 1339 nlockmgr 100005 1 udp 1340 mountd 100005 1 tcp 1271 mountd 100005 2 udp 1340 mountd 100005 2 tcp 1271 mountd 100005 3 udp 1340 mountd 100005 3 tcp 1271 mountd |
OK啦!所以我们得先知道一下我们的主机里面有什么?假设我的主机名称是 test.linux.org ,那么我要知道里头有些什么藉由 NFS 分享出来的目录,就给他 showmount 一下啰!
[root@test root]# showmount -e test.linux.org
Export list for localhost:
/tmp *
/home/linux *.linux.org
/home/public (everyone)
/home/test 192.168.0.100
然后呢?假设我要将 /home/public 挂载在我的 /home/nfs/public 底下,那么我就得先有这个目录才行呀!然后再利用 mount 这个指令来挂载 /home/public 这个目录!有点像这样:
[root@test root]# mkdir -p /home/nfs/public <==建立 public 这个目录,加 -p 可以持续增加目录
[root@test root]# mount -t nfs test.linux.org:/home/public /home/nfs/public
挂载的格式:
[root@test root]# mount -t nfs hostname(orIP):/directory /mount/point
[root@test root]# df
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/hda1 1904920 1235380 572776 69% /
/dev/hdb1 976344 115212 810736 13% /backup
test.linux.org:/home/public
1904920 1235376 572776 69% /home/nfs/public <==这个是远程主机的容量
先注意一下挂载 NFS 档案的格式范例喔!呵呵!这样就可以将数据挂载进来啦!请注意喔!以后,只要您进入您的目录 /home/nfs/public 就等于到了 test.linux.org 那部远程主机的 /home/public 那个目录中啰!很不错吧!那么如何将挂载的 NFS 目录卸载呢?就使用 umount 啊!
[root@test root]# umount /home/nfs/public
可能发生的问题:
通常无法挂载的原因有底下这几个:
- 使用者的权限不符:以上面的例子来说明,我的 /home/test 只能提供 192.168.0.0/24 这个网域,所以,如果我在 test.linux.org 这部机器中,以 localhost 来挂载时,就会无法挂载上,这个权限概念没问题吧!那么您可以试试看:
所以啰!如果您发现上面的显示的讯息时,就表示您的主机权限不能够进入该目录啰!如果确定您的 IP 没有错误,那么请回到 /etc/exports 这个档案中,针对您自己的 IP 来进行修正吧!
[root @test root]# mount -t nfs localhost:/home/test /home/nfs
mount: localhost:/home/test failed, reason given by server: Permission denied
- 忘记启动 portmap :
这个最容易被忘记了!就是忘记了启动 portmap 这个服务啦!如果您发现您的 mount 的讯息是这样:或者是:
[root@test root]# mount -t nfs localhost:/home/test /home/nfs
mount: RPC: Port mapper failure - RPC: Unable to receive那么就赶紧将 portmap 启动吧!!并且也需要将 nfs 重新启动喔!
[root@test root]# mount -t nfs localhost:/home/test /home/nfs
mount: RPC: Program not registered
[root@test root]# /etc/rc.d/init.d/portmap start
[root@test root]# /etc/rc.d/init.d/nfs restart- 被防火墙挡掉了:
这个也很容易忘记了!那就是重新设定一下您的防火墙,这包含了两部份,包括 iptables 与 TCP_Wrappers !因为我们启动了 portmap ,这个东西有两个数据需要分享出来,一个是 port 111 需要提供出去,因此您的 iptables 规则当中,需要开放这个 port 喔!有点像这样的几行字要加入您的 iptables rules 当中:如果您已经开放了这个 port 的连接权限,却还是无法连接成功,那么应该就是 TCP_Wrappers 的问题了!检查一下您的 /etc/hosts.deny 里头是否有这行:
iptables -A INPUT -p TCP --dport 111 -j ACCEPT
iptables -A INPUT -p UDP --dport 111 -j ACCEPT果真如此的话,由于 portmap 是由 portmap 这个 daemon 所启动的,所以您就必须要在 /etc/hosts.allow 里面加入这一行:
[root@test root]# vi /etc/hosts.deny
ALL: ALL或者是将 ALL 改成您所想要让他使用 NFS 的网域即可!这样说可以了解了吗?若想进一步了解一下防火墙,请参考前面章节提过的:简易防火墙建置。
[root@test root]# vi /etc/hosts.allow
portmap: ALL
需要注意的是,由于 NFS 使用的这个 RPC 在 client 端连上主机时,那么您的主机想要关机,那可就会成为『不可能的任务』!如果您的 Server 上面还有 Client 在联机,那么您要关机,可能得要等到数个钟头才能够正常的关机成功!嗄!真的假的!不相信吗?不然您自个儿试试看! ^_^!所以啰,建议您的 NFS Server 想要关机之前,能先『关掉 portmap 与 nfs 』这两个东西!如果无法正确的将这两个 daemons 关掉,那么先以 netstat -utlp 找出 PID ,然后以 kill 将他关掉先!这样才有办法正常的关机成功喔!这个请特别特别的注意呢!
好了!一些注意事项讲完了之后,再来呢?对了!又是最重要的安全设定方面的问题了!那么 NFS 可以设定安全的地方有哪里呢?其实还不少呢?由外而内可以这样看:防火墙的基本概念请参考『简易防火墙建置』一文,最好能将该篇文章给他看完,否则还真难了解底下在干嘛~嗯!假设您已经看完该篇短文了,接着下来我们就得要一步一步的接着建立防火墙啰!
- iptables 防火墙设定;
- TCP_Wrappers 防火墙设定;
- /etc/exports 权限设定。
- 使用 iptables 限制大范围联机:
假设我们的 NFS 主要是针对内部网络开放而已,而对于外部网络只有对学术网络开放,亦即是 140.0.0.0/8 ,那么您可以使用这样的语法:这样大致上就可以让 192.168.0.0/24 这个 C Class 的网域与 140.0.0.0/8 这个 A Class 的网域到您的主机里面来,而其它的联机就视您的原本的 iptables 的状态而定喔!
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 限制更细的范围:
事实上,如果您不懂得如何设定 iptables 的话,那也没关系,我们可以使用 TCP_Wrappers 阿!因为要使用 NFS 就必须要通过 portmap 这一关( 因为要使用 RPC 啦! ),而这个 portmap 可以藉由 TCP_Wrappers 来管理!呵呵!太好了!那么就将他联机的范围限制的更小啰!我们可以在 /etc/hosts.allow 里面规定连上 NFS 主机的主机 IP 与名称,假设限制中的主机只有 192.168.0.0/24 这个 C class 及 140.116.44.125 这个主机,以及后面接的是 ncku.edu.tw 的网域可以连上我的 NFS 主机,那么我可以写成这样:呵呵!这样可就设定好啰!很简单的吧!
[root@test root]# vi /etc/hosts.allow
portmap: 192.168.0.0/255.255.255.0
portmap: 140.116.44.125
portmap: .ncku.edu.tw[root@test root]# vi /etc/hosts.deny
portmap: ALL
- 使用 /etc/exports 设定更安全的权限:
这就牵涉到您的逻辑思考了!怎么设定都没有关系,但是在『便利』与『安全』之间,要找到您的平衡点吶!善用 root_squash 及 all_squash 等功能,再利用 anonuid 等等的设定来规范登入您主机的使用者身份!应该还是有办法提供一个较为安全的 NFS 主机的!通常我们都会约略的建议,不要启动 NFS Server ,即使要启动,最好也是针对某个范围来进行目录的分享!并且,『要分使用者层级来管理』会比较好一些喔!底下我们就来实际的在您的机器上面搞一个简单的 NFS server 吧!
- Client 端挂载的问题:
基本上,在 Client 端挂载的时候,为了担心会不小心刚 NFS 端挂进来的具有 SUID 权限档案的程序执行!这个很可能会危害到系统的安全呢!因为 SUID 本来就不是很安全的嘛!所以呢,您这个 root 也可以将 NFS 所分享的目录以较为安全的情况挂载进来!例如:选择 nosuid 也是一个很不错的抉择喔!
[root@test root]# mount -t nfs -o nosuid,ro hostname:/directory /mount/point
假设环境:实地演练:
- 假设我的 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 使用他的家目录啦!
好了,那么请您先不要看底下的答案,先自己动笔或者直接在自己的机器上面动手作作看,等到得到您要的答案之后,在看底下的说明吧!整个步骤大致上就是这样吶!加油喔!
- 首先,就是要建立 /etc/exports 这个档案的内容啰,您可以这样写吧!
大概就是这样子吧!您可以自行测试看看!
[root @test root]# 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)
- 再来,就是要建立每个对应的目录的实际 Linux 权限了!我们一个一个来看:
这样子一来,权限的问题大概就可以解决啰!
1. /tmp
[root @test root]# ll /
drwxrwxrwt 6 root root 4096 Nov 16 09:07 tmp2. /home/nfs
[root @test root]# mkdir -p /home/nfs <==建立所需要的目录
[root @test root]# chmod 755 -R /home/nfs <==修改较为严格的档案权限
将目录与档案设定成只读!不能写入的状态,会更保险一点!3. /home/upload
[root @test root]# groupadd -g 210 nfs-upload <==先建立所需要的 210 这个群组
[root @test root]# useradd -g 210 -u 210 -M nfs-upload <==建立需要的使用者名称
[root @test root]# mkdir -p /home/upload <==建立起目录了!
[root @test root]# chown -R nfs-upload:nfs-upload /home/upload <==修改拥有者!
如此,则使用者与目录的权限都设定妥当啰!4. /home/andy
[root @test root]# ll /home
drwx------ 3 andy andy 4096 Oct 28 13:37 andy
- 启动 portmap 与 nfs 服务:
[root @test root]# /etc/rc.d/init.d/portmap start
[root @test root]# /etc/rc.d/init.d/nfs start- 在 192.168.0.50 这部机器上面演练一下:
1. 确认可用目录
[andy @linux50 andy]$ 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.502. 建立挂载点:
[andy @linux50 andy]$ mkdir -p /home/zzz/tmp
[andy @linux50 andy]$ mkdir -p /home/zzz/nfs
[andy @linux50 andy]$ mkdir -p /home/zzz/upload
[andy @linux50 andy]$ mkdir -p /home/zzz/andy3. 实际挂载:
[andy @linux50 andy]$ su <==通常 Linux 只允许 root 来挂载!
[root @linux50 andy]# mount -t nfs 192.168.0.100:/tmp /home/zzz/tmp
[root @linux50 andy]# mount -t nfs 192.168.0.100:/home/nfs /home/zzz/nfs
[root @linux50 andy]# mount -t nfs 192.168.0.100:/home/upload /home/zzz/upload
[root @linux50 andy]# mount -t nfs 192.168.0.100:/home/andy /home/zzz/andy
[root @linux50 andy]# exit
在 LPI 网站 http://www.lpi.org 里面提到的,关于 NFS 的考试题库的地方,只有在 LPI level 1 的 102 ,里面的 topic 113 Networking Services ,第四点当中,简易的 NFS 设定。强调的是『应试者需了解 NFS 的设定、启动与关闭的关系』至于会考的档案与指令可能有这些:
- /etc/exports
- /etc/fstab
- mount
- umount