SEED-LABS Firewall Exploration Lab

一、实验目的

这个实验的学习目标有两方面:学习防火墙如何工作,以及为网络建立一个简单的防火墙。学生们将首先实现一个简单的无状态包过滤防火墙,它检查数据包,并根据防火墙规则决定是否丢弃或转发数据包。通过这个实现任务,学生可以对防火墙的工作原理有基本的了解。
• Firewall
• Netfilter
• Loadable kernel module
• Using iptables to set up firewall rules
• Various applications of iptables

二、实验环境

在这里插入图片描述
1.去实验官网下载配置文件并在本地运行。
在这里插入图片描述

三、进行实验

Task 1: Implementing a Simple Firewall

在本任务中,我们将实现一种简单的包过滤类型的防火墙,它将检查每一个进出的包,并执行管理员设置的防火墙策略。因为包处理是在内核中完成的,所以过滤也必须在内核中完成。因此,实现这样的防火墙似乎需要我们修改Linux内核。在过去,这必须通过修改和重新构建内核来实现。现代Linux操作系统提供了几种新的机制来简化对包的操作,而无需重新构建内核映像。这两种机制是可加载内核模块(LKM)和Netfilter。

Task 1.A: Implement a Simple Kernel Module

LKM允许我们在运行时向内核添加一个新模块。这个新模块使我们能够扩展内核的功能,而无需重新构建内核,甚至无需重新启动计算机。防火墙的包过滤部分可以作为LKM来实现。在这个任务中,我们将熟悉LKM。
1.编译内核文件Makefile。
在这里插入图片描述

2.生成的内核模块在hello.ko中,可以进行查看删除模块。
在这里插入图片描述
3.把hello.ko插入到内核中,再开启一个窗口进行监控内核。
在这里插入图片描述

demsg -k -w

在这里插入图片描述
4.从内核中删除hello。
在这里插入图片描述
在这里插入图片描述

Task 1.B: Implement a Simple Firewall Using Netfilter

在这个任务中,我们将把我们的包过滤程序写成一个LKM,然后插入到内核内部的包处理路径中。
1.先测试网络,可以连上8.8.8.8.
在这里插入图片描述

2…运行实验中给定的内核程序,并插入到内核中。
在这里插入图片描述
在这里插入图片描述
3.测试结果。已经可以实现防火墙。
在这里插入图片描述
4.再实现两个钩子,可以实现以下功能:(1)防止其他计算机ping虚拟机;(2)防止其他计算机telnet到虚拟机。请实现两个不同的钩子函数,但将它们注册到同一个netfilter钩子。
我首先启动10.9.0.5容器。
在这里插入图片描述
在这里插入图片描述
结果表示可以实现ping和telnet。
5.

编写内核程序。这一步比较麻烦,我一开始在ping8.8.8.8是拦截的是UDP数据,在ping10.9.0.1是我们需要拦截icmp数据,在telnet10.9.0.1:23时需要拦截TCP数据,所以我们需要在原来程序的基础上在编写一个拦截TCP和ICMP的函数,最后再主函数里面运行即可。具体代码如下。

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/udp.h>
#include <linux/icmp.h>
#include <linux/if_ether.h>
#include <linux/inet.h>


static struct nf_hook_ops hook1, hook2,hook3,hook4; 

