The OpenNET Project / Index page

[ новости /+++ | форум | теги | ]



Индекс форумов
Составление сообщения

Исходное сообщение
"Раздел полезных советов: Создание модуля для iptables, измен..."
Отправлено auto_tips, 02-Май-11 13:24 
Данная статья основывается на материале "Разработка Match-модуля для iptables своими руками" (http://www.linuxjournal.com/article/7184), но код работает на ядрах 2.6.20+.

Мне потребовалось изменить ID IP пакетов, в интернете подходящей инструкции как это сделать на ядре 2.6.24 я не нашел, из-за этого решил написать, как удалось решить задачу.

Для реализации задуманного нам понадобится написать модуль ядра, который будет выполнять проверку и модуль расширения для iptables, который будет работать с модулем ядра - создавать новые цепочки,
использующие наш модуль, выводить информацию о критерии при выводе списка правил на экран, а также проверять корректность передаваемых модулю параметров.

Сначала создадим общий заголовочный файл ipt_ID.h:

   #ifndef _IPT_ID_H
   #define _IPT_ID_H

   enum {
       IPT_ID_RAND = 0,
       IPT_ID_INC
   };

   #define IPT_ID_MAXMODE  IPT_ID_INC

   struct ipt_ID_info {
       u_int8_t        mode;
       u_int16_t       id;
   };

   #endif

Теперь скопируем его в исходники netfilter в директорию
linux/netfilter_ipv4/

Далее рассмотрим модуль ядра ipt_ID.с.

   #include <linux/module.h>
   #include <linux/skbuff.h>
   #include <linux/ip.h>
   #include <net/checksum.h>
   #include <linux/random.h>
   #include <linux/netfilter/x_tables.h>
   #include <linux/netfilter_ipv4/ipt_ID.h>

   MODULE_AUTHOR("Xlise <demonxlise@gmail.com>");
   MODULE_DESCRIPTION("Xtables: IPv4 ID field modification target");
   MODULE_LICENSE("GPL");
   static int count=0;
   static struct iphdr l_iph[5];
   static unsigned int
   id_tg(struct sk_buff *skb, const struct net_device *in,
        const struct net_device *out, unsigned int hooknum,
        const struct xt_target *target, const void *targinfo)
   {
         struct iphdr *iph;
         const struct ipt_ID_info *info = targinfo;
         u_int16_t new_id;
         int i=0;
         if (!skb_make_writable(skb, skb->len))
                 return NF_DROP;

         iph = ip_hdr(skb);

         switch (info->mode) {
                 case IPT_ID_RAND:
                         get_random_bytes(&info->id, sizeof(info->id));
                         new_id = info->id;
                         break;
                 case IPT_ID_INC:


   while (i<5)
   {
   if (l_iph[i].daddr == iph->daddr)
       {
       new_id = l_iph[i].id + htons(1);
       l_iph[i].id = new_id;
       }

   else
       {new_id = iph->id;
       l_iph[count] = *iph;
       count++;
       if (count > 4)
          count = 0;
       }
   i++;
   }
                 default:
                         new_id = iph->id;
                         break;
         }

         if (new_id != iph->id) {
                 csum_replace2(&iph->check, iph->id,
                                           new_id);
                 iph->id = new_id;
         }

         return XT_CONTINUE;
   }

   static bool
   id_tg_check(const char *tablename, const void *e,
              const struct xt_target *target, void *targinfo,
              unsigned int hook_mask)
   {
         const struct ipt_ID_info *info = targinfo;

         if (info->mode > IPT_ID_MAXMODE) {
                 printk(KERN_WARNING "ipt_ID: invalid or unknown Mode %u\n",
                         info->mode);
                 return false;
         }
         if (info->mode != IPT_ID_SET && info->id == 0)
                 return false;
         return true;
   }

   static struct xt_target id_tg_reg __read_mostly = {
         .name           = "ID",
         .family         = AF_INET,
         .target         = id_tg,
         .targetsize     = sizeof(struct ipt_ID_info),
         .table          = "mangle",
         .checkentry     = id_tg_check,
         .me             = THIS_MODULE,
   };

   static int __init id_tg_init(void)
   {
         return xt_register_target(&id_tg_reg);
   }

   static void __exit id_tg_exit(void)
   {
         xt_unregister_target(&id_tg_reg);
   }

   module_init(id_tg_init);
   module_exit(id_tg_exit);

Напишем Makefile для нашего модуля:

   obj-m := ipt_ID.o
   KDIR  := /lib/modules/$(shell uname -r)/build
   PWD   := $(shell pwd)
   $(MAKE) -C $(KDIR) M=$(PWD) modules

добавим модуль в ядро

   insmod ipt_ID.ko

Для создания модуля для iptables нам потребуются исходники для iptables-1.4.4

Создадим файл libipt_ID.c

   #include <stdio.h>
   #include <string.h>
   #include <stdlib.h>
   #include <getopt.h>
   #include <xtables.h>
   #include <linux/netfilter_ipv4/ipt_ID.h>

   #define IPT_ID_USED     1

   static void ID_help(void)
   {
       printf(
   "ID target options\n"
   "  --id-rand value              Set ID to \n"
   "  --id-inc value               Increment ID by \n");
   }

   static int ID_parse(int c, char **argv, int invert, unsigned int *flags,
                    const void *entry, struct xt_entry_target **target)
   {
       struct ipt_ID_info *info = (struct ipt_ID_info *) (*target)->data;
       u_int16_t value;

       if (*flags & IPT_ID_USED) {
               xtables_error(PARAMETER_PROBLEM,
                               "Can't specify ID option twice");
       }

       if (!optarg)
               xtables_error(PARAMETER_PROBLEM,
                               "ID: You must specify a value");

       if (xtables_check_inverse(optarg, &invert, NULL, 0))
               xtables_error(PARAMETER_PROBLEM,
                               "ID: unexpected `!'");

       if (!xtables_strtoui(optarg, NULL, &value, 0, UINT16_MAX))
               xtables_error(PARAMETER_PROBLEM,
                          "ID: Expected value between 0 and 255");

       switch (c) {

               case '1':
                       info->mode = IPT_ID_RAND;
                       break;

               case '2':
                       if (value == 0) {
                               xtables_error(PARAMETER_PROBLEM,
                                       "ID: increasing by 0?");
                       }

                       info->mode = IPT_ID_INC;
                       break;

               default:
                       return 0;

       }

       info->id = value;
       *flags |= IPT_ID_USED;

       return 1;
   }

   static void ID_check(unsigned int flags)
   {
       if (!(flags & IPT_ID_USED))
               xtables_error(PARAMETER_PROBLEM,
                               "TTL: You must specify an action");
   }

   static void ID_save(const void *ip, const struct xt_entry_target *target)
   {
       const struct ipt_ID_info *info =
               (struct ipt_ID_info *) target->data;

       switch (info->mode) {
               case IPT_ID_SET:
                       printf("--id-set ");
                       break;
               case IPT_ID_DEC:
                       printf("--id-dec ");
                       break;

               case IPT_ID_INC:
                       printf("--id-inc ");
                       break;
       }
       printf("%u ", info->id);
   }

   static void ID_print(const void *ip, const struct xt_entry_target *target,
                     int numeric)
   {
       const struct ipt_ID_info *info =
               (struct ipt_ID_info *) target->data;

       printf("ID ");
       switch (info->mode) {
               case IPT_ID_SET:
                       printf("set to ");
                       break;
               case IPT_ID_DEC:
                       printf("decrement by ");
                       break;
               case IPT_ID_INC:
                       printf("increment by ");
                       break;
       }
       printf("%u ", info->id);
   }

   static const struct option ID_opts[] = {
       { "id-set", 1, NULL, '1' },
       { "id-inc", 1, NULL, '2' },
       { .name = NULL }
   };

   static struct xtables_target id_tg_reg = {
       .name           = "ID",
       .version        = XTABLES_VERSION,
       .family         = NFPROTO_IPV4,
       .size           = XT_ALIGN(sizeof(struct ipt_ID_info)),
       .userspacesize  = XT_ALIGN(sizeof(struct ipt_ID_info)),
       .help           = ID_help,
       .parse          = ID_parse,
       .final_check    = ID_check,
       .print          = ID_print,
       .save           = ID_save,
       .extra_opts     = ID_opts,
   };

   void _init(void)
   {
       xtables_register_target(&id_tg_reg);
   }

Далее скопируем файл ipt_ID.h в iptables-1.4.4/include/linux/netfilter_ipv4/ и файл libipt_ID.c в iptables-1.4.4/extensions/
теперь скомпилируем iptables и скопируем файл iptables-1.4.4/extensions/libipt_ID.so в /lib/xtables/

Теперь можно создавать цепочки в iptables

пример:

   iptables -t mangle -A POSTROUTING -j ID --id-rand 1

Будет выдавть всем пакетам случайные ID (единица в конце ничего не обозначает просто я не доделал модуль)

   iptables -t mangle -A POSTROUTING -j ID --id-inc 1

Будет пакетам направленным на один IP присваивать ID постоянно увеличивая на единицу, может хранить в памяти пять таких цепочек (количество цепочек можно увеличить)

P.S. Если кого интересует данная тема, то я доделаю статью и допишу модуль, просто пока всё работает и так не хочется ничего переделывать, но если нужно сделаю.


URL: http://www.linuxjournal.com/article/7184
Обсуждается: http://www.opennet.ru/tips/info/2570.shtml

 

Ваше сообщение
Имя*:
EMail:
Для отправки ответов на email укажите знак ! перед адресом, например, !user@host.ru (!! - не показывать email).
Более тонкая настройка отправки ответов производится в профиле зарегистрированного участника форума.
Заголовок*:
Сообщение*:
 
При общении не допускается: неуважительное отношение к собеседнику, хамство, унизительное обращение, ненормативная лексика, переход на личности, агрессивное поведение, обесценивание собеседника, провоцирование флейма голословными и заведомо ложными заявлениями. Не отвечайте на сообщения, явно нарушающие правила - удаляются не только сами нарушения, но и все ответы на них. Лог модерирования.



Партнёры:
PostgresPro
Inferno Solutions
Hosting by Hoster.ru
Хостинг:

Закладки на сайте
Проследить за страницей
Created 1996-2024 by Maxim Chirkov
Добавить, Поддержать, Вебмастеру