Task 1: Implementing a Simple Firewall

Task 1.A: Implement a Simple Kernel Module

首先使用make进行编译

image-20220729120604957

可以看到hello.ko文件已经出现

使用

 lsmod | grep hello
 dmesg

查看Kernel module

image-20220729121124869

Task 1.B: Implement a Simple Firewall Using Netfilter

1、
make
sudo insmod seedFilter.ko
dig @8.8.8.8 www.example.com
sudo rmmod seedFilter.ko
dig @8.8.8.8 www.example.com

执行上述命令

image-20220729135554329

可以看到在挂载好seedFilter时向8.8.8.8发udp包是失败的,取消挂载后即可成功

2、

image-20220729145108098

NF_INET_PRE_ROUTING

在包经过,进入路由前,经过NF_INET_PRE_ROUTING钩子点

NF_INET_LOCAL_OUT

从本机发出的数据包,在查询路由成功之后,经过NF_INET_LOCAL_OUT钩子点

NF_INET_FORWARD

经过了PRE_ROUTING钩子点之后,如果是路由到转发而不是本地,则经过NF_INET_FORWARD钩子点

NF_INET_POST_ROUTING

转发的数据包或者是本地输出的数据包,最后都会经过NF_INET_POST_ROUTING钩子点

NF_INET_LOCAL_IN

如果数据包发送到本地,经过NF_INET_LOCAL_IN钩子点

3、

实现VM不接受ping与telnet连接

改写样本代码。注:记得加 #include <linux/icmp.h>

#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/if_ether.h>
#include <linux/inet.h>
#include <linux/icmp.h>

static struct nf_hook_ops hook1, hook2; 


unsigned int blockTCP(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 (TCP), port %d\n", &(iph->daddr), port);
            return NF_DROP;
        }
   }
   return NF_ACCEPT;
}

unsigned int blockPing(void *priv, struct sk_buff *skb,
                 const struct nf_hook_state *state)
{
   struct iphdr *iph;
   struct icmphdr *icmph;

   //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_ICMP) {
       icmph = icmp_hdr(skb);
       if (iph->daddr == ip_addr && icmph->type == 8){// Echo-request is 8
            printk(KERN_WARNING "*** Dropping %pI4 (ICMP)\n", &(iph->daddr));
            return NF_DROP;
        }
   }
   return NF_ACCEPT;

}


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

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

   hook2.hook = blockTCP;
   hook2.hooknum = NF_INET_LOCAL_IN;
   hook2.pf = PF_INET;
   hook2.priority = NF_IP_PRI_FIRST;
   nf_register_net_hook(&init_net, &hook2);

   return 0;
}

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

module_init(registerFilter);
module_exit(removeFilter);

MODULE_LICENSE("GPL");

image-20220729174906667

编译运行该程序,可以1看到使用别的机器都没有办法ping通VM本机了。

Task 2: Experimenting with Stateless Firewall Rules

Task 2.A: Protecting the Router

执行以下指令后观察现象

iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT
iptables -A OUTPUT -p icmp --icmp-type echo-reply -j ACCEPT
iptables -P OUTPUT DROP Set default rule for OUTPUT
iptables -P INPUT DROP Set default rule for INPUT

image-20220729194715626

ping得通但telnet连接不上,以下原理

iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT
使进入本机的包icmp包类型为echo-request可以放行
iptables -A OUTPUT -p icmp --icmp-type echo-reply -j ACCEPT
使出本机的icmp包类型为echo-reply放行
iptables -P OUTPUT DROP 
默认规则下所有出本机的包drop掉
iptables -P INPUT DROP 
默认规则下所有进入本机的包drop掉

Task 2.B: Protecting the Internal Network

实验要求:

\1. Outside hosts cannot ping internal hosts.

\2. Outside hosts can ping the router.

\3. Internal hosts can ping outside hosts.

\4. All other packets between the internal and external networks should be blocked.

使用如下代码

