Неприятно, если у провайдера авария и у вас дома пропал доступ в интернет. Вдвойне неприятно, если в этот момент вы находитесь далеко от дома и вам нужно залезть на домашний компьютер или NAS. В моем случае застраховаться от падения канала мне помогла компания МГТС, заменив устаревшую медь на оптику, с которой я получил ещё один канал интернет, и чтение различных мануалов по dd-wrt. Если с оптикой я помочь не смогу, то готовым решением по dd-wrt я с удовольствием поделюсь.
Решение не универсальное, но, как мне кажется, очень простое и на его основе неискушенные пользователи смогут, если не создать свое, то просто расширить свой кругозор и понимание этой популярной прошивки.

Я использую роутер asus rt-n16 и прошивку от тов. Kong 22000++. Интернет от основного провайдера приходит ко мне по кабелю, все настройки получаются роутером по dhcp. В интерфейса dd-wrt это выглядит как-то так:

Фактически, все по умолчанию. Адрес роутера во внутренней сети сменен на 192.168.199.1.
Переключение каналов интернета будет выполняться скриптом, который мы создадим во внутренней памяти роутера JFFS2, соответственно, ��ужно эту внутреннюю память включить. Для этого в разделе Administration-Mangement интерфейса dd-wrt включим соответствующую опцию:

После включения JFFS2 память нужно очистить. Для этого выберем «Clean JFFS2» и нажмем применить. Возможно, нужно будет перезагрузить роутер. Наша задача — добиться того, чтобы появилось свободное место в этой памяти.
Теперь зайдем на роутер при помощи telnet. Я использую для этого putty:
Имя пользователя root, даже если для логина в вебинтерфейс dd-wrt вы используете другое имя. Пароль — тот, который вы используете для логина в вебинтерфейс.
Следующий шаг. Мы подключаем резервный кабель в порт LAN1 роутера. В моем случае резервный кабель идет от оборудования GPON, которое поставил МГТС. Это оборудование раздает интернет в своей локальной сети 192.168.100.0/255.255.255.0. Нам нужно будет «оторвать» необходимый порт нашего роутера от остальных портов и назначить ему адрес из сети оборудования GPON, например, 192.168.100.200.
Теперь информация специфичная для конкретной железки, а именно asus rt-n16. Наберем в терминале следующие команды и посмотрим ответ:
Группы портов объединенны в вэланы. Порт 0 — это WAN порт роутера, порты 1234 — это порты роутера, которые соответствуют (внимание!) портам LAN4,LAN3,LAN2,LAN1 роутера, то есть порт 4 подписан на корпусе роутера LAN1. Порт 8 и порт 8* — это порты процессора, через них мы будем видеть интерфейсы в роутере. Я не хочу вдаваться в подробности, принципиально то, что любой вэлан должен замыкаться на процессор роутера. Давайте «оторвем» 4-ый порт:
а теперь назначим 4 порт в 3-ий вэлан
для того, чтобы новый вэлан был виден, нужно ввести команду
сохраним изменения
По аналогии, можно сделать для других роутеров с прошивкой dd-wrt.
Теперь нелирическое отступление. В вебинтерфейсе ddwrt есть настройки вэланов. Но если попробовать с ними поиграть, то мало того, что ничего не получится, но может случиться, что дальше поможет только сброс роутера.
Адрес нашему новому интерфейсу, который связан с 4-ым портом, мы будем назначать из скрипта при старте. Поэтому, давайте начнём этот скрипт писать. Но прежде, где он будет храниться. Как учит насБоконон dd-wrt wiki, всякий скрипт в папке
В этих строках всё просто. Мы завели в nvram 4-ре новые переменные и занесли в них название интерфейса, адрес, маску и шлюз для нашего резервного порта интернет. Каждый раз при старте мы проверяем, что адрес именно тот, который задан в переменной скрипта, это на случай, если потребуется поменять настройки резервного интернета. Далее кофигурируем порт заданными значениями. С текущими переменными это выглядело бы так:
Добавим к нашему скрипту бесконечный цикл, в котором и будем переключать интернет канал на резервный и обратно:
Словами этот длинный кусок кода можно описать так. Каждые n-цать секунд мы проверяем:
Скрипт включения основного канала wan1.up:
Здесь все просто. Удалили все шлюзы по умолчанию. Да-да, их может быть несколько: если после перезагрузки роутера был недоступен основной канал, то включается резервный интернет и мы имеем один шлюз по умолчанию. Если затем начинает работать основной канал, dd-wrt добавляет ещё один шлюз по умолчанию. Тут уж ничего не поделать. Не хотелось долго думать и появился «грязный хак»:
После того, как удалили все шлюзы по умолчанию, добавим новый шлюз, который записан в переменную wan_gateway nvram (его туда записала логика dd-wrt при получения параметров от основного провайдера). Заменим dns на dns гугл, убьем процесс dnsmasq и запустим этот процесс вновь.
Скрипт для включения резервного канала wan2.up устроен таким-же образом, но адрес шлюза берётся из пременной wan2_gateway nvram и используется интерфейс связанный с 4-ым портом роутера.
Остался маленький скриптик vlan3.wanup, который выполняется после поднятия WAN, сразу после того, как включится файрволл:
Назначение скриптика — добавить правило для ната через резервный интерфейс.
Теперь можно перезагрузить роутер и тестировать. Все скрипты были взяты из моего роутера который живёт своей жизнь и тестирует полученную конфигурацию продолжительное время.
Безусловно, можно и нужно многое поправить\добавить, но моя цель, а именно быстро прикрутить дома резервный канал — выполнена. Главная неприятность — это файрволл и проброс портов при работе с резервным каналом, мне они были не нужны, поэтому я не настраивал. Для тех, кому надо — дополняйте скрипт vlan3.wanup. Желаю удачи в ваших продолжениях!
Идеи статьи были почерпнуты из dd-wrt wiki.
Решение не универсальное, но, как мне кажется, очень простое и на его основе неискушенные пользователи смогут, если не создать свое, то просто расширить свой кругозор и понимание этой популярной прошивки.

