Как стать автором
Обновить

MikroTik в роли тестера сети

Время на прочтение 13 мин
Количество просмотров 44K


Приобрели MikroTik RouterBoard mAP 2n. Отличная модель. Поиграв с ним вдоволь, решили задействовать в качестве тестера малой провайдерской сети. Очень часто, чтобы проверить состояние сети, необходимо расчехлять ноутбук, что порой крайне неудобно в виду расположения оборудования в подвалах, чердаках. Заменить ноутбук полностью, конечно, невозможно, но стандартные тесты можно переложить на плечи нашего «маленького друга». Об этом и будет идти речь в моем посте.

Одна из особенностей mAP 2n — это наличие в нем microUSB, по которому роутер можно питать. Данная особенность дает возможность совместно с портативным зарядным устройством использовать роутер мобильно. В качестве портативного зарядного устройства был выбран HIPER WP-222. В основном его выбор был обусловлен ценой, ну а его водонепроницаемый корпус и наличие фонарика окончательно убедил нас в правильности решения.



Для тестера необходим канал связи с человеком. Первая мысль была задействовать спикер, на котором можно посредством RouterOS творить чудеса, но, к сожалению mAP 2n обделили им. Все, что осталось — это задействовать LED-индикацию. У mAP 2n на передней панели есть 7 светодиодов: Power — им управлять нельзя, один красный — питание кого либо по второму порту и 5 зеленых (WI-Fi, Eth1,2 USR, AP/CAP). Управлять светодиодом можно, назначив ему бридж интерфейс. Включаем, интерфейс светодиод загорается, отключаем — гаснет.

/system leds
set 1 interface=br1 type=interface-status
/interface bridge
set br1 disabled=yes; # гаснет
set br1 disabled=no;  # загорается

Кроме того, чтобы оповестить человека, мы должны придумать, как получить от него какую либо команду. Долго копал в сторону кнопки Reset/Mode, но ничего толком не узнал кроме возможности сбросить настройки, а хотелось бы знать, что же это такое Mode. Пришлось придумать нечто иное. У mAP 2n на борту есть два 10/100 Ethernet порта. По первому роутер можно питать, а по второму он сам будет источником питания, более того, роутер в состоянии определить, что к нему подключили устройство, которое можно питать. Это происходит ввиду наличие сопротивления на 4,5 — 7,8 контактах Ethernet порта от 3kΩ до 26.5kΩ. Не долго думая, соорудили на основе Ethernet коннектора, кнопки от корпуса ПК и резистора на 4kΩ следующую штуку:



Программно проверяем кнопку так:

/interface ethernet
poe set eth2 poe-out=auto-on;
:local status;
/interface ethernet poe monitor eth2 once do={
   :set status $"poe-out-status";
};
:if ($status = "powered-on") do={
   # нажали кнопку
};

Канал связи с человеком имеется необходимо определиться, что именно будем проверять и в какой последовательности.

Начнем:

1. Наличие линка на порту без него дальше и проверять ненужно ничего. Проверять линк будем cable-test инструментом что проверит кабель физически.

:local link;
/interface ethernet cable-test eth1 once do={
   :set link $"status";
};
:if ($link = "link-ok") do={
   # все ок
};

2. На порту должно быть 100Mbps. Многие коммутаторы в виду своих железных проблем начинают глючить и выдают 10Mbps на порт, что нам и нужно исключить. Делаем это так:

:if ([/interface ethernet get eth1 speed] = "100Mbps") do={
   # все ок
};

3. Пинги куда без них? Пингуем шлюз. Тут нужно пропинговать шлюз обычными и большими пакетами это выявит возможные проблемы в цепочке до шлюза. Делаем это так:

:if ([/ping address=[/ip dhcp-client get 0 gateway] interface=ethernet count=1 interval=200ms] = 1) do={
   :if ([/ping address=[/ip dhcp-client get 0 gateway] interface=ethernet count=1 interval=200ms size=1500] = 1) do={
      # все ок
   };
};