iptables -A FORWARD -d 192.168.60.0/24 -p icmp --icmp-type echo-reply -j ACCEPT
iptables -A FORWARD -s 192.168.60.0/24 -p icmp --icmp-type echo-request -j ACCEPT
iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT
iptables -A OUTPUT -p icmp --icmp-type echo-reply -j ACCEPT

iptables -P INPUT DROP
iptables -P FORWARD DROP

image-20220731000423724

可以看到,实现了实验所要求的效果

Task 2.C: Protecting Internal Servers

实验要求如下:

\1. All the internal hosts run a telnet server (listening to port 23). Outside hosts can only access the telnet server on 192.168.60.5, not the other internal hosts.

\2. Outside hosts cannot access other internal servers.

\3. Internal hosts can access all the internal servers.

\4. Internal hosts cannot access external servers.

\5. In this task, the connection tracking mechanism is not allowed. It will be used in a later task.

iptables -A FORWARD -d 192.168.60.5 -p tcp --dport 23 -j ACCEPT
iptables -A FORWARD -d 192.168.60.5 -p tcp --dport 80 -j ACCEPT
iptables -A FORWARD -s 192.168.60.5 -p tcp -j ACCEPT
iptables -P INPUT DROP
iptables -P FORWARD DROP

使用以上代码,可达成实验要求效果,截图如下

image-20220731004705561

Task 3: Connection Tracking and Stateful Firewall

Task 3.A: Experiment with the Connection Tracking

image-20220731120820449

观察得ICMP与TCP连接都一直持续,UDP连接只持续很短一段时间

Task 3.B: Setting Up a Stateful Firewall

iptables -A FORWARD -d 192.168.60.5 -p tcp --dport 23 --syn -m conntrack --ctstate NEW -j ACCEPT
iptables -A FORWARD -s 192.168.60.0/24 -p tcp --syn -m conntrack --ctstate NEW -j ACCEPT
iptables -A FORWARD -p tcp -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A FORWARD -p tcp -j DROP
iptables -P FORWARD ACCEPT

执行以上命令,可使内部机器可连接外部机器。

image-20220731124048785

Task 4: Limiting Network Traffific

iptables -A FORWARD -s 10.9.0.5 -m limit --limit 10/minute --limit-burst 5 -j ACCEPT
iptables -A FORWARD -s 10.9.0.5 -j DROP

image-20220731130317242

分别执行命令1和两条命令,可以看到只有执行了两条命令,该规则才会对包数量进行限制,原因是默认规则就是通过,不走限制规则也可直接通过路由到达192.168.60.5机器

Task 5: Load Balancing

Using the nth mode (round-robin)

iptables -t nat -A PREROUTING -p udp --dport 8080 -m statistic --mode nth --every 3 --packet 0 -j DNAT --to-destination 192.168.60.5:8080
iptables -t nat -A PREROUTING -p udp --dport 8080 -m statistic --mode nth --every 2 --packet 0 -j DNAT --to-destination 192.168.60.6:8080
iptables -t nat -A PREROUTING -p udp --dport 8080 -m statistic --mode nth --every 1 --packet 0 -j DNAT --to-destination 192.168.60.7:8080

启用上述规则,在192.168.60.0/24的三台机器中启用 nc -luk 8080

使用10.9.0.5机器 echo hello |nc -u 10.9.0.11 8080

可以看到将hello平均的分配到了三台机器中

Using the random mode

iptables -t nat -A PREROUTING -p udp --dport 8080 -m statistic --mode random --probability 0.333 -j DNAT --to-destination 192.168.60.5:8080
iptables -t nat -A PREROUTING -p udp --dport 8080 -m statistic --mode random --probability 0.5 -j DNAT --to-destination 192.168.60.6:8080
iptables -t nat -A PREROUTING -p udp --dport 8080 -m statistic --mode random --probability 1 -j DNAT --to-destination 192.168.60.7:8080

image-20220731205441474

可以看到,hello等几率的分配到了三个机器中,相比于上面的nth mode的平均分配 ,random mode是随机分配

发表评论