Jump to content
Калькуляторы

Модифицированный модуль RAWNAT Натим и шейпим 2+ гбит/c с загрузкой ядер 2-3%

По многочисленным просьбам выкладываю небольшую доделку к модулю RAWNAT из пакета xtables-addons. Суть доделки в том, что в отличие от оригинала, меняющего IP пакетов в соответствии с правилом iptables, этот модуль смотрит в находящуюся внутри него таблицу соответствия "старый ip -> новый ip" и меняет в соответствии с ней. Также имеются таблицы не для смены IP, а для установки skb->priority, поэтому получается табличный аналог -j CLASSIFY. Все таблицы в данной версии содержат 65535 записей, что достаточно для обработки подсети /16. Больше нам не требовалось. Имеется таблица для SNAT, DNAT, и 4 таблицы для CLASSIFY.

 

По результатам работы (более полугода), загрузка ядер обычного core i7 при шейпинге (tc htb...) трафика порядка 1.5 гбит/c в обе стороны составляет 2-3% - это на linux 3.7 с отключенным route cache. Такая же ситуация и с натом, но нат у нас делается на одной машине с bgp, который дает основную нагрузку на ядра. Сетевые карты - ixgbe.

 

Собирать следующим образом:

 

./configure

./make

./make install

cd extensions

gcc gcc -o iptrnat iptrnat.c

cp ./iptrnat /usr/local/bin

 

Использование. Для примера имеем две подсети серых адресов 192.168.0.0/19 и 192.168.64.0/19, одну подсеть реальников 195.33.64.0/20.

 

modprobe xt_RAWNAT (в dmesg должно появиться сообщение, что загружен правильный модуль)

 

iptables -A POSTROUTING -t rawpost -s 192.168.0.0/19 -j TABSNAT

iptables -A POSTROUTING -t rawpost -s 192.168.64.0/19 -j TABSNAT

iptables -A PREROUTING -t raw -d 195.33.64.0/20 -j TABDNAT

 

Добавляем сопоставление:

 

iptrnat -a -t 1 -i 195.33.64.5 -r 192.168.10.33

iptrnat -a -t 2 -i 192.168.10.33 -r 195.33.64.5

 

Теперь проходящий с адреса 192.168.10.33 будет превращаться в 195.33.64.5 и наоборот. Такое сопоставление нужно добавлять скриптом при авторизации каждого клиента, например, при помощи lISG.

 

Удаление сопоставления при выходе клиента из сети:

 

iptrnat -d -t 1 -i 195.33.64.5

iptrnat -d -t 2 -i 192.168.10.33

 

Шейпинг можно сделать например так. eth0 - внутренний интерфейс, eth1 - наружный:

 

tc qdisc add dev eth0 root handle 1: htb default 1

tc class replace dev eth0 classid 1:1 htb rate 2000Mbit ceil 2000Mbit quantum 1500 burst 2000k cburst 2000k

tc qdisc add dev eth0 parent 1:1 handle 10: pfifo limit 10000

 

tc qdisc add dev eth1 root handle 1: htb default 1

tc class replace dev eth1 classid 1:1 htb rate 2000Mbit ceil 2000Mbit quantum 1500 burst 2000k cburst 2000k

tc qdisc add dev eth1 parent 1:1 handle 10: pfifo limit 10000

 

iptables -t mangle -A POSTROUTING -s 192.168.0.0/16 -o eth1 -j TABCLAS --cmatch src --ctable 3

iptables -t mangle -A POSTROUTING -s 195.33.64.0/20 -o eth1 -j TABCLAS --cmatch src --ctable 4

iptables -t mangle -A POSTROUTING -d 192.168.0.0/16 -o eth0 -j TABCLAS --cmatch dst --ctable 5

iptables -t mangle -A POSTROUTING -d 195.33.64.0/20 -o eth0 -j TABCLAS --cmatch dst --ctable 6

 

И для каждого клиента создаем правила. Допустим, у клиента с номером $ID имеется 3 адреса - 192.168.10.33, 192.168.55.70 и реальник 195.33.65.95:

 

