2012-09-21 27 views
5

Tôi đang cố nối thêm một số dữ liệu trên một gói từ không gian hạt nhân. Tôi có một máy khách và máy chủ echo. Tôi gõ vào dòng lệnh như: ./client "message" và server chỉ lặp lại nó. Máy chủ được chạy với ./server.Làm cách nào để nối thêm dữ liệu trên gói từ không gian hạt nhân?

Bây giờ, máy khách và máy chủ nằm trên hai máy khác nhau (có thể là máy ảo). Tôi đang viết một mô-đun hạt nhân chạy trên máy khách. Công việc của nó là để thêm "12345" sau khi "tin nhắn" trong khi gói tin đi ra khỏi máy. Tôi đang trình bày mã dưới đây.

/* 
* This is ibss_obsf_cat.c 
*/ 

#include <linux/module.h> 
#include <linux/moduleparam.h> 
#include <linux/kernel.h> 
#include <linux/netfilter.h> 
#include <linux/skbuff.h> 
#include <linux/netdevice.h> 
#include <linux/udp.h> 
#include <linux/ip.h> 

#undef __KERNEL__ 
#include <linux/netfilter_ipv4.h> 
#define __KERNEL__ 


/* 
* Function prototypes ... 
*/ 

static unsigned int cat_obsf_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 hex_dump (char str[], int len) 
{ 

} 

/* 
* struct nf_hook_ops instance initialization 
*/ 

static struct nf_hook_ops cat_obsf_ops __read_mostly = { 
    .pf = NFPROTO_IPV4, 
    .priority = 1, 
    .hooknum = NF_IP_POST_ROUTING, 
    .hook = cat_obsf_begin, 
}; 

/* 
* Module init and exit functions. 
* No need to worry about that. 
*/ 

static int __init cat_obsf_init (void) 
{ 
    printk(KERN_ALERT "cat_obsf module started...\n"); 
    return nf_register_hook(&cat_obsf_ops); 
} 

static void __exit cat_obsf_exit (void) 
{ 
    nf_unregister_hook(&cat_obsf_ops); 
    printk(KERN_ALERT "cat_obsf module stopped...\n"); 
} 

/* 
* Modification of the code begins here. 
* Here are all the functions and other things. 
*/ 

static unsigned int cat_obsf_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 char dt[] = "12345"; 
    unsigned char *tmp; 
    unsigned char *ptr; 

    int i, j, len; 

    if (skb){ 
     iph = ip_hdr(skb); 

     if (iph && iph->protocol && (iph->protocol == IPPROTO_UDP)){ 
      udph = (struct udphdr *) ((__u32 *)iph + iph->ihl); 
      data = (char *)udph + 8; 

      if(ntohs(udph->dest) == 6000){ 
       for (i=0; data[i]; i++); 
       len = i; 

       //printk(KERN_ALERT "\nData length without skb: %d", len); 
       //printk(KERN_ALERT "Data is: %s", data); 
       //printk(KERN_ALERT "dt size: %lu", sizeof(dt)); 
       //printk(KERN_ALERT "skb->len: %d", skb->len); 
       tmp = kmalloc(200*sizeof(char), GFP_KERNEL); 

       memcpy(tmp, data, len); 
       ptr = tmp + len; 
       memcpy(ptr, dt, sizeof(dt)); 

       printk(KERN_ALERT "tmp: %s", tmp); 


       printk(KERN_ALERT "skb->tail: %d", skb->tail); 
       //skb_put(skb, sizeof(dt)); 
       printk(KERN_ALERT "skb->end: %d", skb->end); 
       printk(KERN_ALERT "skb->tail: %d", skb->tail); 
       printk(KERN_ALERT "skb->tail(int): %d", (unsigned int)skb->tail); 

       //memset(data, 0, len + sizeof(dt)); 

       //memcpy(data, tmp, len + sizeof(dt)); 

       //skb_add_data(skb, tmp, len+sizeof(dt)); 

       printk(KERN_ALERT "Now data is: %s", data); 
       for(i=0; data[i]; i++); 
       printk(KERN_ALERT "data length: %d", i); 

       kfree(tmp); 

      }  
     } 
    } 
    return NF_ACCEPT; 
} 

/* 
* Nothing to be touched hereafter 
*/ 

module_init(cat_obsf_init); 
module_exit(cat_obsf_exit); 

MODULE_AUTHOR("Rifat"); 
MODULE_DESCRIPTION("Module for packet mangling"); 
MODULE_LICENSE("GPL"); 

