- 論壇徽章:
- 0
|
本帖最后由 ierent168 于 2014-06-28 10:47 編輯
通過hook函數(shù)獲取網(wǎng)橋上的TCP數(shù)據(jù)包,然后將鉤到的數(shù)據(jù)包源目的MAC地址互換,源目的IP互換,以及TCP端口互換,修改發(fā)回去,發(fā)現(xiàn)數(shù)據(jù)有錯(cuò)誤而且錯(cuò)誤很奇怪。我的鉤子位置在PRE_ROUTING,然后修改后直接在接受包的端口發(fā)出去,不知道各位兄臺(tái)有沒有遇到過。下面是我的代碼?關(guān)鍵是修改TCP以后發(fā)現(xiàn)錯(cuò)誤了。
#include <linux/init.h>
#include <linux/module.h>
#include <linux/netfilter.h>
#include <linux/socket.h>/*PF_INET*/
#include <linux/netfilter_ipv4.h>/*NF_IP_PRE_FIRST*/
#include <linux/skbuff.h>
#include <linux/netdevice.h>
#include <linux/inet.h> /*in_aton()*/
#include <net/ip.h>
#include <net/tcp.h>
#include <linux/netfilter_ipv4/ip_tables.h>
#include <linux/netfilter_bridge.h>
#include <linux/moduleparam.h>
#include <linux/kernel.h>
#define ETHALEN 14
#define NF_IP_PRE_ROUTING 0 //netfilter_ipv4.h have
MODULE_LICENSE("GPL");
MODULE_AUTHOR("lyh");
static struct nf_hook_ops nfho;
//static int a = 0;
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_EMERG "0000000000000000000000000\n");
struct sk_buff *skb;
// struct sk_buff *skbx;
struct net_device *dev;
struct iphdr *iph;
// struct ethernet_header{
// }
int ret;
int tot_len;//定義IP數(shù)據(jù)報(bào)總長度
int iph_len;//IP頭部長度
int tcph_len;//TCP頭部長度
// int i = 0;
struct tcphdr *tcph;
__u16 midder_var;//rst復(fù)位時(shí)候交換源端口和目的端口的中間變量
struct ethhdr *ethh;
unsigned char eth_MAC[6];
int ip_address;
// printk(KERN_EMERG "1111111111111111111111111\n");
// skb = _skb;
skb = skb_copy(_skb,GFP_ATOMIC);
if(skb == NULL)
{
return NF_ACCEPT;
}
iph = ip_hdr(skb);//將skb強(qiáng)制轉(zhuǎn)換成ip結(jié)構(gòu)體型
printk(KERN_EMERG "iph->saddr=%02x\n",iph->saddr);
printk(KERN_EMERG "iph->daddr=%02x\n",iph->daddr);
if(iph == NULL)
{
return NF_ACCEPT;
}
tot_len = ntohs(iph->tot_len);
printk(KERN_EMERG "222222222222222222222222\n");
// 這里假設(shè)通過過濾IP地址,如果過濾掉的包是TCP包,那么直接發(fā)送一個(gè)rst包
// if(iph->daddr == in_aton("192.168.1.7"))
// {
// printk(KERN_EMERG "33333333333333333333333\n");
if(iph->protocol == IPPROTO_TCP)
{
iph_len = ip_hdrlen(skb);
tcph_len = tcp_hdrlen(skb);
//修改MAC部分
{
ethh = eth_hdr(skb);
memcpy(eth_MAC,ethh->h_source,sizeof(ethh->h_source));
memcpy(ethh->h_source,ethh->h_dest,sizeof(ethh->h_dest));
memcpy(ethh->h_dest,eth_MAC,sizeof(ethh->h_source));
/* for(i = 0;i<6;i++)
{
// printk(KERN_EMERG "**************************************************\n");
printk(KERN_EMERG "eth_MAC=%02x;ethh->h_source=%02x;ethh->h_dest=%02x\n",*(eth_MAC+i),*(ethh->h_source+i),*(ethh->h_dest+i));
// printk(KERN_EMERG "**************************************************\n");
}
printk(KERN_EMERG "**************************************************\n");
*/
}
//修改IP部分
{
ip_address = iph->saddr;
iph->saddr = iph->daddr;
iph->daddr = ip_address;
iph->check = 0;
/*
printk(KERN_EMERG "**************************************************\n");
printk(KERN_EMERG "iph->saddr=%02x\n",iph->saddr);
printk(KERN_EMERG "iph->daddr=%02x\n",iph->daddr);
printk(KERN_EMERG "iph->daddr=%02x\n",iph->protocol);
printk(KERN_EMERG "**************************************************\n");
*/
}
//修改TCP部分,使得發(fā)送
{
tcph = tcp_hdr(skb);//將skb強(qiáng)制轉(zhuǎn)換成tcp結(jié)構(gòu)體型
midder_var = tcph->source;
tcph->source = tcph->dest;
tcph->dest = midder_var;
tcph->ack_seq = htonl(ntohl(tcph->seq)+1);
tcph->seq = 0;
tcph->ack = 1;
tcph->rst = 1;
tcph->check = 0;
}
{
printk(KERN_EMERG "**************************************************\n");
printk(KERN_EMERG "iph->saddr=%02x\n",iph->saddr);
printk(KERN_EMERG "iph->daddr=%02x\n",iph->daddr);
printk(KERN_EMERG "iph->protocol=%02x\n",iph->protocol);
printk(KERN_EMERG "tcph->source=%02x\n",tcph->source);
printk(KERN_EMERG "tcph->dest=%02x\n",tcph->dest);
printk(KERN_EMERG "tcph->dest=%02x\n",tcph->dest);
printk(KERN_EMERG "tcph->check=%02x\n",tcph->check);
printk(KERN_EMERG "tcph->rst=%02x\n",tcph->rst);
printk(KERN_EMERG "**************************************************\n");
}
skb->pkt_type = PACKET_OTHERHOST;//發(fā)給別人的幀(監(jiān)聽模式時(shí)會(huì)有這種幀)
skb->ip_summed = CHECKSUM_NONE;//需要軟件重新計(jì)算校驗(yàn)和
skb->csum = csum_partial((unsigned char *)tcph, tot_len-iph_len, 0);
tcph->check = csum_tcpudp_magic(iph->saddr,iph->daddr, tot_len - iph_len, iph->protocol, skb->csum);
iph->check = ip_fast_csum((unsigned char *)iph,iph->ihl);
//測試用
dev = dev_get_by_name(&init_net,"eth7");
if(dev==NULL)
goto out;
skb->dev = dev;
// skb_push(skb, iph_len);
skb_push(skb, ETHALEN);//將skb->data指向l2層,之后將數(shù)據(jù)包通過dev_queue_xmit()發(fā)出
ret = dev_queue_xmit(skb);
// dev_put(skb->dev);
return NF_STOLEN;
}
else
{
return NF_ACCEPT;
}
out:
dev_put(dev);
//free(skb);
printk(KERN_EMERG "send fail\n");
return NF_DROP;
}
static struct nf_hook_ops nfho={
.hook = myhook_func,
.owner = THIS_MODULE,
.pf = PF_BRIDGE,
.hooknum = NF_BR_PRE_ROUTING,
.priority = NF_BR_PRI_FIRST,
};
static int __init myhook_init(void)//__init,表示告訴gcc把該函數(shù)放在init這個(gè)section;
{
int ret;
ret = nf_register_hook(&nfho);
if(ret < 0)
{
printk(KERN_EMERG "can't modify skb hook!\n");
return ret;
}
return ret;
}
static void myhook_fini(void)
{
nf_unregister_hook(&nfho);
}
module_init(myhook_init);
module_exit(myhook_fini);
我要實(shí)現(xiàn)的功能就是將鉤到的TCP數(shù)據(jù)包源目的MAC地址互換,源目的IP互換,以及TCP端口互換,然后RST置1,還有修改序列號(hào),然后再從新發(fā)送到接收端口。但是現(xiàn)在程序的情況是這樣的,MAC地址可以互換,TCP端口也可以互換,但是源目的IP不能完全互換,只能后兩位進(jìn)行互換,而且用wireshark抓包以后顯示,不出是TCP包,也就是原來IP協(xié)議標(biāo)志位也沒篡改了就是 iph->protocol值;但是假如把 這幾句換注釋掉,
tcph->ack_seq = htonl(ntohl(tcph->seq)+1);
tcph->seq = 0;
tcph->ack = 1;
tcph->rst = 1;
tcph->check = 0;
對(duì)TCP頭只進(jìn)行端口互換,那么源目的IP就可以正確互換,而且 iph->protocol值不會(huì)篡改,但是這樣的話功能就實(shí)現(xiàn)不了了。不知道為什么?這個(gè)問題很奇怪。 有沒有人遇到過呢
|
|