7

Ich schreibe Ethernet-Netzwerktreiber für Linux. Ich möchte Pakete empfangen, bearbeiten und erneut senden. Ich weiß, wie Sie das Paket in packet_interceptor Funktion bearbeiten, aber wie kann ich eingehende Pakete in dieser Funktion fallen lassen ??Wie filtern und abfangen Linux-Pakete mit net_dev_add() API?

#include <linux/netdevice.h> 
#include <linux/skbuff.h> 
#include <linux/ip.h> 
#include <net/sock.h> 

struct packet_type my_proto; 

int packet_interceptor(struct sk_buff *skb, 
    struct net_device *dev, 
    struct packet_type *pt, 
    struct net_device *orig_dev) { 

    // I dont want certain packets go to upper in net_devices for further processing. 
    // How can I drop sk_buff here?! 

    return 0; 
} 

static int hello_init(void) { 
    printk(KERN_INFO "Hello, world!\n"); 

    my_proto.type = htons(ETH_P_ALL); 
    my_proto.dev = NULL; 
    my_proto.func = packet_interceptor; 

    dev_add_pack(&my_proto); 
    return 0; 
}  

static void hello_exit(void) { 
    dev_remove_pack(&my_proto); 
    printk(KERN_INFO "Bye, world\n"); 
} 

module_init(hello_init); 
module_exit(hello_exit); 
+0

Haben Sie mit meiner Lösung getestet? – Atle

+0

Hallo @Atle, ich habe in diesen Tagen ein Problem mit meinem Computer. Danke für deine Antwort, ich werde es testen, sobald ich meinen PC booten kann: D. Aber ich erinnere mich, bevor ich dich frage, habe ich diese Lösung getestet, aber es hat nicht funktioniert. Ich werde es wieder ablegen. –

Antwort

6

Sie machen Ihr Modul alle Ethernet-Pakete behandeln. Linux sendet Pakete an alle passenden Protokoll-Handler. Da IP bereits in Ihrem Kernel registriert ist, erhalten sowohl Ihr Modul als auch ip_rcv alle SKBs mit IP-Headern.

Sie können dieses Verhalten nicht ändern, ohne den Kernel-Code zu ändern. Eine Möglichkeit besteht darin, stattdessen ein Netfilter-Modul zu erstellen. Auf diese Weise können Sie das Paket nach der ip_rcv-Funktion abfangen und es löschen, wenn Sie möchten (in Netfilters PREROUTING hook).

Hier ist ein kleines Netfilter-Modul, das ich aus einem Code extrahiert habe, den ich bereits geschrieben habe. Dieses Modul ist noch nicht fertig, aber die wichtigsten Dinge sind vorhanden.

#include <linux/netfilter.h> 
#include <linux/netfilter_ipv4.h> 

// Handler function 
static unsigned int my_handler (
    unsigned int hook, 
    struct sk_buff *skb, 
    const struct net_device *in, 
    const struct net_device *out, 
    int (*okfn)(struct sk_buff *)) 
{ 
    return NF_ACCEPT; 
// or 
    return NF_DROP; 
} 

// Handler registering struct 
static struct nf_hook_ops my_hook __read_mostly = { 
    .hook = my_handler, 
    .pf = NFPROTO_IPV4, 
    .hooknum = (1 << NF_INET_PRE_ROUTING), 
    .priority = NF_IP_PRI_FIRST // My hook will be run before any other netfilter hook 
}; 

int my_init() { 
    int err = nf_register_hook (&my_hook); 
    if (err) { 
      printk (KERN_ERR "Could not register hook\n"); 
    } 
    return err; 
} 
+0

Ich habe das netfilter getestet, es funktioniert sehr gut, aber ich muss mit 'dev_add_pack()' Haken fallen.meine Frage ist, wenn das System zwei Handler (ip_rcv, my_packet_interceptor), wenn ich die SKB in einem meiner Handler ändern, welche von ihnen sind gültig? (Angenommen, ich habe das skb in my_packet_interceptor geändert, so dass ich zwei skb habe, "original" und "changed", welche davon werden weiterverarbeitet?) –

+1

Die Handler werden nacheinander ausgeführt. Ich würde vermuten, dass IP zuerst ausgeführt wird, da es wahrscheinlich vor Ihrem Modul registriert ist. Ich denke nicht, dass der SKB in diesem Stadium kopiert wird, also wird IP wahrscheinlich damit gemacht, bevor Sie es ändern. – Atle

+0

Also, wenn die Handler nacheinander ausgeführt werden, Warum kann ich die Pakete nicht fallen lassen? –

6

Ich ging durch den Kernel-Code Networking (ein Jahr her, seit ich etwas drinnen tat), und ich denke, Sie sollten dies zu tun in der Lage zu tun, ohne irgendetwas undicht:

kfree_skb(skb); 
return NET_RX_DROP; 

bearbeiten

Dies wird in anderen Protokollhandlern wie ip_rcv und arp_rcv getan (das letzte gibt 0 statt NET_RX_DROP zurück, aber ich denke nicht, dass der Rückgabewert sehr wichtig ist). Denken Sie daran, keine anderen Handler anzurufen, wenn Sie den skb fallen lassen.

Blick auf den Code für ip_rcv in ip.c (unten): http://lxr.free-electrons.com/source/net/ipv4/ip_input.c#L375

Wenn alles gut geht, geht es der SKB zu Netfilter die dann ip_rcv_finish Anrufe (wenn es sie nicht fallen lassen). Wenn etwas schief geht, befreit es das SKB und kehrt zurück.

bearbeiten

Wenn mehr als ein Protokoll-Handler eine SKB übereinstimmt, wird der Kernel es für alle von ihnen senden. Wenn Sie in einem der Module kfree_skb() sind, wird der SKB in den anderen Handlern weiterleben.

+0

Heute habe ich getestet, aber es hat nicht funktioniert. Was ist das Problem damit? –

+0

Was meinst du mit "hat nicht funktioniert"? Wurde das Paket vom System empfangen und nicht gelöscht? Passieren die Pakete überhaupt Ihr Modul? – Atle

+1

Ich empfange alle Pakete in 'packet_interceptor' Handler, aber alle Pakete vom System empfangen. http://paste.ubuntu.com/6324987/ –