iptrnat -a -t 3 -i 192.168.10.33 -c 1:$ID

iptrnat -a -t 3 -i 192.168.55.70 -c 1:$ID

iptrnat -a -t 4 -i 195.33.65.95 -c 1:$ID

iptrnat -a -t 5 -i 192.168.10.33 -c 1:$ID

iptrnat -a -t 5 -i 192.168.55.70 -c 1:$ID

iptrnat -a -t 6 -i 195.33.65.95 -c 1:$ID

 

tc class replace dev eth0 parent 1:1 classid 1:$ID htb rate $SPEEDkibit ceil $SPEEDkibit quantum 1500 burst 10k cburst 10k

tc qdisc replace dev eth0 parent 1:$ID handle $ID:0 pfifo limit $QUEUE

 

tc class replace dev eth1 parent 1:1 classid 1:$ID htb rate $SPEEDkibit ceil $SPEEDkibit quantum 1500 burst 10k cburst 10k

tc qdisc replace dev eth1 parent 1:$ID handle $ID:0 pfifo limit $QUEUE

 

Как видно, все работает без заумных фильтров и гигантских деревьев. И почему это раньше никто не реализовал?

 

Скачать можно тут: http://195.22.104.3/xtables-addons-1.41-tabnat.tgz

Edited by vladd

Share this post


Link to post
Share on other sites

интересная штука получается.

 

Можно будет отказаться от хэш-фильтров. Надо потестить.

 

Планируете разработчикам писать - что бы они закоммитили ?

Edited by alexxx71

Share this post


Link to post
Share on other sites

я так понимая что это 1:1 NAT, тоесть просто занатить \24 на один-два ИП не получится ?

Share this post


Link to post
Share on other sites

Я так понял что это 1:1 NAT, но если нет match'а по таблице TABCLAS то пакет идет дальше и рано или поздно попадет под действие ipt_SAME, который его и занатит. Можно вообще не использовать сопоставления, а просто делать CLASSIFY. (итересно - это быстрее чем хеш-фильтры или утопия?)

Я правильно понял ?

Edited by alexxx71

Share this post


Link to post
Share on other sites

интересная штука получается.

 

Можно будет отказаться от хэш-фильтров. Надо потестить.

 

Именно так. Работает все красивее и естественней. Плюс можно один класс делить между несколькими IP, из разных подсетей в произвольном количестве - нам это и надо было, т.к. на многих учетках у пользователей несколько адресов, и чтобы скорость между ними делилась.

 

А в отличие от того же ipfw, работает на нескольких ядрах и нагрузку дает на порядок меньшую. Такое впечатление, что с текущим железом и 10 гиг прожует.

 

Нат да, 1-к-1. Раньше приходилось для такого ната выстраивать огромное дерево и несколько десятков тысяч правил в iptables.

 

Планируете разработчикам писать - что бы они закоммитили ?

Да, надеюсь примут.

Edited by vladd

Share this post


Link to post
Share on other sites

Я так понял что это 1:1 NAT, но если нет match'а по таблице TABCLAS то пакет идет дальше и рано или поздно попадет под действие ipt_SAME, который его и занатит. Можно вообще не использовать сопоставления, а просто делать CLASSIFY.

TABCLAS - для классификации, TABDNAT/TABSNAT - для ната. Можно использовать только то, что нужно.

(итересно - это быстрее чем хеш-фильтры или утопия?)

Не медленнее точно, но гораздо проще и гибче в применении.

Share this post


Link to post
Share on other sites

Приветствую, интересно покрутить данную наработку

 

Вопрос в лоб. Имеем серые подсети скажем 10.ХХХ.0.0/16, 10.YYY.0.0/16 и допустим 10.ZZZ.0.0/16

 

Естественно, у нас нет блоков реальников такого объема. Как в таком случае строить правила iptables 1-в-1? Уменьшать размеры до /24? или можно сделать что-то в духе:

10.XXX.0.0/16 в aaa.bbb.ccc.0/19

10.YYY.0.0/16 в aaa.bbb.ccc.0/19

