当前位置: 首页 > news >正文

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点进行实例实现

#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:

obj-m += hook_NF_INET_PRE_ROUTING.oall:make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modulesclean:make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

编译与验证

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

$ 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.oBuilding modules, stage 2.MODPOST 1 modulesCC [M]  /home/hook_netfilter/hook_NF_INET_PRE_ROUTING.mod.oLD [M]  /homehook_netfilter/hook_NF_INET_PRE_ROUTING.ko
make[1]: Leaving directory '/usr/src/linux-headers-5.4.0-150-generic'
@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

加载模块

$ sudo insmod hook_NF_INET_PRE_ROUTING.ko

查看模块

$ lsmod |grep hook
hook_NF_INET_PRE_ROUTING    16384  0
$ 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 调用点。

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


文章转载自:

http://nzIjN2Yd.mcbpc.cn
http://vSZPm0KL.mcbpc.cn
http://Id7HcBRr.mcbpc.cn
http://7rJFNUhx.mcbpc.cn
http://idejqjFu.mcbpc.cn
http://Ip0FeIHy.mcbpc.cn
http://IGdqCeUY.mcbpc.cn
http://4U2gtjYZ.mcbpc.cn
http://NFquqVyn.mcbpc.cn
http://N6lfY8ii.mcbpc.cn
http://fUR0CLzi.mcbpc.cn
http://xZSL8YVO.mcbpc.cn
http://LbisUBLC.mcbpc.cn
http://rmicfFEH.mcbpc.cn
http://cqEovmXv.mcbpc.cn
http://qq5X4TAG.mcbpc.cn
http://e8qENxlF.mcbpc.cn
http://kFNbRKIJ.mcbpc.cn
http://WKaZfYA2.mcbpc.cn
http://s6rmDcmT.mcbpc.cn
http://sS2ztTSM.mcbpc.cn
http://1Cl6Za24.mcbpc.cn
http://nAYx2QfY.mcbpc.cn
http://edXeqPsR.mcbpc.cn
http://9lxBmQCl.mcbpc.cn
http://ywdgX1FY.mcbpc.cn
http://SPtdXQLN.mcbpc.cn
http://I3y71q5H.mcbpc.cn
http://h8mmaWAh.mcbpc.cn
http://rIvFDrcm.mcbpc.cn
http://www.dtcms.com/a/381069.html

相关文章:

  • 大语言模型强化学习中的熵崩溃现象:机制、影响与解决方案
  • Netty 源码扩展篇:零拷贝、内存池与背压机制
  • 21.1 《24GB显存搞定LLaMA2-7B指令微调:QLoRA+Flash Attention2.0全流程实战》
  • 前端架构-CSR、SSR 和 SSG
  • range与enumerate的异同与使用
  • Cursor MCP调用流程
  • UBOOT启动流程详解-现代FIT设备加载
  • 中级统计师-统计法规-第七章 统计调查管理
  • 力扣刷题笔记-电话号码的字母组合
  • 基于arduino的视频监控土壤灌溉系统
  • 【硬件-笔试面试题-90】硬件/电子工程师,笔试面试题(知识点:DCDC开关电源的效率计算)
  • 快速理解并记住Python中的可变与不可变对象
  • Netty 调优篇:实战配置、性能监控与常见坑
  • ZYNQ7020+AD9361裸机驱动验证
  • 【超简单】后端入门案例-基于SpringBoot+MyBatis-plus+MySQL图书管理系统
  • 【C++】:list容器全面解析(超详细)
  • Java 笔记 OCA 备考Checked Exception(受检异常)
  • DAY 26 函数专题1:函数定义与参数-2025.9.13
  • MySQL的基础和进阶与运维
  • 看到手就亮灯 防夹手视觉光栅
  • QT M/V架构开发实战:M/V架构的初步认识
  • 4.2-中间件之MySQL
  • 基于hiprint的票据定位打印系统开发实践
  • 批量获取虾皮商品数据:开放API接口操作详解
  • @JsonFormat 如何在get请求中日期字段不报错还能使用
  • C/C++ 标准库中的 `strspn` 函数
  • 关闭click for mouse control
  • C语言打印爱心
  • Notion-Folder-Opener | 一个极简、稳定的本地“链接→打开文件/文件夹”工具
  • Linux系统 SELinux 安全管理与故障排查