Я использую роутер asus rt-n16 и прошивку от тов. Kong 22000++. Интернет от основного провайдера приходит ко мне по кабелю, все настройки получаются роутером по dhcp. В интерфейса dd-wrt это выглядит как-то так:

Фактически, все по умолчанию. Адрес роутера во внутренней сети сменен на 192.168.199.1.
Переключение каналов интернета будет выполняться скриптом, который мы создадим во внутренней памяти роутера JFFS2, соответственно, ��ужно эту внутреннюю память включить. Для этого в разделе Administration-Mangement интерфейса dd-wrt включим соответствующую опцию:

После включения JFFS2 память нужно очистить. Для этого выберем «Clean JFFS2» и нажмем применить. Возможно, нужно будет перезагрузить роутер. Наша задача — добиться того, чтобы появилось свободное место в этой памяти.
Теперь зайдем на роутер при помощи telnet. Я использую для этого putty:
putty -telnet 192.168.199.1Имя пользователя root, даже если для логина в вебинтерфейс dd-wrt вы используете другое имя. Пароль — тот, который вы используете для логина в вебинтерфейс.
Лирическое отступление
Первая команда, которую мы введем и её результат у меня
Как видите, свободных байт в nvram немного и именно поэтому мы там не станет хранить наши скрипты. Если эта память исчерпается, то роутер перезагрузиться и восстановит все конфиги dd-wrt по умолчанию. Поэтому же, не стоит, например, загружать сертификаты openvpn в вебинтерфейсе, потому как сохраненные через вебинтерфейс сертификаты будут храниться в переменных nvram. Сертификаты openvpn можно хранить в памяти jffs2 и подключать их в переменной «additional config» настроек openvpn таким образом:

root@DD-WRT:~# nvram show >/dev/null size: 29978 bytes (2790 left)
Как видите, свободных байт в nvram немного и именно поэтому мы там не станет хранить наши скрипты. Если эта память исчерпается, то роутер перезагрузиться и восстановит все конфиги dd-wrt по умолчанию. Поэтому же, не стоит, например, загружать сертификаты openvpn в вебинтерфейсе, потому как сохраненные через вебинтерфейс сертификаты будут храниться в переменных nvram. Сертификаты openvpn можно хранить в памяти jffs2 и подключать их в переменной «additional config» настроек openvpn таким образом:

Следующий шаг. Мы подключаем резервный кабель в порт LAN1 роутера. В моем случае резервный кабель идет от оборудования GPON, которое поставил МГТС. Это оборудование раздает интернет в своей локальной сети 192.168.100.0/255.255.255.0. Нам нужно будет «оторвать» необходимый порт нашего роутера от остальных портов и назначить ему адрес из сети оборудования GPON, например, 192.168.100.200.
Теперь информация специфичная для конкретной железки, а именно asus rt-n16. Наберем в терминале следующие команды и посмотрим ответ:
root@DD-WRT:~# nvram show | grep vlan.*port vlan2ports=0 8 vlan0ports=1 2 3 4 5* vlan1ports=4 3 2 1 8* size: 29978 bytes (2790 left) root@DD-WRT:~# nvram show | grep vlan.*hw vlan2hwname=et0 vlan1hwname=et0 vlan0hwname=et0 size: 29978 bytes (2790 left)
Группы портов объединенны в вэланы. Порт 0 — это WAN порт роутера, порты 1234 — это порты роутера, которые соответствуют (внимание!) портам LAN4,LAN3,LAN2,LAN1 роутера, то есть порт 4 подписан на корпусе роутера LAN1. Порт 8 и порт 8* — это порты процессора, через них мы будем видеть интерфейсы в роутере. Я не хочу вдаваться в подробности, принципиально то, что любой вэлан должен замыкаться на процессор роутера. Давайте «оторвем» 4-ый порт:
root@DD-WRT:~# nvram set vlan0ports="1 2 3 5*" root@DD-WRT:~# nvram set vlan1ports="3 2 1 8*"
а теперь назначим 4 порт в 3-ий вэлан
root@DD-WRT:~# nvram set vlan3ports="4 8"
для того, чтобы новый вэлан был виден, нужно ввести команду
root@DD-WRT:~# nvram set vlan3hwname=et0
сохраним изменения
root@DD-WRT:~# nvram commit
По аналогии, можно сделать для других роутеров с прошивкой dd-wrt.
Теперь нелирическое отступление. В вебинтерфейсе ddwrt есть настройки вэланов. Но если попробовать с ними поиграть, то мало того, что ничего не получится, но может случиться, что дальше поможет только сброс роутера.
А теперь лирическое отступление
Наверное каждый, кто читал про установку dd-wrt на роутер, сталкивался с магическим ритуалом «30 30 30». Это полный сброс роутера. Его настоятельно рекомендуют делать, иначе потом возможны проблемы. Теперь я вам объясню почему. Сброс настроек в вебинтерфейсе затрагивает не все переменные nvram, в частности, те изменения вэланов, которые мы наделали могут остаться. Поэтому ритуал действительно нужен. Но его можно заменить другой командой из терминала (при условии, что вы еще можете зайти на роутер):
Если вы «поиграли» с вэланами и все перестало работать, то вышеприведенные полный сброс «30 30 30» может помочь.
root@DD-WRT:~# erase nvram root@DD-WRT:~# reboot
Если вы «поиграли» с вэланами и все перестало работать, то вышеприведенные полный сброс «30 30 30» может помочь.
Адрес нашему новому интерфейсу, который связан с 4-ым портом, мы будем назначать из скрипта при старте. Поэтому, давайте начнём этот скрипт писать. Но прежде, где он будет храниться. Как учит нас
/jffs/etc/config/ с расширением .startup выполняется при запуске системы до того, как файрвол будет сконфигурирован. Назовём наш скрипт vlan3.startup и напишем следующие строки:#!/bin/sh WAN2_IFNAME=vlan3 WAN2_IPADDR=192.168.100.200 WAN2_GATEWAY=192.168.100.1 WAN2_NETMASK=255.255.255.0 if [ "$(nvram get wan2_ipaddr)" != "$WAN2_IPADDR" ]; then nvram set wan2_ifname=$WAN2_IFNAME nvram set wan2_ipaddr=$WAN2_IPADDR nvram set wan2_gateway=$WAN2_GATEWAY nvram set wan2_netmask=$WAN2_NETMASK nvram commit fi ifconfig $(nvram get wan2_ifname) up $(nvram get wan2_ipaddr) netmask $(nvram get wan2_netmask)
В этих строках всё просто. Мы завели в nvram 4-ре новые переменные и занесли в них название интерфейса, адрес, маску и шлюз для нашего резервного порта интернет. Каждый раз при старте мы проверяем, что адрес именно тот, который задан в переменной скрипта, это на случай, если потребуется поменять настройки резервного интернета. Далее кофигурируем порт заданными значениями. С текущими переменными это выглядело бы так:
ifconfig vlan3 up 192.168.100.200 netmask 255.255.255.0Добавим к нашему скрипту бесконечный цикл, в котором и будем переключать интернет канал на резервный и обратно:
INTERVAL=30 while sleep $INTERVAL do WAN1ALIVE=0 WAN2USING=0 WAN1GW=`nvram get wan_gateway` echo "check" if [ "$WAN1GW" != "0.0.0.0" ]; then if [ "1" = `ping -c 1 $WAN1GW 2>/dev/null | awk '/packets received/ {print $4}'` ]; then WAN1ALIVE=1 echo "wan1alive" fi fi TARGET=`ip -4 route list 0/0 | awk -v gate="via "$WAN2_GATEWAY '$0 ~ gate {print $3}'` if [ ! -z "$TARGET" ]; then WAN2USING=1 echo "wan2using" fi if [ "$WAN1ALIVE" = "1" ] && [ "$WAN2USING" = "1" ]; then /jffs/etc/config/wan1.up echo "Changed active WAN port to 1!" fi if [ "$WAN1ALIVE" = "0" ] && [ "$WAN2USING" = "0" ]; then if [ "1" = `ping -c 1 $WAN2_GATEWAY 2>/dev/null | awk '/packets received/ {print $4}'` ]; then /jffs/etc/config/wan2.up echo "Changed active WAN port to 2!" fi fi done;
Словами этот длинный кусок кода можно описать так. Каждые n-цать секунд мы проверяем:
- Текущий адрес шлюза основного канала. Он хранится в переменной wan_gateway в nvram и назначается автоматически, когда основной шлюз получает параметры по dhcp от основного провайдера. Если этот адрес не равен «0.0.0.0», а «0.0.0.0» он равен тогда, когда адрес не может быть получен, то есть провайдер лежит, мы его пингуем и в случае ответа устанавливаем флаг WAN1ALIVE в единицу, то есть основной канал предполагается рабочим.
- Присутствует ли адрес резервного шлюза в таблице роутинга. Если присутствует, то устанавливаем флаг WAN2USING=1, то есть в данный момент используется резервный интернет канал.
- Если основной канал работает и используется резервный канал, то переключаемся на основной канал интернет.
- Если основной канал не работает и не используется резервный канал, то тестируем доступность шлюза резервного канала и переключаемся на рабочий резерв.
Скрипт включения основного канала wan1.up:
#!/bin/sh # WAN1 DEV=vlan2 GATEWAY=`nvram get wan_gateway` DNS1=8.8.8.8 DNS2=8.8.4.4 nvram set wan_dns="$DNS1 $DNS2" while ip route del default; do :; done ip route add default via $GATEWAY dev $DEV echo "nameserver $DNS1" >/tmp/resolv.dnsmasq echo "nameserver $DNS2" >>/tmp/resolv.dnsmasq pr="$(ps|awk '/dnsmasq/ {print $1}')" kill -9 $pr dnsmasq --conf-file=/tmp/dnsmasq.conf
Здесь все просто. Удалили все шлюзы по умолчанию. Да-да, их может быть несколько: если после перезагрузки роутера был недоступен основной канал, то включается резервный интернет и мы имеем один шлюз по умолчанию. Если затем начинает работать основной канал, dd-wrt добавляет ещё один шлюз по умолчанию. Тут уж ничего не поделать. Не хотелось долго думать и появился «грязный хак»:
while ip route del default; do :; done, а именно удалять все шлюзы по умолчанию, пока не случится ошибка из-за того, что шлюзов больше нет. Некрасиво, придумайте, как лучше.После того, как удалили все шлюзы по умолчанию, добавим новый шлюз, который записан в переменную wan_gateway nvram (его туда записала логика dd-wrt при получения параметров от основного провайдера). Заменим dns на dns гугл, убьем процесс dnsmasq и запустим этот процесс вновь.
Скрипт для включения резервного канала wan2.up устроен таким-же образом, но адрес шлюза берётся из пременной wan2_gateway nvram и используется интерфейс связанный с 4-ым портом роутера.
#!/bin/sh # WAN2 DEV=vlan3 GATEWAY=`nvram get wan2_gateway` DNS1=8.8.8.8 DNS2=8.8.4.4 nvram set wan_dns="$DNS1 $DNS2" while ip route del default; do :; done ip route add default via $GATEWAY dev $DEV echo "nameserver $DNS1" >/tmp/resolv.dnsmasq echo "nameserver $DNS2" >>/tmp/resolv.dnsmasq pr="$(ps|awk '/dnsmasq/ {print $1}')" kill -9 $pr dnsmasq --conf-file=/tmp/dnsmasq.conf
Остался маленький скриптик vlan3.wanup, который выполняется после поднятия WAN, сразу после того, как включится файрволл:
#!/bin/sh iptables -t nat -A POSTROUTING -o $(nvram get wan2_ifname) -j SNAT --to $(nvram get wan2_ipaddr)
Назначение скриптика — добавить правило для ната через резервный интерфейс.
Теперь можно перезагрузить роутер и тестировать. Все скрипты были взяты из моего роутера который живёт своей жизнь и тестирует полученную конфигурацию продолжительное время.
Обобщенный скрипт
Вставляем в окно telnet\ssh следующую простыню и нажимаем «Enter»:
nvram set vlan0ports="1 2 3 5*" nvram set vlan1ports="3 2 1 8*" nvram set vlan3ports="4 8" nvram set vlan3hwname=et0 nvram commit mkdir -p /jffs/etc/config cat << 'EOF' > /jffs/etc/config/vlan3.startup #!/bin/sh WAN2_IFNAME=vlan3 WAN2_IPADDR=192.168.100.200 WAN2_GATEWAY=192.168.100.1 WAN2_NETMASK=255.255.255.0 if [ "$(nvram get wan2_ipaddr)" != "$WAN2_IPADDR" ]; then nvram set wan2_ifname=$WAN2_IFNAME nvram set wan2_ipaddr=$WAN2_IPADDR nvram set wan2_gateway=$WAN2_GATEWAY nvram set wan2_netmask=$WAN2_NETMASK nvram commit fi ifconfig $(nvram get wan2_ifname) up $(nvram get wan2_ipaddr) netmask $(nvram get wan2_netmask) INTERVAL=30 while sleep $INTERVAL do WAN1ALIVE=0 WAN2USING=0 WAN1GW=`nvram get wan_gateway` echo "check" if [ "$WAN1GW" != "0.0.0.0" ]; then if [ "1" = `ping -c 1 $WAN1GW 2>/dev/null | awk '/packets received/ {print $4}'` ]; then WAN1ALIVE=1 echo "wan1alive" fi fi TARGET=`ip -4 route list 0/0 | awk -v gate="via "$WAN2_GATEWAY '$0 ~ gate {print $3}'` if [ ! -z "$TARGET" ]; then WAN2USING=1 echo "wan2using" fi if [ "$WAN1ALIVE" = "1" ] && [ "$WAN2USING" = "1" ]; then /jffs/etc/config/wan1.up echo "Changed active WAN port to 1!" fi if [ "$WAN1ALIVE" = "0" ] && [ "$WAN2USING" = "0" ]; then if [ "1" = `ping -c 1 $WAN2_GATEWAY 2>/dev/null | awk '/packets received/ {print $4}'` ]; then /jffs/etc/config/wan2.up echo "Changed active WAN port to 2!" fi fi done; EOF chmod +x /jffs/etc/config/vlan3.startup cat << 'EOF' > /jffs/etc/config/vlan3.wanup #!/bin/sh iptables -t nat -A POSTROUTING -o $(nvram get wan2_ifname) -j SNAT --to $(nvram get wan2_ipaddr) EOF chmod +x /jffs/etc/config/vlan3.wanup cat << 'EOF' > /jffs/etc/config/wan1.up #!/bin/sh # WAN1 DEV=vlan2 GATEWAY=`nvram get wan_gateway` DNS1=8.8.8.8 DNS2=8.8.4.4 nvram set wan_dns="$DNS1 $DNS2" #`ip -4 route list 0/0 | awk '/default via/ {print "ip route delete default"}'` | sh # ip route delete default while ip route del default; do :; done ip route add default via $GATEWAY dev $DEV echo "nameserver $DNS1" >/tmp/resolv.dnsmasq echo "nameserver $DNS2" >>/tmp/resolv.dnsmasq pr="$(ps|awk '/dnsmasq/ {print $1}')" kill -9 $pr dnsmasq --conf-file=/tmp/dnsmasq.conf EOF chmod +x vi /jffs/etc/config/wan1.up cat << 'EOF' > /jffs/etc/config/wan2.up #!/bin/sh # WAN2 DEV=vlan3 GATEWAY=`nvram get wan2_gateway` DNS1=8.8.8.8 DNS2=8.8.4.4 nvram set wan_dns="$DNS1 $DNS2" #`ip -4 route list 0/0 | awk '/default via/ {print "ip route delete default"}'`|sh # ip route delete default while ip route del default; do :; done ip route add default via $GATEWAY dev $DEV echo "nameserver $DNS1" >/tmp/resolv.dnsmasq echo "nameserver $DNS2" >>/tmp/resolv.dnsmasq pr="$(ps|awk '/dnsmasq/ {print $1}')" kill -9 $pr dnsmasq --conf-file=/tmp/dnsmasq.conf EOF chmod +x /jffs/etc/config/wan2.up
Безусловно, можно и нужно многое поправить\добавить, но моя цель, а именно быстро прикрутить дома резервный канал — выполнена. Главная неприятность — это файрволл и проброс портов при работе с резервным каналом, мне они были не нужны, поэтому я не настраивал. Для тех, кому надо — дополняйте скрипт vlan3.wanup. Желаю удачи в ваших продолжениях!
Идеи статьи были почерпнуты из dd-wrt wiki.
