Маршрут по умолчанию

Материал из Xgu.ru

Перейти к: навигация, поиск
stub.png
Данная страница находится в разработке.
Эта страница ещё не закончена. Информация, представленная здесь, может оказаться неполной или неверной.

Если вы считаете, что её стоило бы доработать как можно быстрее, пожалуйста, скажите об этом.

Автор: Игорь Чубин
Короткий URL: default_gateway


Содержание

[править] Маршрут по умолчанию в Linux

[править] Просмотр маршрута

Просмотреть таблицу маршрутизации в Linux можно множеством способов. Наиболее распространённые это: использовать программы netstat, route или ip.

 %$ netstat -rn
 Kernel IP routing table
 Destination     Gateway         Genmask         Flags   MSS Window  irtt Iface
 192.168.80.0    192.168.1.196   255.255.255.0   UG        0 0          0 eth0
 192.168.1.0     0.0.0.0         255.255.255.0   U         0 0          0 eth0
 0.0.0.0         192.168.1.198   0.0.0.0         UG        0 0          0 eth0
 %$ /sbin/route -n
 Kernel IP routing table
 Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
 192.168.80.0    192.168.1.196   255.255.255.0   UG    0      0        0 eth0
 192.168.1.0     0.0.0.0         255.255.255.0   U     0      0        0 eth0
 0.0.0.0         192.168.1.198   0.0.0.0         UG    0      0        0 eth0
 %$ ip r
 192.168.80.0/24 via 192.168.1.196 dev eth0 
 192.168.1.0/24 dev eth0  proto kernel  scope link  src 192.168.1.197 
 default via 192.168.1.198 dev eth0 


Во втором случае (/sbin/route) использовался полный путь, поскольку программа вызывалась от имени пользователя, у которого по умолчанию каталог /sbin/ не просматривается в поисках исполняемых программ (переменная PATH).

Ключ -n в программах netstat и route говорит о том, что не нужно выполнять обратное преобразование IP-адресов и показывать вместо них DNS-имена.

Если нужна только запись о маршруте по умолчанию, вывод можно отфильтровать:

 %# ip r | grep default

или

 %# ip r l s global
 default via 192.168.1.198 dev eth0 

или

 %# ip ro sh 0.0.0.0/0
 default via 192.168.1.198 dev eth0

и если нужен только IP-адрес:

 %# ip r | awk '/default/{print $3}'
 192.168.1.198

[править] Смена маршрута

[править] Маршрут по умолчанию в FreeBSD

 route add default 192.168.37.2

[править] Маршрут по умолчанию в старых версиях FreeBSD

 route add 0.0.0.0/0 192.168.37.2

[править] Просмотр маршрута

 netstat -rn

[править] Смена маршрута

Процесс установки маршрута по умолчанию может выполнятся двумя способами:
1. Удалением записи о существующем маршруте(фиктивном), а далее добавлением записи о новом:

 # route delete default
 # delete net default
 # route add default 192.168.137.2
 # add net default: gateway 192.168.137.2
 # defaultrouter="192.168.137.2"

2. Изменением маршрута:

 # route change default 192.168.137.2

[править] Установка маршрута по умолчанию при запуске системы

Debian-icon.png

В файле /etc/network/interfaces

Пример:

allow-hotplug eth0
iface eth0 inet static
        address 192.168.137.11
        netmask 255.255.255.0
        network 192.168.137.0
        broadcast 192.168.107.255
# Указывам шлюз по умолчанию для интерфейса eth0
        gateway 192.168.137.2

Ubuntu-icon.png

В файле /etc/network/interfaces

Gentoo-icon.png

В файле /etc/conf.d/net

Fedora-icon.png

В файле /etc/sysconfig/network

Suse-icon.png

В файле /etc/sysconfig/network/routes

Slackware-icon.png

В переменной GATEWAY файла /etc/rc.d/rc.inet1.conf вручную или с помощью программы netconfig [1]

Mandriva-icon.png

В файле /etc/sysconfig/network

ALTLinux-icon.png

В файле /etc/net/ifaces/NAME/iproute

[править] Автоматическая смена маршрута по умолчанию

[править] Задача

