LINUX.ORG.RU
решено ФорумAdmin

как сделать «ping -I eth1 ya.ru» если default via eth4

 , , , ,


0

1

Приветствую, Уважаемые!
Пишу (переделываю) скрипт на переключение между провайдерами (одновременный доступ). Все примеры в инете идут с проверкой на доступность шлюзов провайдеров, а если инет лежит у самого провайдера, то мне совсем такой провайдер не нужен в multipath-маршруте (через nexthop). Значит нужно проверить доступность адресов интернета. Сначала думал пинг на ya.ru, потом решил, что наверное лучше обойтись без DNS и решил делать пинги на DNS-сервера гугла 8.8.8.8 и 8.8.4.4 (можно и другие предложения рассмотреть - это, то что в голову пришло, больше ничего не пришло) Замечательно, но если уже лежит первый провайдер (eth1) и default gateway сделан через второго (eth4), то ping -I eth1 8.8.8.8 - не знает куда слать пакет - или знает? И это я ничего не понимаю? При этом ping -I 192.168.20.2 8.8.8.8 - работает но пакеты идут через eth4. Я и правда не всё понимаю, т.к. не всё разжёвано в «Linux Advanced Routing & Traffic Control HOWTO».

Короче вот скрипт:

#!/bin/bash
GW1="192.168.20.1"
GW2="192.168.30.1"
IPADDR1="8.8.8.8" # DNS google
IPADDR2="8.8.4.4" # DNS google
IF1="eth1"
IF2="eth4"
PROV1="/home/ssv/scripts/rc.prov1.sh"
PROV2="/home/ssv/scripts/rc.prov2.sh"
ROUTING2GW="/home/ssv/scripts/rc.routing.sh"



check_real_gates()
{
	if ping -I $IF1 -c5 -l5 -W2 $GW1 2>&1 | grep "100% packet loss" > /dev/null && ping -I $IF2 -c5 -l5 -W2 $GW2 2>&1 | grep "100% packet loss" > /dev/null ; # Если оба провайдера лежат
	then echo WARNING TWO GATEWAYS Is DOWN!!! ; logger WARNING TWO GATEWAYS Is DOWN!!!;
	elif ping -I $IF1 -c5 -l5 -W2 $GW1 2>&1 | grep "100% packet loss" > /dev/null ; # иначе если лежит первый
		then $PROV2 ;                                                       # запускаем скрипт на второго провайдера
	elif ping -I $IF2 -c5 -l5 -W2 $GW2 2>&1 | grep "100% packet loss" > /dev/null ; # иначе если жив первый
		then $PROV1 ;                                                       # то запускаем скрипт на первого провайдера	
	else $ROUTING2GW ;
	fi
}

change_GW1_GW2()
{
	
	if ping -I $IF1 -c5 -l5 -W2 $IPADDR1 2>&1 | grep "64 bytes from" > /dev/null || ping -I $IF2 -c5 -l5 -W2 $IPADDR1 2>&1 | grep "64 bytes from" > /dev/null ;
		then GW1=$IPADDR1 ; GW2=$IPADDR1 ;
	elif ping -I $IF1 -c5 -l5 -W2 $IPADDR2 2>&1 | grep "64 bytes from" > /dev/null || ping -I $IF2 -c5 -l5 -W2 $IPADDR2 2>&1 | grep "64 bytes from" > /dev/null ;
		then GW1=$IPADDR1 ; GW2=$IPADDR1 ;
	else : ; # т.е. google не пингуется, тогда ничего не меняем, пингуем шлюзы провайдеров.
	fi
}


while : ; do
	change_GW1_GW2
	check_real_gates
	sleep 3
done
------------------------- rc.routing.sh -------------------------
#!/bin/bash

# Определим некоторые переменные. Пусть $IF1 будет именем первого интерфейса (if1 на рисунке), а $IF2 -- именем второго.
# Тогда $IP1 будет IP адресом $IF1 , а $IP2 -- IP адресом $IF2 .
# Далее, $GW1 это IP-адрес шлюза провайдера 1, а GW2 -- IP адрес шлюза провайдера 2.
# Наконец, $GW1_NET это IP сеть, к которой принадлежит $GW1 , а GW2_NET -- сеть, к которой принадлежит GW2 . 