Tôi muốn nhận được "tin nhắn" là "message12345" trong khi gửi ra khỏi máy khách từ không gian hạt nhân. Vì vậy, máy chủ sẽ nhận được "message12345" và echo nó trở lại, và khách hàng sẽ chỉ đọc "message12345" Nhưng tôi gặp rắc rối với skb_put() và skb_add_data() chức năng. Tôi không hiểu tôi đã mắc lỗi gì. Nếu bất cứ ai có thể giúp tôi với mã, tôi sẽ rất biết ơn. Cảm ơn trước. Tôi cũng cho Makefile để thuận tiện. Điều này là dành cho hạt nhân phân phối, không phải cho một hạt nhân được xây dựng.

#If KERNELRELEASE is defined, we've been invoked from the 
#kernel build system and use its language 
ifneq ($(KERNELRELEASE),) 
    obj-m := ibss_obsf_cat.o 

#Otherwise we were called directly from the command 
#line; invoke the kernel build system. 
else 

    KERNELDIR ?= /lib/modules/$(shell uname -r)/build 
    PWD := $(shell pwd) 

default: 
    $(MAKE) -C $(KERNELDIR) M=$(PWD) modules 

endif 

Bây giờ tôi khá thuyết phục rằng skb-> cuối - skb-> đuôi là quá nhỏ mà tôi sẽ phải tạo gói mới trong không gian hạt nhân. Tôi đã sử dụng alloc_skb() skb_reserve() skb_header_pointer() và các chức năng skb hữu ích khác để tạo skb mới, nhưng điều tôi đang hết ý tưởng là cách định tuyến gói mới được tạo trong đường dẫn gói . Cách sử dụng
ip_route_me_harder() Tôi đã xem gói xtables-addons để gợi ý, nhưng chức năng mà họ đã sử dụng khác với chức năng trong hạt nhân Linux. Bất kỳ đề nghị được hoan nghênh.

Trả lời

3

Khoảng một năm trước cho kernel 2.6.26 tôi đã làm nó như thế này:

// Do we need extra space? 
if(len - skb_tailroom(skb) > 0){ 

    // Expand skb tail until we have enough room for the extra data 
    if (pskb_expand_head(skb, 0, extra_data_len - skb_tailroom(skb), GFP_ATOMIC)) { 
    // allocation failed. Do whatever you need to do 
    } 

    // Allocation succeeded 

    // Reserve space in skb and return the starting point 
    your_favourite_structure* ptr = (your_favourite_structure*) 
            skb_push(skb, sizeof(*ptr)); 

    // Now either set each field of your structure or memcpy into it. 
    // Remember you can use a char* 

} 

Đừng quên:

  • Tính toán lại UDP checksum, bởi vì bạn đã thay đổi dữ liệu trong các dữ liệu vận chuyển .

  • Thay đổi trường tot_len (tổng chiều dài) trong tiêu đề ip, vì bạn đã thêm dữ liệu vào gói.

  • Tính toán lại tổng kiểm tra tiêu đề IP, vì bạn đã thay đổi trường tot_len.

tắm lưu ý: Đây chỉ là một điều đơn giản. Tôi thấy trong mã của bạn, bạn đang phân bổ tmp làm mảng 200 byte và sử dụng mảng đó để lưu trữ dữ liệu thư của bạn. Nếu bạn gửi một gói lớn hơn, bạn sẽ có một thời gian khó gỡ lỗi này vì hạt nhân bị treo do bộ nhớ tràn quá đau đớn.

+0

Cảm ơn sự giúp đỡ của bạn. Vâng, các trường độ dài làm tôi lo lắng rất nhiều. –

+0

Và cũng kiểm tra trong không gian hạt nhân khá mơ hồ với tôi lúc đầu. –

+0

@Fred bạn có thể nhận xét về điều này cũng http://stackoverflow.com/questions/12529497/how-to-append-data-on-a-packet-from-kernel-space – user2087340

1

Tôi đã giải quyết được sự cố. Đó là tầm thường. Và tất cả những gì tôi sẽ làm là đăng mã của tôi để tham khảo và thảo luận trong tương lai.

#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> 

#undef __KERNEL__ 
#include <linux/netfilter_ipv4.h> 
#define __KERNEL__ 

#define IP_HDR_LEN 20 
#define UDP_HDR_LEN 8 
#define TOT_HDR_LEN 28 

static unsigned int pkt_mangle_begin(unsigned int hooknum, 
         struct sk_buff *skb, 
         const struct net_device *in, 
         const struct net_device *out, 
         int (*okfn)(struct sk_buff *)); 

static struct nf_hook_ops pkt_mangle_ops __read_mostly = { 
    .pf = NFPROTO_IPV4, 
    .priority = 1, 
    .hooknum = NF_IP_LOCAL_OUT, 
    .hook = pkt_mangle_begin, 
}; 

static int __init pkt_mangle_init(void) 
{ 
    printk(KERN_ALERT "\npkt_mangle module started ..."); 
    return nf_register_hook(&pkt_mangle_ops); 
} 

static void __exit pkt_mangle_exit(void) 
{ 
    nf_unregister_hook(&pkt_mangle_ops); 
    printk(KERN_ALERT "pkt_mangle module stopped ..."); 
} 

static unsigned int pkt_mangle_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 char extra_data[] = "12345"; 
    unsigned char *temp; 
    unsigned int extra_data_len; 
    unsigned int tot_data_len; 

    unsigned int i; 

    __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 (src_port == 6000) { 
       printk(KERN_ALERT "UDP packet goes out"); 
       data = (unsigned char *) skb_header_pointer (skb, IP_HDR_LEN+UDP_HDR_LEN, 0, NULL); 
       data_len = skb->len - TOT_HDR_LEN; 

        temp = kmalloc(512 * sizeof(char), GFP_ATOMIC); 
       memcpy(temp, data, data_len); 

       unsigned char *ptr = temp + data_len - 1; 
       extra_data_len = sizeof(extra_data); 
       memcpy(ptr, extra_data, extra_data_len); 
       tot_data_len = data_len + extra_data_len - 1; 

       skb_put(skb, extra_data_len - 1); 

       memcpy(data, temp, tot_data_len); 

       /* Manipulating necessary header fields */ 
       iph->tot_len = htons(tot_data_len + TOT_HDR_LEN); 
       udph->len = htons(tot_data_len + UDP_HDR_LEN); 

       /* Calculation of IP header checksum */ 
       iph->check = 0; 
       ip_send_check (iph); 

       /* Calculation of UDP checksum */ 
       udph->check = 0; 
       int offset = skb_transport_offset(skb); 
       int len = skb->len - offset; 
       udph->check = ~csum_tcpudp_magic((iph->saddr), (iph->daddr), len, IPPROTO_UDP, 0); 

       } 
     } 
    } 
    return NF_ACCEPT; 
} 


module_init(pkt_mangle_init); 
module_exit(pkt_mangle_exit); 

MODULE_AUTHOR("Rifat Rahman Ovi: <[email protected]>"); 
MODULE_DESCRIPTION("Outward Packet Mangling and Decryption in Kernel Space"); 
MODULE_LICENSE("GPL"); 

Ở đây, tôi quên cập nhật trường độ dài và quên cập nhật tổng kiểm tra. Bây giờ, nếu tôi trình bày mã một cách chính xác ở đây, tất cả sẽ tốt.Có một số chức năng trợ giúp khác không được bao gồm ở đây là .

+2

Tôi không nghĩ rằng mã này là tốt cả. 1) bạn không bao giờ kfree (temp) vì vậy có một rò rỉ bộ nhớ 2) skb_put không mở rộng bộ đệm, vì vậy bạn đang tacking byte vào cuối tải trọng UDP bên trong skb mà không thực sự sở hữu bộ nhớ đó và chỉ hy vọng ti không gây ra các vấn đề. –

+0

ya ... bạn nói đúng. Đó là mô-đun đầu tiên của tôi ngoài thế giới hello. Và nó gây ra vấn đề. Vì vậy, để tăng một gói tin, tôi cần phân bổ một bộ đệm mới và thực hiện một số thao tác. Nó không được đảm bảo rằng việc sử dụng skb_put() sẽ không gây hại theo cách nó được sử dụng. Nhân tiện, nó đã được viết để đệm một số byte trong một gói dữ liệu thực sự, cuối cùng nó đã rõ ràng với tôi sau khi một số hoảng loạn hạt nhân. Nhưng tôi quên mất bài đăng. Cảm ơn cho điểm. Tôi sẽ sớm điều chỉnh mã. U thấy mô tả của mô-đun ... nó chỉ là khởi đầu của một dự án lớn chỉ có một nửa được đề cập ở đây. Cảm ơn. –

+0

Xin chào! Tôi nhận ra rằng đây là một chủ đề rất cũ nhưng bạn có thể cho tôi biết chính xác trong chuỗi gửi/nhận là móc này được gọi là? –

Các vấn đề liên quan