Есть два канала связи с Интернетом, через двух независимых провайдеров. Нужно сделать так, что бы как только Интернет становится недоступным через одно из соединений (не имеет значения из-за того что пропала связь с провайдером, или потому что проблемы у провайдера), автоматически менять маршрут по умолчанию и использовать другой канал.

[править] Решение

Использовать скрипт:

СКРИПТ
Имя скрипта: change_default_route
Путь: /usr/local/sbin/change_default_route
Назначение скрипта: Скрипт контролирует доступность удалённой точки ${REMOTE_SITE} через известные внешние каналы. Если связь через основной канал теряется, осуществляется переход на резервный канал. Как только удалённая точка становится видна через основной канал, скрипт возвращает шлюз по умолчанию на него.

#!/bin/sh

GW_CONF=gateways
GW_RUN=current-gateway
REMOTE_SITE=10.0.3.3
OPENVPN_UPLINK_CONFIG=/etc/openvpn/server.conf

read_gateways_from_files()
{
    [ -f ${GW_CONF} ] && source ${GW_CONF}
    [ -f ${GW_CONF} ] || echo file ${GW_CONF} missing | logger -t $0 -p daemon.error
    GW=`cat ${GW_RUN} 2> /dev/null`
}

change_default_route()
{
  if ip route show | grep -q default
  then
    if ip route show | grep default | grep -q tun
    then
        [ ${GW} == ${DEFAULTGW} ] && return
        route delete default gw "$GW"
        route add default gw "$NEWGW"  && echo $NEWGW > ${GW_RUN}
        kill -1 `openvpn_uplink_pid`
    else
        [ -z "$GW" ] && GW=${DEFAULTGW}
        [ "$GW1" = "$GW" ] && NEWGW=$GW2 || NEWGW=$GW1
        route delete default gw "$GW"
        route add default gw "$NEWGW"  && echo $NEWGW > ${GW_RUN}
    fi
  else
    route add default gw "$DEFAULTGW"
    echo $DEFAULTGW > ${GW_RUN}
  fi
  echo "$1" | logger -t $0 -p daemon.info
}
while true
do
    read_gateways_from_files
    ip route show | grep default | grep -q tun \
    || ping -q -c 1 ${REMOTE_SITE} >& /dev/null \
    || change_default_route "Connection via ${GW} lost. Changing to another gateway (GW1=$GW1; GW2=$GW2; GW was ${GW})"

    [ "${GW}" != "${DEFAULTGW}" -a "${GW}" == "${GW1}" ] \
    && ping -q -c 1 -I "${IP2}" "${REMOTE_SITE}" >& /dev/null \
    && change_default_route "Link via ${GW2} has restored. Changhing default gateway back (GW1=$GW1; GW2=$GW2; GW was ${GW}; now GW is ${GW2} )"

    [ "${GW}" != "${DEFAULTGW}" -a "${GW}" == "${GW2}" ] \
    && ping -q -c 1 -I "${IP1}" "${REMOTE_SITE}" >& /dev/null \
    && change_default_route "Link via ${GW1} has restored. Changhing default gateway back (GW1=$GW1; GW2=$GW2; GW was ${GW}; now GW is ${GW1} )"
    sleep 5
done

Скрипт может быть размещён /usr/local/bin/change_default_route

Скрипт должен вызываться автоматически при старте системы. Например, в /etc/rc.local:

 nohup /usr/local/sbin/change_default_route &

или в /etc/network/interfaces

iface ...
 ....
 up nohup /usr/local/sbin/change_default_route &

Файл /etc/network/gateways должен содержать адреса шлюзов, а также указание какой из них должен использоваться по умолчанию:

#### ISP 1
IP1=10.0.1.1
GW1=10.0.1.2

#### ISP2
IP2=10.0.4.1
GW2=10.0.4.4

### Let ISP1 be default
DEFAULTGW=${GW1}

Если используется OpenVPN, при изменении маршрута скрипт находит и перестартовывает процесс (процессы) openvpn, который держит на один из адресов, указанных в конфигурационном файле OpenVPN OPENVPN_UPLINK_CONFIG в директиве remote.


Если нужна однократная проверка, например, при установке маршрута, для выбора того из них, который работает, используйте такой скрипт:

/usr/local/bin/change_default_route