10.ZZZ.0.0/16 в aaa.bbb.ccc.0/19

 

Вопрос номер два:

 

У нас есть два блока реальников из разных диапазонов и разных размеров: aaa.bbb.ccc.0/19 и ddd.eee.fff.0/20

Сейчас они попилены на более мелкие, но есть возможность воссоединить один из них в большой. Вопрос в том, как строить правила ната имея разные блоки реальников?

 

 

iptrnat -a -t 1 -i 195.33.64.5 -r 192.168.10.33

iptrnat -a -t 2 -i 192.168.10.33 -r 195.33.64.5

 

На что в данном случае влияют эти -t 1 и -t 2?

Как я понял 1 и 2 это номера таблиц.

 

Одна таблица на одно сопоставление идет? Или какой тут принцип?

Edited by micol

Share this post


Link to post
Share on other sites

Доброго времени суток!

 

Очень заинтересовала приведённая разработка. Захотелось посмотреть. Но не удалось собрать.

Тестировал на одной и той же машине с разными версиями ядер (2.6.39 - 3.10.17) Обнаружил две проблемы. Первая возникает при сборке с ядрами версией выше 3.5.7 Её победить удалось. Вторая при сборке с ядром любой версии.

/root/shaping/ipt_TABCLAS/xtables-addons-1.41/extensions/xt_RAWNAT.c: В функции «ipt_rnat_set_ctl»:
/root/shaping/ipt_TABCLAS/xtables-addons-1.41/extensions/xt_RAWNAT.c:437:3: предупреждение: format «%ld» expects argument of type «long int», but argument 2 has type «__be32» [-Wformat] 
/root/shaping/ipt_TABCLAS/xtables-addons-1.41/extensions/xt_RAWNAT.c:437:3: предупреждение: format «%ld» expects argument of type «long int», but argument 3 has type «__be32» [-Wformat]
WARNING: "nf_nat_setup_info" [/root/shaping/ipt_TABCLAS/xtables-addons-1.41/extensions/xt_DNETMAP.ko] undefined!
WARNING: "ipt_unregister_table" [/root/shaping/ipt_TABCLAS/xtables-addons-1.41/extensions/iptable_rawpost.ko] undefined!   
WARNING: "ipt_register_table" [/root/shaping/ipt_TABCLAS/xtables-addons-1.41/extensions/iptable_rawpost.ko] undefined!   
WARNING: "ipt_do_table" [/root/shaping/ipt_TABCLAS/xtables-addons-1.41/extensions/iptable_rawpost.ko] undefined! 
In file included from ../include/net/netfilter/nf_nat.h:4:0,  
                from libxt_DNETMAP.c:14: 
../include/net/netfilter/nf_conntrack_tuple.h:29:7: ошибка: повторное определение «union nf_conntrack_man_proto» 
/usr/include/linux/netfilter/nf_conntrack_tuple_common.h:13:7: замечание: originally defined here 
make[3]: *** [libxt_DNETMAP.oo] Error 1 
make[2]: *** [user-all-local] Error 2 
make[1]: *** [all-recursive] Error 1                                                                                                                         
make: *** [all] Error 2                                                                                                                                      

Дистрибутив: gentoo

gcc версия 4.6.3 (Gentoo 4.6.3 p1.13, pie-0.5.2)

Конфиг ядра 3.5.7 в аттаче.

 

Подскажите, пожалуйста, что пропатчить в исходниках. В первую очередь интересует сборка для ядра 3.10.7

Ежели потребуется дополнительная информация, постараюсь предоставить.

config.gz

Edited by OperationCwal

Share this post


Link to post
Share on other sites

Жаль, что тема заглохла. Очень любопытное решение.

Share this post


Link to post
Share on other sites

Начал доделывать: https://github.com/alexey001/xtables-addons.

Для таргета TABCLAS сделан lookup из таблицы роутинга , в качестве классификатора юзается realm , тоесть както так:

 

iptables ...... -j TABCLAS --rtable 100 --cmatch dst

 

