LINUX.ORG.RU

iptables модуль ядра.

 


0

2

Не получается передать много данных в модуль ядра iptables через расширение для iptables.

Модуль назвал iptable (таблица ip адресов) для фильтрации перебором. На входе имя файла списка IP c флагами SRC или DST

Ошибка при добавлении правила: dmesg: x_tables: ip_tables: iptable.1 match: invalid size 135176 (kernel) != (user) 4104

В модуле ядра объявлено:

struct xt_iptable_mtinfo {
        __u8 iptable0[0x10000]; 
        __u8 flags;
};

описано как:

static struct xt_match iptable_mt4_reg[] __read_mostly = {
        {
                .name      = "iptable",
                .revision  = 1,
                .family    = NFPROTO_IPV4,
                .match     = iptable_mt4,
                .matchsize = sizeof(struct xt_iptable_mtinfo),
                .me        = THIS_MODULE,
        },
};
Загружается соответственно так: return xt_register_matches(iptable_mt4_reg, ARRAY_SIZE(iptable_mt4_reg)); Что качается ядра всё понятно.

Дальше расширение для iptables

libxt_iptables.c Повторное описание структуры:

struct ipt_iptable_info {
        __u8 iptable0[0x10000];
        /* Flags from above */
        __u8 flags;
};
Опции расширений iptables описаны как строка содержащая имя файла таблицы либо для входящего либо для исходящего ip.
static const struct xt_option_entry iptable_mt_opts[] =
{
        {.name = "src-maskfile",  .id = O_SRC_MASK, .type = XTTYPE_STRING, .flags = XTOPT_INVERT},
        {.name = "dst-maskfile",  .id = O_DST_MASK, .type = XTTYPE_STRING, .flags = XTOPT_INVERT},
        XTOPT_TABLEEND,
};

Описано:

static struct xtables_match iptable_mt_reg[] = {
        {
                .next          = NULL,
                .version       = XTABLES_VERSION,
                .name          = "iptable",
                .revision      = 1,
                .family        = NFPROTO_UNSPEC,
                .size          = XT_ALIGN(sizeof(struct ipt_iptable_info)),
                .userspacesize = XT_ALIGN(sizeof(struct ipt_iptable_info)),
                .help          = iptable_help,    
                .print         = iptable_print,   
                .parse         = iptable_parse, 
                .save          = iptable_save,   
                .x6_options    = iptable_mt_opts, 
                .final_check   = iptable_mt_check, 
        },
};

Зарегано:

xtables_register_matches(iptable_mt_reg, ARRAY_SIZE(iptable_mt_reg));

Почему то ядро хочет больший размер конфигурации, а iptables выдает мало. Как будто обрезает структуру при работе с libiptc.

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



Последнее исправление: dryukov (всего исправлений: 1)

Модуль назвал iptable (таблица ip адресов) для фильтрации
перебором. На входе имя файла списка IP c флагами SRC или DST

А это именно с целью понять, как оно пишется, или ipset чем-то не угодил ? Там, правда, нельзя в одном списке делать SRC и DST.

AS ★★★★★
()
Ответ на: комментарий от AS

Ну это укороченный вариант для читаемости, да и не написано ведь еще ) Слабо понимаю принцип как это связано пока что.

Я так понимаю сначала срабатывают условия struct ipt_entry После он идет на struct ipt_entry_match И в конце только на одно правило struct ipt_entry_target

Я так понимаю match получает пакет из цепочки, а дальше должен его обсосать, пощупать на предмет фильтрации. SRC или DST или оба сразу. Но если проверять оба адреса то нагрузка на процессор в 2 раза больше.

ipset не сильно подходит для целей. В планах немого другой способ ускорения фильтрации из 2-х уровней. Но выше описанную проблему это не меняет.

dryukov
() автор топика
Ответ на: комментарий от dryukov

Передавать большие данные в виде структуры в iptables - моветон. Именно из-за этого все, что имеет неопределенный размер разделяет правила и данные (пример ipset)

