totofugaのブログ

ネットワークとかc言語、perlの話。

iptables勉強(2)

iptablesのtargetrの拡張

iptablesだいぶわかってきたので最小構成のtargetを書いてみた

構成ファイル

user空間用とkernel空間用の2種類のファイルを用意する必要がある

user空間用ファイル

iptablesコマンドを拡張するために /lib64/xtables/libに共有ライブラリを作成して配置する

名前はlibipt_<target名>.so

エントリポイントは_initという関数を作りxtables_targetを登録する

xtables.hはiptables-develパッケージに含まれている

#include <xtables.h>                                                                        
#include <stdio.h>                                                                          
                                                                                            
static void MYLOG_help() {                                                                  
    // printf("commandオプションがあればここに記述\n");  // iptables -j MYLOG --helpの時に表示される                                   
}                                                                                           
                                                                                            
static void MYLOG_print(const void *ip, const struct xt_entry_target *target, int numeric) {
    printf(" MYLOG");    // iptables -Lの時に表示される名前                                                                
}                                                                                           
                                                                                            
static struct xtables_target my_log_target = {                                              
    .name  = "MYLOG",                                                                       
    .version = XTABLES_VERSION,                                                             
    .family = NFPROTO_IPV4,                                                                 
    .help = MYLOG_help,                                                                     
    .print = MYLOG_print                                                                    
};                                                                                          
                                                                                            
void _init() {                                                                              
    xtables_register_target(&my_log_target);                                                
}                                                                                           

作成したら共有ライブラリとしてコンパイルして/lib64/xtables/libに配置

gcc -fpic -shared ./libipt_MYLOG.c -o libipt_MYLOG.so

kernel空間用ファイル

user空間用ファイルに対応するカーネルモジュールを作成する

今回はヒットしたらログを出すだけ。

ユーザ空間のファイルとの対応はxt_targetのnameで行なっている

#include <linux/module.h>                                                              
#include <linux/netfilter.h>                                                           
#include <linux/netfilter/x_tables.h>                                                  

MODULE_LICENSE("GPL");

static unsigned int log_mylog(struct sk_buff *skb, const struct xt_action_param *par) {
    printk(KERN_ALERT "run mylog\n");
    return XT_CONTINUE;                                                                
}                                                                                      
                                                                                       
static struct xt_target mylog_target __read_mostly = {                                 
    .name       = "MYLOG",                                                             
    .family     = NFPROTO_IPV4,                                                        
    .target     = log_mylog,                                                           
    .me     = THIS_MODULE,                                                             
};  

static int __init mylog_init(void) {                                                   
    return xt_register_target(&mylog_target);                                          
}   

static void __exit mylog_exit(void) {
    xt_unregister_target(&mylog_target);
}

module_init(mylog_init);
module_exit(mylog_exit);

作成したらカーネルモジュールをロード

insmod mylog.ko

iptables

user空間とkernel空間のファイルを作成すると、iptablesコマンドの-jオプションにて自分の作成したターゲットを指定できる

# iptables -A INPUT -j MYLOG
# iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         
MYLOG      all  --  anywhere             anywhere             MYLOG

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         

この状態でアクセスがあるとカーネルログにrun mylogが出力される