Netfilter挂钩没有被调用

时间:2009-02-27 04:16:40

标签: linux-kernel netfilter

我正在编写一个内核模块,它使用netfilter注册一个钩子。如果我ssh / telnet到加载模块的机器,则不会调用该处理程序。

struct nf_hook_ops my_hook_ops;
my_hook_ops.hook = hook_handler;
my_hook_ops.pf = PF_INET;
my_hook_ops.hooknum = NF_INET_PRE_ROUTING;
my_hook_ops.priority =  NF_IP_PRI_FIRST;
nf_register_hook(&my_hook_ops);

处理程序功能:

unsigned int hook_handler(unsigned int hooknum,
                   struct sk_buff *skb,
                   const struct net_device *in,
                   const struct net_device *out,
                   int (*okfn)(struct sk_buff *))
{


    if(!skb)
        return NF_ACCEPT;

    struct iphdr* ip_header;
    struct tcphdr* tcp_header;
    union  ip_address ipaddr;

    printk(KERN_INFO "Entered handler\n");

    if(skb->protocol == 8)
        return NF_ACCEPT;

    // Log the received packet
    ip_header  = ip_hdr(skb);
    tcp_header = tcp_hdr(skb);
    ipaddr.saddr = ip_header->saddr;
    printk(KERN_INFO "Received packet:\nIP Address: %u.%u.%u.%u\nProtocol: %d\nSource port: %d\nDestination port: %d\n",
            ipaddr.a[0],ipaddr.a[1],ipaddr.a[2],ipaddr.a[3],
            skb->protocol,
            tcp_header->source,
            tcp_header->dest);

    return NF_ACCEPT;
}

正在为协议8(外部网关协议)调用挂钩。第二个printk永远不会打印出来。我错过了什么吗?

3 个答案:

答案 0 :(得分:3)

此处使用的协议与IANA分配的IP协议号不同,其中8个用于EGP,EGP已过时。

定义了sk_buff的协议字段,其中8表示ETH_P_IP。由于您的数据始终是IP流量,因此第一次条件检查始终为真。所以代码的第二部分永远不会被执行。

答案 1 :(得分:1)

有几点想法:

  • 一个钩子处理程序接受(struct skbuff **),而不是(struct skbuff *)
  • 从上面开始,skb->protocol不存在。您想要(*skb)->protocol或者您想要以下成语:
struct sk_buff *sock_buf =  *skb;
if(sock_buff->protocol)
  • 如果数据包是EGP数据包,则不应该期望第二个printk的输出,因为你在它之前返回。

答案 2 :(得分:0)

您需要研究sk_buff如何工作,协议字段由函数“eth_type_trans”初始化,该函数采用ETH_P_ *值。所有ETH_P_ *值都在if_ether中定义。以下是其中一些值。

#define ETH_P_LOOP      0x0060          /* Ethernet Loopback packet     */
#define ETH_P_PUP       0x0200          /* Xerox PUP packet             */
#define ETH_P_PUPAT     0x0201          /* Xerox PUP Addr Trans packet  */
#define ETH_P_IP        0x0800          /* Internet Protocol packet     */

您清楚地看到为Internet Protocol packet定义了0x08。并且您的代码在8(即IP数据包)的情况下明确返回

 if(skb->protocol == 8)
    return NF_ACCEPT;

您的ssh/telnet明确的IP数据包并被上述代码拒绝。请使用if_ethr

中定义的正确协议定义值