Возможно вы искали: 'EarthRise: A Guild Inv...'

May 15 2025 19:34:25
  • Как сделать 8Gamers.Ru домашней страницей?
  • Игры
    • База данных по играх
    • Игровые новости
    • Игровая индустрия
    • Обзоры на игры
    • Прохождения игр
    • Гайды к играм
    • Превью о играх
    • Игровые тизеры
    • Игровые арты
    • Игровые обои
    • Игровые скриншоты
    • Игровые обложки
    • Игровые трейлеры
    • Игровое видео
    • Вышедшие игры
    • Ближайшие релизы игр
  • Кино и ТВ
    • База данных по кино
    • Статьи о кино
    • Постеры
    • Кадры из кино
    • Кино трейлеры
    • Сегодня в кино
    • Скоро в кино
  • Комиксы и манга
    • Манга по алфавиту
    • База данных по комиксах
    • Читать онлайн комиксы
    • Читать онлайн манга
    • База персонажей
  • Читы и коды
    • Чит-коды для PC игр
    • Чит-коды для консольных игр
    • Трейнеры
    • Коды Game Genie
  • Моддинг
    • Модификации
    • Карты к играм
    • Программы для моддинга
    • Статьи о моддинге
  • Геймдев
    • Всё о создании игр
    • Список движков
    • Утилиты в помощь игроделу
    • Конструкторы игр
    • Игровые движки
    • Библиотеки разработки
    • 3D-модели
    • Спрайты и тайлы
    • Музыка и звуки
    • Текстуры и фоны
  • Рецензии
    • Игры
    • Кино
    • Аниме
    • Комиксы
    • Мангу
    • Саундтреки
  • Саундтреки
    • Лирика
  • Файлы
    • Патчи к играм
    • Русификаторы к играм
    • Сохранения к играм
    • Субтитры к кино
  • Медиа
    • Видео
    • Фото
    • Аудио
    • Фан-арты
    • Косплей
    • Фото с виставок
    • Девушки из игр
    • Рисунки
    • Рисуем онлайн
    • Фотохостинг
  • Юмор
    • Анекдоты
    • Афоризмы
    • Истории
    • Стишки и эпиграммы
    • Тосты
    • Цитаты
  • Флеш
    • Азартные
    • Аркады
    • Бродилки
    • Гонки
    • Для девочек
    • Для мальчиков
    • Драки
    • Квесты
    • Леталки
    • Логические
    • Мультфильмы
    • Открытки
    • Приколы
    • Разное
    • Спорт
    • Стратегии
    • Стрелялки
Статистика

Статей: 87772
Просмотров: 96111483
Игры
Injustice:  Gods Among Us
Injustice: Gods Among Us
...
Dark Souls 2
Dark Souls 2
Dark Souls II - вторая часть самой хардкорной ролевой игры 2011-2012 года, с новым героем, сюжето...
Battlefield 4
Battlefield 4
Battlefield 4 - продолжение венценосного мультиплеер-ориентированного шутера от первого ли...
Кино
Steins;Gate
Steins;Gate
Любители японской анимации уже давно поняли ,что аниме сериалы могут дать порой гораздо больше пи...
Ку! Кин-дза-дза
Ку! Кин-дза-дза
Начинающий диджей Толик и всемирно известный виолончелист Владимир Чижов встречают на шумной моск...
Обзоры на игры
• Обзор Ibara [PCB/PS2] 18357
• Обзор The Walking ... 18801
• Обзор DMC: Devil M... 19879
• Обзор на игру Valk... 15877
• Обзор на игру Stars! 17764
• Обзор на Far Cry 3 17948
• Обзор на Resident ... 16024
• Обзор на Chivalry:... 17508
• Обзор на игру Kerb... 17981
• Обзор игры 007: Fr... 16619
Превью о играх
• Превью к игре Comp... 17960
• Превью о игре Mage... 14464
• Превью Incredible ... 14721
• Превью Firefall 13479
• Превью Dead Space 3 16334
• Превью о игре SimC... 14730
• Превью к игре Fuse 15442
• Превью Red Orche... 15542
• Превью Gothic 3 16343
• Превью Black & W... 17354
Главная » Статьи » Разное » Разработка Match-модуля для iptables своими руками. (iptables netfilter firewall module gcc filter linux kernel)

