Если гора не идет к Магомеду… Как поддержать активным ADSL соединение у криворукого провайдера

    Так случилось, что переговоры с провайдером о том, что соединение иногда пропадает, и ADSL модем сей факт не замечает, ни к чему не привели. Пришлось искать другие пути.

    Задача: Програмным путем перезапускать ADSL модем при пропадании соединения, чтобы форсировать переустановку PPPoE сессии.

    Приведенное ниже решение опробовано на ADSL модеме D-link DSL 2640U, но думаю может быть легко адаптировано для любых иных моделей ADSL модемов.



    Итак, решение — php скрипт, который каждые 5 минут проверяет наличие соединения пингуя сайт провайдера.
    Если пинг отсутствует — посылаем ADSL модему команду перезагрузки.

    Средствами Windows XP достаточно проблематично запускать скрипт каждые 5 минут. Поэтому в качестве System Sheduler'а был использован бесплатный System Scheduler компании Splinterware.

    Для простоты предположим, что на компьютере установлен denwer и все файлы расположены в Z:\home\inet-keeper\www\

    Решение:
    В указанной выше директории располагаем

    1) файл inet-keeper.bat, который запускается каждые 5 минут из System Scheduler
    файл inet-keeper.bat запускает одноименный php скрипт:
    z:\usr\bin\php -n -f inet-keeper.php >> inet-keeper.log


    2) файл inet-keeper.php
    содержание файла inet-keeper.php:
    <?php
    set_time_limit(60*5);

    $res = exec("ping google.com -n 10", $output, $var);
    $output = date('r');
    $output .= " ## Ping result: $var"; // 0-ОК 1-Error
    $output .= " ## $res";
    if ($var || substr_count($res, '= 0ms') == 3) // In case like Minimum = 0ms, Maximum = 0ms, Average = 0ms
    {
    $error = true;
    $output .= " ## Error detected!";
    $output .= "\nRebooting modem...\n";
    reboot_modem();
    }
    $output .= "\n";

    if ($error) // or true)
    echo $output;

    function reboot_modem()
    {
    $log = send_request("getlog");
    file_put_contents("logs\\" . date('Y-M-d_H-i-s') . ".html" ,$log);
    send_request("reboot");
    }

    function send_request($r) {
    $login = "admin";
    $password = "admin";
    $auth = base64_encode($login . ":" . $password);
    $fp = fsockopen('192.168.1.1', 80, $errno, $errstr, 60);
    if ($fp)
    {
    switch ($r) {
    case "reboot":
    $out = "GET /rebootinfo.cgi HTTP/1.0\r\n";
    break;
    case "getlog":
    $out = "GET /logview.cmd HTTP/1.0\r\n";
    break;
    default:
    return;
    }
    $out .= "Host: 192.168.1.1\r\n";
    $out .= "Authorization: Basic $auth\r\n";
    $out .= "Connection: Close\r\n\r\n";
    // посылаем запрос
    fwrite($fp, $out);
    $html = "";

    while (!feof($fp)){
    $part=fgets($fp);
    $html.=$part;
    }
    fclose($fp);
    }
    return $html;
    }
    ?>


    В случае, если сайт провайдера (в приведеноом примере google.com) перестанет пинговаться, скрипт запускает модем на перезагрузку, открывая страницу 192.168.1.1/rebootinfo.cgi

    Поскольку модем требует авторизации, в функции send_request есть строки, задающие логин и пароль
    $login = "admin";
    $password = "admin";


    При перезегрузке модема будет
    1) запись об этом в файле inet-keeper.log
    2) в подкаталоке log содержимое страницы системного лога модема (в моём случае — содержимое страницы 192.168.1.1/logview.cmd)

    Средняя зарплата в IT

    113 000 ₽/мес.
    Средняя зарплата по всем IT-специализациям на основании 5 709 анкет, за 2-ое пол. 2020 года Узнать свою зарплату
    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама

    Комментарии 41

      +2
      $fp = fsockopen('192.168.1.1', 80, $errno, $errstr, 60);
      $fp = fsockopen('192.168.1.1', 80, $errno, $errstr, 60);

      Это если он с первого раза не понял?
        +1
        Исправил, спасибо! :)
        +9
        Указанную проблему можно решить при помощи bash в 5 строчек, зачем php?:

        #!/bin/bash
        ping -c 1 google.ru
        if [ $? != «0» ]; then
        wget 192.168.1.1/rebootinfo.cgi --http-user=admin --http-password=admin
        fi
          0
          Ну, как-то по привычке Окнами пользуюсь :)
            –7
            а в MS Windows?
              +7
              Для Windows:

              ping google.ru
              if not errorlevel 0 goto end
              wget 192.168.1.1/rebootinfo.cgi --http-user=admin --http-password=admin
              :end

                –6
                в windows нет комманды wget…
                  +9
                  И php в нем нет:)
                  Можно скачать всего 1 файл и положить в %system%
                    0
                    Спасибо.
                    Но не во всех случаях код выше поможет.
                      0
                      Приведите примеры? :)
                        0
                        см. коммент ниже
                          0
                          Так отработает — результат erorrlevel = 1. Проверьте сами, другое дело, что в скрипте лишний not, но концепция я думаю понятна.
                            0
                            Проверял. Ноль.
                              0
                              что то не очень верится, нельзя ли посмотреть результаты работы скрипта
                              в случае когда отвалилось соединение и когда все в порядке

                              ping google.ru
                              if errorlevel 0 goto end
                              echo FAIL
                              goto end
                              echo OK
                              :end
                                0
                                В данном коде echo OK никогда не отработает…
                                  0
                                  Исправленная версия:

                                  ping google.ru
                                  if errorlevel 0 goto OK
                                  echo FAIL
                                  goto end
                                  :OK
                                  echo OK
                                  :end
                                  pause

                                  Вот пример результатов, когда это не срабатывает:

                                  C:\>ping google.ru

                                  Pinging google.ru [74.125.77.104] with 32 bytes of data:

                                  Request timed out.
                                  Request timed out.
                                  Reply from 192.168.1.1: Destination net unreachable.
                                  Reply from 192.168.1.1: Destination net unreachable.

                                  Ping statistics for 74.125.77.104:
                                  Packets: Sent = 4, Received = 2, Lost = 2 (50% loss),
                                  Approximate round trip times in milli-seconds:
                                  Minimum = 0ms, Maximum = 0ms, Average = 0ms

                                  C:\>if errorlevel 0 goto OK

                                  C:\>echo OK
                                  OK

                                  C:\>pause
                                  Press any key to continue...

                                    0
                                    C:\>ping google.ru

                                    Обмен пакетами с google.ru [209.85.229.104] по 32 байт:

                                    Превышен интервал ожидания для запроса.
                                    Превышен интервал ожидания для запроса.
                                    Превышен интервал ожидания для запроса.
                                    Превышен интервал ожидания для запроса.

                                    Статистика Ping для 209.85.229.104:
                                    Пакетов: отправлено = 4, получено = 0, потеряно = 4 (100% потерь),

                                    C:\echo %errorlevel%
                                    1
                                      0
                                      Видимо когда модем посылает ответ Reply from 192.168.1.1: Destination net unreachable, ping не считает это за ошибку.
                      0
                      Насколько знаю, в PowerShell имеется соответствующий командлет.
                        0
                        Есть.
                        users.ugent.be/~bpuype/wget/
                        0
                        Кстати, если канал отвалился недавно, то пинг может отресолвить хост, но пинги не дойдут, т.е. errorlevel = 0, а результат таймаут.
                        в скрипте есть проверка для подобного случая:
                        Minimum = 0ms, Maximum = 0ms, Average = 0ms
                          +1
                          По моему вы не правы. ErrorLevel будет 0 только в том случае, если ВСЕ пинги вернутся к вам
                  –3
                  спасибо, если не сложно то могли бы для *nix написать?
                  0
                  > Средствами Windows XP достаточно проблематично запускать скрипт каждые 5 минут.
                  Планировщик заданий не осилили?
                  Панель управления > Назначенные задания > Добавить задание
                    –2
                    Там нет возможности запусткать каждые 5 мин. Ежедневно — да
                      0


                      И все таки не осилили.
                        –2
                        Да, заходил, видел.
                        Не понравилось. Видимо вопрос вкуса.
                        Спасибо, что не поленились неделать скринов.
                        0
                      +1
                      Спасибо за решение, оно мне поможет сильно. Только есть одно но. У меня модем стоит за роутером. Висит на wan дырке. И я не могу до него добраться :( Никто случайно ip не знает? Я пробивался как-то раньше, а сейчас не получается. Прошивка роутера dd-wrt. Там что-то типа 192.168.100.1 было, кажется.
                        0
                        tracert www.ru?
                          0
                          Не даёт ничего:

                          1: guard (192.168.1.104) 0.183ms pmtu 1500
                          1: — (192.168.1.1) 1.591ms
                          1: — (192.168.1.1) 1.346ms
                          2: — (192.168.1.1) 1.349ms pmtu 1492
                          2: 212.124.0.1 (212.124.0.1) 54.847ms

                          И дальше интеренет. 192.168.1.1 — ip роутера самого.
                        0
                        Сам работаю у провайдера, среди прочего предлагаем ADSL, иногда ребут модема клиента не помогает, приходится дергать порт на DSLam-е. Редко, но бывает. Оборудование — Paradyne IP 4200.
                          +1
                          Один хабраюзер уже делал то же самое на python, по-моему выглядит получше: habrahabr.ru/blogs/linux/67421/
                            0
                            А почему бы ppoe на компе не поднять? Там в настройках есть пункт — перезвонить при разрыве сессии.
                              0
                              Ну, вообще-то модем с WiFi и в режим бриджа его загонять ни разу не нужно.
                              И проблема в том, что модем не видит разрыва сессии, не знаю почему.
                              Менял модемы, не помогло. Ясно только, что проблема на стороне провайдера.
                            • НЛО прилетело и опубликовало эту надпись здесь
                                0
                                вот так реализовано у меня:
                                в крон
                                */5 * * * * ~/bin/ping_test >/dev/null 2>&1

                                — ping_test — #!/bin/sh
                                /bin/ping -c3 -i1 $GW

                                test=$?

                                if [ $test -ne 0 ]; then
                                ~/bin/modem
                                fi

                                — modem — #!/usr/bin/expect -f
                                spawn telnet $modem_ip
                                expect «login:» { send «admin\n»}
                                expect «Password:» { send «my_password\n»}
                                expect "#" {send «reboot\n»}
                                expect "#" {send «exit\n»}

                                  0
                                  еще вопрос, если на модеме pppoe то зачем модем перезагружать, достаточно pppoe опустить и поднять.
                                  Выйдет гораздо быстрее…

                                  У меня стоит модем роутером держит pppoe за ним wifi роутер бриджом. Возникла идея натравить их друг на друга. Когда нет инета wifiроутер перезапускает пппое на модеме. Когда wifiроутер подвис модем перезапускает роутер.

                                  Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                                  Самое читаемое