如何安全地将数据附加到sk_buff以获取IPTables目标

时间:2015-04-23 20:41:41

标签: memory-management linux-kernel iptables

我正在开发一个需要修改网络数据包并附加额外标头的Linux内核模块。我已经实现了修改部分,重新​​计算了校验和,它工作得很好。但我不知道如何安全追加额外的标题。如果我的输入数据包是这样的:

package javaapplication1;

import javax.swing.*;
import javax.swing.JTextField;
import java.awt.*;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;


public class NewClass extends JFrame {
    final int FRAME_WIDTH = 300;
    final int FRAME_HEIGHT = 200;

    public NewClass() {
        super("ARTICULACION SOCIAL");
        setSize(FRAME_WIDTH, FRAME_HEIGHT);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JLabel heading = new JLabel("Identifiquese para entrar");
        heading.setFont(new Font("Arial", Font.BOLD, 16));
        JLabel namePrompt = new JLabel("Ingrese su nombre de usuario:");
        JTextField nameField = new JTextField(12);
        JLabel namePrompt2 = new JLabel("Ingrese su contraseña:");
        JTextField nameField2 = new JTextField(12);    
        JButton button = new JButton("Ingresar");
        setLayout(new FlowLayout());
        add(heading);
        add(namePrompt);
        add(nameField);
        add(namePrompt2);
        add(nameField2);
        add(button);

        Escuchador escuchar = new Escuchador();
        nameField.addActionListener(escuchar);
        nameField2.addActionListener(escuchar);
        button.addActionListener(escuchar);

    }

    private class Escuchador implements ActionListener{

        public void actionPerformed (ActionEvent event){
            String usuario="";


            if (event.getSource()== nameField) {
               usuario = event.getActionCommand();
            }
        }
    }

}

我希望有一个输出数据包,如:

ip-header / tcp-header / data

对于我所读到的内容,我认为我需要类似下面的代码。我在代码上写了我的具体问题作为评论。我一般担心的是,我在这里编写的代码是否是内存安全的,或者我应该怎么做才能有一个内存安全的方法来附加新的头文件。此外,如果我做错了或有更好的方法,我也会感谢评论。我试图找到例子但到目前为止没有运气。这是代码:

ip-header / tcp-header / my-header / data

我假设变量static unsigned int my_iptables_target(struct sk_buff *skb, const struct xt_action_param *par) { const struct xt_mytarget_info *info = par->targinfo; /* Some code ... */ if (!skb_make_writable(skb, skb->len)) { //Drop the packet return NF_DROP; } struct newheader* myheader; // Check if there is enough space and do something about it if (skb_headroom(skb) < sizeof(struct newheader)) { // So there is no enugh space. /* I don't know well what to put here. I read that a function called pskb_expand_head might * do the job. I do not understand very well how it works, or why it might fail (return value * different from zero). Does this code work: */ if (pskb_expand_head(skb, sizeof(struct newheader) - skb_headroom(skb), 0, GPF_ATOMIC) != 0) { // What does it mean if the code reaches this point? return NF_DROP; } } // At this point, there should be enough space skb_push(skb, sizeof(struct newheader)); /* I also think that skb_push() creates space at the beggining, to open space between the header and * the body I guess I must move the network/transport headers up. Perhaps something like this: */ memcpy(skb->data, skb->data + sizeof(struct newheader), size_of_all_headers - sizeof(struct newheader)); // Then set myheader address and fill data. myheader = skb->data + size_of_all_headers; //Then just set the new header, and recompute checksums. return XT_CONTINUE; } 包含网络和传输头的字节大小。我还认为size_of_all_headers按递增顺序复制字节,因此调用不应成为问题。那么上面的代码是否有效?这一切都是内存安全的吗?有更好的方法吗?是否有这样的例子(或者你能提供一个)吗?

1 个答案:

答案 0 :(得分:0)

我使用的代码类似于问题中的代码,到目前为止,它已经完成了我所做的所有测试。为了回答一些具体问题,我使用了类似的东西:

if (skb_headroom(skb) < sizeof(struct newheader)) {
    printk("I got here!\n");
    if (pskb_expand_head(skb, sizeof(struct newheader) - skb_headroom(skb), 0, GPF_ATOMIC) != 0) {
        printk("And also here\n");
        return NF_DROP;
    }
}

但是没有一个打印语句被执行过。我想这是因为操作系统在内存中保留了足够的空间,因此在给定IP标头限制的情况下不会出现问题。但我认为最好留下if语句来在必要时增加数据包。

我测试和工作的代码的另一个不同之处在于,我没有移动所有其他标头来为我的标题创建空间,而是选择将数据包的主体向下移动。