Разработка Match-модуля для iptables своими руками. (iptables netfilter firewall module gcc filter linux kernel)

Ключевые слова: iptables, netfilter, firewall, module, gcc, filter, linux, kernel, (найти похожие документы)

From: Artem Korneev <tema[Shift+2]smartru.com>
Date: Sun, 10 Mar 2008 17:02:14 +0000 (UTC)
Subject: Разработка Match-модуля для iptables своими руками.

Оригинал: http://linuxkernel.ru/?q=node/215

Как-то LinuxJournal опубликовал небольшую статью Victor Castro по
написанию собственного фаервола на основе Netfilter -
http://www.linuxjournal.com/article/7184 Это, безусловно, ценная и
полезная статья, но что можно сделать с приведённым примером? Вы
решили писать собственный фаервол? Прекрасно, значит моя статья не для
вас. А я хотел бы помочь тем, кто желает лишь дополнить
функциональность имеющегося в Linux фаервола iptables. Тем, кто хочет
написать собственные дополнения для него, если уже имеющаяся
функциональность модулей iptables по какой-либо причине не устраивает.

Для примера я подробно рассмотрю процесс написания модуля для ipv4,
который будет реагировать на поле ID в заголовке IP-пакета. Модуль
будет носить исключительно демонстрационный характер и будет
реагировать тогда, когда последняя цифра в ID пакета будет
соответствовать заданному параметру. Попросту говоря, мы возьмём
остаток от деления ID нацело на 10 и если он будет равен параметру,
модуль посчитает, что пакет соответствует критерию.

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

Начнём с модуля для ядра.
Инициализация модуля. Зарегистрируем процедуры нашего модуля:

static int __init iptest_init(void)
{
return ipt_register_match(&test_match);
}

static void __exit iptest_unload(void)
{
ipt_unregister_match(&test_match);
}

module_init(iptest_init);
module_exit(iptest_unload);


Макросы module_init и module_exit, указывают компиллятору, какая
функция будет вызвана ядром при загрузке нашего модуля, а какая - при
и его удалении. Для регистрации в подсистемах пакетного фильтра, мы
будем использовать процедуру ipt_register_match, для удаления -
процедуру ipt_unregister match.

В качестве параметра функциям ipt_register_match и
ipt_unregister_match передаётся ссылка на экземпляр структуры
ipt_match. Эта структура определена так:

#define ipt_match xt_match


а структура xt_match описана в файле linux/netfilter/x_tables.h. Нас
интересуют следующие поля:

name - имя нашего модуля для netfilter;
match - функция, которая будет выполнять проверку, соответствует ли пакет
критериям нашего модуля;
matchsize - размер структуры, передаваемой в нашу функцию match в поле matchinfo;
me - модуль ядра, обычно указывается THIS_MODULE;

Заполним эту структуру:

static struct ipt_match test_match = {
.name = "test",
.match = match,
.matchsize = sizeof(struct ipt_test_info),
.me = THIS_MODULE,
};


Осталось написать функцию match, которая будет проверять,
соответствует ли данный пакет нашей цепочке. Прототип функции match
приведён в файле linux/netfilter/x_tables.h:

int (*match)(
const struct sk_buff *skb, // буффер сокета, структура подробно описанав
// файле linux/skbuff.h;
const struct net_device *in, // ссылка на устройство, на которое пакет пришёл
const struct net_device *out, // ссылка на устройство, с которого пакет будет
// выпущен после обработки фильтром
const struct xt_match *match, // указатель на структуру xt_match, которой
// принадлежит функция
const void *matchinfo, // указатель на void, по этому указателю функция
// может получить доступ к переданным через cli
// из iptables параметрам
int offset, // честно говоря, не в курсе, что это за
// смещение; если знаете - напишите мне
unsigned int protoff, // аналогично предыдущему
int *hotdrop); // Если установить *hotdrop = 1 и вернуть 0,то
// пакет будет удалён (действие DROP)


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

