netfilter/iptables模块编译及应用
Netfilter/IPTables模块编译及应用
一、Netfilter概述
Netfilter是Linux中的一个强大的网络框架,为多种网络协议(如IPv4、IPv6、ARP等)提供了一套钩子函数。在IPv4中定义了5个钩子函数,这些钩子函数在数据包流经协议栈的5个关键点被调用,就像在5个关键位置设置“鱼钩”来处理数据包。它主要采用连接跟踪(Connection Tracking)、包过滤(Packet Filtering)、地址转换(NAT)、包处理(Packet Mangling)等关键技术。连接跟踪是包过滤、地址转换的基础,它能在协议栈低层截取数据包,将当前数据包及其状态信息与历史数据包及其状态信息进行比较,得到当前数据包的控制信息,根据这些信息决定对网络数据包的操作,达到保护网络的目的。IPTables是连接到NetFilter架构中的重要工具模块,允许使用者对数据报进行过滤、地址转换、处理等操作。Netfilter提供了一个框架,将对网络代码的直接干涉降到最低,并允许用规定的接口将其他包处理代码以模块的形式添加到内核中,具有极强的灵活性,自2.6内核后,netfilter也把NAT加了进来。
二、编译Netfilter模块
(一)前提条件
- 内核环境准备:需要一个适合的Linux内核环境。不同版本的内核可能对Netfilter模块的编译有不同的要求,通常需要安装内核开发包(如
kernel - devel或者linux - headers等相关包,具体名称根据不同的Linux发行版而定)。例如在CentOS系统中,可以使用yum install kernel - devel命令安装内核开发包。 - 开发工具安装:确保系统安装了编译工具,如
gcc、make等工具。
(二)编译过程(以简单的自定义Netfilter模块为例)
- 定义数据结构和钩子函数
- 在编写Netfilter模块时,首先需要定义
nf_hook_ops数据结构,它包含了钩子函数相关的信息,如钩子函数指针、协议类型、钩子点编号、优先级等。例如:c struct nf_hook_ops { nf_hookfn* hook; void* priv; u_int8_t pf; unsigned int hooknum; int priority; }; - 编写钩子函数。这个函数将在数据包经过Netfilter钩子点时被调用,根据自定义的规则处理数据包。例如,一个简单的丢弃UDP输入包的钩子函数:
c static unsigned int hook_func(unsigned int hooknum, struct sk_buff* skb, const struct net_device* in, const struct net_device* out, int (*okfn)(struct sk_buff*)) { if (hooknum == NF_IP_LOCAL_IN) { struct iphdr* iph = ip_hdr(skb); if (iph->protocol == IPPROTO_UDP) { return NF_DROP; } } return NF_ACCEPT; } - 注册和注销钩子函数
- 在模块初始化函数中注册钩子函数。例如: ```c static struct nf_hook_ops nfho;
static int __init my_netfilter_init(void) {
nfho.hook = hook_func;
nfho.pf = PF_INET;
nfho.hooknum = NF_IP_LOCAL_IN;
nfho.priority = NF_IP_PRI_FIRST;
nf_register_hook(&nfho);
return 0;
}
- 在模块退出函数中注销钩子函数:c
static void __exit my_netfilter_exit(void) {
nf_unregister_hook(&nfho);
}
3. **模块编译**
- 编写`Makefile`文件。例如:makefile
obj - m := netmod.o
KERNELDIR?=/lib/modules/$(shell uname - r)/build
PWD := $(shell pwd)
all: $(MAKE) - C $(KERNELDIR) M = $(PWD) modules
clean:
$(MAKE) - C $(KERNELDIR) M = $(PWD) clean
``
- 然后在包含模块源代码和Makefile文件的目录下执行make命令进行编译。编译成功后会生成.ko`文件,这就是编译好的Netfilter模块。
三、Netfilter/IPTables的应用
(一)包过滤(使用IPTables)
- 基本语法:
iptables - A INPUT - p tcp - - dport 80 - j DROP。这条命令的意思是在INPUT链上添加一条规则(- A表示添加),针对协议为tcp(- p tcp),目标端口为80(-- dport 80)的数据包采取丢弃(- j DROP)操作。 - 构建防火墙策略:可以通过组合不同的规则来构建复杂的防火墙策略。例如,允许特定IP地址访问本地的某些服务,同时阻止其他IP地址的访问。
- 允许特定IP访问SSH服务:
iptables - A INPUT - s 192.168.1.100 - p tcp - - dport 22 - j ACCEPT。这里- s表示源IP地址,192.168.1.100是允许访问的IP,- p tcp表示协议为TCP,-- dport 22表示目标端口为SSH服务的22端口,- j ACCEPT表示接受该数据包。 - 阻止其他IP访问SSH服务:
iptables - A INPUT - p tcp - - dport 22 - j DROP。这条规则会阻止除了192.168.1.100以外的IP地址访问SSH服务。
(二)地址转换(NAT - 使用IPTables)
- 源地址转换(SNAT):在数据包送出之前修改数据包的源地址。例如,在一个具有内部网络和外部网络的环境中,如果内部网络的IP地址为私有地址(如
192.168.x.x),要通过一个公网IP地址访问外部网络,就可以使用SNAT。 - 假设公网接口为
eth0,可以使用以下命令实现SNAT:iptables - t nat - A POST_ROUTING - o eth0 - j SNAT - - to - source <公网IP地址>。 - 目的地址转换(DNAT):修改数据包的目的地址。例如,将访问公网IP地址的某个端口的数据包转发到内部网络的某个服务器上。
- 如果公网IP地址为
202.100.100.100,要将访问该公网IP的80端口的数据包转发到内部网络的192.168.1.10服务器的80端口,可以使用以下命令:iptables - t nat - A PREROUTING - d 202.100.100.100 - p tcp - - dport 80 - j DNAT - - to - destination 192.168.1.10:80。
(三)连接跟踪
- 连接跟踪可以让Netfilter能够识别数据包属于哪个连接,这对于实现更复杂的网络策略非常有用。例如,在防火墙规则中,可以根据连接的状态(如
ESTABLISHED、NEW等)来决定是否允许数据包通过。 - 允许已经建立连接的数据包通过:
iptables - A INPUT - m state - - state ESTABLISHED - j ACCEPT。这里- m state表示使用连接跟踪模块,-- state ESTABLISHED表示只允许已经建立连接的数据包通过。
