linux如何修改ip数据包

本文介绍了一个简单的实验程序dsr0.0.1,该程序用于修改IP数据包类型为DSR类型,并加入DSR选项。实现了仅允许运行该程序的机器间通讯,阻止与其他机器的正常通讯。文章提供了详细的代码实现。
dsr0.0.1程序存档及说明---如何修改ip数据包
2007-10-08 19:41:38
本程序功能
 对发送的数据包的数据包类型进行修改
改为dsr类型,设dsr类型的值为24
同时加入dsr选项,保存原来的数据类型

接收的数据包为逆过程
还原原数据包的数据类型
去掉dsr选项


实现的效果
只用同时运行该程序的机子可以进行通讯
无法其他机子的正常通讯

单机测试效果
ping自己的机子可以ping通
但ping其他的机子则不行

本程序算是我的第一个程序吧
主要目的是实验ip数据包的修改方法,以便进一步的编程,可以说是小实验吧
对于如何修改ip数据包作了详细的说明和代码演示
可以为以后编程作参考

特此存档以便后查

测试内核为2.6.20
==========================================
/*DSR处理程序dsr.c*/

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/skbuff.h>
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
#include <linux/string.h>
#include <linux/ip.h>
#include <net/ip.h>
#include <dsr.h>
#define DSR 24

//定义两个结构体,以便向钩子函数注册
static struct nf_hook_ops nfho1;
static struct nf_hook_ops nfho2;

//发送处理程序,截获发送的数据包,添加dsr头部(4字节),将有的协议类型更换为dsr类型
unsigned int dsr_send(unsigned int hooknum,struct sk_buff **skb,const struct net_device *in,const struct net_device *out,int (*okfn)(struct sk_buff *))
{
    struct iphdr *iph_n=(*skb)->nh.iph;
    int iph_len=((*skb)->nh.iph->ihl)*4;//ip首部长度,单位字节
    //printk("skb_headroom %i/n",skb_headroom(*skb));

    //__u8 icmp_type=00000001;
    //if(iph_n->protocol == icmp_type){iph_n->protocol=DSR;ip_send_check(iph_n);return NF_ACCEPT;}
    if(iph_n->protocol!=0)
    {
        unsigned char *dsrh_addr=skb_push((*skb),sizeof(struct dsr_header));//返回值为待写入数据的区域
       
        struct dsr_header dsrh;
        if(dsrh_addr==NULL){printk("the headroom is not enough/n");return NF_DROP;}
        //printk("a is %p/n b is %p/n",dsrh_addr,(*skb)->nh.iph);
       
        (*skb)->nh.iph=memmove(dsrh_addr,iph_n,iph_len);//前移ip头部
        iph_n=(*skb)->nh.iph;
        dsrh_addr+=iph_len;//确定dsr选项的地址
           
        //dsr选项值设定
        dsrh.nextheader=iph_n->protocol;
        dsrh.reserved=00000000;
        dsrh.length=0000000000000000;
        memcpy(dsrh_addr,&dsrh,4);//选项值写入内存相应区域
       
        //更改协议类型为DSR,并校验头部
        iph_n->protocol=DSR;
        iph_n->tot_len=htons((*skb)->len);
        ip_send_check(iph_n);
        //printk("a2 is %p/n b2 is %p/n",dsrh_addr,(*skb)->nh.iph);
        printk("send %i/n%i/n",iph_n->protocol,dsrh.nextheader);
        //printk("the new skb_headroom is %i/n",skb_headroom(*skb));
        return NF_ACCEPT;
    }
   
    else{return NF_DROP;}

    //return NF_ACCEPT;
}

