NetFilter Hook em Kernel 2.6

Esse artigo mostra como montar um módulo personalizado para Kernel 2.6 que trabalhe com o NetFilter. Dentre suas possíveis utilidades, podemos criar: firewall leve, compilado; firewall com alarme; "gatilho" para determinados eventos; contadores de pacotes; etc.

[ Hits: 42.555 ]

Por: Valber Marcel Bueno em 07/11/2005


Exemplo aprimorado



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;
  • nfhook.c.

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

Página anterior     Próxima página

Páginas do artigo
   1. Introdução
   2. Constantes
   3. Estruturas
   4. Exemplo aprimorado
   5. Aplicações
   6. Problemas e correções
   7. Referências e maiores estudos
   8. Maiores dados
Outros artigos deste autor
Nenhum artigo encontrado.
Leitura recomendada

Kernel v3.x no Debian - Compilação em 7 passos práticos

Empacotamento de Kernel em Sistemas Debian-Based

Compilando Kernel do Linux no Debian

Compilando o kernel do Slackware em 10 etapas

Instalando o kernel 2.6.13 pré-compilado no Slackware 10.2

  
Comentários
[1] Comentário enviado por removido em 07/11/2005 - 23:44h

Parabens pelo seu artigo..

[2] Comentário enviado por ygorth em 08/11/2005 - 10:46h

Cara,

excelente tema. Parabens!

[3] Comentário enviado por zero_bala em 08/11/2005 - 11:18h

Que esta vai para o favoritos, nem tenha dúvida! Excelente pesquisa e muito proveitosa para o meio acadêmico. Marcel, você conhece algum livro sobre o assunto?

[4] Comentário enviado por Ângelios em 30/09/2010 - 17:40h

Caros,

Copiei os códigos dos dois exemplos e tentei compila, mais aparece a seguinte mensagem:

nfhook.c:15:26: error: linux/config.h: Arquivo ou diretório não encontrado
nfhook.c:16:26: error: linux/module.h: Arquivo ou diretório não encontrado
nfhook.c:17:24: error: linux/init.h: Arquivo ou diretório não encontrado
nfhook.c:18:27: error: linux/proc_fs.h: Arquivo ou diretório não encontrado
nfhook.c:20:25: error: asm/uaccess.h: Arquivo ou diretório não encontrado
In file included from nfhook.c:21:
/usr/include/linux/netfilter.h:55: error: field ‘in’ has incomplete type
/usr/include/linux/netfilter.h:56: error: field ‘in6’ has incomplete type
In file included from nfhook.c:22:
/usr/include/linux/netfilter_ipv4.h:53: error: ‘INT_MIN’ undeclared here (not in a function)
/usr/include/linux/netfilter_ipv4.h:64: error: ‘INT_MAX’ undeclared here (not in a function)
nfhook.c:32: warning: ‘struct net_device’ declared inside parameter list
nfhook.c:32: warning: its scope is only this definition or declaration, which is probably not what you want
nfhook.c:32: warning: ‘struct sk_buff’ declared inside parameter list
nfhook.c: In function ‘hook_func’:
nfhook.c:36: error: dereferencing pointer to incomplete type
nfhook.c:36: error: dereferencing pointer to incomplete type
nfhook.c: At top level:
nfhook.c:47: error: expected declaration specifiers or ‘...’ before ‘off_t’
nfhook.c: In function ‘show_stats’:
nfhook.c:57: warning: incompatible implicit declaration of built-in function ‘sprintf’
nfhook.c:58: error: ‘offset’ undeclared (first use in this function)
nfhook.c:58: error: (Each undeclared identifier is reported only once
nfhook.c:58: error: for each function it appears in.)
nfhook.c: At top level:
nfhook.c:65: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘nfhook_init’
nfhook.c:105: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘nfhook_exit’
nfhook.c:115: warning: data definition has no type or storage class
nfhook.c:115: warning: parameter names (without types) in function declaration
nfhook.c:116: warning: data definition has no type or storage class
nfhook.c:116: warning: parameter names (without types) in function declaration
nfhook.c:118: error: expected declaration specifiers or ‘...’ before string constant
nfhook.c:118: warning: data definition has no type or storage class

Este aparece quando tento compilar o segundo exemplo.
Não entendo porque estas bibliotecas não foram encontradas.

Estou usando Ubuntu Server 10.04.

Gostaria se possível que me ajudassem.

Valber, muito obrigado pelo artigo.

[5] Comentário enviado por marcelbueno em 30/09/2010 - 19:26h

Caro Angelios,


Faz algum tempo que escrevi este artigo. Para ser mais específico, uns 5 anos. De lá para cá muita coisa mudou: mudei de projeto, de emprego, de distro, de versão de kernel, de área, de estado e até de esposa ;-)

Brincadeiras à parte, creio que partes do seu problema se deve a falta do pacote de kernel-headers, ou kernel-dev. No caso da plataforma fedora (e redhats-like) o comando é algo como "yum install kernel-devel". Suspeito que nos debians-like, o comando seja muito semelhante, utilizando-se do "apt-get".

No entanto, pode ser que algumas coisas aí do meio (constantes principalmente) não sejam mais desta forma, e certas coisas não sejam mais aceitas pelo GCC, kernel, etc. Mas isto você só vai descobrir indo por partes...

Espero ter podido ajudar

[6] Comentário enviado por Ângelios em 01/10/2010 - 18:13h

Marcel,

Não resolveu o problema mais me ajudou muito.

Irei continuar procurando e tentando resolver isso aki.

Caso consiga retorno aki pra passar o conhecimento a diante.




Mudar de vez enquanto é sempre bom! ^^


Contribuir com comentário




Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts