4. NFS导出策略与访问控制

在 ONTAP 中,NFS 客户端能否挂载某个卷、以什么权限访问、root 用户是否被降权,并不是由卷本身单独决定的,而是由导出策略(export policy)统一裁决。可以把导出策略理解成一张“准入规则表”:它把“哪些客户端”和“以什么权限访问哪个卷”绑定在一起。一个 SVM 可以拥有多个导出策略,每个卷(或 qtree)绑定其中一个;当 NFS 请求到达时,ONTAP 先根据客户端 IP 找到匹配的规则,再决定允许或拒绝,以及授予只读还是读写。

理解导出策略的关键,是分清三个层次:策略 → 规则 → 匹配结果。策略是容器,规则是其中的条目,每条规则包含客户端匹配条件、访问权限(ro/rw)、允许的访问协议,以及安全风格等属性。规则按顺序自上而下匹配,第一条命中的规则生效,后续规则不再评估。因此规则顺序本身就是安全边界的一部分,把宽松规则放在前面会覆盖后面的严格规则。

NFS 导出策略匹配与访问裁决流程 NFS 客户端 IP: 10.20.30.15 UID: 0 (root) 导出策略:policy_prod 规则1 clientmatch: 10.20.30.0/24 ro=rw root_squash sec=sys 规则2 clientmatch: 10.20.40.0/24 ro=ro root_squash sec=sys 规则3 clientmatch: 0.0.0.0/0 ro=never (默认拒绝) 自上而下匹配,首条命中即生效 允许读写 root 映射为匿名 UID 65534 允许只读 写操作返回 EROFS 拒绝访问 挂载失败 / Permission denied root squash 与匿名身份映射 客户端 root (UID 0) 发起写请求 root_squash 生效 UID 0 → 匿名 UID 65534 卷内文件属主判定 按匿名 UID/GID 检查权限位

客户端匹配:从最具体到最宽松

clientmatch 支持多种写法:单个 IP、CIDR 网段、主机名、域名通配(如 *.example.com),以及 0.0.0.0/0 表示任意客户端。匹配的粒度越具体,越应该放在前面。一个常见的生产策略结构是:先放管理网段(读写 + root_squash),再放应用服务器网段(读写),然后放办公网段(只读),最后用 0.0.0.0/0 加 ro=never 兜底拒绝。这样即使新增了未规划的客户端,也不会被意外放行。

需要特别注意的是,规则顺序决定结果。如果先写了 0.0.0.0/0 ro=rw,那么后面所有更严格的规则都永远不会被评估。排查“为什么某客户端能写”时,第一步就是按顺序检查哪条规则先命中。

只读与读写:ro 与 rw 的语义

每条规则通过 ro 参数控制访问权限,取值有 ro(只读)、rw(读写)和 never(拒绝)。只读规则下,客户端可以挂载、可以读文件和列目录,但任何写操作(创建、修改、删除、重命名)都会失败,典型错误是 Read-only file system(EROFS)。读写规则则允许完整的文件操作,但最终能否写入还取决于文件系统权限位和属主关系。

这里有一个容易混淆的点:导出策略的 ro/rw 是“卷级闸门”,而 Unix 权限位是“文件级闸门”。两者是“与”的关系——导出策略允许读写,但文件权限是 644 且属主不是该用户,写入依然会被拒绝。排查权限问题时,要同时看这两层。

root squash:为什么要给 root 降权

NFS 客户端上的 root 用户默认拥有极大权限。如果服务端不做处理,客户端 root 就能以 UID 0 身份读写卷内任意文件,这是严重的安全风险。root squash 的作用就是:当请求来自 UID 0 时,ONTAP 将其映射为匿名用户(默认 UID 65534,即 nobody),再按匿名身份去检查文件权限。

与 root squash 相关的还有两个变体:root_squash 只降权 UID 0;all_squash 会把所有用户都映射为匿名用户,适合完全公开的只读共享;none 则不降权,仅在对内可信环境中谨慎使用。默认情况下,新建导出策略规则通常启用 root_squash,这是推荐的安全基线。

匿名 UID/GID 与安全风格

匿名用户的 UID 和 GID 可以在规则中通过 anonuid 和 anongid 指定。默认是 65534:65534,但有些环境会统一映射到某个特定账号,以便卷内文件属主一致。例如把 anonuid 设为 60001,那么所有被 squash 的请求都以 60001 身份访问,卷内相应文件需要把属主或组权限开放给 60001。

安全风格(sec)决定认证方式:sys 使用标准 Unix UID/GID(AUTH_SYS),是 NFSv3 和多数 NFSv4 场景的默认值;krb5、krb5i、krb5p 则分别提供 Kerberos 认证、完整性校验和加密,用于对安全要求更高的环境。安全风格必须与客户端挂载参数一致,否则会出现 Permission denied 或挂载失败。

排查 NFS 权限问题的顺序建议:先确认客户端命中了哪条导出规则(export-policy rule show),再看该规则的 ro/rw 与 sec,然后检查 root squash 是否把当前用户降权,最后核对卷内文件属主与权限位。四层依次排除,比盲目改权限高效得多。

一个可参考的规则配置示例

下面给出一个面向生产环境的导出策略规则示例,包含管理网段读写、应用网段读写、办公网段只读和默认拒绝四类规则。示例参数属于合理假设,实际部署时请按真实网段和账号调整。

# 创建导出策略
export-policy create -vserver svm_prod -policyname policy_prod

# 规则1:管理网段,读写,root_squash
export-policy rule create -vserver svm_prod -policyname policy_prod \
  -ruleindex 1 -clientmatch 10.20.30.0/24 -rorule any -rwrule any \
  -superuser sys -anonuid 65534 -anongid 65534

# 规则2:应用服务器网段,读写
export-policy rule create -vserver svm_prod -policyname policy_prod \
  -ruleindex 2 -clientmatch 10.20.40.0/24 -rorule any -rwrule any \
  -superuser sys -anonuid 65534 -anongid 65534

# 规则3:办公网段,只读
export-policy rule create -vserver svm_prod -policyname policy_prod \
  -ruleindex 3 -clientmatch 10.20.50.0/24 -rorule any -rwrule never \
  -superuser sys -anonuid 65534 -anongid 65534

# 规则4:默认拒绝
export-policy rule create -vserver svm_prod -policyname policy_prod \
  -ruleindex 4 -clientmatch 0.0.0.0/0 -rorule never -rwrule never \
  -superuser sys

# 将策略绑定到卷
volume modify -vserver svm_prod -volume vol_data -policy policy_prod

配置完成后,可以用 export-policy rule show -vserver svm_prod -policyname policy_prod 查看规则顺序和参数,确认没有把宽松规则误放在前面。客户端侧则用 showmount -e <svm_lif> 查看导出的卷列表,再实际挂载并尝试读写,验证 ro/rw 是否符合预期。若只读客户端尝试写入,应看到 EROFS;若被拒绝的客户端尝试挂载,应看到 Permission denied。通过“规则顺序 + 权限语义 + 身份映射 + 安全风格”四个维度交叉验证,才能确保导出策略既安全又可用。