4. Дополнительно по нажатию нашей кнопки тестируем VPN(можно и что либо другое в нашем случае это pptp) и доступ в интернет.

:local gateway "8.8.8.8"; # наш шлюз в интернете
:if ([/interface pptp-client get vpn disabled] != false) do={
   /interface pptp-client set vpn disabled=no;
};
:if ([/interface pptp-client get vpn running] = true) do={
   :if ([/ping address=$gateway interface=vpn count=1 interval=200ms size=1500] = 1) do={
      # все ок
   };
};

Информировать человека было решено так:
Первый тест — проверка линка если все хорошо, то ничего не горит, если все плохо то горит красный светодиод.
Второй тест — проверка на порту 100Mbps, если все хорошо, то горит первый зеленый светодиод, если все плохо то ничего не горит.
Третий тест — пинги если короткие и длинные пинги прошли горит второй зеленый светодиод, если прошли короткие, а длинные пинги нет, то второй светодиод моргает, если ничего не получается второй светодиод не горит.
Четвертый тест по нажатию кнопки, только если все предыдущие удачно завершились — тест VPN и интернета если VPN работает и пинг до внешнего шлюза прошли то горит третий зеленый светодиод, если VPN работает, а пинги не прошли, то третий зеленый светодиод моргает иначе третий зеленый светодиод не горит.

На любом из этапов при провале какого либо теста все тестирование должно возвращаться к началу. Ведь мы можем перебирать кабеля и тестить несколько по очереди. Так же повторюсь кнопкой для проверки VPN и интернета можно воспользоваться только при удачном прохождении предыдущих тестов.

Для первого порта сделали маленький удлинитель, что стало поудобнее и главное исключило возможность запитать его по данному порту.
Светодиод Eth2 — сигнализирует об Wi-Fi активности, ну а Eth1 об линке Eth1. Wi-Fi на устройстве настроен и есть доступ к его управлению со смартфона. Тут можно еще приложение написать для дополнительных тестов через смартфон, но это уже другая история.

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

