2009-02-27 9 views
1

私はnetfilterでフックを登録するカーネルモジュールを作成しています。モジュールがロードされているマシンにssh/telnetを実行すると、ハンドラは呼び出されません。Netfilerフックが呼び出されない

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(外部ゲートウェイプロトコル)のために呼び出されています。 2番目のprintkは決して印刷されません。私は何か不足していますか?

+0

で定義されている適切なプロトコル定義の値を使用してください。 –

答えて

3

ここで使用されるプロトコルは、IANAによって割り当てられたIPプロトコル番号とは異なります.8はEGP用であり、EGPは古くなっています。

sk_buffのプロトコルフィールドが定義されています。そのうち8つはETH_P_IPです。データが常にIPトラフィックであるため、最初の条件チェックは常にtrueです。したがってコードの第2部分は決して実行されません。

1

思考のカップル:

  • フックハンドラは、(構造体skbuff *)、(**構造体skbuff)ではない取る
  • 上記から続く、skb->protocolは存在しません。あなたはどちらか(*skb)->protocolたいか、次のイディオムをしたい:パケットがEGPパケットである
struct sk_buff *sock_buf = *skb; 
if(sock_buff->protocol) 
  • 場合は、その前に戻りますので、あなたは、第二のprintkの出力を期待すべきではありません。
+0

カーネル2.6.27-11を使用しています。netfilter.hには次のような宣言があります。 unsigned int型nf_hookfn(unsigned int型hooknum、 \t \t \tのstruct sk_buffの*のSKB、 \t \t \tのconst構造体net_device *で、 \t \t \t constの構造体net_device *うち、 \t \t \tのint(* okfn)(構造体のtypedef sk_buff *)); – Rohit

+0

EGPなら2行目は印刷されないことを理解します。しかし、telnet/ssh/mysql/http接続が開かれたときに印刷する必要がありますか?今は、EGPパケットだけが得られます。共有メモリの最適化を避けるために別のマシンから呼び出そうとしています。 – Rohit

+0

ああ - それは2.6.24で変更されました。私は新しいカーネルとチェックをして遊びます。 – Stobor

0

sk_buffがどのように動作するかを調べる必要があります。プロトコルフィールドは、ETH_P_ *値をとる `eth_type_trans '関数で初期化されます。すべての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  */ 

明らかに、0x08はInternet Protocol packetに定義されています。そして、あなたのコードは、明らか8(IPパケットである)

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

あなたssh/telnet明確にIPパケット(複数可)の場合に戻り、上記のコードによって拒否します。 if_ethr

関連する問題