IF0="eth0"
IF1="eth1"
IF2="eth4"
#IP0= "192.168.0.26"
IP1="192.168.20.2"
IP2="192.168.30.2"
GW1="192.168.20.1"
GW2="192.168.30.1"
GW1_NET="192.168.20.0/24"
GW2_NET="192.168.30.0/24"
LAN_NET="192.168.0.0/24"


ip route flush table T1 #обнуляем первую таблицу маршрутов
ip route flush table T2 #обнуляем вторую таблицу маршрутов

ip route add $GW1_NET dev $IF1 src $IP1 table T1 #закидываем в первую таблицу инфу о сети первого провайдера
ip route add default via $GW1 table T1           #закидываем в первую таблицу дефолтный гейт на первого провайдера
ip route add $GW2_NET dev $IF2 src $IP2 table T2 #закидываем во вторую таблицу инфу о сети второго провайдера
ip route add default via $GW2 table T2           #закидываем во вторую таблицу дефолтный гейт на второго провайдера


ip route add $GW1_NET dev $IF1 src $IP1 &> /dev/null #заполняем основную таблицу адресов. сеть на первого провайдера
ip route add $GW2_NET dev $IF2 src $IP2 &> /dev/null #заполняем основную таблицу адресов. сеть на второго провайдера


ip rule add from $IP1 table T1     #все пакеты с нашего IP-адреса первого провайдера маршрутизировать по таблице T1
ip rule add from $IP2 table T2     #все пакеты с нашего IP-адреса второго провайдера маршрутизировать по таблице T2



ip route add $LAN_NET     dev $IF0 table T1 #закидываем в первую таблицу инфу о том, что у нас существует локальная сеть
ip route add $GW2_NET     dev $IF2 table T1 #закидываем в первую таблицу инфу о том, что у нас существует еще одна сеть
ip route add 127.0.0.0/8 dev lo   table T1  #закидываем в первую таблицу инфу о существовании лупбека
ip route add $LAN_NET     dev $IF0 table T2 #закидываем во вторую таблицу инфу о том, что у нас существует локальная с
ip route add $GW1_NET     dev $IF1 table T2 #закидываем во вторую таблицу инфу о том, что у нас существует еще одна се
ip route add 127.0.0.0/8 dev lo   table T2  #закидываем во вторую таблицу инфу о существовании лупбека.

ip route del default 
ip route add default scope global nexthop via $GW1 dev $IF1 weight 1 nexthop via $GW2 dev $IF2 weight 1           

ip route flush cache #сбросить кеш маршрутизации

rc.prov2
#!/bin/bash
IF0="eth0"
IF1="eth1"
IF2="eth4"
#IP0= "192.168.0.26"
IP1="192.168.20.2"
IP2="192.168.30.2"
GW1="192.168.20.1"
GW2="192.168.30.1"
GW1_NET="192.168.20.0/24"
GW2_NET="192.168.30.0/24"
LAN_NET="192.168.0.0/24"

ip route flush table T1 #обнуляем первую таблицу маршрутов
ip route flush table T2 #обнуляем вторую таблицу маршрутов

ip route del default 
ip route add default via $GW2 &> /dev/null     #заполняем основную таблицу адресов. дефолтный гейт.

ip route flush cache #сбросить кеш маршрутизации

Команды iptables не стал приводить - итак дофига всего написано. В целом основной вопрос как сделать пинг в инет через «неактивного» провайдера (узнать активен он или нет). Ну и попутно лучше понять linux routing или найти более понятное и детальное руководство или учебник (на русском, английский знаю - но нюансы плохо понимаю).

Ответ на: комментарий от UFO-man

ну дак и не работает, видимо я что-то не так делаю. Да на шлюз идут пинги, а вот если это интернет адрес, то не идут. Хотя посмотрю сейчас tcpdump на «провайдере» (у меня же провайдеры - это другой шлюз на дебиан с двумя lan)

Kluvonog ()
Ответ на: комментарий от Kluvonog

