URL: https://www.opennet.me/cgi-bin/openforum/vsluhboard.cgi
Форум: vsluhforumID1
Нить номер: 89023
[ Назад ]

Исходное сообщение
"Покритикуйте конфигурацию linux-роутера (iproute2, iptables)"

Отправлено georglk , 30-Май-10 16:01 
Требуется подключить локальную сеть к двум провайдерам.
В данный момент я сделал тестовый роутер на Ubunte, вот его конфиг
Что можно сказать по поводу такой реализации?
/etc/network/interfaces:
# The loopback network interface
auto lo
iface lo inet loopback

# The primary network interface
auto eth1
iface eth1 inet static
    address 192.168.1.1
    netmask 255.255.255.0
    network 192.168.1.0
    broadcast 192.168.1.255

# WAN1 network interface aliase
auto eth0
iface eth0 inet static
    address aaa.aaa.aaa.100
    netmask 255.255.255.128
    network aaa.aaa.aaa.0
    broadcast aaa.aaa.aaa.127
    gateway aaa.aaa.aaa.1

# WAN1 network interface aliase
auto eth0:1
iface eth0:1 inet static
address aaa.aaa.aaa.101
netmask 255.255.255.128
network aaa.aaa.aaa.0

# WAN2 network interface aliase
auto eth2
iface eth2 inet static
    address bbb.bbb.bbb.100
    netmask 255.255.255.128
    network bbb.bbb.bbb.0
    broadcast bbb.bbb.bbb.127
    gateway bbb.bbb.bbb.1

# WAN2 network interface aliase
auto eth2:1
iface eth2:1 inet static
address bbb.bbb.bbb.101
netmask 255.255.255.128
network bbb.bbb.bbb.0
-----------------------------------------------

/etc/iproute2/rt_tables:
255     local
254     main
253     default
0       unspec

201      ISP1
202      ISP2
-----------------------------------------------

/etc/rc.firewall/rc.customroute:
varnetwork=/etc/rc.firewall/varnetwork-fixed
. $varnetwork
## Выключаем Reverse Path Filtering для WAN-интерфейсов
if [ -n "$WANIF1" ]; then
  echo 0 > /proc/sys/net/ipv4/conf/$WANIF1/rp_filter
  echo "Disable 'Reverse Path Filtering' for interface WANIF1 ($WANIF1) - [OK]"
else
  echo "Disable 'Reverse Path Filtering' for interface WANIF1 ($WANIF1) - [ERR]"
  echo "WANIF1 ($WANIF1) is not defined"
fi
if [ -n "$WANIF2" ]; then
  echo 0 > /proc/sys/net/ipv4/conf/$WANIF2/rp_filter
  echo "Disable 'Reverse Path Filtering' for interface WANIF2 ($WANIF2) - [OK]"
else
  echo "Disable 'Reverse Path Filtering' for interface WANIF2 ($WANIF2) - [ERR]"
  echo "WANIF2 ($WANIF2) is not defined"
fi
## Добавление таблиц и маршрутов по умолчанию
$ip -statistics rule delete table $ROUTETABLE1                                  # Удаляем наши таблицы, если они присутсвуют в текущей конфигурации (вдруг мы просто перезапускаем скрипт?)
$ip -statistics rule delete table $ROUTETABLE2                                  # Аналогично для второй.
$ip -statistics rule delete table $ROUTETABLE1                                  # И делаем это два раза, так как у нас два правила на каждую таблицу.
$ip -statistics rule delete table $ROUTETABLE2                                  # Аналогично для второй.
#
$ip -statistics route flush table $ROUTETABLE1                                  # Обнуляем первую таблицу маршрутов
$ip -statistics rule add from $WANIP1 table $ROUTETABLE1                        # Все пакеты от ip-адреса первого провайдера маршрутизировать по таблице ROUTETABLE1
$ip -statistics rule add fwmark $FWMARK1 table $ROUTETABLE1                     # Все пакеты, которые имеют метку FWMARK1 маршрутизировать по таблице ROUTETABLE1
$ip -statistics route add default via $WANGW1 dev $WANIF1 table $ROUTETABLE1    #
$ip -statistics route flush cache                                               # Очищаем кэш маршрутизации
#
$ip -statistics route flush table $ROUTETABLE2                                  # Обнуляем вторую таблицу маршрутов
$ip -statistics rule add from $WANIP2 table $ROUTETABLE2                        # Все пакеты от ip-адреса второго провайдера маршрутизировать по таблице ROUTETABLE2
$ip -statistics rule add fwmark $FWMARK2 table $ROUTETABLE2                     # Все пакеты, которые имеют метку FWMARK2 маршрутизировать по таблице ROUTETABLE2
$ip -statistics route add default via $WANGW2 dev $WANIF2 table $ROUTETABLE2    #
$ip -statistics route flush cache                                               # Очищаем кэш маршрутизации

