(CN) Firewall Exploration Lab

SEED Project官网

Firewall Exploration Lab

Task 1 Implementing a Simple Firewall

Task A Implement a Simple Kernel Module

image-20230209153856473 image-20230209153928425 image-20230209153956087 image-20230209154014203 image-20230209154036257

Task B Implement a Simple Firewall Using Netfilter

  1. load
image-20230216182135967 image-20230216182329522

unload:

image-20230216182408129

2.

img

3.

#include <linux/in.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>

static struct nf_hook_ops hook1, hook2, hook3, hook4;
static struct nf_hook_ops hooks[NF_INET_NUMHOOKS];


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;
}

unsigned int blockPing(void *priv, struct sk_buff *skb,const struct nf_hook_state *state)
{
   struct iphdr *iph;
   if (!skb) return NF_ACCEPT;
   iph = ip_hdr(skb);
   if (iph->protocol == IPPROTO_ICMP) {
      printk(KERN_WARNING "*** Dropping ICMP from %pI4 to %pI4\n", &(iph->saddr), &(iph->daddr));
      return NF_DROP;
   }
   return NF_ACCEPT;
}

unsigned int blockTelnet(void *priv, struct sk_buff *skb,const struct nf_hook_state *state)
{
   struct iphdr *iph;
   struct tcphdr *tcph;
   u16 port = 23;
   if (!skb) return NF_ACCEPT;
   iph = ip_hdr(skb);
   if (iph->protocol == IPPROTO_TCP) {
      tcph = tcp_hdr(skb);
      if (ntohs(tcph->dest) == port) {
         printk(KERN_WARNING "*** Dropping Telnet from %pI4:%d to %pI4:%d\n", &(iph->saddr), ntohs(tcph->source), &(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) {
   int i;
   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 = blockPing;
   hook3.hooknum = NF_INET_LOCAL_IN;
   hook3.pf = PF_INET;
   hook3.priority = NF_IP_PRI_FIRST;
   nf_register_net_hook(&init_net, &hook3);

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

   for (i = 0; i < NF_INET_NUMHOOKS; i++) {
      hooks[i].hook = printInfo;
      hooks[i].hooknum = i;
      hooks[i].pf = PF_INET;
      hooks[i].priority = NF_IP_PRI_FIRST;
      nf_register_net_hook(&init_net, &hooks[i]);
   }
   return 0;
}

void removeFilter(void) {
   int i;
   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);

   for (i = 0; i < NF_INET_NUMHOOKS; i++) {
      nf_unregister_net_hook(&init_net, &hooks[i]);
   }
}

module_init(registerFilter);
module_exit(removeFilter);

MODULE_LICENSE("GPL");
image-20230216190223160 image-20230216190254514 image-20230216190613322 image-20230216190716259

Task 2 Experimenting with Stateless Firewall Rules

Task A Protecting the Router

INPUT 和 OUTPUT 的默认 policy 为 DROP,仅仅对于ICMP可行,对于ping可以,但是无法telnet到seed-router

image-20230216193258340 image-20230216193952027 image-20230216194022184 image-20230216194251603

Task B Protecting the Internal Network

要实现路由器所连的两网的相互隔离,仅允许内部主机ping 外部主机,需要添加FORWARD规则,用 -d/-s 参数指定来去的ip段

//task2 b 
iptables -A FORWARD -p icmp --icmp-type echo-reply -d 192.168.60.0/24 -j ACCEPT
iptables -A FORWARD -p icmp --icmp-type echo-request -s 192.168.60.0/24 -j ACCEPT
iptables -A FORWARD -j DROP
image-20230216200841007

测试是否成功:

image-20230216201317614 image-20230216201420467

udp报文也被drop

image-20230216201718467

tcp报文也被drop

image-20230216202205987

Task C Protecting Internal Servers

// task2 c
iptables -A FORWARD -p tcp -s 10.9.0.0/24 --dport 23 -d 192.168.60.5 -j ACCEPT
iptables -A FORWARD -p tcp -s 192.168.60.0/24 --dport 23 -d 192.168.60.0/24 -j ACCEPT
iptables -P FORWARD DROP  
image-20230216210709195
  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.
image-20230216210216009
  1. Outside hosts cannot access other internal servers.
  1. Internal hosts can access all the internal servers.
image-20230216205938547
  1. Internal hosts cannot access external servers.
image-20230216205841862

Task 3 Connection Tracking and Stateful Firewall

Task A Experiment with the Connection Tracking

icmp 30s左右

image-20230217155759285

udp 30s左右

image-20230217160039572

TCP在连接ESTABLISHED后,状态持续时间为432000秒,断开连接进入TIME_WAIT状态,持续时间为120秒。

image-20230217160356018

Task B Setting Up a Stateful Firewall

iptables -A FORWARD -p tcp -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A FORWARD -p tcp -i eth0 --dport 23 --syn -m conntrack --ctstate NEW -d 192.168.60.5 -j ACCEPT
iptables -A FORWARD -p tcp -i eth1 --dport 23 --syn -m conntrack --ctstate NEW -j ACCEPT
iptables -P FORWARD DROP
image-20230217162358177
  1. All the internal hosts run a telnet server (listening to port 23). Outside hosts can only access the telnetserver on 192.168.60.5, not the other internal hosts.
image-20230217161910077
  1. Outside hosts cannot access other internal servers.
image-20230217162301894
  1. Internal hosts can access all the internal servers.
image-20230217162025395
  1. Internal hosts can access external servers.
image-20230217162122469
  1. In this task, the connection tracking mechanism is allowed

我们将添加一条允许内部主机访问任何外部服务器的规则。使用conntrack模块,只放行新的TCP/SYN包和已有TCP连接的数据包,否则无法确定需要放行哪些传入内网的数据包。

Task 4 Limiting Network Traffic

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

设置了drop

image-20230218160445821

查看效果,可以看到前5个数据包都可以正常接收,那是因为limit默认初始包就是5个,因此没有任何问题,从第六个数据包开始后,每隔6秒才会正常处理一个数据包,因为1分钟限制10次数据包的接收,那就表示6秒收一个,效果如下图所示。也可以理解为是一开始可以快速通过5个数据报文,后面的数据报文是每分钟通过10个。

image-20230218160644820

未设置drop:

image-20230218160934312 image-20230218161241495

添加第二条drop规则,超出10个报文后,其余的报文全部丢弃;不添加的话,对于超出的报文没有处理.

Task 5 Load Balancing

image-20230218163152606 image-20230218170720276

使用statistic模块负载均衡,使用-j DNAT –to-destination ip:port指定负载均衡目标,由于是UDP所以只用改destination。

image-20230218170945961
iptables -t nat -A PREROUTING -p udp --dport 8080 -m statistic --mode random --probability 0.33 -j DNAT --to-destination 192.168.60.5:8080
image-20230218171219306
Outis Yang
Outis Yang
2024 Undergraduate in Cyberspace Security

My research interests include Internet of Vehicles(IoV), Penetration Testing and Security research.