netfilter使用

linux内核中ip的打印

//ipv4在linux内核中存在的类型为uint32_t,可以转为string。
void IP2Str(char *s_ip_addr, int size, uint32_t ip)
{
	snprintf(s_ip_addr, size, "%d.%d.%d.%d", ( ip >> 24 ) & 0xff, 
	( ip >> 16 ) & 0xff, ( ip >> 8 ) & 0xff, ip & 0xff);
}
//ipv6转为string
void IP62Str(char *str, int size, struct in6_addr *ip6)
{
	 snprintf(str, size, "%pI6c", ip6);
}

netfilter函数注册

netfilter函数有5个挂载点,分别为NF_BR_LOCAL_IN,NF_BR_LOCAL_OUT,NF_BR_PRE_ROUTING,NF_BR_FORWARD和NF_BR_POST_ROUTING。本文主要使用了NF_BR_LOCAL_IN和NF_BR_LOCAL_OUT。

#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 18, 0)
unsigned int my_local_in_hook(void *priv, struct sk_buff *skb,const struct nf_hook_state *state)
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
unsigned int my_local_in_hook(const struct nf_hook_ops *ops, struct sk_buff *skb, 
			const struct net_device *in, const struct net_device *out,
#ifndef __GENKSYMS__
            const struct nf_hook_state *state
#else
            int (*okfn)(struct sk_buff *)
#endif
		   )
#else
unsigned int my_local_in_hook(unsigned int hooknum,
                               struct sk_buff *skb,
                               const struct net_device *in,
                               const struct net_device *out,
                               int (*okfn)(struct sk_buff *))
#endif
{
	struct iphdr *iph;
	char s_ip_addr[20];
	//char d_ip_addr[20];
	if( unlikely(!skb) ) {
		return NF_ACCEPT;
	}

	iph = ip_hdr(skb);
	if( unlikely(!iph) ) {
		return NF_ACCEPT;
	}
 	memset(s_ip_addr, 0, sizeof(s_ip_addr));
	//memset(d_ip_addr, 0, sizeof(d_ip_addr));
	IP2Str(s_ip_addr, sizeof(s_ip_addr), ntohl(iph->saddr));
	//IP2Str(d_ip_addr, sizeof(d_ip_addr), ntohl(iph->daddr));
	if(likely(iph->protocol == IPPROTO_ICMP)) 
	{
		printk("pinging the host...");
    }
	else if(likely(iph->protocol == IPPROTO_TCP))
	{
		struct tcphdr *tcph = tcp_hdr(skb);
		if( unlikely(!tcph) )
		{
			return NF_ACCEPT;
        }
		if ((int)ntohs(tcph->dest)!=22)
		{
			printk("receive IPPROTO_TCP from %s,%d,%d\n", s_ip_addr,(int)ntohs(tcph->source),(int)ntohs(tcph->dest));
		}
		
	}
	else if(likely(iph->protocol == IPPROTO_UDP))
	{
		struct udphdr *udph = udp_hdr(skb);
		if( unlikely(!udph) )
		{
			return NF_ACCEPT;
        }
        printk("receive IPPROTO_UTP from %s,%d,%d\n", s_ip_addr,(int)ntohs(udph->source),(int)ntohs(udph->dest));
	}

	return NF_ACCEPT;
}

#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 18, 0)
unsigned int my_local_out_hook(void *priv, struct sk_buff *skb,const struct nf_hook_state *state)
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
unsigned int my_local_out_hook(const struct nf_hook_ops *ops, struct sk_buff *skb, 
			const struct net_device *in, const struct net_device *out,
#ifndef __GENKSYMS__
            const struct nf_hook_state *state
#else
            int (*okfn)(struct sk_buff *)
#endif
		   )
#else
unsigned int my_local_out_hook(unsigned int hooknum,
                               struct sk_buff *skb,
                               const struct net_device *in,
                               const struct net_device *out,
                               int (*okfn)(struct sk_buff *))
#endif
{
	struct iphdr *iph;
	char d_ip_addr[20];

	if( unlikely(!skb) ) {
		return NF_ACCEPT;
	}

	iph = ip_hdr(skb);
	if( unlikely(!iph) ) {
		return NF_ACCEPT;
	}
 	memset(d_ip_addr, 0, sizeof(d_ip_addr));
	IP2Str(d_ip_addr, sizeof(d_ip_addr), ntohl(iph->daddr));
	if(likely(iph->protocol == IPPROTO_ICMP)) 
	{
		printk("pinging...\n");
    }
	else if(likely(iph->protocol == IPPROTO_TCP))
	{
		struct tcphdr *tcph = tcp_hdr(skb);
		if( unlikely(!tcph) )
		{
			return NF_ACCEPT;
        }
		printk("send IPPROTO_TCP from %d, to %s:%d\n", (int)ntohs(tcph->source),d_ip_addr,(int)ntohs(tcph->dest));
	}
	else if(likely(iph->protocol == IPPROTO_UDP))
	{
		struct udphdr *udph = udp_hdr(skb);
		if( unlikely(!udph) )
		{
			return NF_ACCEPT;
        }
        printk("send IPPROTO_UTP from %d,to %s:%d\n", (int)ntohs(udph->source), d_ip_addr,(int)ntohs(udph->dest));
	}

	return NF_ACCEPT;
}
 
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 18, 0)
unsigned int my_local_in_hook_v6(void *priv, struct sk_buff *skb,const struct nf_hook_state *state)
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
unsigned int my_local_in_hook_v6(const struct nf_hook_ops *ops,
       struct sk_buff *skb,
       const struct net_device *in,
       const struct net_device *out,
#ifndef __GENKSYMS__
       const struct nf_hook_state *state
#else
       int (*okfn)(struct sk_buff *)
#endif
	   )
#else 
unsigned int my_local_in_hook_v6(unsigned int hooknum,
                               struct sk_buff *skb,
                               const struct net_device *in,
                               const struct net_device *out,
                               int (*okfn)(struct sk_buff *))
#endif
{   
    struct ipv6hdr *iph6;
    char s_addr[40] = {0};
	iph6 = ipv6_hdr(skb);
    if (!iph6)
        return NF_ACCEPT;
 
    /* 过滤 ::/128 空类型地址 */
    if (ipv6_addr_any(&iph6->saddr) || ipv6_addr_any(&iph6->daddr))
        return NF_ACCEPT;
 
    /* 过滤源地址和目的地址相等的报文 */
    if (ipv6_addr_equal(&iph6->saddr, &iph6->daddr))
        return NF_ACCEPT;
 
    /* 过滤环回地址报文 ::1/128 */
    if (ipv6_addr_loopback(&iph6->saddr) || ipv6_addr_loopback(&iph6->daddr))
    {
        return NF_ACCEPT;
    }
    IP62Str(s_addr, 40, &iph6->saddr);
	if (iph6->nexthdr == NEXTHDR_ICMP)
	{
		ptintk("pinging...");
	}
	else if (iph6->nexthdr == NEXTHDR_TCP)
	{
		struct tcphdr *tcph = tcp_hdr(skb);
		if( unlikely(!tcph) )
		{
			return NF_ACCEPT;
        }
        printk("recv ipv6 tcp from %s:%d, to %d\n",s_addr, (int)ntohs(tcph->source), (int)ntohs(tcph->dest));
	}
	else if (iph6->nexthdr == NEXTHDR_UDP)
	{
		struct udphdr *udph = udp_hdr(skb);
		if( unlikely(!udph) )
		{
			return NF_ACCEPT;
        }
        printk("recv ipv6 udp from %s:%d, to %d\n",s_addr, (int)ntohs(udph->source), (int)ntohs(udph->dest));
	}
    return NF_ACCEPT;                          
}
 
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 18, 0)
unsigned int my_local_out_hook_v6(void *priv, struct sk_buff *skb,const struct nf_hook_state *state)
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
unsigned int my_local_out_hook_v6(const struct nf_hook_ops *ops,
       struct sk_buff *skb,
       const struct net_device *in,
       const struct net_device *out,
#ifndef __GENKSYMS__
       const struct nf_hook_state *state
#else
       int (*okfn)(struct sk_buff *)
#endif
	   )