Вот такой скрипт получился в итоге:
В скрипте:
test1, test2, test3 — бридж интерфейсы с привязкой к ним трех светодиодов крайне левых (кроме первого — Power)
link — второй Ethernet порт
ethernet — первый Ethernet порт
off — бридж интерфейс для программной остановки скрипта. Нужен был в отладке для удобства.
8.8.8.8 — заменил адрес нашего шлюза на Google DNS
vpn — pptp соединение
{
    :log info [
        :time {
            :local gateway "8.8.8.8";
            /interface bridge set test1 disabled=yes;
            /interface bridge set test2 disabled=yes;
            /interface bridge set test3 disabled=yes;
            /interface ethernet poe set link poe-out=forced-on;
            /interface pptp-client set vpn disabled=yes;
            :delay 3;
            :local link;
            :local status;
            :local flag false;
            :while ([/interface bridge get off disabled] = true) do={
                /interface ethernet cable-test ethernet once do={
                    :set link $"status";
                };
                :if ($link = "link-ok") do={
                    :if ([/interface ethernet poe get link poe-out] = "forced-on") do={
                        /interface ethernet poe set link poe-out=off;
                    };
                    :if ([/interface ethernet get ethernet speed] = "100Mbps") do={
                        :if ([/interface bridge get test1 disabled] != false) do={
                            /interface bridge set test1 disabled=no;
                        };
                        :if ([/ping address=[/ip dhcp-client get 0 gateway] interface=ethernet count=1 interval=200ms] = 1) do={
                            :if ([/ping address=[/ip dhcp-client get 0 gateway] interface=ethernet count=1 interval=200ms size=1500] = 1) do={
                                :if ([/interface bridge get test2 disabled] != false) do={
                                    /interface bridge set test2 disabled=no;
                                };
                                :if ($flag != true) do={
                                    :if ([/interface ethernet poe get link poe-out] != "auto-on") do={
                                        /interface ethernet poe set link poe-out=auto-on;
                                    };
                                };
                                /interface ethernet poe monitor link once do={
                                    :set status $"poe-out-status";
                                };
                                :if (([/interface ethernet poe get link poe-out] = "auto-on" and $status = "powered-on") or $flag = true) do={
                                    :if ($flag != true) do={
                                        :set flag true;
                                        :if ([/interface pptp-client get vpn disabled] != false) do={
                                            /interface pptp-client set vpn disabled=no;
                                        };
                                        :if ([/interface ethernet poe get link poe-out] != "off") do={
                                            /interface ethernet poe set link poe-out=off;
                                        }
                                    };
                                    :if ([/interface pptp-client get vpn running] = true) do={
                                        :if ([/ping address=$gateway interface=vpn count=1 interval=200ms size=1500] = 1) do={
                                            :if ([/interface bridge get test3 disabled] != false) do={
                                                /interface bridge set test3 disabled=no;
                                            }
                                        } else={
                                            :if ([/interface bridge get test3 disabled] != false) do={
                                                /interface bridge set test3 disabled=no;
                                            };
                                            :delay 0.5;
                                            :if ([/interface bridge get test3 disabled] != true) do={
                                                /interface bridge set test3 disabled=yes;
                                            };
                                            :delay 0.5;
                                        }
                                    } else={
                                        :if ([/interface bridge get test3 disabled] != false) do={
                                            /interface bridge set test3 disabled=no;
                                        };
                                        :delay 0.5;
                                        :if ([/interface bridge get test3 disabled] != true) do={
                                            /interface bridge set test3 disabled=yes;
                                        };
                                        :delay 0.5;
                                    }
                                }
                            } else={
                                :if ([/interface ethernet poe get link poe-out] = "auto-on") do={
                                    /interface ethernet poe set link poe-out=off;
                                };
                                :if ([/interface pptp-client get vpn disabled] != true) do={
                                    /interface pptp-client set vpn disabled=yes;
                                };
                                :set flag false;
                                :if ([/interface bridge get test3 disabled] != true) do={
                                    /interface bridge set test3 disabled=yes;
                                };
                                :if ([/interface bridge get test2 disabled] != false) do={
                                    /interface bridge set test2 disabled=no;
                                };
                                :delay 0.5;
                                :if ([/interface bridge get test2 disabled] != true) do={
                                    /interface bridge set test2 disabled=yes;
                                };
                                :delay 0.5;
                            }
                        } else={
                            :if ([/interface ethernet poe get link poe-out] = "auto-on") do={
                                /interface ethernet poe set link poe-out=off;
                            };
                            :if ([/interface pptp-client get vpn disabled] != true) do={
                                /interface pptp-client set vpn disabled=yes;
                            };
                            :set flag false;
                            :if ([/interface bridge get test2 disabled] != true) do={
                                /interface bridge set test2 disabled=yes;
                            };
                            :if ([/interface bridge get test3 disabled] != true) do={
                                /interface bridge set test3 disabled=yes;
                            }
                        }
                    } else={
                        :if ([/interface ethernet poe get link poe-out] = "auto-on") do={
                            /interface ethernet poe set link poe-out=off;
                        };
                        :if ([/interface pptp-client get vpn disabled] != true) do={
                            /interface pptp-client set vpn disabled=yes;
                        };
                        :set flag false;
                        :if ([/interface bridge get test1 disabled] != true) do={
                            /interface bridge set test1 disabled=yes;
                        };
                        :if ([/interface bridge get test2 disabled] != true) do={
                            /interface bridge set test2 disabled=yes;
                        };
                        :if ([/interface bridge get test3 disabled] != true) do={
                            /interface bridge set test3 disabled=yes;
                        }
                    }
                } else={
                    :if ([/interface ethernet poe get link poe-out] != "forced-on") do={
                        /interface ethernet poe set link poe-out=forced-on;
                    };
                    :if ([/interface pptp-client get vpn disabled] != true) do={
                        /interface pptp-client set vpn disabled=yes;
                    };
                    :set flag false;
                    :if ([/interface bridge get test1 disabled] != true) do={
                        /interface bridge set test1 disabled=yes;
                    };
                    :if ([/interface bridge get test2 disabled] != true) do={
                        /interface bridge set test2 disabled=yes;
                    };
                    :if ([/interface bridge get test3 disabled] != true) do={
                        /interface bridge set test3 disabled=yes;
                    };
                    :delay 3;
                }
            };
            :if ([/interface ethernet poe get link poe-out] != "off") do={
                /interface ethernet poe set link poe-out=off;
            };
            :if ([/interface pptp-client get vpn disabled] != true) do={
                /interface pptp-client set vpn disabled=yes;
            };
            :if ([/interface bridge get test1 disabled] != true) do={
                /interface bridge set test1 disabled=yes;
            };
            :if ([/interface bridge get test2 disabled] != true) do={
                /interface bridge set test2 disabled=yes;
            };
            :if ([/interface bridge get test3 disabled] != true) do={
                /interface bridge set test3 disabled=yes;
            };
            :if ([/interface bridge get off disabled] != true) do={
                /interface bridge set off disabled=yes;
            }
        }
    ]
}