#!/bin/sh
change_default_route()
{
  [ -f /etc/network/gateways ] && source /etc/network/gateways
  GW=`cat /var/run/current-gateway 2> /dev/null` 
  [ -z "$GW" ] && GW=${DEFAULTGW}
  [ "$GW1" = "$GW" ] && NEWGW=$GW2 || NEWGW=$GW1
  route delete default gw "$GW" && route add default gw "$NEWGW" && echo $NEWGW > /var/run/current-gateway
}
for i in 1 2; do ping -q -c 1 ya.ru || ping -q -c 1 google.com || change_default_route ; sleep 1; done 


(ещё один вариант:)

IP1=192.168.201.2
IP2=192.168.211.2
GW1=192.168.201.1
GW2=192.168.211.1

while true
do
if ping -I $IP1 -c 1 10.0.35.1 >& /dev/null
then
        ip route change default via $GW1
else
        ping -I $IP2 -c 1 10.0.35.1 >& /dev/null && ip route change deflt
fi
sleep 1
done


Автоматическая правка файла /etc/default/gateways выполняется при поднятии интерфейса с помощью скрипта:

# cat /etc/ppp/ip-up.d/eb_up 
#!/bin/sh
case $1 in
  ppp200)
    /bin/ip rule add from $4 lookup 3
    /bin/ip route add default via $5 table 3
    /usr/bin/perl -i -p -e 's/GW1=.*/GW1='"$5"/  /etc/network/gateways
    /usr/bin/perl -i -p -e 's/IP1=.*/IP1='"$4"/  /etc/network/gateways
;;
esac
exit 0

[править] Одновременное использование нескольких внешних каналов

[править] Задача

Есть два канала связи с Интернетом, через двух независимых провайдеров. Нужно сделать так, чтобы если происходит обращение через интерфейс 1, ответы должны уходить тоже через интерфейс 1 и с обратным адресом интерфейса 1.

[править] Решение

Настроить и использовать policy routing.

Например для шлюзов GW1 и GW2, которые описываются в /etc/network/gateways:

. /etc/network/gateways
ip rule add from $IP1 lookup 2
ip rule add from $IP2 lookup 3
ip route add default via $GW1 table 2
ip route add default via $GW2 table 3
ip route add default via $DEFAULTGW

Note-icon.gif

При использовании дополнительных таблиц маршрутизации необходимо либо отключить reverse path filter

 echo 0 > /proc/sys/net/ipv4/conf/all/rp_filter 

либо перевести его в менее строгий режим

 echo 2 > /proc/sys/net/ipv4/conf/all/rp_filter 

mamahtehok

Note-icon.gif

Такая схема маршрутизации не будет правильно работать с iptables DNAT. Другими словами, если с помощью iptables/netfilter пробрасывать обращения на какие-то порты внутрь сети, принцип «ответы уходят по тому каналу, по которому приходят запросы» работать не будет.

Как ни странно, проблема с iproute2 и DNAT в некоторых случаях может быть решена (SOLVED) простой парой команд:

iptables -t mangle -A PREROUTING -p tcp --dport 80 -j MARK --set-mark 1
iptables -t mangle -A PREROUTING -p tcp --sport 80 -j MARK --set-mark 1

Таким образом мы можем вручную (через ip rule fwmark 1) указать необходимую таблицу. (N, 21:34, 27 августа 2009 (UTC))


Для решения проблем с трансляцией соединений внутрь сети, необходимо использовать схему с промежуточным шлюзом:

            GW1   GW2
             *     *
             |     | 
         IP1 |     | IP2
      [eth1] |     | [eth2]
            +-------+
            |       |
            |  gw   |
            |       |
            +-------+
    10.0.3.250  |  10.0.3.254
        [eth0]  |  [eth0:1]
                | 
                |
    10.0.3.249  |  10.0.3.253
        [eth1]  |  [eth1:1]
            +-------+
            |       |
            |  pgw  |
            |       |
            +-------+
               | 10.0.3.6
               | [eth0]
               |

В этом случае:

  • на шлюзе gw выполняется проброска на один из внутренних адресов, в зависимости от того, куда пришёл запрос;
  • на шлюзе pgw выполняется дальнейшая проброска внутрь сети.

Подобное решение описывается здесь [2].

[править] Дополнительная информация