//接收处理函数,还原数据包的原有数据类型,去除dsr选项
unsigned int dsr_rcv(unsigned int hooknum,struct sk_buff **skb,const struct net_device *in,const struct net_device *out,int (*okfn)(struct sk_buff *))
{
    struct iphdr *iph_n=(*skb)->nh.iph;
    printk("rcving/n");
   
    if(iph_n->protocol==DSR)
    {
//iph_n->protocol=1;
        int iph_len=((*skb)->nh.iph->ihl)*4;//ip首部长度,单位字节
        unsigned char *dsrh_addr=skb_pull((*skb),sizeof(struct dsr_header));//返回的是去掉了sizeof(dsr_header)后的地址,计ip头应移动到的地址;

        struct dsr_header *dsrh;//=(struct dsr_header *)iph_n+iph_len;
        (*skb)->nh.iph=(struct iphdr *)dsrh_addr;
        dsrh_addr=dsrh_addr+iph_len-sizeof(struct dsr_header);//确定dsr选项部分的地址
        //printk("%p/n",dsrh_addr);
        dsrh=(struct dsr_header *)dsrh_addr;
        //printk("iph %p/ndsr  %p/n",iph_n,dsrh);
        printk("rcv %i/n%i/n",iph_n->protocol,dsrh->nextheader);
        iph_n->protocol=dsrh->nextheader;
        memmove((*skb)->nh.iph,iph_n,iph_len);//ip头后移
        //(*skb)->nh.iph+=iph_len;
        iph_n=(*skb)->nh.iph;
        iph_n->tot_len=htons((*skb)->len);
        //printk("iph2  %p/n",iph_n);
        ip_send_check(iph_n);
    }

    return NF_ACCEPT;
}
//初始化函数,完成向钩子函数的注册
static int __init dsr_init(void)
{
    nfho1.hook=dsr_rcv;
    nfho1.hooknum=NF_IP_PRE_ROUTING;
    nfho1.pf=PF_INET;
    nfho1.priority=NF_IP_PRI_FIRST;
    nf_register_hook(&nfho1);
    nfho2.hook=dsr_send;
    nfho2.hooknum=NF_IP_LOCAL_OUT;
    nfho2.pf=PF_INET;
    nfho2.priority=NF_IP_PRI_FIRST;
    nf_register_hook(&nfho2);
    return 0;
}
//反注册钩子函数,module的出口
static void __exit dsr_exit(void)
{
    nf_unregister_hook(&nfho1);
    nf_unregister_hook(&nfho2);
}
module_init(dsr_init);
module_exit(dsr_exit);
==========================================
dsr.h文件如下
#ifndef _DSR_H
#define _DSR_H

#include <linux/types.h>

struct dsr_header
{
    __u8 nextheader;
    __u8 reserved;
    __u16 length;
};


#endif/*_DSR_H*/
==========================================
makefile文件
obj-m +=dsr.o
KERNELBUILD := /lib/modules/`uname -r`/build/
CFLAGS += -I/home/lightmusic/workspace/dsr/include/
default:
    make -C $(KERNELBUILD) M=$(shell pwd) modules
clean:
    rm -rf *.o .*.cmd *.ko *.mod.c .tmp_versions
==========================================
 
一款改自IPHookIP数据包监控过滤程序 By ccc 2009-6-13 完成(ch2zh1@tom.com) IP包过滤程序采用IPHook驱动器程序,在内核层用钩子回调函数(IpHookFilter)勾住系统自带的IP过滤驱动器(System32\Drivers\IpFltDrv.sys),从而返回过滤驱动器传输的所有IP包数据。可以通过回调函数的返回值(PF_DROP、PF_FORWARD、PF_PASS),指示滤波驱动器对包的处理,是抛弃还是通过。 应用启动驱动器过程可以使用驱动器的安装,或使用系统的服务控制器(ServiceControl)直接启动和停止驱动程序。 服务控制器利用OpenSCManager等服务控制函数控制驱动程序的加载与卸载。这就使得应用程序可以在运行时自动加载和卸载需要的驱动程序。而不必设置驱动程序的安装过程。 初始的IPHook.sys只提供了IP包的监视过程即,仅仅返回IP头信息。在应用中解释并显示这个头信息。经过写改的IPHook增加了对IP包的过滤处理,有几个设置命令: START_IP_HOOK :启动钩子过滤命令,建立连接IP滤波器的回调函数(原始命令) STOP_IP_HOOK :停止钩子过滤命令,撤销IP滤波器回调函数(原始命令) ADD_IP_HOOKADDR :添加过滤IP地址,回调函数判断IP包,以决定是放弃还是通过(新命令) DEL_IP_HOOKADDR :删除过滤IP地址(新命令) ADD_IP_HOOKPORT :添加过滤端口号(新命令) DEL_IP_HOOKPORT :删除过滤端口号(新命令) ADD_IP_OVER_HOOK :添加置换的IP地址,用于对指定目的的IP包置换地址和端口号(New) DEL_IP_OVER_HOOK :取消IP地址置换。(New) 应用程序可一次设置和删除对个滤波地址和端口号。对于重复设置,IPHook可以正确识别并加以剔除。这是一个演示程序主要想说明windows2000驱动程序编程过程,及应用自动加载和卸载驱动的方式。 驱动程序的码在DrvChecked.rar中,要想正确编译,必须安装windows2000 DDK,并在VS2003下设置包含目录指向DDK的目录,库目录也要指向DDK的库目录: C:\NTDDK\inc C:\NTDDK\inc\ddk C:\NTDDK\libchk\i386 并且在排列上一定要排在头两个位置上。 这个驱动程序在VC++下是可以正确编译通过的。驱动程序名:DrvChecked.sys。使用时应该改为:iphook.sys。delphi下的应用程序为:IPPacketMonitor.exe,它使用IPHook.sys。 任何人可以自己编译和修改这个驱动程序,使之能够按照一定的方式运行,这里给出的只是本人的一个想法,希望能给各位带来一点帮助。任何应用程序都可以想打开文件一样使用这个驱动程序,关于使用方法请参考Release Notes.htm提供的线索。 有什么问题和建议请电邮:ch2zh1@tom.com
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值