netfilterは、LinuxカーネルのネットワークスタックのいろいろをフックしてあれこれするためのAPIです。身近なところだと、iptablesやnftablesの実装に利用されています。カーネル内のAPIなので敷居が高そうに思われるかもしれませんが、簡単なLoadable Kernel Module (LKM) を書くだけで利用でき、カーネルに直接変更を加える必要がないので、かなりお手軽です。それでいて、iptablesやnftablesでも利用されているだけあってできることの範囲は広く、パケットの監視やファイアウォールを始めとしてパケットを読み書きするような処理なら割と何でもできます。
この記事では、netfilterを使うカーネルモジュールの基本的な書き方を紹介します。なお、動作確認はKernel 3.14で行いました。カーネルのバージョンによってメンバや定数の名称が変化している場合があるようなので、コンパイルが通らない場合には適当に頑張ってみてください。
コード例
以下がnetfilterを使ったLKMの例です。モジュールロード時にnf_register_hook
関数でフックを登録することで、指定したタイミングでフックハンドラが呼ばれるようになります。ハンドラには対象パケットのsk_buff
が引数として渡されるので、これを煮るなり焼くなり好きにします。ハンドラの戻り値で、パケットをそのまま通すのか、あるいはドロップさせるかなどその後の扱いを指定できます。
mymodule.c
ここでは、一例として特定の相手に対して送信しようとしたSYNパケットをランダムでドロップさせています。ロードするとパフォーマンスがとても悪くなります。
Makefile
Makefileは普通にLKMを作る時と同様の内容でOKです。
以下のコマンドでmakeとLKMのロードが可能です。