#$ip -statistics route add default via $WANGW1                                  # Назначаем шлюз по умолчанию (в данный момент указывается в \etc\network\interfaces)

exit 0
-----------------------------------------------

/etc/rc.firewall/rc.firewall.regular:
varnetwork=/etc/rc.firewall/varnetwork-fixed
. $varnetwork
case "$1" in
  "1" )
  FWMARK2=$FWMARK1
  ;;
  "2" )
  FWMARK1=$FWMARK2
  ;;
  *   )

  ;;
esac
## Политика по умолчению (DENY). Explicitly accept desired INCOMING and OUTGOING connections
# Удаление всех существующих правил (Remove all existing rules belonging to this filter)
# Если не указана таблица ключом -t (--table), то очистка цепочек производится только в таблице filter
# (из Iptables Tutorial 1.1.19)
$iptables -v --flush -t filter
$iptables -v --flush -t nat
$iptables -v --flush -t mangle
$iptables -v --flush -t raw
# Удаление любых существующих пользовательских цепочек (Remove any existing user-defined chains)
$iptables -v --delete-chain -t filter
$iptables -v --delete-chain -t nat
$iptables -v --delete-chain -t mangle
$iptables -v --delete-chain -t raw
# Установка политик по умолчению (DROP) (Set the default policy of the filter to deny)
$iptables -v --policy INPUT    DROP
$iptables -v --policy OUTPUT   DROP
$iptables -v --policy FORWARD  DROP

echo 1 > /proc/sys/net/ipv4/ip_forward

# Загрузка модулей
#$depmod -v -a
$modprobe -v ip_conntrack_ftp
$modprobe -v ip_nat_ftp

# Неограниченный трафик на обратной петле (Unlimited traffic on the loopback interface)
$iptables -v -t filter -A INPUT  -i $LOOPBACKIF -p all -s $LOOPBACKNET -d $LOOPBACKNET -j ACCEPT
$iptables -v -t filter -A OUTPUT -o $LOOPBACKIF -p all -s $LOOPBACKNET -d $LOOPBACKNET -j ACCEPT

# Проброс WEB1EXTISP1 -> WEB1INT
#         WEB1EXTISP2 -> WEB1INT
$iptables -v -t nat -A PREROUTING  -i $WANIF1 -p tcp -d $WEB1EXTISP1 --dport 80 -j DNAT --to-destination $WEB1INT:80
$iptables -v -t filter -A FORWARD  -i $WANIF1 -o $LANIF1 -p tcp -d $WEB1INT --dport 80 -j ACCEPT
$iptables -v -t filter -A FORWARD  -i $LANIF1 -o $WANIF1 -p tcp -s $WEB1INT --sport 80 -j ACCEPT
$iptables -v -t nat -A POSTROUTING -o $WANIF1 -p tcp -s $WEB1INT -j SNAT --to-source $WEB1EXTISP1
$iptables -v -t nat -A PREROUTING  -i $WANIF2 -p tcp -d $WEB1EXTISP2 --dport 80 -j DNAT --to-destination $WEB1INT:80
$iptables -v -t filter -A FORWARD  -i $WANIF2 -o $LANIF1 -p tcp -d $WEB1INT --dport 80 -j ACCEPT
$iptables -v -t filter -A FORWARD  -i $LANIF1 -o $WANIF2 -p tcp -s $WEB1INT --sport 80 -j ACCEPT
$iptables -v -t nat -A POSTROUTING -o $WANIF2 -p tcp -s $WEB1INT -j SNAT --to-source $WEB1EXTISP2

