元素码农
基础
UML建模
数据结构
算法
设计模式
网络
TCP/IP协议
HTTPS安全机制
WebSocket实时通信
数据库
sqlite
postgresql
clickhouse
后端
rust
go
java
php
mysql
redis
mongodb
etcd
nats
zincsearch
前端
浏览器
javascript
typescript
vue3
react
游戏
unity
unreal
C++
C#
Lua
App
android
ios
flutter
react-native
安全
Web安全
测试
软件测试
自动化测试 - Playwright
人工智能
Python
langChain
langGraph
运维
linux
docker
工具
git
svn
🌞
🌙
目录
▶
进程管理
▶
进程调度
调度策略
完全公平调度器
实时调度机制
▶
进程通信
信号机制
共享内存
管道与命名管道
▶
进程状态
上下文切换
僵尸进程处理
进程生命周期
▶
内存管理
▶
虚拟内存
页表机制
地址空间布局
TLB管理
▶
物理内存
伙伴系统
slab分配器
内存碎片处理
▶
文件系统
▶
VFS抽象层
inode机制
文件描述符
挂载机制
▶
具体文件系统
Ext4日志机制
Btrfs特性
Proc文件系统
▶
设备驱动
▶
驱动模型
设备树解析
sysfs接口
热插拔处理
▶
网络栈
▶
协议栈架构
sk_buff结构
Netfilter框架
套接字实现
▶
内核同步机制
▶
锁机制
自旋锁实现
RCU机制
Mutex与信号量
▶
启动过程
▶
引导阶段
GRUB交互
内核解压缩
早期初始化
▶
系统调用
▶
调用机制
陷入门实现
vsyscall优化
安全审计
▶
虚拟化和容器支持
▶
容器技术
命名空间隔离
cgroups实现
OverlayFS原理
发布时间:
2025-03-23 11:04
↑
☰
# Linux Netfilter框架 ## 概述 Netfilter是Linux内核中的网络包过滤框架,它提供了一系列的钩子(hook)函数,使得内核模块可以在网络协议栈的不同位置注册回调函数,实现包过滤、网络地址转换(NAT)和包修改等功能。 ## 架构设计 ### 1. 钩子点 Netfilter在网络协议栈中定义了5个标准的钩子点: ```c enum nf_inet_hooks { NF_INET_PRE_ROUTING, /* 路由前 */ NF_INET_LOCAL_IN, /* 输入 */ NF_INET_FORWARD, /* 转发 */ NF_INET_LOCAL_OUT, /* 输出 */ NF_INET_POST_ROUTING, /* 路由后 */ NF_INET_NUMHOOKS }; ``` ### 2. 数据流向 ```text PREROUTING | [路由判决] | +------+------+ | | LOCAL_IN FORWARD | | 本地进程 POST_ROUTING | | LOCAL_OUT | | | +------+------+ | 网络接口 ``` ## 核心组件 ### 1. 注册钩子 ```c struct nf_hook_ops { /* 用户定义的钩子函数 */ nf_hookfn *hook; /* 协议族(如AF_INET) */ int pf; /* 钩子点 */ int hooknum; /* 优先级 */ int priority; }; /* 注册钩子函数 */ static struct nf_hook_ops nfho = { .hook = hook_func, .pf = PF_INET, .hooknum = NF_INET_PRE_ROUTING, .priority = NF_IP_PRI_FIRST }; static int __init hook_init(void) { return nf_register_net_hook(&init_net, &nfho); } ``` ### 2. 钩子函数 ```c static unsigned int hook_func(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { /* 获取IP头 */ struct iphdr *iph; if (!skb) return NF_ACCEPT; iph = ip_hdr(skb); if (!iph) return NF_ACCEPT; /* 处理数据包 */ if (iph->protocol == IPPROTO_TCP) { /* 处理TCP包 */ return NF_DROP; } return NF_ACCEPT; } ``` ### 3. 返回值 ```c enum nf_verdict { NF_DROP = 0, /* 丢弃包 */ NF_ACCEPT, /* 接受包 */ NF_STOLEN, /* 包被钩子函数接管 */ NF_QUEUE, /* 将包放入队列 */ NF_REPEAT, /* 重新调用钩子 */ NF_STOP, /* 停止遍历钩子链 */ NF_MAX_VERDICT /* 最大值 */ }; ``` ## 实现功能 ### 1. 包过滤 ```c /* 简单的TCP端口过滤 */ static unsigned int port_filter(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { struct iphdr *iph; struct tcphdr *tcph; iph = ip_hdr(skb); if (iph->protocol != IPPROTO_TCP) return NF_ACCEPT; tcph = tcp_hdr(skb); if (ntohs(tcph->dest) == 80) return NF_DROP; /* 丢弃HTTP流量 */ return NF_ACCEPT; } ``` ### 2. NAT实现 ```c /* SNAT(源地址转换)示例 */ static unsigned int snat_func(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { struct iphdr *iph; __be32 new_addr; iph = ip_hdr(skb); new_addr = in_aton("1.2.3.4"); /* 修改源IP地址 */ iph->saddr = new_addr; /* 重新计算校验和 */ ip_send_check(iph); return NF_ACCEPT; } ``` ### 3. 连接跟踪 ```c /* 连接跟踪示例 */ static unsigned int conntrack_func(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { enum ip_conntrack_info ctinfo; struct nf_conn *ct; /* 获取连接跟踪信息 */ ct = nf_ct_get(skb, &ctinfo); if (!ct) return NF_ACCEPT; /* 处理不同连接状态 */ switch (ctinfo) { case IP_CT_NEW: /* 新连接 */ break; case IP_CT_ESTABLISHED: /* 已建立的连接 */ break; case IP_CT_RELATED: /* 相关连接 */ break; } return NF_ACCEPT; } ``` ## 用户空间接口 ### 1. iptables命令 ```bash # 添加规则 iptables -A INPUT -p tcp --dport 80 -j DROP # 配置NAT iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -j SNAT --to-source 1.2.3.4 # 查看规则 iptables -L # 保存规则 iptables-save > /etc/iptables/rules.v4 ``` ### 2. libnetfilter库 ```c #include <libnetfilter_queue/libnetfilter_queue.h> static int cb(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg, struct nfq_data *nfa, void *data) { struct nfqnl_msg_packet_hdr *ph; uint32_t id = 0; ph = nfq_get_msg_packet_hdr(nfa); if (ph) id = ntohl(ph->packet_id); /* 处理数据包 */ return nfq_set_verdict(qh, id, NF_ACCEPT, 0, NULL); } int main(void) { struct nfq_handle *h; struct nfq_q_handle *qh; int fd; /* 打开队列句柄 */ h = nfq_open(); if (!h) exit(1); /* 绑定到IPv4协议族 */ nfq_bind_pf(h, PF_INET); /* 创建队列 */ qh = nfq_create_queue(h, 0, &cb, NULL); if (!qh) exit(1); /* 设置复制模式 */ nfq_set_mode(qh, NFQNL_COPY_PACKET, 0xffff); fd = nfq_fd(h); /* 主循环 */ while ((rv = recv(fd, buf, sizeof(buf), 0)) >= 0) { nfq_handle_packet(h, buf, rv); } nfq_destroy_queue(qh); nfq_close(h); return 0; } ``` ## 性能优化 ### 1. 规则优化 1. **规则顺序** - 将最常匹配的规则放在前面 - 将DROP规则放在ACCEPT规则前面 - 使用自定义链组织规则 2. **减少规则数量** - 合并相似规则 - 使用IPSET管理IP列表 - 清理无用规则 ### 2. 系统调优 ```bash # 增加连接跟踪表大小 sysctl -w net.netfilter.nf_conntrack_max=131072 # 调整超时时间 sysctl -w net.netfilter.nf_conntrack_tcp_timeout_established=7200 # 开启连接跟踪帮助模块 modprobe nf_conntrack_ftp modprobe nf_conntrack_irc ``` ## 调试技巧 ### 1. 日志记录 ```bash # 启用内核日志 iptables -A INPUT -p tcp --dport 80 -j LOG --log-prefix "HTTP_PACKET: " # 查看日志 tail -f /var/log/kern.log ``` ### 2. 跟踪工具 ```bash # 使用iptables跟踪 iptables -t raw -A PREROUTING -p tcp --dport 80 -j TRACE # 查看连接状态 cat /proc/net/nf_conntrack # 查看统计信息 cat /proc/net/stat/nf_conntrack ``` ## 常见问题 ### 1. 性能问题 - 规则过多导致延迟 - 连接跟踪表满 - 内存使用过高 ### 2. 配置错误 - 规则顺序不当 - NAT配置不完整 - 路由配置错误 ### 3. 兼容性问题 - 内核版本差异 - 模块依赖缺失 - 协议支持不完整 ## 总结 Netfilter是Linux网络栈中的核心框架,它通过灵活的钩子机制实现了强大的网络包处理能力。通过合理使用Netfilter,可以实现防火墙、NAT、负载均衡等多种网络功能。理解Netfilter的工作原理和使用方法对于网络编程和系统安全至关重要。 ## 参考资源 1. [Netfilter Architecture](https://www.netfilter.org/documentation/HOWTO/netfilter-hacking-HOWTO.html) 2. Linux内核源码: net/netfilter/ 3. [iptables指南](https://www.frozentux.net/iptables-tutorial/iptables-tutorial.html)