NFS即网络文件系统,它允许网络中的计算机之间通过TCP/IP网络共享资源。在NFS的应用中,本地NFS的客户端应用可以透明地读写位于远端NFS服务器上的文件,就像访问本地文件一样。

我们通过捕获的文件进行分析:

nfs.jpg (163.57 KB, 下载次数: 17)

2016-8-10 15:52 上传

1:客户端向连接服务器的NFS进程,于是询问应该使用哪个端口(GETPORT),数据包中(Reply In 2)表示2号数据包是对该数据包的回应。

2:服务器回应说使用2049端口通信,这里的(Call In 1)表示是对1号数据包的回应。

3:客户端端尝试连接服务器的NFS进程,并且判断通信端口是否被防火墙拦截,还有NFS服务器是否启动。

4:服务器回应,收到请求,可以连接。

5:客户端想连接服务器的挂载:服务,询问该服务的端口。由于mount服务的端口号是比较随机的,因此客户端必须要进行询问。

6:服务器回应自己的mount端口号为1234.

7:客户端尝试连接mount进程。也会判断1234号端口是否被防火墙是否拦截,还有mount服务是否开启。

8:服务器回应,收到请求,可以连接。

9:客户端请求挂载(mount)“/code”这个共享目录。NFS主要提供了/code和/document两个共享目录。

10:服务器同意客户端请求。我们通过观察Packet Details面板内容,服务器要求客户端使用file handle 0x75a18429进行目录的访问。

nfs1.jpg (85.63 KB, 下载次数: 20)

2016-8-10 15:53 上传

11:客户端尝试是否可以连接上NFS进程。

12:服务器回应可以连接。其实这两步完全没有必要,因为NFS一直处于连接的状态。这个问题估计和我们之前讨论的Windows中FTP的主动和被动模式一样,是开发人员的疏忽造成的。如果他们当时能够熟练使用Wireshark进行测试,相信不会出现这样的问题。

13:客户端想要查看文件句柄为0x75a18429的文件属性。

14:服务器为客户端提供了该文件的大小等属性,然后在客户端就可以看到这些信息了。

15:客户端要求查看文件句柄为0x75a18429的文件的属性。

16:服务器为客户端提供该文件的属性。(这两步是多余操作,原因可能同上)

我们利用Wireshark就可以很清楚的判断问题的所在,如果portmap请求没有得到回复,这就说明很可能是防火墙对相关端口进行了拦截;如果发现mount请求被服务器拒绝了,那么可以考虑检查一下共享目录的访问设置。

通过观察数据包来解释NFS文件传输时的所有者问题,如下图:

nfs2.jpg (110.46 KB, 下载次数: 18)

2016-8-10 15:55 上传

从上图的Credentials中可以看到,创建文件的时候数据包 中并没有用户名admin字样,而是使用admin的UID 501来代替所有者用户名,因为NFS协议只认UID不认用户名,当使用admin创建一个用户时会将UID 501写入到文件属性中,但是当另一个客户端上的用户查看文件属性时就看到了UID 501,但是在不同客户端上的UID对应的用户名一般都是不相同的,所以不同客户端看到的所有者就不同了。那么为了防止这样的问题,需要大家在实际的操作中,保证每个客户端的UID与用户名的映射是一致的。

NFS读取文件的过程

我们读取以下捕获文件,分析读取文件abc.txt的过程:

nfs3.jpg (128.92 KB, 下载次数: 24)

2016-8-10 16:06 上传

我们先对文件进行筛选,只留下NFS数据包。我们来逐条分析每个数据包:

1:客户端向服务器询问,是否可以进入FH : 0x75a18429,也就是/code里面。

2:服务器回应允许进入。

3:客户端想要查看这个目录鹿毛的文件和文件夹的句柄。

4:服务器回应客户端的请求,我们查看Packet Details内容:

nfs4.jpg (147.39 KB, 下载次数: 12)

2016-8-10 16:06 上传

返回文件名为abc.txt,文件句柄为0x056560e1。

5:客户端查询abc.txt也就是0x056560e1的文件属性。

6:服务器回应该文件的权限、UID、GID以及文件大小等信息。

7:客户端询问是否可以打开abc.txt文件。

8:服务器同意了请求,并给予了响应权限。

9:从文件abc.txt的偏移量为0的位置,也就是abc.txt文件的开头位置,读取(READ)131072字节的数据。

10:从文件abc.txt的偏移量为131072的位置,再读取131072字节的数据。

148:服务器回应客户端,允许读取131072字节的数据。

288:同上。

这样,NFS就完成了文件的读操作。

NFS写入文件操作

我们还是要对文件数据包进行筛选:

nfs5.jpg (201.39 KB, 下载次数: 20)

2016-8-10 16:08 上传

1:客户端向服务器发出请求,要求进入FH : 0x75a18429,也就是/code里面。

2:服务器接受请求。

4:客户端询问服务器,查找(LOOKUP)名字为abc.txt文件,因为要判断服务器上是否存在这个文件,若不存在就继续写入,如果存在就要询问是否需要覆盖原文件。

5:服务器回应没有这个文件。

6:客户端要求创建(CREATE)一名为abc.txt的文件。

7:服务器答应了这个请求,我们通过Packet Details面板中展开NFS区段,就可以找到文件的file handle是0x056560e1。

nfs6.jpg (41.46 KB, 下载次数: 13)

2016-8-10 16:10 上传

69:客户端要求文件句柄为0x056560e1文件偏移为0的位置,也就是abc.txt文件的开头,写入(WRITE)131072个字节。

104:服务器回应已经写入完成。

130:客户端要求在文件abc.txt文件的偏移131072的位置写入(WRITE)131072个字节。

302:服务器回应已经写入。

306:客户端询问,刚才所写的数据是否已保存,也就是COMMIT操作,只有经过COMMIT过的数据才算是真正的写好了。

307:服务器回应都保存成功。

308:客户端询问刚才写入的文件属性(GETATTR)。

309:服务器回复客户端,文件的权限、UID、GID等信息。

习题

di1.jpg (22.89 KB, 下载次数: 17)

2016-8-10 16:10 上传

以上四个选项中,除了Windows系统其他三个系统都是基于linux内核的,都使用NFS协议,Windows并没有使用这个协议。

di2.jpg (23.18 KB, 下载次数: 20)

2016-8-10 16:11 上传

通过上面的实验可知只有经过COMMIT过的数据才算是真正的写好了。

di3.jpg (22.77 KB, 下载次数: 19)

2016-8-10 16:14 上传

写入文件之前,我们需要先判断文件是否存在,要使用LOOKUP操作。

di4.jpg (25.7 KB, 下载次数: 15)

2016-8-10 16:15 上传

对于写操作而言,如果我们在挂载的时候没有指定任何参数,那么就会采用默认的async(异步)写的方式。而与之相对应的是sync(同步)方式。