PDA

Просмотр полной версии : Два канала на сервере


Elyor Xudayberdiev
21.05.2008, 17:56
Вопрос: как можно с самого сервера пускать запросы через два канала?
заранее всем спасибо.
P.S. если что неясно, по ходу обсуждения буду дописывать. :)

Rustam Khamidov
22.05.2008, 01:39
Решения на линуксе.
Имеем 2 интерфейса к двум разным интернет каналам.
eth0 - IP1, гейт провайдера IPGW1
eth1 - IP2, гейт провайдера IPGW2
(есть еще eth2 - IP3, выход на локалку)
Ставим Squid, слушающий запросы только на eth2 (локалка).
По умолчанию траффик бежит по одному интерфейсу, допустим eth0 (default gateway IPGW1).

Решение 1 (Squid + acl).
Включаем расширенную маршрутизацию:
ip ru add from IP2 table 100
ip ro add table 100 default via IPGW2 dev eth1
Этим мы создали правило, что все исходящие пакеты с src IP2 уходят во внешний мир не по первому, а по второму каналу.

Ставим Squid, слушающий запросы по локалке (bind eth2).
Внимательно читаем раздел tcp_outgoung_address и создаем две строки:
tcp_outgoing_address IP2 aclname1
tcp_outgoing_address IP1
Эти строки означают, что если верна acl (с именем aclname1) то пакет побежит с источника IP2 (по альтернативному каналу), в остальных случаях с источника IP1 по основному маршруту.

Ну и последним выбираем, что мы хотим назначить на acl в сквиде.
а) Можно на acl посадить часть клиентских машин с которых идет запрос.
Тогда часть машин будет уходить в мир по вторичному маршруту, а все остальные клиентские машины по основному. (Смотри синтаксис acl aclname1 src IPaddr/NetMask)
б) Можно на acl посадить список доменов. Тогда если клиент постучится на домен из списка, то запросы в мир к ним будут по вторичному каналу, а все остальные запросы по первому каналу. (Смотри синтаксис acl aclname1 dst "filename". А в файле filename перечисляем домены или айпишники по одному в строку)
с) Комплексное правило или несколько правил, ибо никто нам не запрещает добавить в таком виде:
tcp_outgoing_address IP2 aclname1
tcp_outgoing_address IP2 aclname2
...
tcp_outgoing_address IP2 aclnameN
tcp_outgoing_address IP1
В этом случае пакет будет проверятся последовательно по всем aclname и при первой же успешной acl исполняется. Если не выполнимо ни одно из acl условий то работает последняя строка (основной канал).

Решение 2.
Как и в первом случае включаем расширенную маршрутизацию.
А вот со squid изголяемся. На самом деле их работает 3 штуки. Два слушают запросы только от локального хоста, ничего не кэшируют, но у каждого свой tcp_outgoing_address, IP1 и IP2 соответственно. Третий сквид слушает запросы от локальной сети, занимается кэшированием, но сам никогда не лезет в интернет, а по очереди обращается к двум parent'ам с адреса 127.0.0.1 но разными портами.
Если интересуют подробности покажу конфиги и пример работающей на практике схемы.

