|
想实现一个拦截并可以修改http报文的程序,搭建了一个透明网桥,在netfilter里将目的IP修改成本机,用户态程序监听处理,目前netfilter那部分内核模块总是死机,同样的代码在不同的地方,一个成功一个失败,不知道什么原因
static struct nf_hook_ops nfho_in;
static struct nf_hook_ops nfho_out;
unsigned int hook_func_in(unsigned int hooknum,
struct sk_buff **skb,
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
struct sk_buff *sb = *skb;
struct tcphdr *tcp_buff = NULL;
unsigned char *http_buff = NULL;
int tcp_len = 0;
int http_len = 0;
/*******************************************************************************************************/
if (*((u_short *)(sb->mac.raw + 12)) != 0x0008)
return NF_ACCEPT;
if (sb->nh.iph->protocol != IPPROTO_TCP)
return NF_ACCEPT;
tcp_buff = (struct tcphdr *)(sb->data + sb->nh.iph->ihl * 4);
if (tcp_buff->source != 0x5000 && tcp_buff->dest != 0x5000)
return NF_ACCEPT;
sb = skb_copy(sb, 1);
*skb = sb;
tcp_buff = (struct tcphdr *)(sb->data + sb->nh.iph->ihl * 4);
http_buff = (unsigned char *)tcp_buff + tcp_buff->doff * 4;
/*******************************************************************************************************/
if (tcp_buff->dest == 0x5000)
sb->nh.iph->daddr = 0x6f01a8c0;
/******************************************************************************************************/
// fix sk_buff checksum
tcp_len = ntohs(sb->nh.iph->tot_len) - sb->nh.iph->ihl * 4;
http_len = tcp_len - tcp_buff->doff * 4;
sb->csum = 0;
sb->csum = csum_partial((unsigned char *)http_buff, http_len, 0);
// fix tcp checksum
tcp_buff->check = 0;
tcp_buff->check = csum_tcpudp_magic(sb->nh.iph->saddr, sb->nh.iph->daddr, tcp_len, IPPROTO_TCP, csum_partial((unsigned char *)tcp_buff, tcp_buff->doff * 4, sb->csum));
// fix ip checksum
sb->nh.iph->check = 0;
sb->nh.iph->check = ip_fast_csum((unsigned char *)sb->nh.iph, sb->nh.iph->ihl);
return NF_ACCEPT;
}
unsigned int hook_func_out(unsigned int hooknum,
struct sk_buff **skb,
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
struct sk_buff *sb = *skb;
struct tcphdr *tcp_buff = NULL;
unsigned char *http_buff = NULL;
int tcp_len = 0;
int http_len = 0;
/*******************************************************************************************************/
printk("data out\n");
if (*((u_short *)(sb->mac.raw + 12)) != 0x0008)
return NF_ACCEPT;
if (sb->nh.iph->protocol != IPPROTO_TCP)
return NF_ACCEPT;
tcp_buff = (struct tcphdr *)(sb->data + sb->nh.iph->ihl * 4);
if (tcp_buff->source != 0x5000 && tcp_buff->dest != 0x5000)
return NF_ACCEPT;
//return NF_ACCEPT;
// 执行到下面就死机了
sb = skb_copy(sb, 1);
*skb = sb;
tcp_buff = (struct tcphdr *)(sb->data + sb->nh.iph->ihl * 4);
http_buff = (unsigned char *)tcp_buff + tcp_buff->doff * 4;
/*******************************************************************************************************/
if (tcp_buff->dest == 0x5000)
sb->nh.iph->saddr = 0x0101a8c0;
/******************************************************************************************************/
// fix sk_buff checksum
tcp_len = ntohs(sb->nh.iph->tot_len) - sb->nh.iph->ihl * 4;
http_len = tcp_len - tcp_buff->doff * 4;
sb->csum = 0;
sb->csum = csum_partial((unsigned char *)http_buff, http_len, 0);
// fix tcp checksum
tcp_buff->check = 0;
tcp_buff->check = csum_tcpudp_magic(sb->nh.iph->saddr, sb->nh.iph->daddr, tcp_len, IPPROTO_TCP, csum_partial((unsigned char *)tcp_buff, tcp_buff->doff * 4, sb->csum));
// fix ip checksum
sb->nh.iph->check = 0;
sb->nh.iph->check = ip_fast_csum((unsigned char *)sb->nh.iph, sb->nh.iph->ihl);
return NF_ACCEPT;
}
int init_module()
{
nfho_in.hook = hook_func_in;
nfho_in.hooknum = NF_IP_PRE_ROUTING;
nfho_in.pf = PF_INET;
nfho_in.priority = NF_IP_PRI_FIRST;
nfho_out.hook = hook_func_out;
nfho_out.hooknum = NF_IP_LOCAL_OUT;
nfho_out.pf = PF_INET;
nfho_out.priority = NF_IP_PRI_FIRST;
nf_register_hook(&nfho_in);
nf_register_hook(&nfho_out);
return 0;
}
void cleanup_module()
{
nf_unregister_hook(&nfho_in);
nf_unregister_hook(&nfho_out);
} |
|