Tive que juntar vários pedaços de documentações para conseguir montar um exemplo conciso de como montar um módulo para
kernel 2.6 (que diferem em muito dos módulos para kernel 2.4) e que fosse capaz de utilizar o
netfilter.
Este exemplo (central do tutorial) demonstra como gerar pseudo-arquivos no pseudo-diretório /proc (imagem do kernel).
Basicamente o exemplo é composto de 2 arquivos:
Makefile:
obj-m := nfhook.o
KDIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
default:
$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules
nfhook.c:
/*
Kernel Module for Kernel > 2.6 - Netfilter Hook
Autor: Marcel Bueno
Email: marcel#bueno.com.br
Site : http://marcel.bueno.com.br
Referencias e Créditos:
http://marcel.bueno.com.br/wiki/index.php/Nfhook
http://uqconnect.net/~zzoklan/documents/netfilter.html
http://www.captain.at/programming/kernel-2.6/
http://www.netfilter.org/documentation/tutorials/lw-2000/tut-6.html
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/proc_fs.h>
#include <linux/ip.h>
#include <asm/uaccess.h>
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
// Controle de versão
static char *version = "0.0.1";
// Objeto de estrutura do nosso hook
static struct nf_hook_ops nfho;
// Função usada pelo HOOK do Netfilter (veja mais para frente)
unsigned int hook_func (
unsigned int hooknum,
struct sk_buff **pskb,
const struct net_device *indev,
const struct net_device *outdev,
int (*okfn)(struct sk_buff *)
)
{
// Só vamos adicionar uma linha no message-log com o código do hook
// (para cada pacote), tamanho e de que placa veio para exemplificar...
printk("Nfhook %d Length %d Source %s ...
", hooknum, (*pskb)->len, indev->name );
// Neste ponto, poderíamos trabalhar um pequeno firewall, com IFs, CASES e afins,
// Gravar um contador, separar IPs em arrays, etc.
// Sejam criativos ;-)
return NF_ACCEPT;
// Os tipos de retornos possíveis podem ser vistos logo acima, neste tutorial
}
// Mostra algo quando há leitura do arquivo no /proc
static int show_stats(char *buffer, char **start, off_t offset, int length)
{
int size;
// buffer é nossa variável de retorno (o arquivo)
// Poderíamos escrever qualquer coisa aqui, desde
// contadores simples, até sofisticados arrays
//
// Utilize cat /proc/nfhook/stats para visualizar o resultado
//
size = sprintf(buffer, "NFHOOK %s
", version);
*start = buffer + offset;
size -= offset;
return (size > length) ? length : (size > 0) ? size : 0;
}
// Inicia módulo no kernel (insmod)
static int __init nfhook_init(void)
{
struct proc_dir_entry *proc_nfhook;
struct proc_dir_entry *proc_nfhook_stats;
// Preenche os dados para a estrutura de HOOK
nfho.hook = hook_func; /* função a ser usada pelo hook*/
nfho.hooknum = NF_IP_PRE_ROUTING; /* IPv4 Prerouting */
nfho.pf = PF_INET;
nfho.priority = NF_IP_PRI_FIRST; /* Adiciona como primeiro hook da lista */
// Registrando o processo de HOOK
nf_register_hook(&nfho);
// Cria os apontamentos em /proc/nfhook
proc_nfhook = proc_mkdir("nfhook", 0);
if (!proc_nfhook)
{
printk (KERN_ERR "cannot create /proc/nfhook
");
return -ENOMEM;
}
// Pseudo arquivo... quando executar um CAT, utilizar o procedimento show_stats
proc_nfhook_stats = create_proc_info_entry("nfhook/stats", 0, 0, show_stats);
if (!proc_nfhook_stats)
{
printk (KERN_ERR "cannot create /proc/nfhook/stats
");
remove_proc_entry("nfhook", 0);
return -ENOMEM;
}
// Você pode também montar um procedimento ao gravar no arquivo /proc/nfhook/stats !
// proc_nfhook_stats->write_proc = add_to_nfhook; (Não implementei)
return 0;
}
// Ao remover o módulo (rmmod)
static void __exit nfhook_exit(void)
{
/* Remove os pontos de acesso ao /proc */
remove_proc_entry("nfhook/stats", 0);
remove_proc_entry("nfhook", 0);
/* Retira o HOOK da memória */
nf_unregister_hook(&nfho);
}
module_init(nfhook_init);
module_exit(nfhook_exit);
MODULE_LICENSE("GPL");
Existindo estes 2 arquivos, simplesmente compile com o comando:
# make
Se tudo correr bem, será gerado um arquivo chamado "nfhook.ko". Para inserí-lo como módulo no kernel:
# insmod ./nfhook.ko