NFS
1、NFS(网络文件系统Network File System)可能启动的进程有nfsd、rpc.mountd、rpc.statd、lockd(内核态)、rpc.idmapd、rpc.gssd、rpc.svcgssd。nfsd使用2049的TCP和2049的UDP端口,其它的端口号由portmap随机提供(portmap自己监听在111端口);
2、NFS的各个版本概述:
a> NFS v1是SUN公司研发的,包含在Sun的操作系统里,没有单独公开发行过;
b> NFS v2是最原始的NFS协议,在RFC 1094中描述。基于UDP协议,最大单个文件4G;
c> NFS v3在RFC 1813中描述,相对于v2增加了TCP协议支持,安全的async异步写入支持,服务器端访问控制,支持大于16Y的单个文件大小(64bit),提高了一次读写的最大大小,某些版本可以为RPC开启基于kerberos的身份验证(RHEL使用的版本就可以)。v3相对于v2在性能上是一个大的跃进,但从安全的角度来看并没有多少提升;
d> NFS v4在RFC 3530中描述,相对于v3,它把lock和mount都整合进了核心协议中(原来在辅助协议),开发了新的ACL机制,引入对UTF8字符集的支持。NFS v4要求所有的实现都必须支持kerberos的身份验证(RPCSEC_GSS)(替代原有的基于UID、GID的身份验证),www.linuxidc.com 要求所有实现必须支持多种加密传输模式。从安全角度而言NFS v4是一个大的跃进,但目前它没有v3版本使用得广泛;
3、NFS v3的连接过程:
a> 客户端问服务器端的portmap:rpc.mount目前的用哪个端口?
b> 客户端向服务器端的rpc.mount请求挂载NFS;
c> 服务器端的rpc.mount判断权限后给客户端一个文件句柄;
d> 客户端使用这个句柄与服务器端的nfsd交流(使用TCP或UDP的2049端口),以读写文件;
e> 文件锁是由lockd和rpc.stats管理的;
4、NFSv3协议的服务器端是无状态的,所以就算机器重启了,NFS服务起来以后,客户端依然可以拿着旧文件句柄继续读写文件。但是服务器端的lockd进程是有状态的,重启就有点麻烦,解决方案是服务器端的rpc.statd让客户端报告自己手里的锁,然后重新让lockd恢复锁状态。这种锁状态机制是到v3版本才引入的;v2版本在crash之后会出现锁错误;
5、NFS v3的验证机制:
a> NFS v3及其附属协议采用标准的RPC AUTH_SYS(又称AUTH_UNIX)机制验证挂载后的客户端对具体文件的权限,服务器完全信任客户端声名的自己的权限(其实不能被称为是“验证”了);
b> 大概过程就是客户端会在读写之前告诉服务器自己的UID和GID,然后NFS就把这些ID视同自己系统上的ID来验证权限;
c> 客户端可以很容易伪造出高权限的ID以达到攻击的目的,防御的临时解决之道是不让NFS暴露在公有网络上且不打开NFS的root权限(是比较弱的防御);
d> 还有一个麻烦是,不同客户端上同一个username的UID想保持同步是件不容易的事;
e> 为了解决NFS 验证机制的不足,www.linuxidc.com 为NFS引入的解决之道就是kerberos(也就是RPCSEC_GSS验证机制);
6、NFS的UID/GID同步问题初步讨论:
a> 最简单的办法就是用root_squash或者all_squash来做UID映射,把所有用户都映射成匿名用户。需要注意的是匿名用户的UID其实是-2,所以65534其实只是在16bit用户ID的系统上的表现,在一些32bit用户ID的系统上-2会被表现为4294967294;
b> pam_lisfile.so和pan_limits.so这两个PAM模块可以帮助我们确保NFS用户不会得到shell登录权限;
c> UID和GID在不同客户端之间不同的根治方法是使用NIS或者LDAP的方式直接把UID/GID统一掉;
7、NFS v3的安全怎么做?
a> 不要把包含配置文件的目录export出去;
b> export整个文件系统的根出去,而不是export文件系统中某个目录出去。因为即使只是export一个目录出去,攻击者也可能通过猜测的方式得到文件系统中其它目录的读写权限。比如说一个ext3挂载在/mnt/下了,用NFS export/mnt/data1/出去,攻击者就可能读写/mnt/data2/下的文件。这显然不是我们希望的,因此不如干脆共享整个文件系统(也就是/mnt/)出去。或者也可以使用NFS的substree_check来帮我们做检查来防止这种入侵,但是这个选项会较大幅度降低NFS的性能;
c> 如果一个文件系统挂载点是另一个文件系统的子目录,那么父系统开启crossmnt或者子系统开启nohide就可以把两个文件系统都共享出去,使用这个选项的时候要小心,别共享了自己不想共享的内容出去;
d> 虽然nfsd固定使用2049端口,但是lockd、mountd、statd都使用portmap随机分配的端口,这让防火墙很难配置,而且还可能占用还没起来的其它服务的端口。可以在/etc/sysconfig/nfs中把这些进程的端口都配置成固定的,这样配置防火墙(只放行自己信任的IP)就容易了;
e> NFS基于IP的认证方式让伪造身份成为可能,基于AUTH_SYS(UID/GID)的授权方式让越权变成可能,明文的、没有完整性校验(有校验网络传输完整,没有安全性完整校验)的传输协议让嗅探和篡改变成可能。要解决这些问题,就要采用NFS v4了;
f> NFS是个十分复杂的服务,很多部分要求root权限运行,还运行在内核态里。如果不是必要就尽量不要启动它,以防止未来发现的漏洞给攻击者可乘之机;
8、rpcinfo -p可以查看portmap分配出去的端口;
9、NFS v4的相对v3的变化:
a> NFS版本4把周边附属协议的lockd、rpc.mountd、rpc.statd都整合进了主协议中,进程也都整合进了nfsd里。整个服务的进程结构精简了很多,防火墙只需要开放2049和111端口NFS即可正确提供服务;
b> 新增了一个必须运行的rpc.idmapd进程(服务器端和客户端都要运行),支持RPC验证协议,用于保持username-uid的映射,解决了之前版本的那个麻烦的UID不一致问题。当然,还是可以选择AUTH_SYS的验证方式,自己去弄那麻烦;
c> NFS v4原生可以支持基于kerberos的RPCSEC_GSS安全认证,开启这个功能的话能简化配置,提高安全性,也解决了UID不一致的问题;
d> 精简的协议带来了一定的速度提升(约10%,详见http://www.Fedoraforum.org/forum/showthread.php?t=219433);
e> NFSv4仍在继续开发中,见www.nfsv4.org;
10、NFS v4引入了一个叫做pseudo filesystem(伪文件系统)的机制,网上挺多针对它的讨论的,挺多人认为这个纯属脱裤子放屁,教材上也没提它能带来什么好处。大概意思就是说要先选一个目录表明fsid=0作为一个伪文件系统的根,然后所有需要export的目录和文件系统都挂载在这个伪文件系统的下,就如同是它的一个子目录。我翻了一下RFC3530(http://www.ietf.org/rfc/rfc3530.txt),RFC里的意思呢,主要是为了解决命名空间的问题,有了这个伪文件系统根,再加上主机名,基本命名空间就都散开不会冲突了。再一个,用了这个之后客户端直接用READDIR就能遍历服务器端的所有export,特别在服务器新export了东西以后,客户端不用做出任何更改便可直接使用新的东西(如果有权限的话)。更详细的见RFC3530 7.3.0;
11、RFC2203介绍了NFS如何利用kerberos的验证机制(又唤RPCSEC_GSS),v3和v4版本都可以用,需要在客户端使用rpc.gssd,在服务器端使用rpc.svcgssd来完成沟通。rpc.svcgssd会通过GSSAPI去获得kerberos的验证信息,而rpc.gssd则负责去向kerberos获得权限认证。它们也会帮忙解决username-uid/groupname-gid映射的麻烦。但是启用了kerberos验证就不能使用基于IP的验证了(当然iptables是可以用的)在Linux 2.6.23和nfs-utils1.1.1后变为可能;
12、kerberos有几种帮助NFS做安全的模式,这些模式需要在服务器端/etc/exports中指定:
a> krb5。仅使用kerberos来做用户身份验证;
b> krb5i。除了之上,再加上安全的数据完整性校验(基于对称密钥的签名);
c> krb5p。除了之上,再加上把所有数据都加密;
13、目前SELinux还没有能力在NFS的服务器和客户端之间传递安全上下文,这个工作正在进行中,所以目前服务器端和客户端分别有自己的安全上下文(客户端的上下文是统一的,自己设置的)。SELinux为NFS预置了一些很有用的布尔值,如nfs_export_all_rw和use_nfs_home_dirs;
14、cat /proc/net/rpc/nfs4.idtoname/content可以看到NFSv4的名字映射;
15、客户端完全重启NFSv4模块的方法,顺序执行以下:
a> umount -at nfs4;
b> 停止rpc.gssd、rpc.idmapd、autofs;
c> 重启内核模块:modprobe -r nfs lockd fscache nfs_acl rpcsec_gss_krb5 authrpcgss autofs4;
d> 启动rpc.gssd、rpc.idmapd、autofs;
e> 重新挂载NFSv4文件系统;
16、整理一下启用kerberos验证的NFSv4的几个要素:
a> kerberos机制正常;
b> 服务器正确下载了自己principal的keytab;
c> rpc.svcgssd和rpc.gssd正常启动;
d> TGT正确且没过期(可用klist查看);
e> rpc.idmapd正确配置了;
17、用于NFS的kerberos目前只能用des-cbc-md5的加密方式(要在kadd的时候声名);
18、NFS v3虽然可以使用kerberos,但并没有v4支持地那么完整。由于它的MOUNT协议还是只支持AUTH_SYS,因此还是需要给未授权用户MOUNT的权限,当然把它们限制到只读是可以的;
19、在高可用的环境下,虽说NFS的句柄是服务器端无状态的,即在服务器重启之后依然可用,但如果NFS服务从一个服务器飘到另一个服务器上提供服务了,那么旧的文件句柄则可能会因为fsid的改变而变得不可用。此时,在配置文件中指定每一个export的fsid是个不错的主意;