Chinaunix首页 | 论坛 | 博客
  • 博客访问: 52072
  • 博文数量: 14
  • 博客积分: 1545
  • 博客等级: 上尉
  • 技术积分: 170
  • 用 户 组: 普通用户
  • 注册时间: 2010-05-13 00:33
文章分类

全部博文(14)

文章存档

2011年(4)

2010年(10)

我的朋友

分类: LINUX

2011-04-20 23:37:46

例子是通过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);
阅读(2202) | 评论(0) | 转发(1) |
0

上一篇:没有了

下一篇:linux下获取网口ip、netmask、gateway

给主人留下些什么吧!~~