1 Отредактировано Agressor (12.11.2007 15:26:21)

Тема: 2 канала в Интернет

Сделано мной лично и опробовано неоднократно. Замечания приветствуются. Только если это исправления в самих скриптах - пишите в личку, я буду править основной пост. Дабы не раздувалось smile Ранее публиковал этот материал на wiki.opennet.ru

===== Условия: =====
Есть два канала к разным провайдерам (ADSL) с динамическим выделением адресов. Есть локальная офисная сеть. Есть шлюз под Linux.
===== Задача: =====
Необходимо обеспечить бесперебойный выход в интернет локалки с распределением нагрузки на оба канала и специфической маршрутизацией к сетям провайдеров. Применительно к Днепродзержинску - использовались каналы Укртелеком и Мегалан.
===== Аппаратное обеспечение: =====
Шлюз локальной сети в виде простенького старенького компьютера с установленным Linux с установленными пакетами iptables, rp-pppoe, iproute2 и тремя сетевыми картами - eth0 - локальная сеть, eth1 и eth2 соответственно к провайдерам (в ADSL модемы или кабельную сеть с организацией связи по протоколу ppp-oe).
===== Решение: =====
Тестировалось на ASPLinux 11.2, но вполне применимо с небольшими изменениями и к другим дистрибутивам.
Модемы переводим в режим bridge - т.е. ppp-oe сессии у нас будет поднимать наш шлюз. Да и ADSL модем в таком режиме работает намного устойчивей.
Считаем что интерфейс eth0 в локальную сеть уже был настроен, и ему присвоен адрес из подсетки 172.16.0.0/24 - к примеру 172.16.0.254. Компы локальной сети тогда будут иметь адреса 172.16.0.1 по 172.16.0.253. Это ВАЖНО применительно к Мегалану, так как Вы все знаете какие адреса раздает пользователям Мегалан. У нас ведь нет желания ходить к другу на комп через Европу, так ведь?? smile Создаем интерфейсы ppp при помощи утилиты adsl-setup, следуя указаниям на экране.
Интерфейсы eth1 и eth2 настраивать нет необходимости - главное проверить что они присутствуют в выводе команды lspci:

# lspci|grep Ethernet
00:09.0 Ethernet controller: Realtek Semiconductor Co., Ltd. RTL-8139/8139C/8139C+ (rev 10)
00:0a.0 Ethernet controller: Intel Corporation 82557/8/9 [Ethernet Pro 100] (rev 08)
00:0c.0 Ethernet controller: Intel Corporation 82557/8/9 [Ethernet Pro 100] (rev 08)

И для них загружены соответствующие модули ядра:

# lsmod|grep mii
mii                     5569  3 8139cp,8139too,e100

После создания интерфейсов ppp мы наблюдаем такую картину:

# ls /etc/sysconfig/network-scripts|grep ifcfg
ifcfg-eth0
ifcfg-lo
ifcfg-ppp0
ifcfg-ppp1

Требуется отредактировать файлы конфигурации интерфейсов, созданные при помощи утилиты adsl-setup, приведя их к такому виду:

# cat /etc/sysconfig/network-scripts/ifcfg-ppp0
LCP_INTERVAL=20
FIREWALL=NONE
PEERDNS=yes
PROVIDER=DSLppp0
LCP_FAILURE=3
BROADCAST=""
ETH=eth2      # У вас может отличатся
CLAMPMSS=1412
DEMAND=no
USERCTL=no
USER=username1prov1   # Изменить на реальное имя (login)
CONNECT_TIMEOUT=0
CONNECT_POLL=6
BOOTPROTO=none
NAME=DSLppp0
TYPE=xDSL
DEVICE=ppp0
SYNCHRONOUS=no
MTU=1492
NETMASK=""
IPADDR=""
DEFROUTE=no    # Будем задавать позже
NETWORK=""
PING=.
PPPOE_TIMEOUT=30   # Уменьшить время до 30 сек
ONBOOT=yes
PIDFILE=/var/run/pppoe-ppp0.pid    # Необходимо разнести pid файл

и второй интерфейс:

# cat /etc/sysconfig/network-scripts/ifcfg-ppp1
LCP_INTERVAL=20
FIREWALL=NONE
PEERDNS=yes
PROVIDER=DSLppp1
LCP_FAILURE=3
BROADCAST=""
ETH=eth1      # У вас может отличатся
CLAMPMSS=1412
DEMAND=no
USERCTL=no
USER=username2prov2    # Изменить на реальное имя (login)
CONNECT_TIMEOUT=0
CONNECT_POLL=6
BOOTPROTO=none
NAME=DSLppp1
TYPE=xDSL
DEVICE=ppp1
SYNCHRONOUS=no
MTU=1492
NETMASK=""
IPADDR=""
DEFROUTE=no         # Будем задавать позже
NETWORK=""
PING=.
PPPOE_TIMEOUT=30    # Уменьшить время до 30 сек
ONBOOT=yes
PIDFILE=/var/run/pppoe-ppp1.pid    # Необходимо разнести pid файл

Для информации - логины и пароли для доступа находятся в файлах /etc/ppp/chap-secrets или /etc/ppp/pap-secrets (зависит от типа авторизации у провайдера).
Формат этих файлов следующий:

# Secrets for authentication using CHAP (or PAP)
# client            server        secret       IP addresses
"username1prov1"       *       "passwd1prov1"    *          # Провайдер1
"username2prov2"       *       "passwd2prov2"    *          # Провайдер2

Проверим что ppp-oe соединение устанавливается - ifup ppp0 затем ifup ppp1 - посмотрим вывод ifconfig. Все в порядке? IP от провайдеров получены?
Опускаем интерфейсы - ifdown ppp0 затем ifdown ppp1. Идем дальше.
Для наведения порядка и присваивания каждому ppp-oe интерфейсу фиксированного имени необходимо изменить файл /etc/ppp/ip-up, приведя его к виду

#!/bin/bash
# This file should not be modified -- make local changes to
# /etc/ppp/ip-up.local instead
PATH=/sbin:/usr/sbin:/bin:/usr/bin
export PATH

LOGDEVICE=$6
REALDEVICE=$1

# Фиксируем имена ppp-oe (DSL) интерфейсов добавляя префикс dsl
NEWNAME="dsl${LOGDEVICE}"
    [ -z "${LOGDEVICE}" ] && NEWNAME="$1"
if [ -x /sbin/ip ]; then
    /sbin/ip link set $1 down
    /sbin/ip link set $1 name ${NEWNAME}
    /sbin/ip link set ${NEWNAME} up
fi
sleep 3
########### Зафиксировали

[ -f /etc/sysconfig/network-scripts/ifcfg-${LOGDEVICE} ] && /etc/sysconfig/network-scripts/ifup-post ifcfg-${LOGDEVICE}

/etc/ppp/ip-up.ipv6to4 ${LOGDEVICE}
[ -x /etc/ppp/ip-up.local ] && /etc/ppp/ip-up.local "$@"
exit 0

После этого наши ppp интерфейсы в выводе команды ifconfig будут иметь имена dslppp0 и dslppp1 соответственно.

Далее необходимо изменить файл /etc/sysconfig/network-scripts/ifup-post, вставив в него в самом конце перед последней строчкой exit 0 следующее:

##### При поднятии любого ppp (DSL) интерфейса запускаем скрипт
sleep 3
if [ "${DEVICETYPE}" = "ppp" -o "${DEVICETYPE}" = "ippp" ]; then
/etc/sysconfig/route/balance
fi
#####

Определимся для себя, где будем хранить скрипт отслеживающий состояние интерфейсов и в соответствии с ним задающий маршрутизацию.
К примеру создаем каталог mkdir -p /etc/sysconfig/route. Кроме скрипта в нем будет находится еще несколько служебных файлов.
Далее необходимо изменить файл /etc/sysconfig/network-scripts/ifup-post, вставив в него в самом конце перед последней строчкой exit 0 следующее:

##### При падении любого ppp (DSL) интерфейса запускаем скрипт
if [ "${DEVICETYPE}" = "ppp" -o "${DEVICETYPE}" = "ippp" ]; then
/etc/sysconfig/route/balance
fi
#####

Добавляем таблицы в файл /etc/iproute2/rt_tables - получается примерно такое:

# reserved values
#
#255    local
#254    main
#253    default
#0      unspec
#
# local
#
#1      inr.ruhep
# Ниже наши два провайдера
1       alice
2       utel

