Linux Netfilter 之 如何完成一个自制的防火墙实例

完成内容

我将创建一个简单的防火墙demo,帮助你熟悉网络内核编程。这个demo将基于Linux的Netfilter框架实现。

基础框架

基础概念

Netfilter 框架

  • Netfilter 是 Linux 内核中的一个框架,用于对网络数据包进行过滤、修改和重定向。它提供了多个钩子点(hook points),允许用户在不同的网络层插入自定义逻辑。

Netfilter 主要功能

  1. 数据包过滤(如防火墙)。
  2. 网络地址转换(NAT,包括 SNAT 和 DNAT)。
  3. 数据包修改(如修改 TTL、TOS 等字段)。
  4. 数据包日志记录。

Netfilter 钩子点

  1. NF_INET_PRE_ROUTING:数据包进入网络栈后,但在路由决策之前。适合用于 DNAT(目标地址转换)或数据包标记。

    1)netfilter的内核挂载点在代码中的位置:内核代码路径 :/net/ipv4/ip_input.c

    2)具体函数 :在 ip_rcv()

    ip_rcv_finish是路由查找后的回调函数

  2. NF_INET_LOCAL_IN:数据包目标是本机(即目标地址是本机的 IP 地址)。适合用于过滤或修改进入本机的数据包。

    1)内核代码路径 :/net/ipv4/ip_input.c

    2)具体函数 :在 ip_local_deliver()

  3. NF_INET_FORWARD:数据包需要被转发到其他主机(即本机作为路由器)。适合用于过滤或修改转发的数据包。

    1)内核代码路径 :/net/ipv4/ip_forward.c

    2)具体函数 :在 ip_forward()

  4. NF_INET_LOCAL_OUT:数据包从本机发出。适合用于过滤或修改从本机发出的数据包。

    1)内核代码路径 :/net/ipv4/ip_output.c

    2)具体函数 :在 __ip_local_out()

  5. NF_INET_POST_ROUTING:数据包在路由决策之后,但在发送到网络接口之前。适合用于 SNAT(源地址转换)或数据包标记

    1)内核代码路径 :/net/ipv4/ip_output.c

    2)具体函数 :在 ip_output()

在NF_INET_PRE_ROUTING点进行实例实现

c 复制代码
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
#include <linux/ip.h>
#include <linux/tcp.h>

staticunsignedintcustom_hook(void*priv,structsk_buff*skb,conststructnf_hook_state*state){
    structiphdr*ip_header =ip_hdr(skb);
    if(ip_header->protocol == IPPROTO_TCP){// 只处理 TCP 数据包
        structtcphdr*tcp_header =tcp_hdr(skb);
        printk(KERN_INFO "Custom Netfilter Hook: TCP packet to port %u\n",ntohs(tcp_header->dest));
        if(ntohs(tcp_header->dest)==22){   // 只处理目标端口为 22 的数据包
            printk(KERN_INFO "Custom Netfilter Hook: TCP packet to port 22\n");
                return NF_DROP;// 丢弃数据包
        }
    }
    return NF_ACCEPT;// 允许数据包继续传递
}

staticstructnf_hook_ops nfho ={
    .hook     = custom_hook,
    .pf       = NFPROTO_IPV4,          //作用在ip层
    .hooknum  = NF_INET_PRE_ROUTING,// 在 PRE_ROUTING 阶段处理数据包
    .priority = NF_IP_PRI_FIRST,      // 优先级
};

staticint __init pre_routing_module_init(void){
    nf_register_net_hook(&init_net,&nfho);
    printk(KERN_INFO "Custom Netfilter Hook registered\n");
    return0;
}

staticvoid __exit pre_routing_module_exit(void){
    nf_unregister_net_hook(&init_net,&nfho);
    printk(KERN_INFO "Custom Netfilter Hook unregistered\n");
}

module_init(pre_routing_module_init);
module_exit(pre_routing_module_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("pre_routing_module_init");
MODULE_DESCRIPTION("Netfilter hook example");

Makefile:

c 复制代码
obj-m += hook_NF_INET_PRE_ROUTING.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

编译与验证

终端中运行以下命令来编译内核模块

c 复制代码
$ make 
make -C /lib/modules/5.4.0-150-generic/build M=/home/hook_netfilter modules
make[1]: Entering directory '/usr/src/linux-headers-5.4.0-150-generic'
  CC [M]  /homehook_netfilter/hook_NF_INET_PRE_ROUTING.o
  Building modules, stage 2.
  MODPOST 1 modules
  CC [M]  /home/hook_netfilter/hook_NF_INET_PRE_ROUTING.mod.o
  LD [M]  /homehook_netfilter/hook_NF_INET_PRE_ROUTING.ko
make[1]: Leaving directory '/usr/src/linux-headers-5.4.0-150-generic'
c 复制代码
@ubuntu:hook_netfilter$ ls 
hook_NF_INET_PRE_ROUTING.c   hook_NF_INET_PRE_ROUTING.mod    hook_NF_INET_PRE_ROUTING.mod.o  Makefile       Module.symvers
hook_NF_INET_PRE_ROUTING.ko  hook_NF_INET_PRE_ROUTING.mod.c  hook_NF_INET_PRE_ROUTING.o      modules.order

加载模块

c 复制代码
$ sudo insmod hook_NF_INET_PRE_ROUTING.ko

查看模块

c 复制代码
$ lsmod |grep hook
hook_NF_INET_PRE_ROUTING    16384  0
c 复制代码
$ dmesg | tail
[716700.997388] Custom Netfilter Hook registered
[709907.950324] Custom Netfilter Hook: TCP packet to port 22
[709907.950325] Custom Netfilter Hook: TCP packet to port 22

验证结果

验证成功(无法连接)

我们可以用一个框图来简单罗列数据方向

意味着 custom_hook 函数被挂载到了 ip_rcv() 函数中的 NF_HOOK 调用点。

这是最早能抓到包的地方,所有进入的数据包(无论是发往本机还是需要转发的)都会经过这里,过滤规则会非常早地生效。

相关推荐
小成202303202651 小时前
Linux高级02
linux·开发语言
mounter6251 小时前
【硬核前沿】CXL 深度解析:重塑数据中心架构的“高速公路”,Linux 内核如何应对挑战?-- CXL 协议详解与 LSF/MM 最新动态
linux·服务器·网络·架构·kernel
++==1 小时前
Linux 进程间通信与线程同步技术详解:IPC 机制、线程 API、同步工具与经典同步问题
linux
特长腿特长1 小时前
centos、ubantu系列机的用户和用户组的结构是什么?具体怎么配置?用户组权限怎么使用?这篇文章持续更新,帮助你复习linux的基础知识
linux·运维·centos
zzzyyy5381 小时前
Linux环境变量
linux·运维·服务器
pluvium272 小时前
记对 xonsh shell 的使用, 脚本编写, 迁移及调优
linux·python·shell·xonsh
无级程序员2 小时前
centos7 安装 llvm-toolset-7-clang出错的问题解决
linux·centos
CHHC18803 小时前
NetCore树莓派桌面应用程序
linux·运维·服务器
云栖梦泽4 小时前
Linux内核与驱动:9.Linux 驱动 API 封装
linux·c++
si莉亚5 小时前
ROS2安装EVO工具包
linux·开发语言·c++·开源