Chinaunix首页 | 论坛 | 博客
  • 博客访问: 3926760
  • 博文数量: 93
  • 博客积分: 3189
  • 博客等级: 中校
  • 技术积分: 4229
  • 用 户 组: 普通用户
  • 注册时间: 2009-02-02 13:29
个人简介

出没于杭州和青岛的程序猿一枚,对内核略懂一二

文章分类

全部博文(93)

文章存档

2016年(2)

2015年(3)

2014年(11)

2013年(29)

2012年(16)

2011年(5)

2010年(5)

2009年(22)

分类: LINUX

2009-02-20 10:52:49

给大家贴一个linux内核转发数据包的模块,要想读懂代码需要熟悉iptables,2.6内核的模块编程。这里就不详细解释程序代码了,该看懂的自然就会看懂,不该看懂的讲了也看不懂。大体说一下流程吧,首选注册内核hook,然后对指定mark的数据包(这里只分析了tcp和udp的包)转发的指定的目的地址(第三层地址/ip)。

/*************ltw,tony ipt_REDIRECT.c*/
/**    using:insmod ipt_hook.ko remark=2 dst=192.168.0.116
    default remark=1,dst=127.0.0.1
 */

#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/netfilter.h>
#include <linux/ip.h>
#include <linux/ipv6.h>
#include <linux/ctype.h>
#include <linux/inet.h>
#include <net/checksum.h>
#include <net/tcp.h>
#include <net/udp.h>

#include <net/netfilter/nf_conntrack.h>
#include <net/netfilter/nf_conntrack_expect.h>
#include <net/netfilter/nf_conntrack_ecache.h>
#include <net/netfilter/nf_conntrack_helper.h>
#include <linux/netfilter/nf_conntrack_ftp.h>
#include <linux/types.h>
#include <linux/skbuff.h> //skb_network_header(skb) CHECKSUM_UNNECESSARY

#include <linux/in.h> //IPPROTO_xxx

#include <linux/timer.h>
#include <net/xfrm.h>
#include <linux/netfilter.h>
#include <linux/netdevice.h> //netif_receive_skb netif_rx

#include <linux/if.h>
#include <linux/inetdevice.h>
#include <net/protocol.h>
#include <linux/netfilter_ipv4.h>
#include <linux/netfilter/x_tables.h>
#include <net/netfilter/nf_nat_rule.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("ltw");
static int remark=1;
char *dst="127.0.0.1";
module_param(remark,uint,0644);
module_param(dst,charp,0644);
MODULE_PARM_DESC(remark,"Copy the packet with the mark is remark");
static struct nf_hook_ops myhook;
unsigned int myhook_func(unsigned int hooknum,struct sk_buff *skb,const struct net_device *in,const struct net_device *out,int(*okfn)(struct sk_buff*))
{
    //printk(KERN_ALERT "get hook\n");

    struct iphdr *nowiph;
    nowiph=(struct iphdr*)skb_network_header(skb);
    __u32 mark=skb->mark;
    __be32 mydst;
    mydst = in_aton(dst);
    //__be32 testip= in_aton("203.208.37.99");

    //if(nowiph->saddr==testip&&nowiph->daddr==mydst) printk("OK\n");

    if(nowiph->daddr==mydst)
    {
        printk("%8x-%8x\n",ntohl(nowiph->saddr),ntohl(nowiph->daddr));
        //if(mydst==in_aton("127.0.0.1")) skb->pkt_type=5;

        return NF_ACCEPT;
    }
    //printk(KERN_ALERT "mark=%d\n",mark);

    if(mark==remark)
    {
        //printk(KERN_ALERT "OK\n");

        struct sk_buff *myskb=skb_copy(skb,GFP_ATOMIC);
        struct iphdr *myiph;
        //myskb->pkt_type=PACKET_OTHERHOST;

        myiph=(struct iphdr*)skb_network_header(myskb);
        if(myiph==NULL)
        {
            kfree_skb(myskb);
            return NF_ACCEPT;
        }
        myiph->daddr=mydst;
        if(myiph->protocol==IPPROTO_TCP)
        {
            __wsum csum=0;
            struct tcphdr *mytcphdr;
            unsigned int tcphoff;
            mytcphdr=(struct tcphdr*)(myskb->data+myiph->ihl*4);
            if(mytcphdr==NULL)
            {
                kfree_skb(myskb);
                return NF_ACCEPT;
            }
            nf_reset(myskb);
            tcphoff=myiph->ihl*4;
            ip_send_check(myiph);
            mytcphdr->check=0;
            csum=skb_checksum(myskb,tcphoff,myskb->len-tcphoff,0);
            myskb->csum=csum;
            myskb->ip_summed=CHECKSUM_NONE;
            /*mytcphdr->check=csum_tcpudp_magic(myiph->saddr,myiph->daddr,myskb->len,IPPROTO_TCP,csum_partial((char *)mytcphdr,myskb->len-tcphoff,0));
            mytcphdr->check+=0x1400;*/

            mytcphdr->check=0;
            mytcphdr->check=tcp_v4_check(myskb->len-tcphoff,myiph->saddr,myiph->daddr,csum_partial(mytcphdr,myskb->len-tcphoff,0));
            //printk("%u--%u\n",ntohs(myiph->saddr),ntohs(myiph->daddr));

            netif_rx(myskb);
        }
        else if(myiph->protocol==IPPROTO_UDP)
        {
            int csum=0;
            struct udphdr *myudphdr;
            unsigned int udphoff;
            myudphdr=(struct udphdr*)(myskb->data+myiph->ihl*4);
            if(myudphdr==NULL)
            {
                kfree_skb(myskb);
                return NF_ACCEPT;
            }
            udphoff=myiph->ihl*4;
            myskb->csum=0;
            ip_send_check(myiph);
            csum=skb_checksum(myskb,udphoff,myskb->len-udphoff,0);
            myskb->csum=csum;
            myskb->ip_summed=CHECKSUM_NONE;
            myudphdr->check=0;
            myudphdr->check=csum_tcpudp_magic(myiph->saddr,myiph->daddr,myskb->len-udphoff,IPPROTO_UDP,csum_partial(myudphdr,myskb->len-udphoff,0));
            nf_reset(myskb);
            netif_rx(myskb);
        }
    }
    return NF_ACCEPT;
}
static int __init myhook_init(void)
{
    printk(KERN_ALERT "ipt_hook init\n");
    memset(&myhook,0,sizeof(struct nf_hook_ops));
    myhook.hook=myhook_func;
    myhook.owner=THIS_MODULE;
    myhook.pf=PF_INET;
    myhook.hooknum=NF_IP_PRE_ROUTING;
    myhook.priority=INT_MAX;
    return nf_register_hook(&myhook);
}
static void __exit myhook_exit(void)
{
    nf_unregister_hook(&myhook);
}
module_init(myhook_init);
module_exit(myhook_exit);

 

转载时请注明出处(pengliang.cublog.cn),谢谢。

阅读(8281) | 评论(1) | 转发(3) |
给主人留下些什么吧!~~

lantiaoxian2015-12-01 18:00:29

博主,请教一下,客户端发送数据是怎么设置mark为2的?