Сам скрипт должен стартовать сразу после запуска роутера. Для этого воспользуемся scheduler:

/system scheduler
add name=tester on-event=":delay 3;/system script run tester;" policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive start-time=startup

Конфиг роутера.
# RouterOS 6.21.1
#
/interface bridge
add disabled=yes mtu=1500 name=off
add mtu=1500 name=test1
add mtu=1500 name=test2
add mtu=1500 name=test3
/interface ethernet
set [ find default-name=ether1 ] name=ethernet
set [ find default-name=ether2 ] name=link poe-out=off
/interface wireless
set [ find default-name=wlan1 ] band=2ghz-b/g/n channel-width=20/40mhz-Ce \
    country=russia disabled=no distance=indoors frequency=2437 \
    frequency-mode=superchannel l2mtu=1600 mode=ap-bridge radio-name="" ssid=\
    wifiточка wireless-protocol=802.11
/interface wireless nstreme
set wlan1 enable-polling=no
/ip neighbor discovery
set ethernet discover=no
/interface wireless security-profiles
set [ find default=yes ] authentication-types=wpa-psk,wpa2-psk eap-methods="" \
    group-ciphers=tkip,aes-ccm mode=dynamic-keys unicast-ciphers=tkip,aes-ccm \
    wpa-pre-shared-key=пароль wpa2-pre-shared-key=пароль
/ip pool
add name=default-dhcp ranges=192.168.88.10-192.168.88.254
/ip dhcp-server
add address-pool=default-dhcp disabled=no interface=wlan1 name=default
/interface pptp-client
add add-default-route=no allow=mschap1,mschap2 connect-to=vpn.сервер.ru \
    dial-on-demand=no disabled=no keepalive-timeout=60 max-mru=1400 max-mtu=\
    1400 mrru=disabled name=vpn password=пароль profile=default-encryption \
    user=логин
/system logging action
set 1 disk-file-name=""
set 2 remember=yes
/interface bridge port
add interface=link
add interface=wlan1
/ip address
add address=192.168.88.1/24 interface=wlan1 \
    network=192.168.88.0
/ip dhcp-client
add dhcp-options=hostname,clientid disabled=\
    no interface=ethernet use-peer-ntp=no
/ip dhcp-server network
add address=192.168.88.0/24 dns-server=\
    192.168.88.1 gateway=192.168.88.1
/ip dns
set allow-remote-requests=yes
/ip dns static
add address=192.168.88.1 name=router
/ip firewall filter
add chain=input protocol=icmp
add chain=input connection-state=established
add chain=input connection-state=related
add action=drop chain=input in-interface=\
    all-ppp
add chain=forward connection-state=\
    established
add chain=forward connection-state=related
add action=drop chain=forward \
    connection-state=invalid
/ip firewall mangle
add action=mark-routing chain=prerouting new-routing-mark=vpn src-address=\
    192.168.88.10-192.168.88.254