Сделал дефолтным второго првайдера (запустил rc.prov2), запустил ping -I eth1 8.8.8.8 - ответ от 192.168.20.2 (IP интерфейса eth1) - dest. host unreachable.
tcpdump на провайдере ничего не показывает - т.е. ничего не приходит на него.

Kluvonog ()

начала думал пинг на ya.ru, потом решил, что наверное лучше обойтись без DNS

А смысл тебе от интернета без DNS? Forever i2p? Не нравятся DNS провайдера, прописывай сервера того же гугла или комодо по умолчанию.

Deleted ()
Ответ на: комментарий от Deleted

Вы меня не так поняли - я хотел сказать - при выполнении команды ping обойтись без запросов на днс сервер.
Как мне кажется, в случае если лёг первый провайдер и он же был дефолтным днс запрос не разрешится через второго, даже если второй уже ожил, но не станет дефолтным только после отработки скрипта.

Kluvonog ()
Ответ на: комментарий от Kluvonog

Ну окей, DNS для простого ping не нужно. В скрипте, там где change_gw1_gw2 я вижу странность: подразумевается логическое ИЛИ, а баш не выполнит вторую половину если с первой всё будет ок, т. е. статус $? = 0. || между командами и между условиями в квадратных скобках ведёт себя по разному. А ещё есть команда test.

То же и && касается, если команда до && завершилась фейлом, после && выполнения не жди.

Deleted ()

В целом основной вопрос как сделать пинг в инет через «неактивного» провайдера (узнать активен он или нет).

Добавить маршрут до конкретного адреса. Что-то вида route add 8.8.8.8/32 gw ip_другого_провайдера

xscrew ★★ ()
Ответ на: комментарий от Deleted

спасибо что обратили на это внимание (я об этом не думал), но в данном случае это не критично - здесь идёт проверка: доступен ли хоть один из серверов гугла хоть через какого-нибудь провайдера, и если доступен, то сменить значение переменных GW1, GW2.
Вцелом, можно и переписать скрипт, чтобы выполнялось меньше пингов используя результаты команд.

Kluvonog ()
Ответ на: комментарий от xscrew

Что-то вида route add 8.8.8.8/32 gw ip_другого_провайдера


Да мог бы догадаться - ведь видел же добавление статических маршрутов до ДНС серверов провайдера в одном из примеров. Огромное спасибо!
Т.е. в итоге нужно либо пинговать через каждого провайдера свой сервер ДНС и прописать статичный маршрут один раз, либо прописывать этот маршрут перед выполнением команды ping в скрипте, либо прописывать эти маршруты в момент переключения на одного из провайдеров. Обдумаю и выложу результат с пояснениями

Kluvonog ()

Примерно так

ip rule add from 192.168.20.2 tab 10 prio 101
ip rule add from 192.168.30.2 tab 15 prio 102
#меняем приоритет таблицы main
ip ru del prio 32766
ip rule add from all tab main prio 100

#Переносим основной роут из таблицы main в таблицу default
ip r d default
ip r a default via 192.168.30.1 tab default
#Задае маршруты по умолчанию для таблиц 10 и 15
ip r a default via 192.168.20.1 tab 10
ip r a default via 192.168.20.1 tab 15

Вместо манипуляций с таблицами main и default можно перенести все прикрепленные сети в таблицы 10 и 15 типа

ip r a 192.168.20.0/24 dev eth0 src 192.168.20.1 tab 10
ip r a 192.168.30.0/24 dev eth0 src 192.168.30.1 tab 15
а потом пингуем

ping 8.8.8.8 -I 192.168.30.1

или

ping 8.8.8.8 -I 192.168.20.1

swelf ()
Ответ на: комментарий от swelf

Пару опечаток:

последняя строка в первом коде

ip r a default via 192.168.30.1 tab 15

во втором коде

ip r a 192.168.30.0/24 dev eth1 src 192.168.30.1 tab 15

или как там у тебя интрефейсы называются

swelf ()
Ответ на: комментарий от swelf

Спасибо, но 1.

ip r a 192.168.20.0/24 dev eth0 src 192.168.20.2 tab 10
ip r a 192.168.30.0/24 dev eth1 src 192.168.30.2 tab 15

- не работает
-тогда эти правила заменяют правило более общее без src на эти сети и на что это в итоге повлияет? На nat не повлияло (проверил с локальной сети ping 192,168,20,1 ) - хотя думал, что повлияет.
2. С первым кодом я ещё не разобрался и не попробовал

Kluvonog ()
Ответ на: комментарий от swelf

Первый код мне не понятен по причине незнания матчасти (да и узнать не понимаю где - какое руководство смотреть): видимо нужно понимать вопрос приоретов правил в ip rule
видимо тут имеется ввиду, что сначала пакет должен прогоняться по таблицам 10 15 (в данном случае) с высоким приоритетом, а потом уже по таблице дефолт куда перенесли маршрут. Но тут проблема мне видится у таблицы дефолт приоритет 32767 - выше чем у таблиц 10 и 15. Или я не прав?

Kluvonog ()

В итоге вот что получилось

В скрипте rc.hotplug.sh добавил функцию do_prerouting в которой сделал статические маршруты до нужных адресов. Так же изменил код, чтобы постоянно не перезаписывать правила, если ничего и не изменилось (т.е. не изменилось состояние провайдеров). Ну и понятно, что для полного счастья нужен скрипт для iptables, но тут итак уже много написано.
В итоге получились такие скрипты (их проверял, всё работает)
rc.hotplug.sh

#!/bin/bash
GW1="192.168.20.1"
GW2="192.168.30.1"
IPADDR1="8.8.8.8" # DNS google
IPADDR2="8.8.4.4" # DNS google
IF1="eth1"
IF2="eth4"
PROV1="/home/ssv/scripts/rc.prov1.sh"
PROV2="/home/ssv/scripts/rc.prov2.sh"
ROUTING2GW="/home/ssv/scripts/rc.routing.sh"
LASTSTATE=0 # эти переменные фиксируют состояния 0 - лежат оба провайдера; 1 - лежит первый;
STATE=0     #  2 - лежит второй; 3 - оба работают. Начальное значение стоит "0", чтобы если есть инет хоть где-то
            # то он прописался

do_prerouting()
{
	route del -host $IPADDR1 
	route del -host $IPADDR2
	route add -host $IPADDR1 gw $GW1 #добавляем статические маршруты до нужных нам хостов
	route add -host $IPADDR2 gw $GW2 # то что меня и интересовало.
}
check_real_gates()
{
	LASTSTATE=$STATE
	if ping -I $IF1 -c5 -l5 -W2 $IPADDR1 2>&1 | grep "100% packet loss"  > /dev/null  && ping -I $IF2 -c5 -l5 -W2 $IPADDR2 2>&1 | grep "100% packet loss" > /dev/null ;
	then # Если оба провайдера лежат
		STATE=0;
	elif ping -I $IF1 -c5 -l5 -W2 $IPADDR1 2>&1 | grep "100% packet loss" > /dev/null ; then # иначе если лежит первый
		STATE=1 ;   
	elif ping -I $IF2 -c5 -l5 -W2 $IPADDR2 2>&1 | grep "100% packet loss" > /dev/null ; then # иначе если лежит второй
		STATE=2 ;        	
	else                   # иначе если оба работают
		STATE=3 ;
	fi
	if [ "$LASTSTATE" -ne "$STATE" ] ; then # если состояние изменилось
		case "$STATE" in
			"0") logger WARNING TWO GATEWAYS Is DOWN!!! ;;
			"1") $PROV2 ;;
			"2") $PROV1 ;; 
			"3") $ROUTING2GW ;;
		esac
	fi
}

do_prerouting
while : ; do
	check_real_gates
	sleep 5
done