### Маркировки по-умолчанию ------------------------------------------------------------------------------------------- #
### На самом деле можно не маркировать одно из направлений, приняв его за напрвление по умолчанию
### Для этого направления в цепочке PREROUTING интерфейса LANIF1 отменяем маркировку и
### и указывает самым последним правило в POSTROUTING без указания -m mark --mark
### например, $iptables -v -t nat -A POSTROUTING -o $WANIFx -s $LANNET1 -j SNAT --to-source $WANIPx
### где WANIFx и WANIPx - интерфейс и ip-адрес через которые будет NAT-ится по умолчанию
$iptables -v -t mangle -A PREROUTING -p tcp -i $LANIF1 -s $TRUSTHOST1 -m mac --mac-source $TRUSTMAC6 -d ! $LANNET1 -m multiport --dport 21,5190 -j MARK --set-mark $FWMARK1
$iptables -v -t mangle -A PREROUTING -p tcp -i $LANIF1 -s $TRUSTHOST1 -m mac --mac-source $TRUSTMAC6 -d ! $LANNET1 -m multiport --dport 80,443,25,465,993,8010,8100 -j MARK --set-mark $FWMARK2

# Разрешение прохождения всего трафика (FORWARD) от $TRUSTHOST1
$iptables -v -t filter -A FORWARD -i $LANIF1 -o $WANIF1 -p all -s $TRUSTHOST1 -m mac --mac-source $TRUSTMAC6 -j ACCEPT
$iptables -v -t filter -A FORWARD -i $WANIF1 -o $LANIF1 -p all -d $TRUSTHOST1 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
$iptables -v -t filter -A FORWARD -i $LANIF1 -o $WANIF2 -p all -s $TRUSTHOST1 -m mac --mac-source $TRUSTMAC6 -j ACCEPT
$iptables -v -t filter -A FORWARD -i $WANIF2 -o $LANIF1 -p all -d $TRUSTHOST1 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

# POSTROUTING
# NAT для пакетов имеющих метку FWMARK1
$iptables -v -t nat -A POSTROUTING -o $WANIF1 -s $LANNET1 -m mark --mark $FWMARK1 -j SNAT --to-source $WANIP1
# NAT для пакетов имеющих метку FWMARK2
$iptables -v -t nat -A POSTROUTING -o $WANIF2 -s $LANNET1 -m mark --mark $FWMARK2 -j SNAT --to-source $WANIP2
-----------------------------------------------
где WEB1INT веб-сервер внутри локальной сети (WEB1EXTISP1 и WEB1EXTISP2 его "внешнии" ip-адреса от разных провайдеров)
TRUSTHOST1 - клиенская рабочая станция, с разделеным между провайдерами трафиком