//blocking ping 8.8.8.8
unsigned int blockUDP(void *priv, struct sk_buff *skb,
                       const struct nf_hook_state *state)
{
   struct iphdr *iph;
   struct udphdr *udph;

   u16  port   = 53;
   char ip[16] = "8.8.8.8";
   u32  ip_addr;

   if (!skb) return NF_ACCEPT;

   iph = ip_hdr(skb);
   // Convert the IPv4 address from dotted decimal to 32-bit binary
   in4_pton(ip, -1, (u8 *)&ip_addr, '\0', NULL);

   if (iph->protocol == IPPROTO_UDP) {
       udph = udp_hdr(skb);
       if (iph->daddr == ip_addr && ntohs(udph->dest) == port){
            printk(KERN_WARNING "*** Dropping %pI4 (UDP), port %d\n", &(iph->daddr), port);
            return NF_DROP;
        }
   }
   return NF_ACCEPT;
}
//blocking ping vm:10.9.0.1
unsigned int blockICMP(void *priv, struct sk_buff *skb,
                       const struct nf_hook_state *state)
{
   struct iphdr *iph;
   struct icmphdr *icmph;

   //u16  port   = 53;
   char ip[16] = "10.9.0.1";
   u32  ip_addr;

   if (!skb) return NF_ACCEPT;

   iph = ip_hdr(skb);
   // Convert the IPv4 address from dotted decimal to 32-bit binary
   in4_pton(ip, -1, (u8 *)&ip_addr, '\0', NULL);

   if (iph->protocol == IPPROTO_ICMP) {
       icmph = icmp_hdr(skb);
       if (iph->daddr == ip_addr && icmph->type==ICMP_ECHO){
            printk(KERN_WARNING "*** Dropping %pI4 (ICMP)\n", &(iph->daddr));
            return NF_DROP;
        }
   }
   return NF_ACCEPT;
}
//blcoking telnet 10.9.0.1:23
unsigned int blockTelnet(void *priv, struct sk_buff *skb,
                       const struct nf_hook_state *state)
{
   struct iphdr *iph;
   struct tcphdr *tcph;

   u16  port   = 23;
   char ip[16] = "10.9.0.1";
   u32  ip_addr;

   if (!skb) return NF_ACCEPT;

   iph = ip_hdr(skb);
   // Convert the IPv4 address from dotted decimal to 32-bit binary
   in4_pton(ip, -1, (u8 *)&ip_addr, '\0', NULL);

   if (iph->protocol == IPPROTO_TCP) {
       tcph = tcp_hdr(skb);
       if (iph->daddr == ip_addr && ntohs(tcph->dest) == port){
            printk(KERN_WARNING "*** Dropping %pI4 (Telnet), port %d\n", &(iph->daddr), port);
            return NF_DROP;
        }
   }
   return NF_ACCEPT;
}
unsigned int printInfo(void *priv, struct sk_buff *skb,
                 const struct nf_hook_state *state)
{
   struct iphdr *iph;
   char *hook;
   char *protocol;

   switch (state->hook){
     case NF_INET_LOCAL_IN:     hook = "LOCAL_IN";     break; 
     case NF_INET_LOCAL_OUT:    hook = "LOCAL_OUT";    break; 
     case NF_INET_PRE_ROUTING:  hook = "PRE_ROUTING";  break; 
     case NF_INET_POST_ROUTING: hook = "POST_ROUTING"; break; 
     case NF_INET_FORWARD:      hook = "FORWARD";      break; 
     default:                   hook = "IMPOSSIBLE";   break;
   }
   printk(KERN_INFO "*** %s\n", hook); // Print out the hook info

   iph = ip_hdr(skb);
   switch (iph->protocol){
     case IPPROTO_UDP:  protocol = "UDP";   break;
     case IPPROTO_TCP:  protocol = "TCP";   break;
     case IPPROTO_ICMP: protocol = "ICMP";  break;
     default:           protocol = "OTHER"; break;

   }
   // Print out the IP addresses and protocol
   printk(KERN_INFO "    %pI4  --> %pI4 (%s)\n", 
                    &(iph->saddr), &(iph->daddr), protocol);

   return NF_ACCEPT;
}


int registerFilter(void) {
   printk(KERN_INFO "Registering filters.\n");

   hook1.hook = printInfo;
   hook1.hooknum = NF_INET_LOCAL_OUT;
   hook1.pf = PF_INET;
   hook1.priority = NF_IP_PRI_FIRST;
   nf_register_net_hook(&init_net, &hook1);

   hook2.hook = blockUDP;
   hook2.hooknum = NF_INET_POST_ROUTING;
   hook2.pf = PF_INET;
   hook2.priority = NF_IP_PRI_FIRST;
   nf_register_net_hook(&init_net, &hook2);
   
   hook3.hook = blockICMP;
   hook3.hooknum = NF_INET_PRE_ROUTING;
   hook3.pf = PF_INET;
   hook3.priority = NF_IP_PRI_FIRST;
   nf_register_net_hook(&init_net, &hook3);
   
   hook4.hook = blockTelnet;
   hook4.hooknum = NF_INET_PRE_ROUTING;
   hook4.pf = PF_INET;
   hook4.priority = NF_IP_PRI_FIRST;
   nf_register_net_hook(&init_net, &hook4);

   return 0;
}

void removeFilter(void) {
   printk(KERN_INFO "The filters are being removed.\n");
   nf_unregister_net_hook(&init_net, &hook1);
   nf_unregister_net_hook(&init_net, &hook2);
   nf_unregister_net_hook(&init_net, &hook3);
   nf_unregister_net_hook(&init_net, &hook4);
}

module_init(registerFilter);
module_exit(removeFilter);

MODULE_LICENSE("GPL");

6.运行Makefile并插入到内核中去。
在这里插入图片描述
7.查看结果。
在这里插入图片描述
ping的结果表明所有icmp包均被防火墙拦截。
在这里插入图片描述
telnet结果表明所有TCP数据包也被防火墙拦截。

  • 3
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值