struct ipt_test_info {
u_int8_t test;
u_int8_t invert;
};


Результатом выполнения функции match должно стать true для случая,
когда пакет соответствует критериям правила и false, если не
соответствует. Вот как будет выглядеть эта функция для нашего модуля:

static int
match(const struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
const struct xt_match *match,
const void *matchinfo,
int offset,
unsigned int protoff,
int *hotdrop)
{
const struct ipt_test_info *info = matchinfo;

return (skb->nh.iph->id % 10 == info->test) ^ info->invert;
}


Мы полчаем через matchinfo доступ к данным, используемым нашим модулем
- поле test сравниваем с остатком от деления id проверяемого пакета на
10 и если остаток равен заданному значению, мы возвращаем true. Также
учитывается возможность инвертирования правила (через указание '!' при
добавлении правила) - в этом случае будет возвращено обратное
значение. Доступ к полю id пакета мы получаем через буфер сокета -
структуру sk_buff, поле nh.iph. Структура поля iph описана в файле
linux/ip.h, в своём модуле мы использовали лишь поле id этой
структуры.

Вот полный текст полученного модуля ядра с указанием всех заголовочных
файлов и нужных макросов:

#include <linux/module.h>
#include <linux/skbuff.h>

#include <linux/netfilter_ipv4/ip_tables.h>

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Artem Korneev <tema[Shift+2]smartru.com>");
MODULE_DESCRIPTION("test iptables match module");

struct ipt_test_info {
u_int8_t test;
u_int8_t invert;
};

static int
match(const struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
const struct xt_match *match,
const void *matchinfo,
int offset,
unsigned int protoff,
int *hotdrop)
{
const struct ipt_test_info *info = matchinfo;

return (skb->nh.iph->id % 10 == info->test) ^ info->invert;
}

static struct ipt_match test_match = {
.name = "test",
.match = match,
.matchsize = sizeof(struct ipt_test_info),
.me = THIS_MODULE,
};

static int __init iptest_init(void)
{
return ipt_register_match(&test_match);
}

static void __exit iptest_unload(void)
{
ipt_unregister_match(&test_match);
}

module_init(iptest_init);
module_exit(iptest_unload);


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

ifneq ($(KERNELRELEASE),)
obj-m := ipt_test.o

else
KDIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)

default:
$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules

clean:
rm -f *.o *~ core
endif


Скомпилируем его командой make и загрузим через insmod:

insmod ipt_test.ko


После загрузки Вы можете видеть наш модуль в списке загруженных
модулей ядра:

lsmod | grep ipt_test
ipt_test 2432 0


Отлично. С модулем ядра мы закончили. Теперь нам нужно написать
расширение для iptables (userspace-части), которое позволит нам
использовать наш модуль в качестве критерия выбора пакетов.

Используем функцию register_match для регистрации своего расширения в
iptables:

register_match(&test);


В качестве параметра функция register_match принимает ссылку на
структуру типа iptables_match, описанние которой Вы можете найти в
файле iptables.h. Нас интересуют следующие поля этой структуры:

next - здесь нужно передать NULL, ядро само заполнит это поле;
name - имя, по этому имени позднее мы будем обращаться к нашему критерию
через параметр iptable -m;
version - версия iptables, здесь допустим макрос IPTABLES_VERSION;
size - размер структуры, которую мы передаём в модуль ядра;
userspacesize - размер структуры, видимый в пространстве пользователя;
help - ссылка на функцию, которая будет вызвана для вывода краткой
справки пользователю при запросе iptables -m test -h;
parse - эта функция заполняет структуру, передаваемую модулю ядра на
основе данных, переданных через аргумерты командной строки;
final_check - ссылка на функцию, производящую заключительную проверку
правильности заполнения передаваемой в ядро структуры;
print - ссылка на функцию, которая выводит на экран информацию о нашем
критерии при вызове iptables -L;
save - ссылка на функцию, которая выводин на экран информацию о нашем
критерии при вызове iptables-save;
extra_opts - дополительные опции командной строки;