В файл /etc/rc.firewall/varnetwork-fixed вынесены все переменные
## Определение переменных. (При необходимости отредактируйте с учетом конфигурации вашей системы)
# Настройки для LAN1 интерфейса
LANIP1="192.168.1.1"                        # IP адрес внешнего интерфейса (LAN1)
LANIF1="eth1"                               # Внешний сетевой интерфейс (LAN1) подключение к интернету
LANNET1="192.168.1.0/24"                    # Диапазон реальных IP адресов (LAN1)
# Настройки для WAN1 интерфейса
WANIP1="aaa.aaa.aaa.100"                    # IP адрес внешнего интерфейса (WAN1)
WANIF1="eth0"                               # Внешний сетевой интерфейс (WAN1) подключение к интернету
WANNET1="aaa.aaa.aaa.0/25"                  # Диапазон реальных IP адресов (WAN1)
WANGW1="aaa.aaa.aaa.1"                      # Шлюз провайдера (WAN1)
# Настройки для WAN2 интерфейса
WANIP2="bbb.bbb.bbb.100"                    # IP адрес внешнего интерфейса (WAN2)
WANIF2="eth2"                               # Внешний сетевой интерфейс (WAN2) подключение к интернету
WANNET2="bbb.bbb.bbb.0/25"                  # Диапазон реальных IP адресов (WAN2)
WANGW2="bbb.bbb.bbb.1"                      # Шлюз провайдера (WAN2)
# Настройки для LOOPBACK интерфейса
LOOPBACKIP="127.0.0.1"                      # IP адрес обратной петли
LOOPBACKIF="lo"                             # Интерфейс обратной петли
LOOPBACKNET="127.0.0.0/8"                   # Зарезервированый диапазон адресов обратной петли
# Имена таблиц маршрутизации из файла /etc/iproute2/rt_tables
ROUTETABLE1="ISP1"
ROUTETABLE2="ISP2"
# Метки пакетов из файла /etc/rc.firewall/rc.firewall.regular
FWMARK1=10
FWMARK2=11
# Хосты внутри сети
WEB1EXTISP1="aaa.aaa.aaa.101"                # Внешний IP адрес из сети WANNET1
WEB1EXTISP2="bbb.bbb.bbb.101"                # Внешний IP адрес из сети WANNET2
WEB1INT="192.168.1.10"                       # Внутренний IP адрес из сети LANNET1
## Доверительные хосты и сети
TRUSTNET6="192.168.1.20/32"                  # Клиентский хост
TRUSTMAC6="xx:xx:xx:xx:xx:xx"                # Клиентский хост MAC
-----------------------------------------------
При загрузки из файла /etc/rc.local запускается rc.customroute и rc.firewall.regular

Думаю как организовать переключение в случаи недоступности одного из каналов
Пока есть вот такой скрипт, но какой-то он косолапый...
/etc/rc.firewall/testchannels:
TESTHOST1="всегда_работающий_отечественный_IP"
TESTHOST2="всегда_работающий_зарубежный_IP"
CPING="4"
RCFIREWALL=/etc/rc.firewall/rc.firewall.regular

varnetwork=/etc/rc.firewall/varnetwork-fixed
. $varnetwork

# Процедура проверки
ICMPTest () {
  ping -I $WANIF1 -q -c $CPING $TESTHOST1 > /dev/null
  WANIF1TESTHOST1="$?"
  ping -I $WANIF1 -q -c $CPING $TESTHOST2 > /dev/null
  WANIF1TESTHOST2="$?"
  ping -I $WANIF2 -q -c $CPING $TESTHOST1 > /dev/null
  WANIF2TESTHOST1="$?"
  ping -I $WANIF2 -q -c $CPING $TESTHOST2 > /dev/null
  WANIF2TESTHOST2="$?"
}
## Тест ICMP-обмена с тестовыми хостами
ICMPTest

