(495) 925-0049, ITShop интернет-магазин 229-0436, Учебный Центр 925-0049
  Главная страница Карта сайта Контакты
Поиск
Вход
Регистрация
Рассылки сайта
 
 
 
 
 

Программирование в Linux: Netfilter Kernel Programming (исходники)

Источник: wmate

В этой статье я постараюсь дать начальные сведения о netfilter'e и о том, как предотвратить Land-подобную атаку с помощью написания модуля для ядра.
И так, netfilter - это подсистема фильтрации пакетов в ядрах ветки 2.4/6.x, он же - первый встроенный в ядро контекстный брэндмауер (Stateful Firewall). Контекстный брэндмауер отличается от обычного тем, что он может определять, является ли настоящий пакет частью какого-либо соединения. В частности, в TCP протокол встроена система трехэтапного квинтирования. Для этого клиент шлет серверу запрос на соединение, указав в хедере флаг syn, на что сервак отвечает ему таким же пакетом, но плюс к syn флагу он еще добавляет флаг ack, указывая тем самым, что он хочет с ним установить соединение, после согласия на это клиента. Ну, так вот, обычный брэндмауер не способен отличить пакет, который будет идти в этой сессии соединения или же это какой-либо другой пакет, владелец которого уже секунд 20 назад установил соединение. Зато контекстный брэндмауер определяет, относится ли этот пакет к нашему с ним соединению или же к другому, посмотрев для этого таблицу коннектов. Примерно таким же образом он обрабатывает и другие протоколы: UDP, ICMP, etc (смотри /etc/protocols). В частности, такой тип брэндмауеров используется в Cisco. Ну да ладно, много интересного об архитектуре и особенностях netfilter'a вы можете узнать, поботав доки с www.netfilter.org.

А теперь поговорим о том, как же нам запрогать netfilter. Он способен перехватывать пакеты следующих сетевых стеков: IPv4, IPv6, DECnet. Мы рассмотрим только IPv4. Для данного стека в хереде /usr/include/linux/netfilter_ipv4.h определены следующие возможные значения захвата IP-пакетов (так называемые хуки):

.NF_IP_PRE_ROUTING: решаем, что делать с пакетом на входе.
1.NF_IP_LOCAL_IN: входящий, для нашего компа.
2.NF_IP_FORWARD: если пакет предназначен для другого интерфейса.
3.NF_IP_LOCAL_OUT: если этот пакет создан локально.
4.NF_IP_POST_ROUTING: решаем что делать с пакетом на выходе.
Перед тем, как к нам прилетит пакет, вызывается NF_IP_PRE_ROUTING хук. Далее вызывается функция, которая и решит, что мы сделаем с пакетом. Эти функции определены в /usr/include/linux/netfilter.h:

0.NF_DROP: отбросить пакет.
1.NF_ACCEPT: пропустить на дальнейшую обработку.
2.NF_STOLEN: запомнить этот пакет в понятии котекстного брандмауера.
3.NF_QUEUE: поставить пакет в очередь.
4.NF_REPEAT: вызвать эту функцию повторно.
Структура объявления хуков определена в /usr/include/linux/netfilter.h:

struct nf_hook_ops
{
/* член списка этой структуры используется для поддержки списка хуков
netfilter'a и он не несет никакой смысловой нагрузки на регистрацию хука */
 struct list_head list;
/* укаказатель на хук-функию, см.выше */
 nf_hookfn *hook;
/* какое семейство протоколов будем использовать. Так как мы обусловились
работать со стеком IPv4, то посмотрев хедер /usr/include/linux/socket.h,
узнаем что это PF_INET */
 int pf;
/* какой из хуков мы будем использовать, см.выше */
 int hooknum;
/* каждому хуку можно назначить свой приоритет, для нашего стека см. файл
/usr/include/linux/netfilter_ipv4.h */
 int priority;
};
Теперь же, чтобы зарегистрировать хук, нам понадобиться функция nf_register_hook, прототип которой определен в файле /usr/include/linux/netfilter.h.

int nf_register_hook(struct nf_hook_ops *reg);
В качестве аргумента эта функция принимает выше обозначенную структуру. Для определения данных, которые передаются в хук-функцию, используется прототип nf_hookfn, который определен в том же хедере:

typedef unsigned int nf_hookfn(unsigned int hooknum,
          struct sk_buff **skb,
          const struct net_device *in,
          const struct net_device *out,
          int (*okfn)(struct sk_buff *));