Заполним эту структуру:

static struct iptables_match test = {
.next = NULL,
.name = "test",
.version = IPTABLES_VERSION,
.size = IPT_ALIGN(sizeof(struct ipt_test_info)),
.userspacesize = IPT_ALIGN(sizeof(struct ipt_test_info)),
.help = &help,
.parse = &parse,
.final_check = &final_check,
.print = &print,
.save = &save,
.extra_opts = opts
};


Напишем реализацию функции help:

static void
help(void) {
printf( "test match v%s options:n"
"[!] --test valuen",
IPTABLES_VERSION);

fputc('n', stdout);
}

struct ipt_test_info {
u_int8_t test;
u_int8_t invert;
};


Функция parse проверяет введённый параметр, заполняет передаваемую в
ядро структуру и возвращает true, если параметр корректен. Прототип
функции описан в объявлении структуры iptables_match.

static int
parse(int c, char **argv, int invert, unsigned int *flags,
const struct ipt_entry *entry,
unsigned int *nfcache,
struct ipt_entry_match **match)
{
struct ipt_test_info *testinfo = (struct ipt_test_info *)(*match)->data;

switch (c) {
case '1':
if (*flags == 1)
exit_error(PARAMETER_PROBLEM,
"test match: only use --test once!");

check_inverse(optarg, &invert, &optind, 0);
parse_test(argv[optind-1], testinfo);
if (invert)
testinfo->invert = 1;

*flags = 1;
break;

default:
return 0;
}
return 1;
}


Проверяем корректность параметров, проверяем аргументы на инверсию с
помощью процедуры check_inverse и вызываем собственную функцию
заполнения передаваемой в ядро структуры, описанную ниже:

static void
parse_test(const char *s, struct ipt_test_info *info)
{
unsigned int test;

if (string_to_number(s, 0, 9, &test) != -1) {
info->test = ( u_int8_t )test;
return;
}
exit_error(PARAMETER_PROBLEM, "Bad test value `%s'", s);
}


Здесь всё должно быть понятно.

В функции final_check нам нужно лишь убедиться, что все параметры
прочитаны верно. В нашем случае достаточно просто проверить, что flags
имеет ненулевое значение:

static void
final_check(unsigned int flags)
{
if (!flags)
exit_error(PARAMETER_PROBLEM, "test match: You must specify `--test'");
}


Функция print также довольно проста:

static void
print(const struct ipt_ip *ip,
const struct ipt_entry_match *match,
int numeric)
{
const struct ipt_test_info *info = (const struct ipt_test_info *)match->data;

printf("test match ");
if (info->invert)
printf("!");
printf("%i", info->test);
}


Мы получаем доступ к параметрам правила через передаваемый указатель
match->data, а далее просто выводим информацию на экран.

Функция save почти аналогична:

static void
save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
{
const struct ipt_test_info *info = (const struct ipt_test_info *)match->data;

if (info->invert)
printf("! ");
printf("--test %i", info->test);
}


Стуктура opts в нашем случае будет иметь вид:

static struct option opts[] = {
{ "test", 1, 0, '1' },
{0}
};


Последним должен быть 0 как признак конца списка. Если Ваш модуль не
имеет параметров - передайте список из одного элемента {0}.

Вот полный текст полученного модуля расширения iptables с указанием
всех заголовочных файлов и нужных макросов:

#include <stdio.h>
#include <netdb.h>
#include <string.h>
#include <stdlib.h>
#include <getopt.h>
#if defined(__GLIBC__) && __GLIBC__ == 2
#include <net/ethernet.h>
#else
#include <linux/if_ether.h>
#endif
#include <iptables.h>

static void
help(void) {
printf( "test match v%s options:n"
"[!] --test valuen",
IPTABLES_VERSION);

fputc('n', stdout);
}

