Да, все мы знаем, что USB модем, который непосредственно соединён с MikroTik, может периодически подвисать. Проблема кроется в том, что когда модем переключает режим работы, например с lte на 3G, в момент переключения модем может кратковременно потребовать большего тока на порту USB, но в связи c аппаратной особенностью Микротик этого сделать не может.

Решение данной проблемы либо подключить модем через активный USB hub, либо перевести модем принудительно только в один режим (например lte). Но зачастую нам необходимо наличие любой связи, минимум подключиться к самому MikroTik, а в таком случае, если к lte подключиться нельзя, то MikroTik останется без интернета.

Даже если вы проделаете данные настройки, то ни кто вам не можем гарантировать, что модем не зависнет, так как там обычно ядро linux. Самый верный способ решения зависания модема, это сбросить питание на порту USB.

На помощь нам приходит RouterOS скрипт, при аппаратной поддержке со стороны RouterBoad возможности сбрасывать питание на порту.

Вы сами должны определить, поддерживает ли ваша модель аппаратный сброс питания на порту USB, данную информацию можно получить с сайта MikroTik.com, оставим это за пределами данной статьи.

Остаётся понять, каким образом определить работает ли наш свисток. Первое, что приходит нам в голову, это пинговать сам свисток, если он выступает как LTE интерфейс, то да, это возможно, но нам данная процедура не скажет есть ли интернет за свистком. К примеру если у вас заблокирована сим карта, посе разблокировки вам необходимо пройти перерегистрацию на базовой станции, а для этого необходимо произвести перезагрузку модема, либо помните ответ от операторов ОПСОС-ов мы слышим: "Вытащите и вставьте сим карту обратно", по сути сброс питания, в том числе эмулирует и данную операцию.

Я же предлагаю проверять наличие интернета за "свистком" с помощью протокола ICMP и при этом не проверять банально только один хост, а проверять группу хостов, и если хотя бы один из хостов доступен, то считать, что интернет есть и можем дальше спокойно продолжать работать, но если все хосты не доступны, то сбросить питание на USB порту.

Обращаю ваше внимание, только если ВСЕ хоста не доступны.

Подготовка

Нам необходимо подготовить маршрутизатор для того, чтобы когда мы будем проверять доступность хостов трафик до необходимых хостов, отправлялся только через LTE модем. Для этого мы будем использовать именованную таблицу маршрутизации, её имя будет статичное onlyLTE.

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

Первое, что необходимо сделать, это указать процедуре Routing Decision, что если необходимо отправить пакет через данную таблицу маршрутизации, то не должен производиться поиск подходящего маршрута в таблице main, это особенность RouterOS, которую необходимо учесть.

Выполняем

[admin@MikroTik.Me] >/ip route rule add routing-mark=onlyLTE action=lookup-only-in-table table=onlyLTE

Теперь нам необходимо создать дефолтный маршрут.

Если у вас одна версия модема без изменений, то скорее всего по DHCP вы получаете один и тот же шлюз или может вы вообще отключили на модеме DHCP сервер, в таком случае вам достаточно добавить дефолтный маршрут через данный шлюз, и указать что это таблица onlyLTE.

Делается данный маршрут следующей командой.

[admin@MikroTik.Me] > /ip route add gateway=192.168.8.1 routing-mark=onlyLTE

Надо напомнить, что если вы не указываете dst-address это эквивалентно тому, что вы укажите dst-address=0.0.0.0/0.

DHCP

Если у вас разные модемы, или вы предпочитаете подстраховаться, и сделать так, чтобы даже если модем измениться и ваша схема продолжала работать, вы можете прибегнуть к функционалу dhcp-script для автоматического создания или обновления дефолтного маршрута.

Поместите скрипт, указанный ниже, в поле script DHCP клиента.

:local Rcount [/ip route print count-only where routing-mark="onlyLTE"];
:if ($Rcount=0) do={
    /ip route add gateway="$"gateway-address"" routing-mark="onlyLTE";
} else={
    /ip route set gateway="$"gateway-address"" [find routing-mark="onlyLTE"];
}

