章节大纲

  • 在本任务中,我们将实现一种简单的包过滤类型防火墙,它会检查每个传入和传出的数据包,并执行管理员设置的防火墙策略。由于数据包的处理是在内核中完成的,因此过滤过程也必须在内核中完成。因此,要实现这样的防火墙,似乎我们需要修改 Linux 内核。在过去,这的确需要通过修改和重新编译内核来完成。然而,现代的 Linux 操作系统提供了几种机制,使得无需重新编译内核就可以实现防火墙。这些机制包括可加载内核模块(Loadable Kernel Module, LKM)和 Netfilter。
     
    LKM(可加载内核模块)允许我们在系统运行时向内核添加一个新模块。通过这个新模块,我们可以扩展内核的功能,而无需重新编译内核甚至重启计算机。防火墙的包过滤部分可以通过 LKM 实现。在本任务中,我们将熟悉 LKM 的基本用法。

    以下是一个简单的可加载内核模块示例。当该模块被加载时,它会打印出 "Hello World!"。当模块从内核中移除时,它会打印出 "Bye-bye World!"。这些信息不会显示在屏幕上,而是记录在 /var/log/syslog 文件中。你可以使用 "dmesg" 命令查看这些信息。

    /* hello.c(在实验设置文件中已包含)*/
    #include <linux/module.h>
    #include <linux/kernel.h>
    
    int initialization(void)
    {
        printk(KERN_INFO "Hello World!\n");
        return 0;
    }
    
    void cleanup(void)
    {
        printk(KERN_INFO "Bye-bye World!.\n");
    }
    
    module_init(initialization);
    module_exit(cleanup);

    接下来我们需要创建一个 Makefile 文件,其内容如下(文件已包含在实验设置文件中)。只需运行 make,上述程序就会被编译成一个可加载的内核模块(如果将以下内容粘贴到 Makefile 中,请确保将 make 命令前的空格替换为 Tab)。

    obj-m += hello.o
    
    all:
            make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
    
    clean:
            make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

    生成的内核模块文件名为 hello.ko。你可以使用以下命令加载模块、列出所有模块以及移除模块。此外,可以使用 "modinfo hello.ko" 查看有关该内核模块的信息。

    $ sudo insmod hello.ko     (插入模块)
    $ lsmod | grep hello       (列出模块)
    $ sudo rmmod hello         (移除模块)
    $ dmesg                    (查看信息)
    $ sudo dmesg               (在 Ubuntu 22.04 中,此命令需要超级用户权限)

    任务: 请在你的虚拟机上编译此简单内核模块,并在虚拟机上运行它。在本任务中,我们不使用容器。请在实验报告中展示你的运行结果。

    注意:如果你在 Apple Silicon 机器上(通过 Ubuntu 22.04 虚拟机)编译内核模块,可能会看到一条错误消息,提示 gcc-12 未安装。可以使用以下命令安装它:"sudo apt install gcc-12"