В твоем случае проще дописать к ipset новый тип (взяв за основу has:ip) или использовать hash:net,net Или подправить has:ip,port,ip чтоб при 0-м порте он его не сравнивал.

Правильный способ - данные для правил предварительно загружать через procfs. Простой шаблон - xt_condition из xtables-addons

vel ★★★★★
()
Последнее исправление: vel (всего исправлений: 2)
Ответ на: комментарий от vel

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

По цепочке netfilter и так очень много шагов, тем более если они сделаны кучей отдельных правил, которые описываются цепочками.

Короче ситуация сложилась таким образом, что полез в libiptc. Оказалось, что общение идет через s(g)etsockopt() а длинна пакета видимо ограниченная вещь (вроде как одни говорят настройкой, а другие размером страницы памяти переданной системному вызову).

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

Таким образом для меня произошло открытие ! если одновременно могут выполняться несколько потоков команд iptables то необходимо их синхронизировать чтобы не потерять цепочки.

Наконец то я догнал откуда у меня раньше были очень редкие проблемы с самописным pppoe сервером, на котором правила были в скриптах, и иногда почему-то появлялись правила которые вроде как не должны были появляться.

Но таким макаром могут и не добавиться правила ограничивающие доступ, что страшнее.

Это так, в качестве отступления )))

PS. Переписал модуль, передаю только имя файла, флаги направления проверки, инверсии. Модуль будет сам подгружать хеш и точный список блокировок из указанного файла, с индексами быстрого перехода к блоку.

dryukov
() автор топика

для фильтрации перебором. На входе имя файла списка IP c флагами SRC или DST

Про ipset ты, конечно, в курсе?

chimera19
()
Ответ на: комментарий от dryukov

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

теперь понимашь, почему большие размеры структур плохо ?

Таким образом для меня произошло открытие ! если одновременно могут выполняться несколько потоков команд iptables то необходимо их синхронизировать чтобы не потерять цепочки.

Тебя ждут еще многие открытия на счет атомарности действий, гонок и других увлекательный веще, которые делают написание модулей ядра веселее.

PS. Переписал модуль, передаю только имя файла, флаги направления проверки, инверсии. Модуль будет сам подгружать хеш и точный список блокировок из указанного файла, с индексами быстрого перехода к блоку.

Поздравляю! ты написал свой урезанный ipset.

ipset из-за ограничений [sg]etsockopt в pagesize был вынужден перейти на netlink.

в ipset решены все твои проблемы. То, что ты хочешь есть в hash:ip,port,ip - нужно выкинуть порт и протокол. HKEY_DATALEN урезать до 2*sizeof(u32) и hash_ipportip4_data_equal() подправить.

hash - это достаточно быстро, быстрее будет только исполняемый код (как jit в bpf)

Кроме того, в ipset есть обмен 2-х сетов именами, т.о. реализуется мгновенная(атомарная) смена набора.

vel ★★★★★
()
Ответ на: комментарий от vel

Да дело то наверное в том, что не так часто возникает необходимость программировать, тем более для электрика )))

Всё от низкого знания темы, просто использовал iptables и не думал как оно там внутри, тут понадобилось ускорить его работу вот и полез со своим модулем расширения.

От этого и плясал, а то что __sockopt() в ядре поддерживается чисто ради древней совместимости только что узнал.

Да за пару дней вникнуть в историю развития интерфейсов обмена с ядром и его работу видимо сложно ))) тем более ели всегда пользовался iptables и особо в тему не вникал, а отсутствие информации видимо как раз связано с его древностью.

Но спасибо за помощь и наводку на тему вопроса о том, как сделать еще лучше :)

Нашел чтиво в тему. http://www.programmersclub.ru/%D0%A0%D0%B0%D0%B1%D0%BE%D1%82%D0%B0-%D1%81-netlink-%D0%B2-linux-%D0%A7%D0%B0%D1%81%D1%82%D1%8C-1/

dryukov
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.