## Действия по результатам тестов ICMP-обмена с тестовыми хостами
# 0000 - 0  # 0100 - 2  # 1000 - 2  # 1100 - 2
# 0001 - 1  # 0101 - 6  # 1001 - 6  # 1101 - 4
# 0010 - 1  # 0110 - 6  # 1010 - 6  # 1110 - 4
# 0011 - 1  # 0111 - 5  # 1011 - 5  # 1111 - 3
##
# 0 - доступно всё                        -> переключаем на штатный режим     0000
# 1 - полностью доступен первый канал     -> переключаем на первый            0001, 0010, 0011
# 2 - полностью доступен второй канал     -> переключаем на второй            0100, 1000, 1100
# 3 - полностью недоступны все каналы     -> бездействие                      1111
# 4 - полностью недоступен первый канал   -> переключаем на второй            1101, 1110
# 5 - полностью недоступен второй канал   -> переключаем на первый            0111, 1011
# 6 - частично доступны все каналы        -> бездействие                      0101, 0110, 1001, 1010
Handler () {
  case "$1" in
    "0" )
    if [ -r $STATUSFILE ]; then
      rm -f $STATUSFILE
      if [ -x $MAIL ]; then
        # Отправляем письмо
      fi
      # Запускаем RCFIREWALL "$1" ("0")
      sh $RCFIREWALL
    fi
    ;;
    "1" | "5" )
    if [ -r $STATUSFILE ]; then
      read CURRENTSTATUS < $STATUSFILE
      if $STATUSFILE -ne "$1"; then
        echo "$1" > $STATUSFILE
        if [ -x $MAIL ]; then
          # Отправляем письмо
        fi
        # Запускаем RCFIREWALL "1"
        sh $RCFIREWALL "1"
      if
    else
      echo "$1" > $STATUSFILE
      if [ -x $MAIL ]; then
        # Отправляем письмо
      fi
      # Запускаем RCFIREWALL "1"
      sh $RCFIREWALL "1"
    fi
    ;;
    "2" | "4" )
    if [ -r $STATUSFILE ]; then
      read CURRENTSTATUS < $STATUSFILE
      if $STATUSFILE -ne "$1"; then
        echo "$1" > $STATUSFILE
        if [ -x $MAIL ]; then
          # Отправляем письмо
        fi
        # Запускаем RCFIREWALL "2"
        sh $RCFIREWALL "2"
      if
    else
      echo "$1" > $STATUSFILE
      if [ -x $MAIL ]; then
        # Отправляем письмо
      fi
      # Запускаем RCFIREWALL "2"
      sh $RCFIREWALL "2"
    fi
    ;;
    "3" )
    if [ -r $STATUSFILE ]; then
      read CURRENTSTATUS < $STATUSFILE
      if $STATUSFILE -ne "$1"; then
        echo "$1" > $STATUSFILE
        if [ -x $MAIL ]; then
          # Отправляем письмо
        fi
    else
      echo "$1" > $STATUSFILE
      if [ -x $MAIL ]; then
        # Отправляем письмо
      fi
    fi
    ;;
    *   )
    if [ -r $STATUSFILE ]; then
      read CURRENTSTATUS < $STATUSFILE
      if $STATUSFILE -ne "$1"; then
        echo "$1" > $STATUSFILE
        if [ -x $MAIL ]; then
          # Отправляем письмо
        fi
    else
      echo "$1" > $STATUSFILE
      if [ -x $MAIL ]; then
        # Отправляем письмо
      fi
    fi
    ;;
  esac
}

# 0 - доступно всё                        -> переключаем на штатный режим     0000
if [ $WANIF1TESTHOST1 -eq 0 -a $WANIF1TESTHOST2 -eq 0 -a $WANIF2TESTHOST1 -eq 0 -a $WANIF2TESTHOST2 -eq 0 ]; then
  Handler "0"
  exit 0
fi
# 1 - полностью доступен первый канал     -> переключаем на первый            0001, 0010, 0011
if [ $WANIF1TESTHOST1 -eq 0 -a $WANIF1TESTHOST2 -eq 0 -a $WANIF2TESTHOST1 -eq 0 -a $WANIF2TESTHOST2 -eq 1 ]; then
  Handler "1"
  exit 0
fi
if [ $WANIF1TESTHOST1 -eq 0 -a $WANIF1TESTHOST2 -eq 0 -a $WANIF2TESTHOST1 -eq 1 -a $WANIF2TESTHOST2 -eq 0 ]; then
  Handler "1"
  exit 0
fi
if [ $WANIF1TESTHOST1 -eq 0 -a $WANIF1TESTHOST2 -eq 0 -a $WANIF2TESTHOST1 -eq 1 -a $WANIF2TESTHOST2 -eq 1 ]; then
  Handler "1"
  exit 0
fi
# 2 - полностью доступен второй канал     -> переключаем на второй            0100, 1000, 1100
if [ $WANIF1TESTHOST1 -eq 0 -a $WANIF1TESTHOST2 -eq 1 -a $WANIF2TESTHOST1 -eq 0 -a $WANIF2TESTHOST2 -eq 0 ]; then
  Handler "2"
  exit 0
fi
if [ $WANIF1TESTHOST1 -eq 1 -a $WANIF1TESTHOST2 -eq 0 -a $WANIF2TESTHOST1 -eq 0 -a $WANIF2TESTHOST2 -eq 0 ]; then
  Handler "2"
  exit 0