Создадим скрипт, в котором будем указывать статические маршруты к DNS серверам и сетям провайдеров (ведь так удобней? и быстрее...) и к некоторым другим.
Если не указать эти маршруты, то может возникнуть затруднение с резолвингом имен вашим кеширующим DNS сервером и соответственно долгий отклик удаленных хостов.
Выполним команду touch /etc/sysconfig/route/providers.lan && chmod 744 /etc/sysconfig/route/providers.lan Пропишем в созданый файл примерно такое содержание:

#!/bin/bash
GW1=`/sbin/ifconfig dslppp0|grep "inet addr"|awk '{print $3}'|cut -d ':' -f 2`  # Alice
GW2=`/sbin/ifconfig dslppp1|grep "inet addr"|awk '{print $3}'|cut -d ':' -f 2`  # Utel

# For Utel - сеть одного провайдера,
# В ресурсы Укртелекома ходим только через его соединение!
route $1 -net 82.207.0.0/16 gw $GW2
route $1 -net 91.124.0.0/16 gw $GW2
route $1 -net 195.5.0.0/16 gw $GW2
route $1 -net 92.113.0.0/16 gw $GW2

# For Alice - сеть другого провайдера
# В ресурсы Мегалана ходим только через его соединение!
route $1 -net 193.110.20.0/24 gw $GW1
route $1 -net 192.168.0.0/16 gw $GW1
route $1 -net 193.110.23.0/24 gw $GW1

# For ICQ - нестабильно работает через nexthop, приходится задавать маршрут жестко :(
# Изменить под себя возможно потребуется только $GW2
route $1 -net 64.12.0.0/16 gw $GW2
route $1 -net 205.188.0.0/16 gw $GW2
route $1 -net 152.163.0.0/24 gw $GW2

# For мои любимые хосты или сети с играми, и т.д - сколько угодно...
route $1 -host 213.28.61.21 gw $GW1
route $1 -host 92.73.6.11 gw $GW2
route $1 -net 13.33.15.0/24 gw $GW1

Создаем сам скрипт touch /etc/sysconfig/route/balance && chmod 744 /etc/sysconfig/route/balance со следующим содержанием:
(в данном примере скрипт ориентирован на провайдера у которого есть доступ во всю сеть кроме UA-IX (Укртелеком), и провайдера с полным доступом (Мегалан), при этом каналы и ценовая политика их одинакова. Отредактировать его так, чтобы к примеру разделять доступ в Российские сети через одного провайдера, а на мир делить поровну - труда не представляет.)

#!/bin/bash
sleep 5
# Задаем интерфейсы и локальную сеть
IFIN=eth0       # Local Network
IFOUT1=dslppp0  # Allice - есть доступ в сеть UA-IX
IFOUT2=dslppp1  # Utel - доступа в сеть UA-IX нет
LOCALNET=172.16.0.0/24 # Local network

# Определяем IP и GATEWAY наших интерфейсов
IPIN=`ifconfig ${IFIN}|grep "inet addr"|awk '{print $2}'|cut -d ':' -f 2`
IPOUT1=`ifconfig ${IFOUT1}|grep "inet addr"|awk '{print $2}'|cut -d ':' -f 2`
GW1=`ifconfig ${IFOUT1}|grep "inet addr"|awk '{print $3}'|cut -d ':' -f 2`
IPOUT2=`ifconfig ${IFOUT2}|grep "inet addr"|awk '{print $2}'|cut -d ':' -f 2`
GW2=`ifconfig ${IFOUT2}|grep "inet addr"|awk '{print $3}'|cut -d ':' -f 2`

# Задаем таблицы маршрутизации
TABLE1=alice
TABLE2=utel

# Принимаем за правило что интерфейс в локалку (eth0) всегда UP, поэтому проверяем наличие только ppp интерфейсов.
# Если поднят только какой-то один ppp - задаем его шлюз по умолчанию
if [[ `ip link show ${IFOUT1}|grep "UP"|awk '{print $3}'|cut -d ',' -f 4`  !=  `ip link show ${IFOUT2}|grep "UP"|awk '{print $3}'|cut -d ',' -f 4` ]];
then
        if [ `ip link show ${IFOUT1}|grep "UP"|awk '{print $3}'|cut -d ',' -f 4` ] && [ "UP" ];then
