Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1672013
  • 博文数量: 782
  • 博客积分: 2455
  • 博客等级: 大尉
  • 技术积分: 4140
  • 用 户 组: 普通用户
  • 注册时间: 2011-04-06 21:37
个人简介

Linux ,c/c++, web,前端,php,js

文章分类

全部博文(782)

文章存档

2015年(8)

2014年(28)

2013年(110)

2012年(307)

2011年(329)

分类: LINUX

2013-12-04 11:17:36

例子是通过netfilter的hook来实现修改源IP,对应的内核版本是2.6.21以后
tcp端口:9877
本地ip: 192.168.3.88
伪IP:192.168.7.88

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

MODULE_AUTHOR("st");

#ifdef MODULE_LICENSE

MODULE_LICENSE("Dual BSD/GPL");

#endif /* MODULE_LICENSE */

#ifndef NF_IP_PRE_ROUTING
#define NF_IP_PRE_ROUTING 0
#endif

#ifndef NF_IP_POST_ROUTING
#define NF_IP_POST_ROUTING 4
#endif

static unsigned int ip_post_fn(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 iphdr *ihead = ip_hdr(sb);
    struct tcphdr *thead = (struct tcphdr *)((unsigned int *)ihead + ihead->ihl);

    if ihead->protocol != IPPROTO_TCP || thead->dest != htons(9877)) {
        return NF_ACCEPT;
    }

    ihead->saddr = 0x5807a8c0;    //ip:192.168.7.88
    int tcplen = sb->len - ihead->ihl * 4;

    if(sb->data_len == 0){    //没有分片数据的情况,三次握手是没有分片数据的
        thead->check = 0;
        thead->check = tcp_v4_check(tcplen, ihead->saddr, ihead->daddr,
            csum_partial((char *)thead, tcplen, 0));
    }
    else{ //有分片数据的情况,这里只考虑一个分片数据,当然类似地可以处理多分片数据的情况
        thead->check = 0;
        thead->check = tcp_v4_check(tcplen, ihead->saddr,ihead->daddr,
            csum_partial((char *)thead, tcplen - sb->data_len,
            csum_partial((char *)(page_address(skb_shinfo(sb)->frags[0].page)
                + skb_shinfo(sb)->frags[0].page_offset),
                skb_shinfo(sb)->frags[0].size, 0)));
    }

    ihead->check = 0;
    ihead->check = ip_fast_csum((unsigned char *)ihead, ihead->ihl);

    sb->csum = ~tcp_v4_check(tcplen, ihead->saddr,
        ihead->daddr, 0);

    return NF_ACCEPT;
}

static unsigned int ip_pre_fn(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 iphdr *ihead = ip_hdr(sb);
    struct tcphdr *thead = (struct tcphdr *)((unsigned int *)ihead + ihead->ihl);
    if (ihead->protocol != IPPROTO_TCP || thead->source != htons(9877)) {
        return NF_ACCEPT;
    }

    ihead->daddr = 0x5803a8c0;     //ip:192.168.3.88
   
    sb->csum = tcp_v4_check(sb->len - ihead->ihl * 4, ihead->saddr,
        ihead->daddr, 0);

    ihead->check = 0;
    ihead->check = ip_fast_csum((unsigned char *)ihead, ihead->ihl);

    return NF_ACCEPT;
}

static struct nf_hook_ops ip_post_ops = {
    .hook = ip_post_fn,
    .pf = PF_INET,
    .hooknum = NF_IP_POST_ROUTING,
    .priority = NF_IP_PRI_FIRST,
};

static struct nf_hook_ops ip_pre_ops = {
    .hook = ip_pre_fn,
    .pf = PF_INET,
    .hooknum = NF_IP_PRE_ROUTING,
    .priority = NF_IP_PRI_FIRST,
};

int hello_init_module(void)
{
    int ret = 0;
    if ((ret = nf_register_hook(&ip_post_ops)) < 0) {
        printk("can't register ip_post_ops hook\n");
        return ret;
    }

    if ((ret = nf_register_hook(&ip_pre_ops)) < 0) {
        printk("can't register ip_pre_ops hook\n");
        nf_unregister_hook(&ip_post_ops);
        return ret;
    }

    return 0;
}

void hello_cleanup_module(void)
{
    nf_unregister_hook(&ip_post_ops);
    nf_unregister_hook(&ip_pre_ops);
}

module_init(hello_init_module);
module_exit(hello_cleanup_module);
阅读(1674) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~