fi
if [ $WANIF1TESTHOST1 -eq 1 -a $WANIF1TESTHOST2 -eq 1 -a $WANIF2TESTHOST1 -eq 0 -a $WANIF2TESTHOST2 -eq 0 ]; then
  Handler "2"
  exit 0
fi
# 3 - полностью недоступны все каналы     -> бездействие                      1111
if [ $WANIF1TESTHOST1 -eq 1 -a $WANIF1TESTHOST2 -eq 1 -a $WANIF2TESTHOST1 -eq 1 -a $WANIF2TESTHOST2 -eq 1 ]; then
  Handler "3"
  exit 0
fi
# 4 - полностью недоступен первый канал   -> переключаем на второй            1101, 1110
if [ $WANIF1TESTHOST1 -eq 1 -a $WANIF1TESTHOST2 -eq 1 -a $WANIF2TESTHOST1 -eq 0 -a $WANIF2TESTHOST2 -eq 1 ]; then
  Handler "4"
  exit 0
fi
if [ $WANIF1TESTHOST1 -eq 1 -a $WANIF1TESTHOST2 -eq 1 -a $WANIF2TESTHOST1 -eq 1 -a $WANIF2TESTHOST2 -eq 0 ]; then
  Handler "4"
  exit 0
fi
# 5 - полностью недоступен второй канал   -> переключаем на первый            0111, 1011
if [ $WANIF1TESTHOST1 -eq 0 -a $WANIF1TESTHOST2 -eq 1 -a $WANIF2TESTHOST1 -eq 1 -a $WANIF2TESTHOST2 -eq 1 ]; then
  Handler "5"
  exit 0
fi
if [ $WANIF1TESTHOST1 -eq 1 -a $WANIF1TESTHOST2 -eq 0 -a $WANIF2TESTHOST1 -eq 1 -a $WANIF2TESTHOST2 -eq 1 ]; then
  Handler "5"
  exit 0
fi
# 6 - частично доступны все каналы        -> бездействие                      0101, 0110, 1001, 1010
if [ $WANIF1TESTHOST1 -eq 0 -a $WANIF1TESTHOST2 -eq 1 -a $WANIF2TESTHOST1 -eq 0 -a $WANIF2TESTHOST2 -eq 1 ]; then
  Handler "6"
  exit 0
fi
if [ $WANIF1TESTHOST1 -eq 0 -a $WANIF1TESTHOST2 -eq 1 -a $WANIF2TESTHOST1 -eq 1 -a $WANIF2TESTHOST2 -eq 0 ]; then
  Handler "6"
  exit 0
fi
if [ $WANIF1TESTHOST1 -eq 1 -a $WANIF1TESTHOST2 -eq 0 -a $WANIF2TESTHOST1 -eq 0 -a $WANIF2TESTHOST2 -eq 1 ]; then
  Handler "6"
  exit 0
fi
if [ $WANIF1TESTHOST1 -eq 1 -a $WANIF1TESTHOST2 -eq 0 -a $WANIF2TESTHOST1 -eq 1 -a $WANIF2TESTHOST2 -eq 0 ]; then
  Handler "6"
  exit 0
fi
-----------------------------------------------
засовываем его в cron и запускает, например, каждые 5 минут
Подскажите, может есть более элегантный способ это реализовать?

Плюс к этому есть пара вопросов...
Как выбрать эти "всегда работающие ip"?
И какая утилита в linux позволяет отправлять письма через указанный внешний сервер. Дело в том, что ставить на роутер mta не хочется, а на сколько я помню mail, nail этого требуют. В данном же случаи была бы удобна утилита схожая с postie, которой можно указать через какой сервер отправлять сообщение


Содержание

Сообщения в этом обсуждении
"Покритикуйте конфигурацию linux-роутера (iproute2, iptables)"
Отправлено Дядя Федор , 30-Май-10 17:37 
emerge -s ssmtp
....
Homepage:      ftp://ftp.debian.org/debian/pool/main/s/ssmtp/
Description:   Extremely simple MTA to get mail off the system to a Mailhub
License:       GPL-2