rc.routing.sh
#!/bin/bash
# Определим некоторые переменные. Пусть $IF1 будет именем первого интерфейса (if1 на рисунке), а $IF2 -- именем второго.
# Тогда $IP1 будет IP адресом $IF1 , а $IP2 -- IP адресом $IF2 .
# Далее, $GW1 это IP-адрес шлюза провайдера 1, а GW2 -- IP адрес шлюза провайдера 2.
# Наконец, $GW1_NET это IP сеть, к которой принадлежит $GW1 , а GW2_NET -- сеть, к которой принадлежит GW2 . 
IF0="eth0"
IF1="eth1"
IF2="eth4"
#IP0= "192.168.0.26"
IP1="192.168.20.2"
IP2="192.168.30.2"
GW1="192.168.20.1"
GW2="192.168.30.1"
GW1_NET="192.168.20.0/24"
GW2_NET="192.168.30.0/24"
LAN_NET="192.168.0.0/24"

ip route flush table T1 #обнуляем первую таблицу маршрутов
ip route flush table T2 #обнуляем вторую таблицу маршрутов
ip route add $GW1_NET dev $IF1 src $IP1 table T1 #закидываем в первую таблицу инфу о сети первого провайдера
ip route add default via $GW1 table T1           #закидываем в первую таблицу дефолтный гейт на первого провайдера
ip route add $GW2_NET dev $IF2 src $IP2 table T2 #закидываем во вторую таблицу инфу о сети второго провайдера
ip route add default via $GW2 table T2           #закидываем во вторую таблицу дефолтный гейт на второго провайдера
ip route add $GW1_NET dev $IF1 src $IP1 &> /dev/null #заполняем основную таблицу адресов. сеть на первого провайдера
ip route add $GW2_NET dev $IF2 src $IP2 &> /dev/null #заполняем основную таблицу адресов. сеть на второго провайдера
ip rule del table T1     #все пакеты с нашего IP-адреса первого провайдера маршрутизировать по таблице T1
ip rule del table T2     #все пакеты с нашего IP-адреса второго провайдера маршрутизировать по таблице T2
ip rule add from $IP1 table T1     #все пакеты с нашего IP-адреса первого провайдера маршрутизировать по таблице T1
ip rule add from $IP2 table T2     #все пакеты с нашего IP-адреса второго провайдера маршрутизировать по таблице T2
ip route add $LAN_NET     dev $IF0 table T1 #закидываем в первую таблицу инфу о том, что у нас существует локальная сеть
ip route add $GW2_NET     dev $IF2 table T1 #закидываем в первую таблицу инфу о том, что у нас существует еще одна сеть
ip route add 127.0.0.0/8 dev lo   table T1  #закидываем в первую таблицу инфу о существовании лупбека
ip route add $LAN_NET     dev $IF0 table T2 #закидываем во вторую таблицу инфу о том, что у нас существует локальная с
ip route add $GW1_NET     dev $IF1 table T2 #закидываем во вторую таблицу инфу о том, что у нас существует еще одна се
ip route add 127.0.0.0/8 dev lo   table T2  #закидываем во вторую таблицу инфу о существовании лупбека.
ip route del default 
ip route add default scope global nexthop via $GW1 dev $IF1 weight 1 nexthop via $GW2 dev $IF2 weight 1           
ip route flush cache #сбросить кеш маршрутизации

rc.prov1.sh
#!/bin/bash
IF0="eth0"
IF1="eth1"
IF2="eth4"
#IP0= "192.168.0.26"
IP1="192.168.20.2"
IP2="192.168.30.2"
GW1="192.168.20.1"
GW2="192.168.30.1"
GW1_NET="192.168.20.0/24"
GW2_NET="192.168.30.0/24"
LAN_NET="192.168.0.0/24"

ip route del default 
ip route add default via $GW1 &> /dev/null     #заполняем основную таблицу адресов. дефолтный гейт.
ip route flush cache #сбросить кеш маршрутизации

rc.prov2.sh
#!/bin/bash
IF0="eth0"
IF1="eth1"
IF2="eth4"
#IP0= "192.168.0.26"
IP1="192.168.20.2"
IP2="192.168.30.2"
GW1="192.168.20.1"
GW2="192.168.30.1"
GW1_NET="192.168.20.0/24"
GW2_NET="192.168.30.0/24"
LAN_NET="192.168.0.0/24"

ip route del default 
ip route add default via $GW2 &> /dev/null     #заполняем основную таблицу адресов. дефолтный гейт.
ip route flush cache #сбросить кеш маршрутизации

Kluvonog ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.