Данный скрипт будет срабатывать каждый раз, когда будет получен IP адрес с помощью данного DHCP клиента и он создаст или обновит маршрут. Тем самым подготовим конфигурацию до того состояния, когда выполнение скрипта будет однозначно правильным.

Скрипт

Для начала нам необходимо определить список хостов, которые мы будем проверять протоколом ICMP. Я предлагаю использовать публичные DNS сервера, но вы можете использовать свои сервера, возможно офисные или любые другие, но постарайтесь выбрать такие хосты, чтобы их доступность была на высоте.

Объявим переменную с типом массив, где через запятую перечислим все хосты, которые необходимо проверять протоколом ICMP.

:local addr [:toarray "8.8.8.8,8.8.4.4,77.88.8.8,77.88.8.1,77.88.8.88,77.88.8.2"];

Также объявим переменную для того чтобы мы могли проверять, как прошла проверка в прошлую итерацию, к сожалению метода continue в циклах RouterOS нет.

:local InternetIsset false;

Далее тело цикла

:foreach ipp in $addr do={
    :if ($InternetIsset=false) do={
        :if ([/ping address=$ipp routing-table="onlyLTE" count=3] = 0) do={
            /log warning message="LTE Internet fail for address $ipp";
        } else={
            /log warning message="LTE Internet for success $ipp";
            :set InternetIsset true;
        }
    }
}

Первая строка - отвечает за тело цикла, запускаем цикл для каждого элемента массива и внутри цикла будет переменная ipp, в которой будет храниться один элемент массива, т.е. IP адрес хоста, доступность которого мы будем проверять протоколом ICMP.

Вторая строка - Проверяем, необходимо ли проверять наличие Интернета. Когда будет запущен скрипт, данная переменная будет равна значению false, но как только минимум одна проверка пройдёт удачно, скрипт значение данной переменной установит в true, и соответственно все остальные проверки будут пропущены. Другими словами проверка будет осуществляться пока переменная ровна значению true.

Третья строка - :if ([/ping address=$ipp routing-table="onlyLTE" count=3] = 0) Проверяем доступность хоста тремя пакетами ICMP, и если мы не получим ни одного пакета в ответ, то признаем, что данный хост недоступен через LTE модем.

Выводим сообщение, что хост не доступен.

/log warning message="LTE Internet fail for address $ipp";

Но если попытка прошла успешно, то признаём то, что интернет за LTE модемом есть, выводим сообщение об этом, и устанавливаем значение переменной InternetIsset в true, тем самым предотвращаем следующие проверки.

И в конце нам необходимо что то сделать с результатом.

:if ($InternetIsset=false) do={
    /log warning message="USB Power Reset Action";
    /system routerboard usb power-reset duration=5;
}

Если переменная InternetIsset имеет значение false, т.е если после прохождения всех итераций, перебрав весь массив и попытавшись получить ответ по протоколу ICMP ни один хост не ответил, то значение данной переменной будет ровно false

Соответственно сбрасываем питание на USB порту на 5 секунд и выводим сообщение в лог.

Скрипт целиком.

:local addr [:toarray "8.8.8.8,8.8.4.4,77.88.8.8,77.88.8.1,77.88.8.88,77.88.8.2"];
:local InternetIsset false;
:foreach ipp in $addr do={
    :if ($InternetIsset=false) do={
        :if ([/ping address=$ipp routing-table="onlyLTE" count=3] = 0) do={
            /log warning message="LTE Internet fail for address $ipp";
        } else={
            /log warning message="LTE Internet for success $ipp";
            :set InternetIsset true;
        }
    }
}
:if ($InternetIsset=false) do={
    /log warning message="USB Power Reset Action";
    /system routerboard usb power-reset duration=5;
}

Далее добавьте данный скрипт в выполнение по расписанию и живите спокойно, оптимальный период пять минут.

Актуальная версия скрипта

Рассказать друзьям

Чатик телеграм

@mikrotikme