原力注入

FUSE 文件系统 - 使用 securefs 实现文件系统透明加解密

题外话:最近作者去了西安,对唐朝的历史产生了浓厚的兴趣,B 站 up 主渤海小史 笔者关注了一两年了,最近正好出了一半书《大唐气象》,看了几期视频,感觉非常好,推荐给大家!

1. 背景

为了满足应用程序对敏感数据的安全存储需求,我们需要一个透明的文件系统。该文件系统需要能够在应用程序无需额外处理的情况下,自动完成数据的加密与解密,以保证数据的机密性和完整性。

相关文章:

Linux 用户态文件系统 FUSE 简介

Linux FUSE 文件系统的相关一些管理操作

基于 FUSE 的简单文件系统实现

2. securefs

2.1 securefs 介绍

securefs 是一个基于 FUSE 的用户态文件系统,专注于提供安全、透明的文件加密功能。其主要特点包括:

  • • 文件加密:透明加密文件内容与文件名,用户无需感知。

  • • 跨平台支持:兼容 Linux、macOS 和 Windows。

  • • 高性能:通过分块加密和多线程加速提升操作效率。

  • • 灵活配置:支持用户选择加密算法和模式。

  • • 易用性:通过简单的命令行工具实现挂载、解挂载与加密文件夹管理。

主页:https://github.com/netheril96/securefs

完整命令参考:https://github.com/netheril96/securefs/blob/master/docs/usage.md

2.2 securefs 原理与关键技术点

2.2.1 文件系统原理

  • • FUSE 支持:

    • • 使用 FUSE 提供用户态文件系统接口,挂载加密文件夹。

    • • 实现了 read, write, readdir 等核心回调函数。

  • • 透明加密:

    • • 文件内容在写入时加密,读取时解密,用户操作无感知。

    • • 文件名和元数据(如大小、时间戳)也可加密。

2.2.2 加密机制

  • • 文件内容加密:

    • • 使用分块加密方式(通常 4KB 或 64KB),支持随机访问。

    • • 支持 AES-CBC 和 AES-GCM 等模式:

      • • AES-CBC 需要唯一的初始化向量(IV)。

      • • AES-GCM 提供数据完整性验证。

  • • 文件名加密:

    • • 加密后的文件名存储在底层文件系统中,通过 Base64 或 Hex 编码。

  • • 密钥管理:

    • • 使用 PBKDF2 或 Argon2 派生强加密密钥。

    • • 加密密钥仅在内存中临时存储,避免明文存储。

2.2.3 性能优化

  • • 分块加密:仅对访问的块执行加解密操作,减少不必要的开销。

  • • 缓存机制:对解密后的数据进行短期缓存,减少重复计算。

  • • 多线程并发:利用多核 CPU 性能,加速加密和解密过程。

2.2.4 跨平台实现

  • • 基于 libfuse(Linux/macOS)和 WinFSP(Windows)实现跨平台支持。

  • • 使用 OpenSSL 等通用密码库确保加密兼容性。

2.3 安全性分析

2.3.1 数据加密

  • • 使用 AES 算法提供高强度数据加密,保障机密性。

  • • AES-GCM 提供完整性验证,防止数据被篡改。

2.3.2 文件名加密

  • • 文件名加密避免泄露文件结构信息,但可能对性能有一定影响。

2.3.3 抗暴力破解

  • • 密钥派生函数(PBKDF2 或 Argon2)加入随机盐,增强密码抗性。

  • • 限制暴力破解所需的计算资源,提高安全性。

2.3.4 降低攻击面

  • • 用户态文件系统限制对内核的直接操作,减少潜在漏洞。

  • • 不在磁盘存储明文密钥,避免密钥泄露风险。

2.4 应用场景

  • • 个人隐私保护:

    • • 适合对本地敏感文件夹进行加密存储,保护隐私。

  • • 企业数据保护:

    • • 提供透明的加密存储,适合企业文件存储和共享的安全需求。

  • • 云存储安全:

    • • 加密数据后上传至云端,确保数据即使被窃取也不可解读。

  • • 安全文件传输:

    • • 通过挂载加密的文件夹,保障传输过程中的数据安全。

3. 验证

目标设计

  • • 使用 securefs 将 /encrypted 目录作为加密文件存储路径;

  • • 将 /mnt/secure 作为明文视图挂载点,应用程序通过 VFS 接口访问 /mnt/secure,无需感知加密解密逻辑;

  • • 自动完成挂载、卸载以及清理工作,确保加密文件系统的安全性和使用便捷性;

  • • 程序需要在容器中运行(即需要用 namespace 做进程间隔离)。

非目标

  • • 防止 root 用户访问加密后的数据(可以解密):因为 securefs 是以 fuse 文件系统方式,因此即使用 namespace 隔离,root 用户仍然可以通过 nsenter 进入到进程的 mnt namespace 中 查看。

如果要实现进程级别的文件访问安全,首先需要在进程中直接进行文件内容的加密和解密,此外需要防止恶意用户(包括 root 用户)获取到密钥。

3.1 准备工作

我们需要准备以下文件。

ll
-rw-r--r--  1 root root     937 Jan 16 04:02 Dockerfile
-rwxr-xr-x  1 root root     761 Jan 16 05:18 entrypoint.sh*
-rwxrwxrwx  1 root root 4725040 Apr 22  2024 securefs*

每个文件的说明如下。

3.1.1 Dockerfile

cat Dockerfile
# 使用 Ubuntu 20.04 作为基础镜像
FROM ubuntu:20.04

# 设置环境变量,避免交互式安装提示
ENV DEBIAN_FRONTEND=noninteractive

