首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >你的文件正在被篡改!90% 的人还不知道这个内核级防护神器

你的文件正在被篡改!90% 的人还不知道这个内核级防护神器

作者头像
不吃草的牛德
发布2026-04-23 12:13:05
发布2026-04-23 12:13:05
1030
举报
文章被收录于专栏:RustRust

你可能不知道,你的服务器正在被偷偷入侵。

想象一下这个场景:

凌晨 3 点,你还在睡梦中。

黑客已经通过某个漏洞登录了你的服务器,悄无声息地修改了 /etc/passwd 添加了后门用户,篡改了 /var/log/auth.log 抹掉了入侵痕迹,甚至替换了 /bin/login 来记录所有管理员的密码。

等你早上醒来,服务器已经不再属于你了。

传统防护手段?形同虚设。

AIDE?Tripwire?它们只能告诉你"文件被改了",但无法阻止。

等你发现,黑客早就跑了。

😰

多年前为了过等保三,亲手用 python 撸了一套类似系统,但未达到理想目标。

但今天,我要给你介绍一个内核级的解决方案——用 Rust + eBPF 实现文件防篡改,在文件被修改之前,直接拦截!


一、为什么传统的文件监控几乎没用?

先来科普一个残酷的现实:

传统的文件完整性工具,都是"事后诸葛亮"。

它们是这样工作的:

  1. 1. 定期扫描文件系统
  2. 2. 对比哈希值
  3. 3. 发现变化 → 报警

问题在哪里?

  • • ⚠️ 延迟:10 分钟扫描一次,黑客早干完活了
  • • ⚠️ 无法阻止:只能看,不能拦
  • • ⚠️ 性能差:全盘扫描,CPU 飞起

等你知道被黑的时候,黄花菜都凉了。

而 eBPF 不一样。

它是 Linux 内核的"瑞士军刀",可以在系统调用的关键时刻插入代码,实时拦截、修改、阻止操作。

什么意思?

当有人试图打开文件并写入时,eBPF 程序在内核中就能检测到,直接返回"拒绝访问",连磁盘都不让你碰。

这不是防火墙,这是直接给文件系统装了个金刚罩。


二、为什么选择 Rust + eBPF?

eBPF 的三大优势:

  1. 1. 🚀 性能逆天:事件驱动,内核级执行,比用户空间程序快几个数量级
  2. 2. 🔒 安全性超高:eBPF 验证器会检查每一行代码,不会让有问题的程序跑进内核
  3. 3. 🎯 灵活性爆炸:网络、安全、观测……什么场景都能用

Rust 完美契合 eBPF:

  • 内存安全:没有 C 语言的悬空指针、缓冲区溢出
  • 高性能:编译后 native 性能,零运行时开销
  • 现代化:用 cargo 管理依赖,用 Rust 写代码,爽到飞起

一个安全 + 一个高性能 = 绝配。

今天我们用 Aya 库(Rust 生态最流行的 eBPF 框架)来实现。


三、实战:手把手教你实现文件防篡改

第一步:环境准备

首先,确保你的 Linux 内核版本 >= 5.7,并且启用了 BPF LSM:

代码语言:javascript
复制
# 检查 LSM 是否包含 bpf
cat /sys/kernel/security/lsm

输出应该包含 bpf,如果没有,编辑 GRUB 配置添加:

代码语言:javascript
复制
lsm=...,bpf

然后重启。

安装 Rust 和 Aya 工具链:

代码语言:javascript
复制
# 安装 Rust
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

# 安装 eBPF 开发工具
cargo install cargo-generate
cargo install bpf-linker

生成项目模板:

代码语言:javascript
复制
cargo generate --name file-protect -d program_type=lsm -d lsm_hook=file_open https://github.com/aya-rs/aya-template
cd file-protect

第二步:编写 eBPF 内核程序

我们使用 LSM 的 file_open 钩子来拦截文件打开操作。

如果是写模式且目标文件在保护列表中,直接返回 -EPERM(权限拒绝)。

编辑 ebpf/src/main.rs

代码语言:javascript
复制
#![no_std]
#![no_main]

use aya_bpf::{
    macros::{lsm, map},
    programs::LsmContext,
    maps::HashMap,
    cty::{c_int, c_long},
};

#[map]
static mut PROTECTED_FILES: HashMap<u32, u32> = HashMap::<u32, u32>::with_max_entries(1024, 0);

#[lsm(hook = "file_open")]
pub fn file_open(ctx: LsmContext) -> i32 {
    unsafe {
        let file = ctx.arg::<*const file>(0);
        let flags = (*file).f_flags as u32;

        // 检查是否为写模式
        if flags & (O_WRONLY | O_RDWR) == 0 {
            return 0; // 只读操作,放行
        }

        // 获取 inode 号作为唯一标识
        let inode = (*(*file).f_inode).i_ino as u32;

        // 检查是否在保护列表中
        if let Some(_) = PROTECTED_FILES.get(&inode) {
            return -EPERM; // 拒绝!不允许写入
        }

        0
    }
}

#[panic_handler]
fn panic(_info: &core::panic::PanicInfo) -> ! {
    unreachable!()
}

核心逻辑:

  1. 1. 拿到文件的打开标志(flags)
  2. 2. 判断是否为写模式(O_WRONLY | O_RDWR)
  3. 3. 获取文件的 inode 号
  4. 4. 在 HashMap 中查找这个 inode
  5. 5. 如果在保护列表 → 返回 -EPERM,直接拦截

简单粗暴,但极其有效。

编译 eBPF 程序:

代码语言:javascript
复制
cargo xtask build-ebpf

第三步:编写用户空间加载程序

eBPF 程序跑在内核里,但需要用户空间程序来加载、配置和管理。

编辑 userspace/src/main.rs