# Если не подняты оба интерфейса, а поднят только dslppp0 то удаляем принудительную маршрутизацию в dslppp1
# /sbin/route del default gw ${GW2}
bash /etc/sysconfig/route/ua-ix.lan del
/etc/sysconfig/route/providers.lan del
# и делаем маршрут по умолчанию через живой dslppp0 интерфейс
/sbin/route add default gw ${GW1} &> /dev/null
    else
        if [ `ip link show ${IFOUT2}|grep "UP"|awk '{print $3}'|cut -d ',' -f 4` ] && [ "UP" ];then
# Если не поднят dslppp0 а поднят dslppp1 интерфейс то делаем маршрут по умолчанию через живой dslppp1 интерфейс
#/sbin/route del default gw ${GW1}
bash /etc/sysconfig/route/ua-ix.lan del
/etc/sysconfig/route/providers.lan del
/sbin/route add default gw ${GW2} &> /dev/null
        fi
    fi
fi

# Проверяем если подняты оба ppp интерфейса - делаем маршрутизацию через них с балансировкой нагрузки
if [[ `ip link show ${IFOUT1}|grep "UP"|awk '{print $3}'|cut -d ',' -f 4`  !=  `ip link show ${IFOUT2}|grep "UP"|awk '{print $3}'|cut -d ',' -f 4` ]];
then :
else

# Удаляем статические таблицы маршрутизации по умолчанию
/sbin/route del default gw ${GW1} &> /dev/null
/sbin/route del default gw ${GW2} &> /dev/null
bash /etc/sysconfig/route/ua-ix.lan del
/etc/sysconfig/route/providers.lan del

# Описываем через какие таблицы кто ходит
/sbin/ip route add ${LOCALNET} via ${IPIN} table ${TABLE1} &> /dev/null
/sbin/ip route add ${LOCALNET} via ${IPIN} table ${TABLE2} &> /dev/null
/sbin/ip route add 127.0.0.0/8 dev lo table ${TABLE1} &> /dev/null
/sbin/ip route add 127.0.0.0/8 dev lo table ${TABLE2} &> /dev/null
/sbin/ip route add 0/0 via ${GW1} table ${TABLE1} &> /dev/null
/sbin/ip route add 0/0 via ${GW2} table ${TABLE2} &> /dev/null

# Задание правил маршрутизации по IP-адресу источника
/sbin/ip rule add from ${IPOUT1} lookup ${TABLE1}
/sbin/ip rule add from ${IPOUT2} lookup ${TABLE2}

# Распределяем нагрузку на два канала
/sbin/ip route add default equalize nexthop via ${GW1} dev ${IFOUT1} weight 1 nexthop via ${GW2} dev ${IFOUT2} weight 1 &> /dev/null

# Получаем и обрабатываем список Украинских сетей (UA-IX) - на выбор два источника
# Эту часть можно вынести в отдельный файл и запускать по cron - кому как удобнее
#/usr/bin/wget -q --no-cache -O /etc/sysconfig/route/uaix.lan http://noc.mirotel.net/uaix.nets.txt - С некоторых пор эта ссылка не работает
/usr/bin/wget -q --no-cache -O /etc/sysconfig/route/uaix.lan http://www.colocall.net/ua/prefixes.txt
# Гы-гы... следующие две строки коряво сделаны... может кто подправит?
/usr/bin/perl -pi.bak -e "s/^(.*)$/route add -net \$1 gw $GW1/" /etc/sysconfig/route/uaix.lan
/usr/bin/replace 'add' '$1' < /etc/sysconfig/route/uaix.lan > /etc/sysconfig/route/ua-ix.lan
rm -f /etc/sysconfig/route/uaix.*

# Задаем маршрутизацию в UA-IX через нужный интерфейс - в нашем случае dslppp0
bash /etc/sysconfig/route/ua-ix.lan add

# Задаем маршрутизацию к DNS серверам и сетям провайдеров через их интерфейсы
/etc/sysconfig/route/providers.lan add

fi
exit 0

Пока все.
Результат работы
http://vi.net.ua/torrent3.png

Слушаю это, работаю в Gentoo.

2

Re: 2 канала в Интернет

Спасибо! Когда-то интересовался этим вопросом, но как-то само собой отпало. Обязательно на заметку.

http://lug.dp.ua/userbar.png