# 备份原始 sources.list 文件并替换为国内镜像源,安装依赖
RUN cp /etc/apt/sources.list /etc/apt/sources.list.bak && \
    sed -i 's|http://archive.ubuntu.com/ubuntu/|http://mirrors.aliyun.com/ubuntu/|g' /etc/apt/sources.list && \
    sed -i 's|http://security.ubuntu.com/ubuntu/|http://mirrors.aliyun.com/ubuntu/|g' /etc/apt/sources.list && \
    apt update && \
    apt install -y --no-install-recommends libfuse-dev && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/*

COPY securefs /usr/bin/securefs

# 复制启动脚本到容器中
COPY entrypoint.sh /usr/local/bin/entrypoint.sh

# 确保启动脚本具有可执行权限
RUN chmod +x /usr/local/bin/entrypoint.sh

# 设置启动脚本为容器的默认入口点
ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]

3.1.2 entrypoint.sh

cat entrypoint.sh
#!/bin/bash

# 定义加密目录和挂载点
ENC_DIR="/encrypted"
MOUNT_DIR="/mnt/secure"

# 确保目录存在
mkdir -p "$ENC_DIR" "$MOUNT_DIR"

# 检查是否已经创建加密文件系统
if [ ! -f "$ENC_DIR/.securefs.json" ]; then
    echo "Creating a new encrypted filesystem in $ENC_DIR"
    securefs create "$ENC_DIR" --pass "your-password"
fi

# 挂载加密文件系统
echo "Mounting encrypted filesystem from $ENC_DIR to $MOUNT_DIR"
securefs mount -b "$ENC_DIR" "$MOUNT_DIR" --pass "your-password"

# 设置挂载目录的权限,仅允许当前用户访问
chmod 700 "$MOUNT_DIR"

# 捕获退出信号,确保容器停止时卸载加密文件系统
trap "securefs unmount $MOUNT_DIR; exit" SIGINT SIGTERM EXIT

# 启动容器的主要进程
exec "$@"

3.3.3 securefs 可执行文件

当前 release 包的地址:https://github.com/netheril96/securefs/releases/tag/v1.0.0

wget https://github.com/netheril96/securefs/releases/download/v1.0.0/securefs-linux-amd64-release.zip
unzip securefs-linux-amd64-release.zip
chmod +x securefs

3.2 构建镜像

docker build -t securefs:v1 .
3.3 运行
docker run --rm -d --privileged -e SECUREFS_PASSWORD=your-password -v /encrypted:/encrypted securefs:v1 sleep 360

3.4 验证

docker ps

docker exec -it <container_id> /bin/bash

findmnt -l | grep secure
/mnt/secure                     securefs                                                                                            fuse.securefs rw,nosuid,nodev,relatime,user_id=0,group_id=0

ll /mnt/secure/
total 4
drwxr-xr-x 2 root root 70 Jan 16 03:40 ./
drwxr-xr-x 1 root root 20 Jan 16 05:40 ../

echo "aaaabbbbb" > /mnt/secure/a.txt

ll /mnt/secure/
total 4
drwxr-xr-x 2 root root 70 Jan 16 03:40 ./
drwxr-xr-x 1 root root 20 Jan 16 05:40 ../
-rw-r--r-- 1 root root 10 Jan 16 05:45 a.txt

cat /mnt/secure/a.txt
aaaabbbbb

# 从容器中退出
exit

# 主机上执行
ll /encrypted/
total 12
drwxr-xr-x  2 root root   70 Jan 16 03:40 ./
drwxr-xr-x 23 root root 4096 Jan 16 03:38 ../
-rw-r--r--  1 root root  570 Jan 16 03:39 .securefs.json
-rw-r--r--  1 root root   54 Jan 16 05:45 V6CCZUUT7KEPPIVABAW226RFRZZAQHT7VA

4. 更多方案对比

参考:https://nuetzlich.net/gocryptfs/comparison/

4.1 概述

项目名称首次发布编程语言许可证开发状态平台支持用户界面反向模式支持
gocryptfs2015GoMIT活跃Linux、macOS,第三方支持 Windows 和 Android命令行界面(CLI),第三方图形界面(GUI)是(自 v1.1 起,支持只读)
EncFS2003C++LGPLv3 / GPLv3维护中Linux、macOS,第三方支持 Windows命令行界面(CLI),第三方图形界面(GUI)是(有限的写入支持)
eCryptFS2006CGPLv2活跃Linux集成于登录过程否
Cryptomator2014JavaGPLv3活跃Linux、macOS、Windows图形界面(GUI),第三方命令行界面(CLI)否
securefs2015C++MIT活跃Linux、macOS、Windows命令行界面(CLI),第三方图形界面(GUI)否
CryFS2015C++LGPLv3活跃Linux、macOS、Windows(实验性)命令行界面(CLI),第三方图形界面(GUI)否

4.2 一般安全性

项目名称文档可用性密码哈希算法
gocryptfs是scrypt
EncFS是PBKDF2
eCryptFS否无(在外部工具中实现)
Cryptomator是scrypt
securefs是PBKDF2
CryFS是scrypt

4.3 文件内容加密

项目名称加密算法完整性保护文件大小混淆
gocryptfsGCM是否
EncFSCBC否否
eCryptFSCBC否是(4 KB 增量)
CryptomatorCTR是否
securefsGCM是否
CryFSGCM是是(分块存储)

4.4 文件名加密

项目名称加密算法前缀泄漏相同名称泄漏最大名称长度最大路径长度目录扁平化
gocryptfsEME否否255 字符4095 字符否
EncFSCBC否否175 字符4095 字符否
eCryptFSCBC是是143 字符4095 字符否
CryptomatorAES-SIV否否1024 字符4095 字符是
securefsAES-SIV否否143 字符4095 字符是
CryFSGCM否否1024 字符4095 字符是