| Admin 
 
Регистрация: 05.10.2005 Проживание: Москва Сообщения: 291 | 
 "Стрим - бери от жизни все!" или "Linux advanced routing дубль 2" 
 Поставили перед нами такую задачу - при наличии нескольких каналов в интернет разделять по ним нагрузку. Причем не просто разделять по протоколам, типа веб-трафик туды, а почту сюды, а каждое соединение с чередованием пакетов по разным интерфейсам.
Я где-то про это писал, что роутить пакеты можно по маркам от iptables, подробно на этом останавливаться не буду, лишь в общих чертах опишу подводные камни
 1. Казалось бы, достаточно каждое новое соединение маркировать путем -j MARK , ан нет, никто не застрахован от того, что последующие пакеты в этом TCP-соединении не пойдут через другой интерфейс, а это недопустимо.
 Для этого я нашел в ядре такое действие, как -j CONNMARK - маркирует все соединение! Отлично, будет иметь в виду. Далее.
 2. Теперь надо найти средство, позволяющее чередовать пакеты... С этим сложнее, искал долго, есть для iptables такой матч как -m nth, позволяющий чередовать, однако не мог найти патч на ядро 2.6.14 нормальный, а встроенной опции нету. И тут - о щастье - в ядре 2.6.18 обнаружилась опция "statistic" match support! Она включает в себя nth и random. Поясню. Nth позволяет маркировать каждый n-ный пакет, random - путем случайного выбора (но еще можно задавать вероятность). Отлично, это работает, теперь далее.
 3. Надо заставить ip route видеть марки, которые мы даем пакетам. Оказалось, что он не видит марки от CONNMARK... Есть над чем подумать! Надо, значит, дополнительно эту TCP-сессию еще промаркировать путем MARK, и предварительно для этого надо проверить, чтоб на пакете стоял connmark.
 Опять же в 2.6.18 нашел - m connmark для iptables, супер! Теперь мы такие коненкты промаркируем.
 4. Далее дело техники - засунуть пакеты из цепочки OUTPUT (для случая, когда пакеты уходят со шлюза) и цепочки PREROUTING (для транзитных пакетов) в дополнительную цепочку, где будет происходить их маркирование. Но PREROUTING только в интерфейсов, смотрящих в локальную сеть. Это есть.
 5. Подсунуть для ip route эти марки.
 6. И последнее - все эти манипуляции обернем в rc-скрипт формата gentoo, чтоб поднять/остановить этот роутинг можно было.
 
 Теперь собственно правила, скрипт, требования и т.д...
 | 
| Admin 
 
Регистрация: 05.10.2005 Проживание: Москва Сообщения: 291 | 
 "Стрим - бери от жизни все!" или "Linux advanced routing дубль 2" 
 Требования - iptables версии 1.3.6 или выше, ядро 2.6.18, пакет iproute2.
 Опции, какие необходимо включить в ядре:
 
 <*>   "CONNMARK" target support
 <*>   "MARK" target support
 
 <*>   "connmark" connection mark match support
 <*>   "statistic" match support
 
 <*>   Packet mangling
 
 [*]   IP: advanced router
 [*]   IP: policy routing
 [*]     IP: use netfilter MARK value as routing key
 
 Файл конфига и стартовый скрипт:
 
 # /etc/conf.d/routing
 IPTABLES="/sbin/iptables"
 #GW="192.168.29.1"
 DEVS_INT="eth0 eth1"
 DEVS_EXT="ppp1 ppp2 ppp3"
 NO_DEST="192.168.0.0/16"
 
 
 
 # /etc/init.d/routing
 #!/sbin/runscript
 
 opts="start stop restart info"
 
 depend() {
 need net
 }
 
 info() {
 einfo "[iptables]"
 $IPTABLES -t mangle -nxvL routing 2> /dev/null
 $IPTABLES -t mangle -nxvL routing_n 2> /dev/null
 einfo "[rules]"
 ip rule list |grep fwmark
 einfo "[routes]"
 
 i=1
 for d in ${DEVS_EXT}
 do
 ip route list table $i
 i=`expr $i + 1`
 done
 
 }
 stop() {
 ebegin "Stopping advanced router"
 $IPTABLES -t mangle -D OUTPUT -j routing 2> /dev/null > /dev/null
 for d in ${DEVS_INT}
 do
 $IPTABLES -t mangle -D PREROUTING -i $d -j routing 2> /dev/null > /dev/null
 done
 $IPTABLES -t mangle -F routing 2> /dev/null > /dev/null
 $IPTABLES -t mangle -X routing 2> /dev/null > /dev/null
 
 $IPTABLES -t mangle -F routing_n 2> /dev/null > /dev/null
 $IPTABLES -t mangle -X routing_n 2> /dev/null > /dev/null
 
 i=1
 for d in ${DEVS_EXT}
 do
 ip route del table $i
 ip rule del table $i
 i=`expr $i + 1`
 done
 
 eend
 }
 start() {
 ebegin "Starting advanced router"
 
 $IPTABLES -t mangle -N routing
 $IPTABLES -t mangle -N routing_n
 
 #Add user rules here!####
 $IPTABLES -t mangle -A routing -m state --state NEW,RELATED -j routing_n
 ###########################
 
 $IPTABLES -t mangle -I OUTPUT -j routing
 for d in ${DEVS_INT}
 do
 $IPTABLES -t mangle -I PREROUTING -i $d -j routing
 done
 
 #Get number of external interfaces
 devs=0
 for d in ${DEVS_EXT}
 do
 devs=`expr $devs + 1`
 done
 ####################################
 
 for d in ${NO_DEST}
 do
 $IPTABLES -t mangle -A routing_n -d $d -j RETURN
 done
 
 i=1
 for d in ${DEVS_EXT}
 do
 #Routing marks
 $IPTABLES -t mangle -A routing -m connmark --mark $i -j MARK --set-mark $i
 $IPTABLES -t mangle -A routing_n -m statistic --mode=nth --every $devs --packet `expr $i - 1` -j CONNMARK --set-mark $i
 ##############
 
 #Routing rules and routes ##
 ip rule add fwmark $i table $i
 if [ ! -z $GW ]; then
 ip route add default via $GW dev $d table $i
 fi
 
 if [ -z $GW ]; then
 ip route add default dev $d table $i
 fi
 #################
 
 i=`expr $i + 1`
 done
 eend
 }
 | 
| Admin 
 
Регистрация: 05.10.2005 Проживание: Москва Сообщения: 291 | 
 "Стрим - бери от жизни все!" или "Linux advanced routing дубль 2" 
 Что мы имеем в итоге - новые открывающиеся соединения (состояния NEW или RELATED) распределяются по указанным в конфиге интерфейсам (в данном случае - ppp1 ppp2 ppp3)
 Побочное применение данной технологии можно найти в следующем:
 Есть известный домашний канал Стрим, там предположим есть безлимитный канал на 1 Мбит. Так вот они разрешают поднимать несколько соединений! Поднимаем 6 коннектов, указываем их в конфиге, нагрузка распределяются по всем интерфейсам (например, если качать флешгетом в 6 потоков, либо пользовать bittorrent), и на Стриме имеем безлимитку на 6 Мбит   |