/ip firewall nat
add action=masquerade chain=srcnat \
    out-interface=all-ppp
/ip route
add distance=1 gateway=vpn routing-mark=vpn
/ip upnp
set allow-disable-external-interface=no
/snmp
set trap-community=public
/system clock manual
set time-zone=+05:00
/system leds
set 1 interface=wlan1 type=wireless-status
set 3 interface=test2 type=interface-status
set 4 interface=test1 type=interface-status
add interface=test3 leds=user-led type=interface-status
/system routerboard settings
set cpu-frequency=400MHz
/system scheduler
add name=tester on-event=":delay 3;\r\
    \n/system script run tester;" policy=\
    ftp,reboot,read,write,policy,test,password,sniff,sensitive start-time=\
    startup
/system script
add name=tester policy=\
    ftp,reboot,read,write,policy,test,password,sniff,sensitive source="{:log i\
    nfo [:time {:local gateway \"8.8.8.8\";/interface bridge set test1 di\
    sabled=yes;/interface bridge set test2 disabled=yes;/interface bridge set \
    test3 disabled=yes;/interface ethernet poe set link poe-out=forced-on;/int\
    erface pptp-client set vpn disabled=yes;:delay 3;:local link;:local status\
    ;:local flag false;:while ([/interface bridge get off disabled] = true) do\
    ={/interface ethernet cable-test ethernet once do={:set link \$\"status\";\
    };:if (\$link = \"link-ok\") do={:if ([/interface ethernet poe get link po\
    e-out] = \"forced-on\") do={/interface ethernet poe set link poe-out=off;}\
    ;:if ([/interface ethernet get ethernet speed] = \"100Mbps\") do={:if ([/i\
    nterface bridge get test1 disabled] != false) do={/interface bridge set te\
    st1 disabled=no;};:if ([/ping address=[/ip dhcp-client get 0 gateway] inte\
    rface=ethernet count=1 interval=200ms] = 1) do={:if ([/ping address=[/ip d\
    hcp-client get 0 gateway] interface=ethernet count=1 interval=200ms size=1\
    500] = 1) do={:if ([/interface bridge get test2 disabled] != false) do={/i\
    nterface bridge set test2 disabled=no;};:if (\$flag != true) do={:if ([/in\
    terface ethernet poe get link poe-out] != \"auto-on\") do={/interface ethe\
    rnet poe set link poe-out=auto-on;}};/interface ethernet poe monitor link \
    once do={:set status \$\"poe-out-status\";};:if (([/interface ethernet poe\
    \_get link poe-out] = \"auto-on\" and \$status = \"powered-on\") or \$flag\
    \_= true) do={:if (\$flag != true) do={:set flag true;:if ([/interface ppt\
    p-client get vpn disabled] != false) do={/interface pptp-client set vpn di\
    sabled=no;};:if ([/interface ethernet poe get link poe-out] != \"off\") do\
    ={/interface ethernet poe set link poe-out=off;}};:if ([/interface pptp-cl\
    ient get vpn running] = true) do={:if ([/ping address=\$gateway interface=\
    vpn count=1 interval=200ms size=1500] = 1) do={:if ([/interface bridge get\
    \_test3 disabled] != false) do={/interface bridge set test3 disabled=no;}}\
    \_else={:if ([/interface bridge get test3 disabled] != false) do={/interfa\
    ce bridge set test3 disabled=no;};:delay 0.5;:if ([/interface bridge get t\
    est3 disabled] != true) do={/interface bridge set test3 disabled=yes;};:de\
    lay 0.5;}} else={:if ([/interface bridge get test3 disabled] != false) do=\
    {/interface bridge set test3 disabled=no;};:delay 0.5;:if ([/interface bri\
    dge get test3 disabled] != true) do={/interface bridge set test3 disabled=\
    yes;};:delay 0.5;}}} else={:if ([/interface ethernet poe get link poe-out]\
    \_= \"auto-on\") do={/interface ethernet poe set link poe-out=off;};:if ([\
    /interface pptp-client get vpn disabled] != true) do={/interface pptp-clie\
    nt set vpn disabled=yes;};:set flag false;:if ([/interface bridge get test\
    3 disabled] != true) do={/interface bridge set test3 disabled=yes;};:if ([\
    /interface bridge get test2 disabled] != false) do={/interface bridge set \
    test2 disabled=no;};:delay 0.5;:if ([/interface bridge get test2 disabled]\
    \_!= true) do={/interface bridge set test2 disabled=yes;};:delay 0.5;}} el\
    se={:if ([/interface ethernet poe get link poe-out] = \"auto-on\") do={/in\
    terface ethernet poe set link poe-out=off;};:if ([/interface pptp-client g\
    et vpn disabled] != true) do={/interface pptp-client set vpn disabled=yes;\
    };:set flag false;:if ([/interface bridge get test2 disabled] != true) do=\
    {/interface bridge set test2 disabled=yes;};:if ([/interface bridge get te\
    st3 disabled] != true) do={/interface bridge set test3 disabled=yes;}}} el\
    se={:if ([/interface ethernet poe get link poe-out] = \"auto-on\") do={/in\
    terface ethernet poe set link poe-out=off;};:if ([/interface pptp-client g\
    et vpn disabled] != true) do={/interface pptp-client set vpn disabled=yes;\
    };:set flag false;:if ([/interface bridge get test1 disabled] != true) do=\
    {/interface bridge set test1 disabled=yes;};:if ([/interface bridge get te\
    st2 disabled] != true) do={/interface bridge set test2 disabled=yes;};:if \
    ([/interface bridge get test3 disabled] != true) do={/interface bridge set\
    \_test3 disabled=yes;}}} else={:if ([/interface ethernet poe get link poe-\
    out] != \"forced-on\") do={/interface ethernet poe set link poe-out=forced\
    -on;};:if ([/interface pptp-client get vpn disabled] != true) do={/interfa\
    ce pptp-client set vpn disabled=yes;};:set flag false;:if ([/interface bri\
    dge get test1 disabled] != true) do={/interface bridge set test1 disabled=\
    yes;};:if ([/interface bridge get test2 disabled] != true) do={/interface \
    bridge set test2 disabled=yes;};:if ([/interface bridge get test3 disabled\
    ] != true) do={/interface bridge set test3 disabled=yes;};:delay 3;}};:if \
    ([/interface ethernet poe get link poe-out] != \"off\") do={/interface eth\
    ernet poe set link poe-out=off;};:if ([/interface pptp-client get vpn disa\
    bled] != true) do={/interface pptp-client set vpn disabled=yes;};:if ([/in\
    terface bridge get test1 disabled] != true) do={/interface bridge set test\
    1 disabled=yes;};:if ([/interface bridge get test2 disabled] != true) do={\
    /interface bridge set test2 disabled=yes;};:if ([/interface bridge get tes\
    t3 disabled] != true) do={/interface bridge set test3 disabled=yes;};:if (\
    [/interface bridge get off disabled] != true) do={/interface bridge set of\
    f disabled=yes;}}]}"
/tool mac-server
set [ find default=yes ] disabled=yes
add interface=link
add interface=wlan1
add interface=ethernet
/tool mac-server mac-winbox
set [ find default=yes ] disabled=yes
add interface=link
add interface=wlan1
add interface=ethernet


Надеюсь данный материал будет кому нибудь полезен.

В конце прикреплю несколько фото поделки.






P.S. Сейчас по нажатию кнопки еще и статистика сбрасывается на email сисадмина. Так же результат теста ширины канала и еще некоторая информация которая может пригодиться.
Теги:
Хабы:
+22
Комментарии 7
Комментарии Комментарии 7

Публикации

Истории

Ближайшие события

Московский туристический хакатон
Дата 23 марта – 7 апреля
Место
Москва Онлайн
Геймтон «DatsEdenSpace» от DatsTeam
Дата 5 – 6 апреля
Время 17:00 – 20:00
Место
Онлайн