C 如何在内核空间中使用netfilter挂钩路由拆分的数据包
我必须在PRE_路由钩子中将大数据包拆分为小数据包。我已经做了必要的步骤,将数据包拆分成更小的数据包,创建skb,设置ip和udp报头等。但我不明白的是如何路由数据包?我现在可以在数据包中附加数据了(这可以在我前面的问题中看到:)。但现在我只能选择路由分离的数据包。提前谢谢 我在下面给出我的代码(到目前为止我可以写)。 让我们假设该模块在服务器机器上运行。服务器在端口6000上运行。然后,客户端发送一条消息“ThisIsUsedForTesting”。根据代码,服务器应该得到“ThisI”:一个更小的数据包。我现在不关心第二个包裹。我可以很容易地改变包的大小。但是现在可以有两个或更多的数据包 运行此模块后,服务器将收到消息:“ThisI”。但当回响时, 这包东西没有开箱。我为PRE_路由编写模块,此时机器应该oops,但服务器进程得到消息,然后机器oops。 我不理解这些情况。欢迎任何帮助/建议。如果我可以管理第一个拆分的数据包,我认为,其余的数据包可以自动处理,所以这里没有给出它们的代码:C 如何在内核空间中使用netfilter挂钩路由拆分的数据包,c,linux,linux-kernel,C,Linux,Linux Kernel,我必须在PRE_路由钩子中将大数据包拆分为小数据包。我已经做了必要的步骤,将数据包拆分成更小的数据包,创建skb,设置ip和udp报头等。但我不明白的是如何路由数据包?我现在可以在数据包中附加数据了(这可以在我前面的问题中看到:)。但现在我只能选择路由分离的数据包。提前谢谢 我在下面给出我的代码(到目前为止我可以写)。 让我们假设该模块在服务器机器上运行。服务器在端口6000上运行。然后,客户端发送一条消息“ThisIsUsedForTesting”。根据代码,服务器应该得到“ThisI”:一个
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/skbuff.h>
#include <linux/netfilter.h>
#include <linux/netdevice.h>
#include <linux/ip.h>
#include <linux/udp.h>
#include <linux/mm.h>
#include <linux/err.h>
#include <linux/crypto.h>
#include <linux/init.h>
#include <linux/crypto.h>
#include <linux/scatterlist.h>
#include <net/ip.h>
#include <net/udp.h>
#include <net/route.h>
#include <linux/netfilter_ipv4.h>
#define IP_HDR_LEN 20
#define UDP_HDR_LEN 8
#define TOT_HDR_LEN 28
static unsigned int pkt_split_begin(unsigned int hooknum,
struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff *));
static void skb_print_info(const struct sk_buff *skb);
static void ip_print_info(struct iphdr *iph);
static void udp_print_info(struct udphdr *udph);
static void data_print_info(unsigned char *data, int len);
static struct nf_hook_ops pkt_split_ops __read_mostly = {
.pf = NFPROTO_IPV4,
.priority = 1,
.hooknum = NF_INET_PRE_ROUTING,
.hook = pkt_split_begin,
};
static int __init pkt_split_init(void)
{
printk(KERN_ALERT "\npkt_split module started ...");
return nf_register_hook(&pkt_split_ops);
}
static void __exit pkt_split_exit(void)
{
nf_unregister_hook(&pkt_split_ops);
printk(KERN_ALERT "pkt_split module stopped ...");
}
static unsigned int pkt_split_begin (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;
struct udphdr *udph;
unsigned char *data;
unsigned int data_len;
unsigned int i;
unsigned char *temp;
unsigned char *temp1, *temp2;
unsigned char *ptr;
__u16 dst_port, src_port;
if (skb) {
iph = (struct iphdr *) skb_header_pointer (skb, 0, 0, NULL);
if (iph && iph->protocol &&(iph->protocol == IPPROTO_UDP)) {
udph = (struct udphdr *) skb_header_pointer (skb, IP_HDR_LEN, 0, NULL);
src_port = ntohs (udph->source);
dst_port = ntohs (udph->dest);
if (dst_port == 6000) {
printk(KERN_ALERT "\nUDP packet goes in");
data = (unsigned char *) skb_header_pointer (skb, IP_HDR_LEN+UDP_HDR_LEN, 0, NULL);
data_len = skb->len - TOT_HDR_LEN;
temp = kmalloc(50 * sizeof(char), GFP_ATOMIC);
memcpy(temp, data, data_len);
temp1 = kmalloc(50 * sizeof(char), GFP_ATOMIC);
temp2 = kmalloc(50 * sizeof(char), GFP_ATOMIC);
unsigned int len1, len2;
len1 = 5;
len2 = data_len - len1;
memcpy(temp1, temp, len1);
temp1[len1] = '\0';
printk(KERN_ALERT "temp1: %s", temp1);
ptr = temp + len1;
memcpy(temp2, ptr, len2);
printk(KERN_ALERT "temp2: %s", temp2);
struct sk_buff *skb1, *skb2;
struct iphdr *iph1, *iph2;
struct udphdr *udph1, *udph2;
unsigned char *data1, *data2;
int data_len1, data_len2;
skb1 = skb_copy(skb, GFP_ATOMIC);
skb2 = skb_copy(skb, GFP_ATOMIC);
iph1 = (struct iphdr *) skb_header_pointer(skb1, 0, 0, NULL);
udph1 = (struct udphdr *) skb_header_pointer(skb1, IP_HDR_LEN, 0, NULL);
data1 = (unsigned char *) skb_header_pointer(skb1, TOT_HDR_LEN, 0, NULL);
data_len1 = skb1->len - len2 - TOT_HDR_LEN + 1;
memset(data1, 0, data_len);
memcpy(data1, temp1, data_len1);
skb1->len = data_len1 + TOT_HDR_LEN;
iph1->tot_len = htons(data_len1 + TOT_HDR_LEN);
udph1->len = htons(data_len1 + UDP_HDR_LEN);
skb1->tail = skb1->tail - data_len2 + 1;
/* Calculation of IP header checksum */
iph1->check = 0;
ip_send_check (iph1);
/* Calculation of UDP checksum */
udph1->check = 0;
int offset = skb_transport_offset(skb1);
int len = skb1->len - offset;
udph1->check = ~csum_tcpudp_magic((iph1->saddr), (iph1->daddr), len, IPPROTO_UDP, 0);
struct sk_buff *tempskb;
tempskb = skb_copy(skb, GFP_ATOMIC);
*tempskb = *skb;
*skb = *skb1;
*skb1 = *tempskb;
(*okfn)(skb);
skb_print_info(skb1);
ip_print_info(iph1);
udp_print_info(udph1);
data_print_info(data1, data_len1);
kfree_skb(skb1);
}
}
}
return NF_DROP;
}
static void skb_print_info (const struct sk_buff *skb)
{
printk(KERN_ALERT "\nPrinting SKB info: ");
printk(KERN_ALERT "len: %d", skb->len);
printk(KERN_ALERT "tail: %d", skb->tail);
printk(KERN_ALERT "end: %d", skb->end);
printk(KERN_ALERT "head: %x", skb->head);
printk(KERN_ALERT "data: %x", skb->data);
printk(KERN_ALERT "\ntail pointer = %x", skb_tail_pointer(skb));
printk(KERN_ALERT "end pointer = %x", skb_end_pointer(skb));
printk(KERN_ALERT "\nheadroom = %d", skb_headroom(skb));
printk(KERN_ALERT "\ntailroom = %d", skb_tailroom(skb));
}
void ip_print_info (struct iphdr *iph)
{
printk(KERN_ALERT "\nPrinting IP header info:");
printk(KERN_ALERT "ihl = %d", iph->ihl);
printk(KERN_ALERT "version = %d", iph->version);
printk(KERN_ALERT "tos = %d", iph->tos);
printk(KERN_ALERT "tot_len = %d", ntohs(iph->tot_len));
printk(KERN_ALERT "id = %d", ntohs(iph->id));
printk(KERN_ALERT "frag_off = %d", ntohs(iph->frag_off));
printk(KERN_ALERT "ttl = %d", iph->ttl);
printk(KERN_ALERT "protocol = %d", iph->protocol);
printk(KERN_ALERT "check = %x", ntohs(iph->check));
printk(KERN_ALERT "saddr = %x", ntohl(iph->saddr));
printk(KERN_ALERT "daddr = %x", ntohl(iph->daddr));
}
void udp_print_info (struct udphdr *udph)
{
printk(KERN_ALERT "\nPrinting UDP header info: ");
printk(KERN_ALERT "source = %d", ntohs(udph->source));
printk(KERN_ALERT "dest = %d", ntohs(udph->dest));
printk(KERN_ALERT "len = %d", ntohs(udph->len));
printk(KERN_ALERT "check = %x", ntohs(udph->check));
}
void data_print_info (unsigned char *data, int len)
{
printk(KERN_ALERT "\nPrinting data info: ");
printk(KERN_ALERT "Data: %s", data);
printk(KERN_ALERT "data_len: %d", len);
}
module_init(pkt_split_init);
module_exit(pkt_split_exit);
MODULE_AUTHOR("Rifat Rahman Ovi: <rifatrahmanovi@gmail.com>");
MODULE_DESCRIPTION("Outward Packet Mangling and Decryption in Kernel Space");
MODULE_LICENSE("GPL");
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#定义IP_HDR_LEN 20
#定义UDP_HDR_LEN 8
#定义TOT_HDR_LEN 28
静态无符号整数pkt_split_begin(无符号整数hooknum,
结构sk_buff*skb,
const struct net_device*in,
const结构网络设备*out,
内部(*okfn)(结构sk_buff*);
静态无效skb_打印信息(常量结构SKU buff*skb);
静态无效ip_打印_信息(结构iphdr*iph);
静态无效udp_打印_信息(结构udphdr*udph);
静态无效数据打印信息(无符号字符*数据,整数长度);
静态结构nf_hook_ops pkt_split_ops_uuuread_moly={
.pf=NFPROTO_IPV4,
.优先级=1,
.hooknum=NF\u INET\u PRE\u路由,
.hook=pkt\u split\u begin,
};
静态整数初始化pkt拆分初始化(void)
{
printk(内核警报“\npkt\u分割模块已启动…”);
返回nf_寄存器_挂钩(&pkt_拆分_操作);
}
静态无效uu退出包装u拆分u退出(无效)
{
nf_取消注册_hook(&pkt_split_ops);
printk(内核警报“pkt_拆分模块已停止…”);
}
静态无符号整数pkt_split_begin(无符号整数hooknum,
结构sk_buff*skb,
const struct net_device*in,
const结构网络设备*out,
int(*okfn)(结构sk_buff*))
{
结构iphdr*iph;
结构udphdr*udph;
无符号字符*数据;
无符号整数数据;
无符号整数i;
无符号字符*temp;
无符号字符*temp1,*temp2;
无符号字符*ptr;
__u16 dst_端口、src_端口;
如果(skb){
iph=(结构iphdr*)skb_头_指针(skb,0,0,NULL);
如果(iph&&iph->协议&&(iph->协议==IPPROTO_UDP)){
udph=(struct udphdr*)skb_头_指针(skb,IP_HDR_LEN,0,NULL);
src_port=ntohs(udph->source);
dst_端口=ntohs(udph->dest);
如果(dst_端口==6000){
printk(内核警报“\nUDP数据包进入”);
数据=(无符号字符*)skb_头_指针(skb,IP_HDR_LEN+UDP_HDR_LEN,0,NULL);
data_len=skb->len-TOT_HDR_len;
温度=kmalloc(50*sizeof(char),GFP_原子);
memcpy(温度、数据、数据长度);
temp1=kmalloc(50*sizeof(char),GFP_原子);
temp2=kmalloc(50*sizeof(char),GFP_原子);
无符号整数len1,len2;
len1=5;
len2=数据_len-len1;
memcpy(temp1、temp1、len1);
temp1[len1]='\0';
printk(内核警报“temp1:%s”,temp1);
ptr=温度+透镜1;
memcpy(temp2、ptr、len2);
printk(内核警报“temp2:%s”,temp2);
结构sk_buff*skb1,*skb2;
结构iphdr*iph1,*iph2;
结构udphdr*udph1,*udph2;
无符号字符*data1,*data2;
int data_len1,data_len2;
skb1=skb_拷贝(skb,GFP_原子);
skb2=skb_拷贝(skb,GFP_原子);
iph1=(结构iphdr*)skb_头_指针(skb1,0,0,NULL);
udph1=(结构udphdr*)skb_头_指针(skb1,IP_HDR_LEN,0,NULL);
数据1=(无符号字符*)skb_头_指针(skb1,TOT_HDR_LEN,0,NULL);
data_len1=skb1->len-len2-TOT_HDR_len+1;
memset(数据1,0,数据长度);
memcpy(数据1、临时1、数据1);
skb1->len=数据len1+TOT\u HDR\u len;
iph1->tot_len=htons(数据_len1+tot_HDR_len);
udph1->len=htons(数据len1+UDP\u HDR\u len);
skb1->tail=skb1->tail-data_len2+1;
/*IP报头校验和的计算*/
iph1->check=0;
ip_发送_检查(iph1);
/*UDP校验和的计算*/
udph1->check=0;
int offset=skb_传输_offset(skb1);
int len=skb1->len-偏移量;
udph1->check=~csum\u tcpudp\u magic((iph1->saddr),(iph1->daddr),len,IPPROTO\u UDP,0);
结构sk_buff*tempskb;
tempskb=skb_拷贝(skb,GFP_原子);
*tempskb=*skb;
*skb=*skb1;
*skb1=*tempskb;
(*okfn)(skb);
skb_打印_信息(sk
okfn
okfn(skb);
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/skbuff.h>
#include <linux/netfilter.h>
#include <linux/netdevice.h>
#include <linux/ip.h>
#include <linux/udp.h>
#include <linux/mm.h>
#include <linux/err.h>
#include <linux/crypto.h>
#include <linux/init.h>
#include <linux/crypto.h>
#include <linux/scatterlist.h>
#include <net/ip.h>
#include <net/udp.h>
#include <net/route.h>
#include <linux/netfilter_ipv4.h>
#define IP_HDR_LEN 20
#define UDP_HDR_LEN 8
#define TOT_HDR_LEN 28
static unsigned int pkt_split_begin(unsigned int hooknum,
struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff *));
static void skb_print_info(const struct sk_buff *skb);
static void ip_print_info(struct iphdr *iph);
static void udp_print_info(struct udphdr *udph);
static void data_print_info(unsigned char *data, int len);
static struct nf_hook_ops pkt_split_ops __read_mostly = {
.pf = NFPROTO_IPV4,
.priority = 1,
.hooknum = NF_INET_PRE_ROUTING,
.hook = pkt_split_begin,
};
static int __init pkt_split_init(void)
{
printk(KERN_ALERT "\npkt_split module started ...");
return nf_register_hook(&pkt_split_ops);
}
static void __exit pkt_split_exit(void)
{
nf_unregister_hook(&pkt_split_ops);
printk(KERN_ALERT "pkt_split module stopped ...");
}
static unsigned int pkt_split_begin (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;
struct udphdr *udph;
unsigned char *data;
unsigned int data_len;
unsigned int i;
unsigned char *temp;
unsigned char *temp1, *temp2;
unsigned char *ptr;
__u16 dst_port, src_port;
if (skb) {
iph = (struct iphdr *) skb_header_pointer (skb, 0, 0, NULL);
if (iph && iph->protocol &&(iph->protocol == IPPROTO_UDP)) {
udph = (struct udphdr *) skb_header_pointer (skb, IP_HDR_LEN, 0, NULL);
src_port = ntohs (udph->source);
dst_port = ntohs (udph->dest);
if (dst_port == 6000) {
printk(KERN_ALERT "\nUDP packet goes in");
data = (unsigned char *) skb_header_pointer (skb, IP_HDR_LEN+UDP_HDR_LEN, 0, NULL);
data_len = skb->len - TOT_HDR_LEN;
temp = kmalloc(50 * sizeof(char), GFP_ATOMIC);
memcpy(temp, data, data_len);
temp1 = kmalloc(50 * sizeof(char), GFP_ATOMIC);
temp2 = kmalloc(50 * sizeof(char), GFP_ATOMIC);
unsigned int len1, len2;
len1 = 5;
len2 = data_len - len1;
memcpy(temp1, temp, len1);
temp1[len1] = '\0';
printk(KERN_ALERT "temp1: %s", temp1);
ptr = temp + len1;
memcpy(temp2, ptr, len2);
printk(KERN_ALERT "temp2: %s", temp2);
struct sk_buff *skb1, *skb2;
struct iphdr *iph1, *iph2;
struct udphdr *udph1, *udph2;
unsigned char *data1, *data2;
int data_len1, data_len2;
skb1 = skb_copy(skb, GFP_ATOMIC);
skb2 = skb_copy(skb, GFP_ATOMIC);
iph1 = (struct iphdr *) skb_header_pointer(skb1, 0, 0, NULL);
udph1 = (struct udphdr *) skb_header_pointer(skb1, IP_HDR_LEN, 0, NULL);
data1 = (unsigned char *) skb_header_pointer(skb1, TOT_HDR_LEN, 0, NULL);
data_len1 = skb1->len - len2 -TOT_HDR_LEN + 1;
memset(data1, 0, data_len);
memcpy(data1, temp1, data_len1);
skb1->len = data_len1 + TOT_HDR_LEN;
iph1->tot_len = htons(data_len1 + TOT_HDR_LEN);
udph1->len = htons(data_len1 + UDP_HDR_LEN);
skb1->tail = skb1->tail - data_len2 + 1;
/* Calculation of IP header checksum */
iph1->check = 0;
ip_send_check (iph1);
/* Calculation of UDP checksum */
udph1->check = 0;
int offset = skb_transport_offset(skb1);
int len = skb1->len - offset;
udph1->check = ~csum_tcpudp_magic((iph1->saddr), (iph1->daddr), len, IPPROTO_UDP, 0);
/* Dealing with the second packet */
iph2 = (struct iphdr *) skb_header_pointer(skb2, 0, 0, NULL);
udph2 = (struct udphdr *) skb_header_pointer(skb2, IP_HDR_LEN, 0, NULL);
data2 = (unsigned char *) skb_header_pointer(skb2, TOT_HDR_LEN, 0, NULL);
data_len2 = skb2->len - len1 - TOT_HDR_LEN;
memset(data2, 0, data_len);
memcpy(data2, temp2, data_len2);
skb2->len = data_len2 + TOT_HDR_LEN;
iph2->tot_len = htons(data_len2 + TOT_HDR_LEN);
udph2->len = htons(data_len2 + UDP_HDR_LEN);
skb2->tail = skb2->tail - data_len1;
/* Calculation of IP header checksum */
iph2->check = 0;
ip_send_check (iph2);
/* Calculation of UDP checksum */
udph2->check = 0;
offset = skb_transport_offset(skb1);
len = skb2->len - offset;
udph2->check = ~csum_tcpudp_magic((iph2->saddr), (iph2->daddr), len, IPPROTO_UDP, 0);
okfn(skb1);
okfn(skb2);
}
}
}
return NF_DROP;
}
static void skb_print_info (const struct sk_buff *skb)
{
printk(KERN_ALERT "\nPrinting SKB info: ");
printk(KERN_ALERT "len: %d", skb->len);
printk(KERN_ALERT "tail: %d", skb->tail);
printk(KERN_ALERT "end: %d", skb->end);
printk(KERN_ALERT "head: %x", skb->head);
printk(KERN_ALERT "data: %x", skb->data);
printk(KERN_ALERT "\ntail pointer = %x", skb_tail_pointer(skb));
printk(KERN_ALERT "end pointer = %x", skb_end_pointer(skb));
printk(KERN_ALERT "\nheadroom = %d", skb_headroom(skb));
printk(KERN_ALERT "\ntailroom = %d", skb_tailroom(skb));
}
void ip_print_info (struct iphdr *iph)
{
printk(KERN_ALERT "\nPrinting IP header info:");
printk(KERN_ALERT "ihl = %d", iph->ihl);
printk(KERN_ALERT "version = %d", iph->version);
printk(KERN_ALERT "tos = %d", iph->tos);
printk(KERN_ALERT "tot_len = %d", ntohs(iph->tot_len));
printk(KERN_ALERT "id = %d", ntohs(iph->id));
printk(KERN_ALERT "frag_off = %d", ntohs(iph->frag_off));
printk(KERN_ALERT "ttl = %d", iph->ttl);
printk(KERN_ALERT "protocol = %d", iph->protocol);
printk(KERN_ALERT "check = %x", ntohs(iph->check));
printk(KERN_ALERT "saddr = %x", ntohl(iph->saddr));
printk(KERN_ALERT "daddr = %x", ntohl(iph->daddr));
}
void udp_print_info (struct udphdr *udph)
{
printk(KERN_ALERT "\nPrinting UDP header info: ");
printk(KERN_ALERT "source = %d", ntohs(udph->source));
printk(KERN_ALERT "dest = %d", ntohs(udph->dest));
printk(KERN_ALERT "len = %d", ntohs(udph->len));
printk(KERN_ALERT "check = %x", ntohs(udph->check));
}
void data_print_info (unsigned char *data, int len)
{
printk(KERN_ALERT "\nPrinting data info: ");
printk(KERN_ALERT "Data: %s", data);
printk(KERN_ALERT "data_len: %d", len);
}
module_init(pkt_split_init);
module_exit(pkt_split_exit);
MODULE_AUTHOR("Rifat Rahman Ovi: <rifatrahmanovi@gmail.com>");
MODULE_DESCRIPTION("Inward Packet Splitting in kernel space");
MODULE_LICENSE("GPL");