在 Linux 中使用 Netfilter 构建无状态防火墙

嘻嘻笔记 28 0

》》》点击全文阅读《《《

Linux 内核有一个 Netfilter 框架,它允许我们执行各种与网络相关的操作。 本文是一个关于如何使用 Netfilter 构建防火墙模块的简单教程。

Netfilter 框架是 Linux 内核中的钩子或处理程序的集合,有助于过滤或捕获套接字缓冲区。 我们可以在输入或输出,甚至在网络数据包的转发路径上实现包过滤。 iptables 是使用 Netfilter 框架实现的流行工具。

在 Linux 中使用 Netfilter 构建无状态防火墙-第1张图片-嘻嘻笔记

如图 1 所示,一个数据包可以在五个不同的阶段进行过滤或处理。 所以有五个可能的钩子,程序员可以在其中附加一个定制的处理程序并实现他们自己的防火墙。 这些钩子是(仅适用于 Linux 内核 5.10 或更高版本):

在 Linux 中使用 Netfilter 构建无状态防火墙-第2张图片-嘻嘻笔记

图 1:处理阶段

  • NF_INET_PRE_ROUTING: 一旦网络数据包进入堆栈,在任何路由决策发生之前,就会调用此钩子。
  • NF_INET_LOCAL_IN: 路由后,如果发现包是本地网络的,就触发这个钩子。
  • NF_INET_FORWARD: 如果在路由之后发现数据包是针对另一个网络域的,而不是针对本地进程的,则调用此钩子。
  • NF_INET_LOCAL_OUT: This is called in case the packet is sent from a local process using send or sendto (POSIX calls).
  • NF_INET_POST_ROUTING: 在整个堆栈处理结束后,任何本地或转发的数据包即将到达接口之前调用此处理程序。

我编写了一个示例代码来展示如何使用 Netfilter 框架构建防火墙。 我使用的是 Linux 内核 5.10。 在此示例中,我已阻止从本地进程发送的所有 ICMP 和 HTTP/HTTPS 数据包。 这个程序必须从内核空间运行,而不是在用户空间。 因此开发了一个内核模块。

整个代码可在 https://github.com/SupriyoGanguly/Linux-Firewall-by-netfilter 获得。 您可以下载代码文件以检查和了解实现。

包过滤

我们创建了一个 firewall.c 文件,可从上述链接下载。 在 firewall.c 中, netfilter_ops 是一个 struct nf_hook_ops 变量。 在 init-module 部分中, netfilter_ops 使用以下内容进行初始化:

netfilter_ops.hook = main_hook; ``//the` `handler ``function``netfilter_ops.pf = PF_INET; ``//tells` `the Protocol is IPv4``netfilter_ops.hooknum = NF_INET_POST_ROUTING; ``//process` `at post-routing stage``netfilter_ops.priority = NF_IP_PRI_FIRST; ``//priority

以下是 firewall.c 的片段:

static struct nf_hook_ops netfilter_ops;` `/* This ``function` `is called by hook. */` `static unsigned int main_hook(void *priv, struct sk_buff *skb, const struct nf_hook_state *state)``{``//struct` `udphdr *udp_header;``int dstPort;``struct tcphdr *hdr;``struct iphdr *ip_header = (struct iphdr *)skb_network_header(skb);` `if` `(ip_header->protocol == IPPROTO_ICMP) {``//` `udp_header = (struct udphdr *)skb_transport_header(skb);``printk(KERN_INFO “Drop icmp packet.\n”);``return` `NF_DROP;``}` `if` `(ip_header->protocol == IPPROTO_TCP) {``hdr = (struct tcphdr *) skb_transport_header(skb);``dstPort = ntohs(hdr->dest);``if``((dstPort==443) || (dstPort==80)) /*drop https and http*/ {``printk(“Drop HTTPS``/HTTP` `packet\n”);``return` `NF_DROP;``}``}``return` `NF_ACCEPT;``}

main_hook 是 NF_INET_POST_ROUTING 钩子 的处理函数的名称。 在此函数中,任何数据包(无论是使用 ICMP 协议从本地接口转发还是发送)都将使用第一个“if”语句丢弃,其中它检查套接字缓冲区的 IPv4 标头中的 IP_PROTOCOL。 当钩子返回 NF_DROP 时,它告诉内核驱动程序不要继续处理数据包。

第二个“if”语句检查是否会丢弃任何目标端口号为 443(对于 HTTPS)或端口号为 80(对于 HTTP)的 TCP 数据包。

现在我们可以使用 Make 语句来编译这个模块 (filewall.c) 。 之前,我们可以成功 ping 一个 IP 地址为 192.168.29.1 的本地网络设备的 IP 。 图 2 显示,在我们实施firewall.c

在 Linux 中使用 Netfilter 构建无状态防火墙-第3张图片-嘻嘻笔记

图 2:成功 ping

但插入模块后,ping 开始失败(如图 3 所示)。

在 Linux 中使用 Netfilter 构建无状态防火墙-第4张图片-嘻嘻笔记

图 3:不成功的 ping

这表明在 POST_ROUTING 钩子中,数据包被丢弃并且不发送到线路。 命令的日志 dmesg 如图 4 所示,描述了模块的功能。

图 4:dmesg 的输出

在此示例中,您还可以看到 NF_DROP 或 NF_ACCEPT 返回值的使用。 这些值的含义是不言自明的。 但是还有更多的返回值,包括:

  • NF_REPEAT: 重复钩子函数。
  • NF_QUEUE: 排队等待用户空间处理的数据包。 要在用户空间实现这一点,我们需要使用库 nfnetlink 和 netfilter_queue。
  • NF_STOLEN: 进一步处理数据包和释放内存取决于您的模块。

数据包丢失

Netfilter 也可用于数据包修饰或修改。 在同一个 URL (https://github.com/SupriyoGanguly/Linux-Firewall-by-netfilter) 中,您可以找到另一个文件 Mangle.c 。 对应的 makefile 是 Makefile_mangle 。

在这个钩子中,ICMP ping 数据包源 IP 在发送数据包之前被修改。 你可以看到下面的代码:

/* This ``function` `to be called by hook. */` `static unsigned int main_hook(void *priv, struct sk_buff *skb, const struct nf_hook_state *state)``{` `struct iphdr *ip_header = (struct iphdr *)skb_network_header(skb);` `if` `(ip_header->protocol == IPPROTO_ICMP) {``printk(KERN_INFO “Mangle icmp packet. %x\n”,ip_header->saddr);``ip_header->saddr = 0xd01da8c0;``}` `return` `NF_ACCEPT;``}

Wireshark 捕获的输出如图 5 所示,在加载此模块之前,对目标 IP 192.168.29.1 的 ping 请求来自接口的原始 IP,即 192.168.29.207。 但是加载完模块后,ping请求来自修改后的接口IP,即192.168.29.208。 但是,物理接口 IP 不变。

在 Linux 中使用 Netfilter 构建无状态防火墙-第5张图片-嘻嘻笔记

图 5:Wireshark 的输出

编译代码

要编译和测试下载的模块,只需使用:

$ ``make` `$ ``sudo` `insmod firewall

要删除它,请使用以下命令:

$ ``sudo` `rmmod firewall

本文是使用 Netfilter 构建防火墙模块的简单教程。 您还可以通过简单地使用此示例中的 NF_INET_PRE_ROUTING 挂钩编号来进行数据包捕获。 您甚至可以使用此示例为您的设备模拟中间人攻击,以测试网络安全。

》》》点击全文阅读《《《

标签: 防火墙 网络过滤器

抱歉,评论功能暂时关闭!