You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Linux服务器下,如何安全存储DEK以让指定进程访问数据库加密数据?

如何在Linux上安全存储DEK并仅限指定进程访问

你的这个需求很贴合实际场景——用KEK解锁DEK,再让特定进程(自研应用、Nginx脚本)安全访问DEK,同时防止其他进程碰它。下面我给你几个可落地的方案,从简单到灵活,你可以根据自己的技术栈选择:

方案一:基于文件系统权限的临时存储(最易实现)

这个方案利用Linux的用户组和权限机制,把明文DEK存到内存文件系统(/run是tmpfs,重启就消失,不会落到磁盘),只给指定进程的运行用户开放读取权限:

  1. 创建专属用户组
    先建一个专门用来控制DEK访问的用户组,比如dek-access,把需要访问DEK的进程运行用户加进去:

    groupadd dek-access
    # 把你的应用运行用户加入组
    usermod -aG dek-access appuser
    # 把Nginx的运行用户(通常是www-data)加入组
    usermod -aG dek-access www-data
    
  2. 准备存储目录
    在/run下创建一个目录,设置好权限,防止无关用户看到这个目录:

    mkdir -p /run/dek
    chown root:dek-access /run/dek
    chmod 0750 /run/dek
    
  3. 启动时解密DEK并写入文件
    系统启动时,让管理员输入KEK,解密存在磁盘上的加密DEK,然后写入权限严格控制的文件:

    # 假设你之前用OpenSSL加密DEK存到了/etc/dek/encrypted_dek.key
    openssl enc -aes-256-cbc -d -in /etc/dek/encrypted_dek.key -out /run/dek/secret.key -k $(read -s -p "Enter KEK: " kek && echo $kek)
    # 设置文件权限:只有root和dek-access组能读
    chmod 0640 /run/dek/secret.key
    chown root:dek-access /run/dek/secret.key
    

    注意:不要直接在命令行输入KEK,用read -s隐藏输入,避免被命令历史记录捕获。

  4. 进程读取DEK

    • 你的自研应用:直接读取/run/dek/secret.key即可,用完记得从内存中清除(比如用memset覆盖变量内存)。
    • Nginx下的脚本(比如PHP):用file_get_contents('/run/dek/secret.key')读取,用完立即unset变量。

方案二:共享内存存储(无磁盘落地,更安全)

如果不想DEK以文件形式存在哪怕是内存文件系统里,可以用Linux的共享内存(Shared Memory),数据完全在内存中,重启后自动消失:

  1. 创建共享内存并写入DEK
    写一个简单的C程序(或者用现成工具),在解密DEK后创建共享内存区域,设置权限为dek-access组可访问:

    #include <sys/mman.h>
    #include <fcntl.h>
    #include <unistd.h>
    #include <string.h>
    #include <grp.h>
    #include <sys/stat.h>
    
    int main() {
        // 创建共享内存对象,名称自定义
        int shm_fd = shm_open("/dek_shared_mem", O_CREAT | O_RDWR, 0640);
        // 设置共享内存大小(假设DEK是256位,32字节)
        ftruncate(shm_fd, 32);
        // 映射到进程内存
        char *dek_ptr = mmap(NULL, 32, PROT_WRITE, MAP_SHARED, shm_fd, 0);
        // 写入解密后的DEK(这里替换成实际的明文DEK)
        strncpy(dek_ptr, "your_decrypted_dek_value", 32);
        // 设置共享内存的所属组为dek-access
        struct group *grp = getgrnam("dek-access");
        fchown(shm_fd, getuid(), grp->gr_gid);
        // 清理资源
        munmap(dek_ptr, 32);
        close(shm_fd);
        return 0;
    }
    
  2. 进程读取共享内存
    你的应用和Nginx脚本可以通过连接这个共享内存对象读取DEK。如果是脚本,可以写一个小的C工具编译成二进制,脚本调用这个工具获取DEK,避免直接处理共享内存的复杂操作。

方案三:守护进程+Unix域套接字(细粒度控制)

如果需要更严格的访问控制(比如只允许特定进程ID访问,或者验证请求合法性),可以用一个守护进程来管理DEK,通过Unix域套接字提供访问:

  1. 编写DEK守护进程
    守护进程启动时用KEK解密DEK,然后监听一个Unix域套接字,设置套接字权限为dek-access组可访问。当收到指定进程的请求时,返回DEK。
    核心逻辑:

    • 监听套接字:socket(AF_UNIX, SOCK_STREAM, 0)
    • 设置套接字权限:chmod("/run/dek_socket", 0660),chown到root:dek-access
    • 接受连接后,验证客户端的用户ID(通过getsockopt获取SO_PEERCRED),确认是dek-access组的用户后返回DEK
  2. 进程请求DEK
    你的应用和Nginx脚本通过连接这个Unix域套接字,发送请求获取DEK。这种方式可以避免DEK直接暴露,守护进程还可以记录所有访问日志,方便审计。

关键注意事项

  • KEK的输入安全:系统启动时,最好用systemd的交互式服务(Type=oneshot)或者启动界面(比如Plymouth)让管理员输入KEK,不要用普通命令行输入,防止被历史记录或进程列表捕获。
  • 加密存储DEK:平时DEK必须以加密状态存在磁盘上,比如用AES-256加密,不要存明文。
  • 最小权限原则:确保你的应用和Nginx脚本的运行用户只有必要的权限,比如appuser只需要读DEK和访问数据库,不要用root运行。
  • 内存清除:进程读取DEK后,用完要立即从内存中清除(比如用memset覆盖变量,脚本中unset变量),防止内存dump泄露DEK。

内容的提问来源于stack exchange,提问作者Lieuwe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 04:32:26