Решение 3.
На базе iptables. Приблизительно, как здесь (http://securepoint.com/lists/html/NetFilter/2006-11/msg00087.html)

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

У каждого из трех решений свои достоинства и недостатки.
Опишу основную проблему - необходима равномерная загрузка каналов и единовременную работоспособность протокола https а также сайтов использующих сессии и cookies.

В решении 1 нет проблемы https и сессиями, но трудно составить acl-условия для равномерной загрузки. Мы же не знаем насколько активны те или иные компы или расписать список доменов которые составят основной траффик.
Для решения1. На практике я взял анализ месячной статистики заходов, выбрал список максимальной загрузки около 50% обращений и составил список acl aclname dst "filename". (Можно также взять выборку не по кол-ву посещений, а по траффику по доменам).

Для решений 2 и 3. Легко достигатся практически равномерная загрузка каналов, но проблема https и сессий. Нельзя установить https соединение если от тебя пакеты приходят то с одного айпи, то с другого.

Поэтому на практике модернизировал решение 2. Одна из acl это регулярное выражение для URL на наличе протокола https. Далее по жалобам пользователей (-; у которых перестали работать некоторые форумы и некоторые сайты с авторизацией составил список доменов, которые всегда работают по какому-то одному каналу через acl dst "filename".

Для решения 3 элегантным должно быть решение с connection tracking. Т.е. каждый новый пакет SYN для tcp-сессии по очереди используют то один, то другой канал, но все остальные пакеты сессии должны идти в том канале, в котором пробежал первый пакет. Сам не использовал, но есть знакомые с проекта iptables.org, которые разрабатывают подобные решения. По их опыту это решение сжирает память для tcp сессий, а так же неслабо нагружает проц и ресурсы системы. Сам на практике баловался давно, но при необходимости могу помочь рыть в нужном направлении.

Elyor Xudayberdiev
22.05.2008, 09:38
Rustam Khamidov, Вам конечно большое спасибо за предоставленные материалы, но, как я писал выше, нужно пускать запросы с самого сервера через несколько каналов. Соответсвенно, сквида отпадает сама-собой. (а пользователей пускать через несколько каналов я уже проделывал, и со сквидой, и iptables'ом, и iprout'ом :))
Остаётся только третье решение - но оно не сработало.
iptables'у дал значит команду:
-A POSTROUTING -s 192.168.0.1 -d 192.168.2.1 -j SNAT --to-source 192.168.1.1
-A PREROUTING -s 192.168.0.1 -d 192.168.2.1 -j MARK --set-mark 0x1
дальше в iproute:
ip rule add from 192.168.1.1 table 1
ip rule add fwmark 0x1 table 1
ip route add default via 192.168.1.2 table 1
результат:
пакет выходит с первого интерфейса с адресом 192.168.1.1, но идёт через первый канал. (смотрел на tcpdump, он мне показывал, что пакет идёт с адресом 192.168.1.1)
вот такие пироги.
заранее всем спасибо.

Rustam Khamidov
22.05.2008, 10:09
Остаётся только третье решение - но оно не сработало.
iptables'у дал значит команду:
-A POSTROUTING -s 192.168.0.1 -d 192.168.2.1 -j SNAT --to-source 192.168.1.1
-A PREROUTING -s 192.168.0.1 -d 192.168.2.1 -j MARK --set-mark 0x1
дальше в iproute:
ip rule add from 192.168.1.1 table 1
ip rule add fwmark 0x1 table 1
ip route add default via 192.168.1.2 table 1
результат:
пакет выходит с первого интерфейса с адресом 192.168.1.1, но идёт через первый канал. (смотрел на tcpdump, он мне показывал, что пакет идёт с адресом 192.168.1.1)
вот такие пироги.

Вы получили ровно тот результат, который соответствует вашим правилам.
Вы метите все пакеты и ждете динамического распределения канала? (-;
А не пробовали все-таки открыть указанную мною ссылку и поинтересоваться, что за -m nth и зачем его используют.
Как в первый раз распылятся не буду. Могу только сказать, что проверял - работает.

еще один из вариантов перенаправить все запросы на 80 порт прозрачному сквиду из первых двух решений, тем более у Вас есть удачный опыт по ним.


p.s. Есть еще -m random

Rustam Khamidov
22.05.2008, 10:15
О, кстати, раз такая тяга к маршрутизации, попробуй bgp (зебру).

Elyor Xudayberdiev
22.05.2008, 10:19
ждете динамического распределения канала?
речи о динамической распределении канала и не было! я же написал -d 192.168.2.1, значит мне нужно, когда именно сервер спрашивает именно 192.168.2.1, запрос нужно пустить через второй канал. (а ip первого интерфейса, как Вы догадались наверно, 192.168.0.1. шлюз первого канала стоит по умолчанию, соответсвенно пакет с самого сервера уходит с адресом 192.168.0.1 (согласен, перемудрил с объяснением, надеюсь Вы меня поняли :)))

Rustam Khamidov
22.05.2008, 10:24
ждете динамического распределения канала?
речи о динамической распределении канала и не было! я же написал -d 192.168.2.1, значит мне нужно, когда именно сервер спрашивает именно 192.168.2.1, запрос нужно пустить через второй канал. (а ip первого интерфейса, как Вы догадались наверно, 192.168.0.1. шлюз первого канала стоит по умолчанию, соответсвенно пакет с самого сервера уходит с адресом 192.168.0.1 (согласен, перемудрил с объяснением, надеюсь Вы меня поняли :)))

дайте мне результат команды
ip addr ls
и
ip ro ls
только в чистом виде (до ваших экспериментов)

Rustam Khamidov
22.05.2008, 10:29
Без натов. Только маршрутизацией.

ip ru add to 192.168.2.1 table 100
ip ro add table 100 default via x.x.x.x src yy.yy.yy.yy

И всё

Elyor Xudayberdiev
22.05.2008, 10:32
Прошу прощения, я не могу дать результаты в чистом виде, потому что это делается на рабочем сервере. А если я уберу команды iprout'а, то у всех наших клиентов пропадёт связь, и меня повесят за одно место :).
есть ещё какие-нибудь решения?
p.s. надеюсь на Ваше понимание

Efim Kushnir
22.05.2008, 11:53
Прошу прощения, я не могу дать результаты в чистом виде
2 Rustam Khamidov, да ладно тебе капризничать, а то ты первый раз в слепую админишь :)

Makarov
22.05.2008, 22:22
ждете динамического распределения канала?
речи о динамической распределении канала и не было! я же написал -d 192.168.2.1, значит мне нужно, когда именно сервер спрашивает именно 192.168.2.1, запрос нужно пустить через второй канал. (а ip первого интерфейса, как Вы догадались наверно, 192.168.0.1. шлюз первого канала стоит по умолчанию, соответсвенно пакет с самого сервера уходит с адресом 192.168.0.1 (согласен, перемудрил с объяснением, надеюсь Вы меня поняли :)))

Читать здесь -> http://lartc.org/howto/ Конкретно по Вашему вопросу Then, your preference for default route: ip route add default via $P1 Next, you set up the routing rules. These actually choose what routing table to route with. You want to make sure that you route out a given interface if you already have the corresponding source address: ip rule add from $IP1 table T1 ip rule add from $IP2 table T2 PS. Сначала нужно поставить вопрос, а потом искать на него ответ. Пока Вы не определились с вопросом ответа Вы, скорее всего, не найдете ______________________ не могу толком ответить - сообщение ломается __________________