struct ipt_test_info {
u_int8_t test;
u_int8_t invert;
};

static struct option opts[] = {
{ "test", 1, 0, '1' },
{0}
};

static void
parse_test(const char *s, struct ipt_test_info *info)
{
unsigned int test;

if (string_to_number(s, 0, 9, &test) != -1) {
info->test = ( u_int8_t )test;
return;
}
exit_error(PARAMETER_PROBLEM, "Bad test value `%s'", s);
}

static int
parse(int c, char **argv, int invert, unsigned int *flags,
const struct ipt_entry *entry,
unsigned int *nfcache,
struct ipt_entry_match **match)
{
struct ipt_test_info *testinfo = (struct ipt_test_info *)(*match)->data;

switch (c) {
case '1':
if (*flags == 1)
exit_error(PARAMETER_PROBLEM,
"test match: only use --test once!");

check_inverse(optarg, &invert, &optind, 0);
parse_test(argv[optind-1], testinfo);
if (invert)
testinfo->invert = 1;

*flags = 1;
break;

default:
return 0;
}
return 1;
}

static void
final_check(unsigned int flags)
{
if (!flags)
exit_error(PARAMETER_PROBLEM, "test match: You must specify `--test'");
}

static void
print(const struct ipt_ip *ip,
const struct ipt_entry_match *match,
int numeric)
{
const struct ipt_test_info *info = (const struct ipt_test_info *)match->data;

printf("test match ");
if (info->invert)
printf("!");
printf("%i", info->test);
}

static void
save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
{
const struct ipt_test_info *info = (const struct ipt_test_info *)match->data;

if (info->invert)
printf("! ");
printf("--test %i", info->test);
}

static struct iptables_match test = {
.next = NULL,
.name = "test",
.version = IPTABLES_VERSION,
.size = IPT_ALIGN(sizeof(struct ipt_test_info)),
.userspacesize = IPT_ALIGN(sizeof(struct ipt_test_info)),
.help = &help,
.parse = &parse,
.final_check = &final_check,
.print = &print,
.save = &save,
.extra_opts = opts
};

void _init(void)
{
register_match(&test);
}


Теперь скопируем наш исходник в каталог iptables/extensions исходных
кодов iptables, добавим в Makefile в этом же каталоге упоминание о
нашем модуле в список модулей пакетного фильтра. У меня получилась
такая строчка:

PF_EXT_SLIB:=ah addrtype comment connlimit connmark conntrack dscp ecn
esp hashlimit helper icmp iprange length limit mac mark multiport
owner physdev pkttype policy realm rpc sctp standard state tcp tcpmss
test tos ttl udp unclean CLASSIFY CONNMARK DNAT DSCP ECN LOG MARK
MASQUERADE MIRROR NETMAP NFQUEUE NOTRACK REDIRECT REJECT SAME SNAT
TARPIT TCPMSS TOS TRACE TTL ULOG


Соберём iptables командой make. Где-то в длинном списке сообщений
можно увидеть сообщение об удачной компилляции нашего модуля. У меня
получилось следующее:

cc -shared -o extensions/libipt_tcpmss.so
extensions/libipt_tcpmss_sh.o
cc -O2 -Wall -Wunused -I/usr/src/linux/include -Iinclude/
-DIPTABLES_VERSION="1.3.6" -fPIC -o extensions/libipt_test_sh.o -c
extensions/libipt_test.c


После этого необходимо установить iptables командой make install.

Отлично. Теперь создадим правило, использующее наш модуль:

# iptables -A INPUT -m test --test 1


После выполнения команды мы можем увидеть правило в выводе iptables:

# iptables -L -n --line-numbers -v

Chain INPUT (policy ACCEPT 11451 packets, 967K bytes)
num pkts bytes target prot opt in out source destination
1 1150 95767 0 -- * * 0.0.0.0/0 0.0.0.0/0 test match 1


Теперь, дабы убедиться, что модуль наш работает, добавим ещё одно
правило, регистрирующее все пакеты, попадающие в цепочку INPUT и
обнулим все счётчики в этой цепочке:

#iptables -A INPUT
#iptables -Z INPUT


Если Вы используете сеть и через какое-то время проверите состояние
счётчиков в цепочке INPUT, Вы сможете убедиться, что значения
различаются примерно в 10 раз:

Chain INPUT (policy ACCEPT 25658 packets, 1857K bytes)
num pkts bytes target prot opt in out source destination
1 2501 179K 0 -- * * 0.0.0.0/0 0.0.0.0/0 test match 1
2 25658 1857K 0 -- * * 0.0.0.0/0 0.0.0.0/0


Из чего можно предположить, что наш модуль работает правильно.
Выводимая нашим модулем информация, как было сказано ранее, задаётся в
функции print.

Также мы можем видеть правила, использующие наш модуль, в выводе
iptables-save:

...
-A INPUT -m test --test 1
-A INPUT
...


Как мы можем видеть, правило выводится именно в том формате, который
мы определили в функции save.

Вывод iptables -m test -h также вполне предсказуем:

test match v1.3.6 options:
[!] --test value


Вот и всё.

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

Все приведённые примеры были проверены на ядре Linux 2.6.18 SMP для
архитектуры x86_64, версия iptables - 1.3.6, но я предполагаю, что всё
описанное должно работать на любых свежих версиях ядра 2.6, в т.ч. и
для архитектуры i386, а также свежих версиях iptables. Цветовая схема
подсветки синтаксиса в коде примеров соответствует схеме "elflord"
редактора vim.

При составлении статьи не использовались никакие литературные
источники. Вся информация была почерпнута исключительно из
собственного опыта, исходных кодов ядра Linux и исходных кодов
iptables. Допускается свободное копирование текста статьи при условии
указания авторства.

Автор был бы очень признателен, если бы Вы высказали своё мнение о
прочитанной статье. Все замечания, предложения и отзывы о статье можно
присылать на адрес tema[Shift+2]smartru.com

С уважением, Artem Korneev. April 14, 2007.
1328 Прочтений •  [Разработка Match-модуля для iptables своими руками. (iptables netfilter firewall module gcc filter linux kernel)] [08.05.2012] [Комментариев: 0]
Добавил: Ukraine Vova
Ссылки
HTML: 
[BB Url]: 
Похожие статьи
Название Добавил Добавлено
• Разработка Match-модуля для iptable... Ukraine Vova 08.05.2012
Ни одного комментария? Будешь первым :).
Пожалуйста, авторизуйтесь для добавления комментария.

Проект входит в сеть сайтов «8Gamers Network»

Все права сохранены. 8Gamers.NET © 2011 - 2025

Статьи
Рецензия на Pressure
Рецензия на Pressure
Чтобы обратить на себя внимание, начинающие маленькие разработчики, как правило, уходят в жанры, ...
Рецензия на Lost Chronicles of Zerzura
Рецензия на Lost Chron...
Игры, сделанные без любви и старания, похожи на воздушный шар – оболочка есть, а внутри пусто. Lo...
Рецензия на The Bridge
Рецензия на The Bridge
«Верх» и «низ» в The Bridge — понятия относительные. Прогуливаясь под аркой, можно запросто перей...
Рецензия на SimCity
Рецензия на SimCity
Когда месяц назад состоялся релиз SimCity, по Сети прокатилось цунами народного гнева – глупые ош...
Рецензия на Strategy & Tactics: World War 2
Рецензия на Strategy &...
Название Strategy & Tactics: World War II вряд ли кому-то знакомо. Зато одного взгляда на ее скри...
Рецензия на игру Scribblenauts Unlimited
Рецензия на игру Scrib...
По сложившейся традиции в информационной карточке игры мы приводим в пример несколько похожих игр...
Рецензия на игру Walking Dead: Survival Instinct, The
Рецензия на игру Walki...
Зомби и продукция-по-лицензии — которые и сами по себе не лучшие представители игровой биосферы —...
Обратная связь | RSS | Донейт | Статистика | Команда | Техническая поддержка