Здесь первый аргумент - это номер хука, а второй - указатель на указатель на sk_buff структуру, которая определена в /usr/include/linux/skbuff.h хедере. Это нужно для того, чтобы ядро знало, с какими пакетами мы работаем. Следующие два аргумента - это указатели на net_device структуру, определенную в /usr/include/linux/netdevice.h. Они используются для того, чтобы ядро знало, что за интерфейс мы используем (eth0, tap0, lo, etc). In и Out, соответственно, входящий и исходящий интерфейсы. В частности, in будет осуществлен для NF_IP_PRE_ROUTING и NF_IP_LOCAL_IN, а out - для NF_IP_POST_ROUTING и NF_IP_LOCAL_OUT хуков. Последний аргумент - функция, которая в качестве аргумента опять же принимает структуру sk_buff. Эта функция нужна, чтобы зря не расходовать процессор ожиданием пакета, который поставлен в очередь с помощью функции NF_QUEUE.

Так как все основные определения я уже дал, остается зашарить в ядерном написании модулей. Для этой цели поботайте статейки dev0id'a о "Linux Kernel Modules". Все, теперь я предоставлю исходник нашего фильтра пакетов, который будет обнаруживать пакеты, которые шлются при Land-атаке, т.е. где порт и IP атакуемого сервера совпадают с портом и IP этого же сервера (т.е. source=destination ip/port).

/* хедеры */
#define __KERNEL__
#define MODULE
#include
#include
#include
#include
#include
/* структура, которую мы будем использовать для регистрации нашей функции */
static struct nf_hook_ops nfho;

/* интерфейс, который мы используем */
static char *drop_if = "eth0";
/* тут указываем наш ip-адрес, в данном случае 192.168.168.1 */
static unsigned char *drop_ip = "xc0xa8xa8x01";
/* порт. Укзываем пока что один открытый 80-ый порт, но реально дописать программу,
которая будет отслеживать все открытые TCP/UDP-порты */
unsigned char *deny_port = "x00x50";

/* это наша хук-функция */
unsigned int hook_func(unsigned int hooknum,
    struct sk_buff **skb,
    const struct net_device *in,
    const struct net_device *out,
    int (*okfn)(struct sk_buff *))
{
 struct sk_buff *sb = *skb;
 struct tcphdr *port;
 port = (struct tcphdr *)(skb->data + (skb->nh.iph->ihl * 4));
 if ((strcmp(in->name, drop_if) == 0) &&
  (sb->nh.iph->saddr == drop_ip) &&
  ((skb->nh.iph->protocol != IPPROTO_TCP) //
   (skb->nh.iph->protocol != IPPROTO_UDP)) &&
  ((port->dest) == *(unsigned short *)deny_port))
 {
  printk("Packet dropped...");
  return NF_DROP;
 }else{
  return NF_ACCEPT;
 }
}

/* стандартная функция инициализации */
int init_module()
{
    nfho.hook     = hook_func;
    nfho.hooknum  = NF_IP_PRE_ROUTING;
    nfho.pf       = PF_INET;
    nfho.priority = NF_IP_PRI_FIRST;
 
    nf_register_hook(&nfho);
   
    return 0;
}
 
/* стандартная функция удаления модуля */
void cleanup_module()
{
    nf_unregister_hook(&nfho);
}
Ну вот собственно и все, что я хотел рассказать в этой вводной статье. Ботайте физику и, физтех - рулез!

Основные источники:
[0] http://netfilter.org
[1] http://lists.netfilter.org/pipermail/netfilter-devel/
[2] http://www.geocities.com/victorhugo83/
[3] http://www.linuxsecurity.com/feature_stories/kernel-netfilter.html



 Распечатать »
 Правила публикации »
  Написать редактору 
 Рекомендовать » Дата публикации: 10.11.2006 
 

Магазин программного обеспечения   WWW.ITSHOP.RU
ABBYY FineReader 14 Standard Full
ABBYY Lingvo x6 Многоязычная Домашняя версия, электронный ключ
Quest Software. TOAD for Oracle Edition
Stimulsoft Reports.Ultimate Single License Includes one year subscription, source code
VMware Fusion 10 Pro, ESD
 
Другие предложения...
 
Курсы обучения   WWW.ITSHOP.RU
 
Другие предложения...
 
Магазин сертификационных экзаменов   WWW.ITSHOP.RU
 
Другие предложения...
 
3D Принтеры | 3D Печать   WWW.ITSHOP.RU
 
Другие предложения...
 
Новости по теме
 
Рассылки Subscribe.ru
Информационные технологии: CASE, RAD, ERP, OLAP
Программирование на Microsoft Access
CASE-технологии
OS Linux для начинающих. Новости + статьи + обзоры + ссылки
СУБД Oracle "с нуля"
Программирование на Visual С++
Краткие описания программ и ссылки на них
 
Статьи по теме
 
Новинки каталога Download
 
Исходники
 
Документация
 
 



    
rambler's top100 Rambler's Top100