Пишу этот пост из-за того что многие сталкиваются с проблемой p2p траффика
и нет нормального средства для по его управлению.
Задача стоит в дропанье данного вида трафика
Система RHEL 5.4
Первые ссылки по поиску решения вели на
http://l7-filter.sourceforge.net/фильтр 7 слоя который состоит из патчей к ядру и модулей к фаерволу (ака iptables)
поставить его не получилось по той причине что RHEL 5.4 это коммерческая ОС и исходников нет есть только девел пакеты
взял установил пакеты kernel-devel и iptables-devel
дальше нашёл http://ipp2p.org/
тоже запушенный проект , скачал последнюю версию и там как раз собирался кернель модуль и шаред библиотека к фаерволу
этот модуль конечно же требовал девел пакеты кернеля и фаервола
в файле Makefile в наглую заменяю значение строки IPTABLES_SRC = на IPTABLES_SRC = /usr (ибо туда по дефолту устанавливаются девел пакеты из рпм)
соответсвенно IPTABLES_INCLUDE будет иметь значение IPTABLES_INCLUDE = -I$(IPTABLES_SRC)/include
компиляция и сборка проходит нормально но не работает шаред библиотека
погуглив нашёл что надо заменить линковщик
далее переходим к мейк рулу который будет собирать шаред библиотеку
libipt_ipp2p.so: libipt_ipp2p.c ipt_ipp2p.h
$(CC) $(CFLAGS) $(IPTABLES_OPTION) $(IPTABLES_INCLUDE) -fPIC -c libipt_ipp2p.c
ld -shared -o libipt_ipp2p.so libipt_ipp2p.o
в данном куске надо заменить третью строчку и заменить линковщик на gcc
$(CC) -shared -o libipt_ipp2p.so libipt_ipp2p.o
сборка модуля ядра пройдёт нормально но шаред библиотека не собралась вывалилась ошибка
gcc -shared -o libipt_ipp2p.so libipt_ipp2p.o
libipt_ipp2p.o: In function '_init':
libipt_ipp2p.c: (.text+0x20): multiple definition of '_init' /usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../lib64/crti.o:(.init+0x0): first defined here
collect2: ld returned 1 exit status
make: *** [libipt_ipp2p.so] Error 1
ошибка говорит о том что функция инит уже определена в файле crti.o
пошарил в сети а именно в мануалах по написанию шаред библиотек и наткнулся на вот эту ссылку http://mech.math.msu.su/~zubr/library.html
ниже отрывок
########################################################################################
Функции _init и _fini.
В библиотеке могут содержаться функции со специальными именами _init и _fini. Функция _init выполняется всегда непосредственно перед загрузкой библиотеки. Функция _fini выполняется всегда непосредственно перед выгрузкой библиотеки. Покажем на примере, как скомпилировать библиотеку, содержащую функцию _init. Файл libhello.c сделаем таким:
#include
void _init(void){
printf("Load library!\n");
}
void hello(void){
printf("Hello, library world?\n");
}
Объектный файл libhello.o создается без проблем. При попытке создать библиотеку получаем ошибку
gcc -g -shared -Wl,-soname,libhello.so.1 -o libhello.so.1.0 libhello.o -lc
libhello.o: In function `_init':
/home/zubr/demo_library/shared/libhello.c:2: multiple definition of `_init'
/usr/lib/gcc-lib/i386-redhat-linux/2.96/../../../crti.o(.init+0x0): first defined here
collect2: ld returned 1 exit status
Для прояснения проблемы добавим в ключи компилятора -v. Этот ключ позволяет получить подробности работа компилятора.
gcc -v -g -shared -Wl,-soname,libhello.so.1 -o libhello.so.1.0 libhello.o -lc
Reading specs from /usr/lib/gcc-lib/i386-redhat-linux/2.96/specs
gcc version 2.96 20000731 (Red Hat Linux 7.3 2.96-110)
/usr/lib/gcc-lib/i386-redhat-linux/2.96/collect2 -m elf_i386 -shared -o libhello.so.1.0 /usr/lib/gcc-lib/i386-redhat-linux/2.96/../../../crti.o /usr/lib/gcc-lib/i386-redhat-linux/2.96/crtbeginS.o -L/usr/lib/gcc-lib/i386-redhat-linux/2.96 -L/usr/lib/gcc-lib/i386-redhat-linux/2.96/../../.. -soname libhello.so.1 libhello.o -lc -lgcc -lc -lgcc /usr/lib/gcc-lib/i386-redhat-linux/2.96/crtendS.o /usr/lib/gcc-lib/i386-redhat-linux/2.96/../../../crtn.o
libhello.o: In function `_init':
/home/zubr/demo_library/shared/libhello.c:2: multiple definition of `_init'
/usr/lib/gcc-lib/i386-redhat-linux/2.96/../../../crti.o(.init+0x0): first defined here
collect2: ld returned 1 exit status
Отсюда видно, что компилятор gcc указывает среди объектных файлов, подлежащих компиляции командой collect2, файл /usr/lib/crti.o, который содержит функцию _init. Коль скоро имеем две функции с одним и тем же именем, получаем ошибку. Получить желаемое следующим образом. Явно вызовем collect2 с теми же аргументами, которые, за исключением /usr/lib/gcc-lib/i386-redhat-linux/2.96/../../../crti.o .
/usr/lib/gcc-lib/i386-redhat-linux/2.96/collect2 -m elf_i386 -shared -o libhello.so.1.0 /usr/lib/gcc-lib/i386-redhat-linux/2.96/crtbeginS.o -L/usr/lib/gcc-lib/i386-redhat-linux/2.96 -L/usr/lib/gcc-lib/i386-redhat-linux/2.96/../../.. -soname libhello.so.1 libhello.o -lc -lgcc -lc -lgcc /usr/lib/gcc-lib/i386-redhat-linux/2.96/crtendS.o /usr/lib/gcc-lib/i386-redhat-linux/2.96/../../../crtn.o
Это успешно создает libhello.1.0. Далее создание библиотеки происходит стандартным образом.
/sbin/ldconfig -n .
gcc -Wall -g -c demo_use.c -o demo_use.o
gcc -g -o demo_use1 demo_use.o -L. -lhello
Теперь при выполнении demo_use1 получаем
LD_LIBRARY_PATH="." ./demo_use1
Load library!
Hello, library world?
То есть происходит неявный вызов _init, что и требовалось. Примечание: На вашей машине файл, содержащий стандартную функцию _init, может иметь другое имя. Смотрите внимательно в диагностическую информацию gcc. Ключ -nostartfiles для компилятора gcc позволяет не линковать стартовые файлы, в которых присутствуют функции _init и _fini по умолчанию. Использование этого ключа также решает проблему.
#################################################################################################
указанный первый способ меня не устроил я решил добавить ключ -nostartfiles
окончательно строка имеет вид
$(CC) -shared -nostartfiles -o libipt_ipp2p.so libipt_ipp2p.o
после чего модуль собрался нормально и скомпилировалась шаред библиотека
но не тут то было модуль не работал и выдавал ошибку
kernel: ip_tables: ipp2p match: invalid size 16 != 8
догадаться можн обыло сразу в чём дело ибо я уже прочёл мануал по написанию модулей для фаервола но по старинке просто потянуло к гуглу
вот ссылочка http://www.debian-administration.org/articles/562 описание установки этого модуля и все в коментах ругают мол нифига не пашет и смотрю ошибочка вроде как у меня и в низу ответ на коммент
Gentoo people had fixed it. Try:
http://gentoo.mirror.solnet.ch/net-firewall/ipp2p/files/ipp2p-0.8 .2-matchsize.patch
It worked for me.
хех смотрим патчик он такой
diff -Nru ipp2p-0.8.2.orig/ipt_ipp2p.c ipp2p-0.8.2/ipt_ipp2p.c
--- ipp2p-0.8.2.orig/ipt_ipp2p.c 2006-09-27 12:52:00.000000000 +0300
+++ ipp2p-0.8.2/ipt_ipp2p.c 2007-01-14 18:26:23.000000000 +0200
@@ -843,15 +843,6 @@
}
-// TODO: find out what this structure is for (scheme taken
-// from kernel sources)
-// content seems to have a length of 8 bytes
-// (at least on my x86 machine)
-struct ipp2p_match_info {
- long int dunno_what_this_is_for;
- long int i_also_dunno_what_this_is_for;
-};
-
static struct ipt_match ipp2p_match = {
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
{ NULL, NULL },
@@ -870,7 +861,7 @@
.name = "ipp2p",
.match = &match,
.family = AF_INET,
- .matchsize = sizeof(struct ipp2p_match_info),
+ .matchsize = XT_ALIGN(sizeof(struct ipt_p2p_info)),
.checkentry = &checkentry,
.me = THIS_MODULE,
#endif
как видно из патчика всеголишь в файле ipt_ipp2p.c закоментируем (или удалим в случае патча) структуру
struct ipp2p_match_info {
long int dunno_what_this_is_for;
long int i_also_dunno_what_this_is_for;
};
и заменяем красную строчку на синию
.matchsize = sizeof(struct ipp2p_match_info),
.matchsize = XT_ALIGN(sizeof(struct ipt_p2p_info)),
выполняем make clean && make и всё модуль готов к работе
незабываем скопировать полученный кернель модуль и шаред библиотеку в нужные места а именно
cp ipt_ipp2p.ko /lib/modules/2.6.18-164.el5/kernel/net/netfilter/ipt_ipp2p.ko
сменить права доступа к файлу а именно
chmod 744 /lib/modules/2.6.18-164.el5/kernel/net/netfilter/ipt_ipp2p.ko
и скопируем шаред библиотеку (у меня архитектура x86_64 и модули фаервола лежат в директории /lib64)
cp libipt_ipp2p.so /lib64/iptables/libipt_ipp2p.soвыполняем
depmod -a и всё вроде всё готова запускаем iptables (service iptables start)
и следуем инструкциям ридми файла
iptables -m ipp2p --help покажет нужную инфу по использованию
iptables -A FORWARD -m ipp2p --bit -j DROP добавляем к примеру правило блокирования битторрент протокола
запускаем на клиентской машине биттореент клиен и пытаемся поставит что-либо на скачку
чтобы увидеть статистику работоспособности модуля выполняем
iptables -L -v -n и видем строчку на подобии этой
Chain FORWARD (2 preferences)
pkts bytes target proto opt in out source destination
0 0 ACCEPT all -- lo * 0/0 0/0
3194 737K DROP all -- * * 0/0 0/0
ipp2p v0.8.2 --ipp2p
видно как попадают пакетики торрета и дропаются
усё
пс: осталась ещё одна задача ограничить всякое там потоковое видео ютуб и другой медиа контент
думаю писать модуль под фаервол (хотя модуль стринг чтото не сработал)