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
}