WAFL与系统安全
WAFL —— NetApp的文件服务器
WAFL:Write Anywhere File Layout —— NetApp 设计的企业级文件系统
- 设计目标
- 请求服务速度快:吞吐率(op/s)更多,I/O带宽更高
- 支持大文件系统,且文件系统不断增长
- 高性能软件RAID
- 宕机后快速恢复
- 独特之处
- 磁盘布局受 LFS 启发
- 引入快照
- 使用 NVRAM 记录日志(写前日志)
inode、间址块和数据块
- WAFL 使用4KB块
- inode:借鉴 UNIX FS
- 16个指针(64B)用于文件块索引
- 文件大小 <= 64B
- 文件数据直接存储在 inode中
- 文件大小 <= 64KB
- inode存储在16个指向数据块的指针
- 文件大小 <= 64MB
- inode存储在16个指向间址块的指针
- 每个间址块存储1024个指向数据块的指针
- 文件大小 > 64MB
- inode存储在16个指向二级间址块的指针
WAFL的磁盘布局
- 主要数据结构
- 一个根 inode:整个FS的根,位于磁盘上固定位置
- 一个inode file:包含所有inode
- 一个block map file:指示所有空闲块
- 一个i-node map file:指示所有空闲inode
为什么将元数据存储于文件中?
- 元数据块可以写在磁盘上任何位置
- 这是"WAFL"名字的由来,Write Anywhere File Layout
- 使得动态增加文件系统的大小变得容易
- 增加一个磁盘会引发inode个数的增加
- inode保存在文件,扩展inode文件大小即可
- 能够通过 Copy-on-Write 来创建快照
- COW:未写前共享数据,写时拷贝
- 新的数据和元数据都可以COW写到磁盘上的新位置
- 固定元数据位置无法使用COW,否则无法定位元数据
快照(snapshot)
- 快照是文件系统的一个只读版本 – 1993 年提出
- 成为文件服务器必备特性
- 快照用法
- 系统管理员配置快照的个数和频率
- 最初系统能支持 20 个快照
- 用快照可以恢复其中任何一个文件
快照的实现
WAFL:所有的块构成一棵树
- 创建快照
- 复制根 inode
- 新的根 inode 用于当前的 Active FS
- 旧的根 inode 指向快照
- 创建快照之后
- 第一次写一个块: 把从它到根的数据块都复制(COW)
- Active FS 的根 inode 指向新数据块
- 写数据块
- 后续对这些数据块的写不再触发 COW
- 每个快照都是一个一致状态的只读 FS
快照数据结构
Block Map File —— 每个 4KB 磁盘块对应一个 32位的表项
- 表项值为0:该块为空闲块
- 第0位=1:该块属于活动文件系统
- 第1位=1:该块属于第一个快照
- 第2位=1:该块属于第二个快照
...
快照创建
- 问题
- 创建快照时,除了拷贝根inode,需要把缓存的文件块写回磁盘
- 此时,可能仍然有很多文件写请求到来
- 若这些写请求都不处理,会导致文件系统长时间挂起
- WAFL的解决方案
- 在创建快照前,将块缓存中的脏块标记为"in-snapshot",表示要写回磁盘
- 所有对"in-snapshot"缓存块的修改请求被挂起
- 没有标记为"in-snapshot"的缓存数据可以修改(即处理写请求),但不能写回磁盘
- 本质:区分需要被写回的脏块和其他块,减少挂起的写请求数量
- 步骤
- 为所有"in-snapshot"的缓存块分配磁盘空间
- 包括数据、inode
- 更新 block map file
- 对每个表项,将 Active FS位的值(即1)拷贝到新快照位
- 刷回
- 把所有的"in-snapshot"缓存块写到它们新的磁盘位置
- 每写回一个块,重启它上面被挂起文件请求
- 复制根inode
- 为所有"in-snapshot"的缓存块分配磁盘空间
- 性能较快
快照删除
- 删除快照的根inode
- 清除block map file中的位
- 对于block map file的每一个表项,清除与该快照对应的位
文件系统一致性
- 定期创建一致点
- 一致点:存储控制器中使用 NVRAM 缓存的数据被刷回磁盘,并更新了文件系统中相应的指针
- 每10秒创建一个一致点
- 特殊的内部快照,用户不可见
- 在一致点之间的多个请求
- 第i个一致点
- 若干写操作
- 第 i+1 个一致点(自动增长)
- 若干写操作
- ...
- 宕机恢复
- 将文件系统恢复到最后一个一致点
- 最后一个一致点之后到宕机前的写操作:靠日志进行恢复
非易失RAM(Non-Volatile RAM)
- NVRAM
- 闪存:写比较慢 vs NVRAM
- 带电池的 DRAM:快
- 电池容量有限,持续时间不长
- DRAM容量有限
- 日志写入 NVRAM
- 记录自上一个一致点以来的所有写请求
- 正常关机:先停止 NFS 服务,再创建一个快照,然后关闭 NVRAM
- 宕机恢复:用 NVRAM 中的日志来恢复从最后一个一致点以后的修改
- 使用两个日志
- 一个日志写回磁盘时,另一个日志写入 NVRAM 中缓冲
- 可以避免写日志时,无法处理新的写请求
安全保护
安全与保护
- 数据机密性:未经许可,不能看到数据
- 任何用户不能读写其他用户的文件
- 数据完整性:未经许可,不能修改或删除数据
- 数据在网络传输过程中被拦截和修改,可以采用加密
- 系统可用性:干扰系统使得它不可用
- 给一个服务器发送大量的请求
保护:策略与机制
- 安全策略:定义目标,即要达到的效果
- 通常是一组规则,定义可接受的行为和不可接受的行为
- 例子
- /etc/password 文件只有 root 能写
- 每个用户最多只能用 50GB 的磁盘空间
- 任何用户都不允许读其他用户的 mail 文件
- 机制:用什么样的方法来达到目标
保护机制
- Authentication(身份认证)
- 验明身份
- UNIX:密码/口令
- 类比机场:身份证或护照
- 验明身份
- Authorization(授权)
- 决定"A是不是准许做某件事"
- 通常使用角色(role)定义授予的操作权限,使用简单的数据库保存角色定义
- Admission Control(访问控制)
- 做出“访问是否准许”的决定
- 有时和系统承载压力相关联,系统负载高时,进行访问控制
身份认证
- 通常是用密码来验证
- 一串字符(字母 + 数字)
- 用户必须记住密码
- 密码是以加密形式存储
- 使用一种单向的“安全Hash”算法
- 缺点
- 每个用户都要记很多密码
- 弱密码风险,"dictionary attack"
访问控制表(ACL)
- 每个对象有一个 ACL 表
- 定义每个用户的权限
- 每个表项为 <user,privilege>
- 简单,大多数系统都采用
- UNIX 的 owner,group,other
- 实现
- ACL 实现在内核中
- 在登录系统时进行身份验证
- ACL 存储在每个文件中或文件元数据中
- 打开文件时检查 ACL
Capabilities
- 超级用户具有特权,可以执行高权限操作
- 例如passwd,chown,chmod等
- 权能:将超级用户特权细分,分成不同的、细粒度权限
- CAP_CHOWN: 对文件 UIDs 和 GIDs 做修改
- CAP_KILL: 绕过发送信号时的权限检查
- CAP_NET_ADMIN: 执行多种网络有关的操作
- 可以为每个线程独立设置权能
- 实现
- 权能表保存在内核
访问控制
- 需要一个可信权威
- 进行访问控制
- ACL或权能表都需要保护
- 内核是一个可信权威
- 内核什么事可以做
- 如果有 bug ,整个系统都可能被破坏
- 它越小、越简单越好
- 安全的强度由保护系统链上最薄弱的环节决定
一些简单的攻击
- 滥用合法权利
- UNIX: root能做任何事情
- 例如:读你的 mail 文件, 以你的身份发送email, 把你的邮箱删除, ...
- UNIX: root能做任何事情
- 拒绝服务(DoS)
- 耗尽系统所有资源
- 例如
- 运行一个 shell
脚本:
while (1) {mkdir foo; cd foo;} - 运行一个 C
程序:
while (1) {fork(); malloc(1000)[40]=1;}
- 运行一个 shell
脚本:
- 偷听
- 侦听网络上传输的包