7

저는 리눅스 용 이더넷 네트워크 드라이버를 작성하고 있습니다. 나는 패킷을 받고 편집하고 다시 보내고 싶다. packet_interceptor 함수에서 패킷을 편집하는 방법을 알고 있지만 수신 패킷을이 함수에 어떻게 놓을 수 있습니까 ??net_dev_add() API를 사용하여 Linux 패킷을 필터링하고 차단하는 방법은 무엇입니까?

#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

내 솔루션으로 테스트 해 보았습니까? – Atle

+0

안녕하세요, 요즘에는 컴퓨터에 문제가 있습니다. 답장을 보내 주셔서 감사 드리며, PC를 부팅하자마자 테스트 해 보겠습니다. D. 하지만 나는이 해결책을 시험했지만, 그것이 효과가 없다는 것을 당신에게 묻는다. 나는 그것을 다시 트레이닝 할 것이다. –

답변

6

모듈이 모든 이더넷 패킷을 처리하게합니다. Linux는 모든 일치하는 프로토콜 핸들러에 패킷을 보냅니다. IP는 이미 커널에 등록되어 있으므로, 모듈과 ip_rcv는 모두 IP 헤더가있는 모든 SKB를 수신하게됩니다.

커널 코드를 변경하지 않고이 동작을 변경할 수 없습니다. 한 가지 가능성은 대신 netfilter 모듈을 만드는 것입니다. 이렇게하면 ip_rcv 함수 다음에 패킷을 가로 채고 원하는 경우 드롭 할 수 있습니다 (Netfilters PREROUTING 후크에서).

여기 제가 이미 작성한 일부 코드에서 추출한 작은 Netfilter 모듈입니다. 이 모듈은 완성되지 않았지만 주요 요소는 제자리에 있습니다.

#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

netfilter를 테스트했는데 잘 작동하지만'dev_add_pack()'후크를 사용하여 제거해야합니다.내 질문은 시스템에 두 핸들러 (ip_rcv, my_packet_interceptor)가있는 경우 해당 핸들러 중 하나에서 skb를 변경할 때 유효한 것인가? (my_packet_interceptor에서 skb를 변경 했으므로 두 개의 skb, 원래와 변경된 것 중 어떤 것이 더 처리 될 것인가?) –

+1

핸들러는 서로 후에 실행됩니다. 아마도 IP가 모듈 이전에 등록되어있을 것이므로 처음에는 IP가 실행되었다고 추측 할 수 있습니다. 나는 SKB가이 단계에서 복사되지 않는다고 생각한다. 그래서 당신이 그것을 바꾸기 전에 IP는 아마도 그것으로 끝날 것이다. – Atle

+0

그래서 핸들러가 서로 후에 실행되면 왜 패킷을 삭제할 수 없습니까? –

6

나는 (내가 거기 안에 아무것도 한 이후 년) 코드를 커널 네트워킹을 통해 가고, 나는 당신이 어떤 누출없이이 작업을 수행 할 수 않는해야한다고 생각 :

kfree_skb(skb); 
return NET_RX_DROP; 

편집

ip_rcvarp_rcv과 같은 다른 프로토콜 처리기에서 수행됩니다 (마지막 값은 NET_RX_DROP 대신 0을 반환하지만 반환 값은 별 의미가 없습니다). skb를 떨어 뜨리면 다른 핸들러를 호출하지 않도록하십시오. (맨 아래) ip.c에서 ip_rcv의 코드에서

봐는 : 모든 것이 잘된다면 http://lxr.free-electrons.com/source/net/ipv4/ip_input.c#L375

, 그것은 (그것을 드롭하지 않는 경우) 다음 ip_rcv_finish를 호출 넷 필터에 SKB을 전달합니다. 무언가가 잘못되면 skb가 해제되어 반환됩니다. 하나 이상의 프로토콜 핸들러는 SKB 일치하는 경우

편집

, 커널은 그들 모두에게 보내드립니다. 모듈 중 하나에 kfree_skb()이 있으면 SKB는 다른 핸들러에서 계속 실행됩니다.

+0

오늘 테스트했지만 작동하지 않았습니다. 그것의 문제점은 무엇입니까? –

+0

"작동하지 않았다"는 것은 무엇을 의미합니까? 패킷이 droppen 대신 시스템에 수신 되었습니까? 패킷이 모듈에도 입력됩니까? – Atle

+1

'packet_interceptor' 핸들러에 모든 패킷을 받았지만 시스템에서받은 모든 패킷. http://paste.ubuntu.com/6324987/ –

관련 문제