ip route add 1.2.3.4 dev lo realm 1/100 table 100.

 

Соответственно будет брать из таблицы 100 (при совпадении) realm и засовывать его в priority (class). Ну и переведен на xtables поновее.

 

Если нужны realm > 255 патч к iproute2.

 

diff --git a/lib/rt_names.c b/lib/rt_names.c
index 911e4d2..aac5859 100644
--- a/lib/rt_names.c
+++ b/lib/rt_names.c
@@ -307,7 +307,7 @@ int rtnl_rtrealm_a2n(__u32 *id, const char *arg)
       }

       res = strtoul(arg, &end, 0);
-       if (!end || end == arg || *end || res > 255)
+       if (!end || end == arg || *end || res > 65535)
               return -1;
       *id = res;
       return 0;

 

 

Решение АБСОЛЮТНО не тестированное (времени не было), но вроде должно работать :)

 

P.S. Все работает , но надо учитывать что в tc класс - hex , в iproute realm - dec , t.e например для tc класс 1:20 для iproute realm 1/32

Edited by alex_001

Share this post


Link to post
Share on other sites

Тот самый случай, когда и хочется, и колется. ;)

Share this post


Link to post
Share on other sites

с отключенным route cache

Кто-нибудь имеет больше информации о том как это делать и какой профит с включенным "route cache" и без?

Share this post


Link to post
Share on other sites

ThreeDHead

Как сделать - поставить ядро начиная с 3.6 и выше. Сведения про профит противоречивы, но вероятно после отключения стало лучше, раз его глобально выпилили.

Share this post


Link to post
Share on other sites

но вероятно после отключения стало лучше

Лучше стало только в части cache thrashing неконтролируемым внешним воздействием - его больше нет. В остальном, очевидно, что существует некий размер таблицы маршрутизации, при котором новая схема начнет проигрывать.

 

https://home.regit.org/2013/03/david-miller-routing-cache-is-dead-now-what/

http://www.spinics.net/lists/netdev/msg205545.html

Edited by vitalyb

Share this post


Link to post
Share on other sites

vitalyb

Спасибо, стало яснее.

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

Share this post


Link to post
Share on other sites

Что есть "отключенный route cache"? Как это делается и какие накладные и какой профит?

Share this post


Link to post
Share on other sites

Что есть "отключенный route cache"? Как это делается и какие накладные и какой профит?

Про профит написали. Что это есть - этакая динамическая route table , lookup делался по ней и только если нет в кэше лезло в осн. таблицу (заполняя попутно кэш). Я так понимаю смогли выпилить когда осн. таблицу стали хранить в trie (раньше это была опция) , размер уменьшился , и видимо время выборки стало практически равным времени выборки из кэша.

Проблемы с кэшем как уже указывали - возможность DOS'a и необходимость сборки мусора (старых записей).

Сам кэш можно посмотреть - 'ip route sh cache'

Share this post


Link to post
Share on other sites

Т.е. "отключенный route cache", это ничто иное как тупо версия ядра >= 3.6

Не совсем. В более ранних версиях, точно не скажу с каких, он отключался автоматически если начинал идти "плохой" трафик. см. крутилку

/proc/sys/net/ipv4/rt_cache_rebuild_count

Share this post


Link to post
Share on other sites

Небольшой скрипт для управления всей конструкцией. https://github.com/alexey001/farsh/tree/master/shell

инициализация: shp.sh shaper_init; shp.sh shaper_load.

Ссылка на ebuild для klish - в пред. посте.

Действия по добавлению/изменению лучше делать через clish - проверки на правильность параметров в самом скрипте не делал.

Edited by alex_001

Share this post


Link to post
Share on other sites

Планируете разработчикам писать - что бы они закоммитили ?

Да, надеюсь примут.

v2.4 (2014-01-09)

=================

Enhancements:

- Support for Linux up to 3.13

Changes:

- remove unmaintained RAWSNAT/RAWDNAT code

 

 

ЗЫ. Коллеги, ни у кого сырцов не осталось? До автора не достучался, ссылка мертвая. (((

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this