#else
unsigned int my_local_out_hook_v6(unsigned int hooknum,
                               struct sk_buff *skb,
                               const struct net_device *in,
                               const struct net_device *out,
                               int (*okfn)(struct sk_buff *))
#endif
{   
    /* do something */
    struct ipv6hdr *iph6;
    char d_addr[40] = {0};
	iph6 = ipv6_hdr(skb);
    if (!iph6)
        return NF_ACCEPT;
 
    /* 过滤 ::/128 空类型地址 */
    if (ipv6_addr_any(&iph6->saddr) || ipv6_addr_any(&iph6->daddr))
        return NF_ACCEPT;
 
    /* 过滤源地址和目的地址相等的报文 */
    if (ipv6_addr_equal(&iph6->saddr, &iph6->daddr))
        return NF_ACCEPT;
 
    /* 过滤环回地址报文 ::1/128 */
    if (ipv6_addr_loopback(&iph6->saddr) || ipv6_addr_loopback(&iph6->daddr))
    {
        return NF_ACCEPT;
    }
    IP62Str(d_addr, 40, &iph6->daddr);
	if (iph6->nexthdr == NEXTHDR_TCP)
	{
		struct tcphdr *tcph = tcp_hdr(skb);
		if( unlikely(!tcph) )
		{
			return NF_ACCEPT;
        }
		printk("send ipv6 tcp from %d, to %s:%d\n",(int)ntohs(tcph->source), d_addr, (int)ntohs(tcph->dest));
	}
	else if (iph6->nexthdr == NEXTHDR_UDP)
	{
		struct udphdr *udph = udp_hdr(skb);
		if( unlikely(!udph) )
		{
			return NF_ACCEPT;
        }
        printk("send ipv6 udp from %d, to %s:%d\n",(int)ntohs(udph->source), d_addr, (int)ntohs(udph->dest));
	}
    return NF_ACCEPT;                          
}
 
static struct nf_hook_ops my_hook_ops[] __read_mostly = 
{
	{
		.hook = my_local_in_hook,          //hook处理函数
		.pf = PF_INET,              //协议类型
		//.hooknum = NF_BR_PRE_ROUTING,    //hook注册点
		.hooknum = NF_BR_LOCAL_IN,
		.priority = NF_IP_PRI_FIRST,      //优先级
	},
	{
		.hook = my_local_out_hook,          //hook处理函数
		.pf = PF_INET,              //协议类型
		//.hooknum = NF_BR_PRE_ROUTING,    //hook注册点
		.hooknum = NF_BR_LOCAL_OUT,
		.priority = NF_IP_PRI_FIRST,      //优先级
	},
	{
        .hook = my_local_in_hook_v6,       /* 钩子处理函数 */
        .pf = NFPROTO_IPV6,                 /* 协议类型IPv6 */
        .hooknum = NF_BR_LOCAL_IN,     /* Pre_Routing链 */
        .priority = NF_IP_PRI_FIRST + 20,   /* 优先级 */
    },
    {
        .hook = my_local_out_hook_v6,        /* 钩子处理函数 */
        .pf = NFPROTO_IPV6,                   /* 协议类型IPv6 */
        //.hooknum = NF_INET_LOCAL_IN,       /* Post_Routing链 */
		.hooknum = NF_BR_LOCAL_OUT, 
        .priority = NF_IP_PRI_FIRST + 20,     /* 优先级 */
    },
};

//注册hook函数
void my_netfilter_init(void)
{
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 13, 0)
	if ( nf_register_net_hooks(&init_net, my_hook_ops, ARRAY_SIZE(my_hook_ops)) != 0 ) {
#else
	if ( nf_register_hooks(my_hook_ops, ARRAY_SIZE(my_hook_ops)) != 0) { 
#endif
		goto err;
	}
	return;
 
err:
	return;
}

//取消hook
 void netfilter_exit(void)
{
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 13, 0)
	nf_unregister_net_hooks(&init_net, my_hook_ops, ARRAY_SIZE(my_hook_ops));
#else
	nf_unregister_hooks(my_hook_ops, ARRAY_SIZE(my_hook_ops));
#endif
}
 
  • 7
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值