代码语言:javascript
复制
use aya::{Bpf, maps::HashMap, include_bytes_aligned};
use std::fs::metadata;
use std::path::Path;

#[tokio::main]
async fn main() -> Result<(), anyhow::Error> {
    // 1. 加载编译好的 eBPF 程序
    let mut bpf = Bpf::load(include_bytes_aligned!(
        "../../target/bpfel-unknown-none/debug/file-protect"
    ))?;

    // 2. 获取 eBPF 程序并附加到 LSM 钩子
    let program: &mut Lsm = bpf.program_mut("file_open").unwrap();
    program.load()?;
    program.attach()?;

    // 3. 获取用户空间和内核共享的 HashMap
    let mut protected_files: HashMap<_, u32, u32> = HashMap::try_from(
        bpf.map_mut("PROTECTED_FILES")?
    )?;

    // 4. 添加保护文件:例如 /etc/passwd
    let path = Path::new("/etc/passwd");
    let inode = metadata(path)?.ino() as u32;
    protected_files.insert(&inode, &1, 0)?;

    println!("🛡️  文件防篡改程序已启动!");
    println!("📁 已保护文件:/etc/passwd");

    // 5. 保持程序运行
    loop {}
}

运行程序:

代码语言:javascript
复制
sudo RUST_LOG=info cargo run

第四步:测试效果

现在,尝试修改 /etc/passwd

代码语言:javascript
复制
sudo vim /etc/passwd

或者:

代码语言:javascript
复制
echo "test:x:0:0::/root:/bin/bash" >> /etc/passwd

会发生什么?

代码语言:javascript
复制
Permission denied

无论你用 vim、echo 还是任何工具,都别想修改这个文件。

黑客再牛,也突破不了内核级别的拦截。

爽不爽?


四、进阶:更强大的防护策略

上面的代码只是一个起点,真正的防护需要更多钩子的配合:

1. 防止文件被删除

使用 inode_unlink 钩子:

代码语言:javascript
复制
#[lsm(hook = "inode_unlink")]
pub fn inode_unlink(ctx: LsmContext) -> i32 {
    // 类似逻辑:检查 inode 是否在保护列表
    // 如果是,返回 -EPERM
}

2. 防止文件被重命名

使用 inode_rename 钩子:

代码语言:javascript
复制
#[lsm(hook = "inode_rename")]
pub fn inode_rename(ctx: LsmContext) -> i32 {
    // 检查 old_dir 和 new_dir 的 inode
    // 防止受保护文件被移动到其他位置
}

3. 动态配置保护列表

可以参考 ebpfguard 项目,从 YAML 文件加载保护策略:

代码语言:javascript
复制
protected_files:
  - /etc/passwd
  - /etc/shadow
  - /etc/ssh/sshd_config
  - /var/log/auth.log

4. 实时警报

当拦截到篡改尝试时,通过 perf event 发送通知到用户空间:

代码语言:javascript
复制
// 内核空间
prog_helper::send_alert(inode);

// 用户空间
let mut perf = PerfBuffer::try_from(bpf.map("EVENTS")?)?;
loop {
    let events = perf.read(&mut callbacks).await?;
    for event in events {
        println!("🚨 警报!有人试图篡改文件 inode: {}", event.inode);
    }
}

五、真实案例:ebpfguard 和 kprotect

如果你想看看生产级的实现,可以参考这两个开源项目:

  • ebpfguard:用 Rust 编写的高级 eBPF 防护框架
  • kprotect:专注于文件保护的内核模块替代方案

它们都使用了类似的技术思路,但功能更完善、边界处理更细致。

建议:先从这个小项目开始理解原理,再参考它们的代码。


六、总结

技术栈总结:

组件

作用

Rust

编写安全的用户空间和 eBPF 程序

Aya

Rust 的 eBPF 库,简化开发流程

LSM (Linux Security Modules)

内核安全框架,提供钩子

eBPF

内核级编程,无需修改内核

核心优势:

  1. 1. 🚀 实时防护:在修改发生前拦截,不是事后检测
  2. 2. 🔒 内核级安全:黑客无法绕过,普通用户空间程序拿它没办法
  3. 3. ⚡ 极低开销:eBPF 事件驱动,比传统扫描快几个数量级
  4. 4. 🦀 Rust 安全:内存安全,无惧缓冲区溢出等低级错误

七、最后的灵魂拷问 ❓

  1. 1. 你服务器的关键文件,有真正的保护吗?
  2. 2. 如果黑客现在入侵,你能阻止他篡改配置文件吗?
  3. 3. 还在用"事后报警"的传统工具吗?

安全不是口号,是行动。

用 Rust + eBPF 给自己装一个内核级金刚罩,让黑客无处下手。

代码已经给你了,去试试吧!

如果这篇内容对你有帮助,点个在赞,让更多同行学会这项硬核技能🚀

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2026-01-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Rust火箭工坊 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 你可能不知道,你的服务器正在被偷偷入侵。
  • 一、为什么传统的文件监控几乎没用?
    • 它们是这样工作的:
    • 问题在哪里?
  • 二、为什么选择 Rust + eBPF?
    • eBPF 的三大优势:
    • Rust 完美契合 eBPF:
  • 三、实战:手把手教你实现文件防篡改
    • 第一步:环境准备
    • 第二步:编写 eBPF 内核程序
    • 第三步:编写用户空间加载程序
    • 第四步:测试效果
  • 四、进阶:更强大的防护策略
    • 1. 防止文件被删除
    • 2. 防止文件被重命名
    • 3. 动态配置保护列表
    • 4. 实时警报
  • 五、真实案例:ebpfguard 和 kprotect
  • 六、总结
    • 技术栈总结:
    • 核心优势:
  • 七、最后的灵魂拷问 ❓
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档