вторник, 29 сентября 2015 г.

DNS-имя в mail-сервере (v6.33rc16).

v6.33rc16


*) winbox - allow to specify dns name in all the tunnels;
*) winbox - allow to enter dns name in email server;
*) email - allow server to be specified as fqdn which is resolved on each send;
*) ppp - added on-up & on-down scripts to ppp profile
Можно указывать днс-имя mail-сервера. Долой резольв в скриптах!


суббота, 19 сентября 2015 г.

Глобальные переменные и перезагрузка.

В связи с введение нового функционала - "функций" стоит сказать, что глобальные переменные очищаются при перезагрузке роутера. Это нужно учитывать при написании скриптов!

Безопасная удаленная работа на устройстве Mikrotik.

Что надо сделать при удалённой работе с Mikrotik. Аналог Reload.

Баловаться с FireWall на удаленном компе или роутере - к дальней дороге

Вводная: При удалённом программировании вполне можно ошибиться и вбить что-нибудь, что ограничит собственный доступ. В cisco есть хорошая команда reload in, но к сожалению в mikrotik её нет. Но её заменяет целых две возможности

Установка своего скрипта по-умолчанию в устройства Mikrotik.

Бывает передаешь на офисы несколько однотипных устройств Mikrotik. Если в процессе настройки возникли ошибки, или устройство перестало отвечать, можно попросить персонал сбросить роутер по умолчанию. После сброса можно что б применял ваш скрипт с базовыми настройками. Этот скрипт можно поставить в программе Netinstall.
Дополнительно можно почитать тут:
http://forum.mikrotik.com/viewtopic.php?f=9&t=28169

Скрипт делающий функцию(в виде глобальной переменной) из скрипта.

В версии 6.2 ввели использование функций. Для того, что-бы  из скрипта сделать функцию используем код:
:local fnArray;
:foreach f in=[/system script find where name~"^Function.*"] do={:set fnArray ($fnArray.",".[/system script get $f name])};
:set fnArray [:toarray $fnArray];
:foreach f in=$fnArray do={:exec script=":global \"$f\" [:parse [/system script get $f source]]"; /log info ("Defined function ".$f);};
Все скрипты которые у вас есть и начинаются с "Function." появятся в виде глобальный переменных с тем же названием. Дальше их можно использовать как функции.
  Например, есть скрипт Function.1 с телом log info 1. После использования вышеуказанного кода:
:put $Function.1
Output:
log info 1

Спасибо dissident76 с офф. форума.

пятница, 18 сентября 2015 г.

Arxont: Вывод только нужного значения в консоли Mikrotik (...

Arxont: Вывод только нужного значения в консоли Mikrotik Вводная: Необходимо вывести только одно единственное значение в консоль.

Arxont: Кастомизация стартового приглашения консоли Mikrot...

Arxont: Кастомизация стартового приглашения консоли Mikrot...: Вводная: Необходимо при логине к роутеру Mikrotik вывести в консоль некоторую информацию. 

Функции.

Если в скрипте нужно использовать повторяющийся кусок кода можно использовать функцию:
#define function and run it
:global myFunc do={:put "hello from function"}
$myFunc
output:
hello from function
Таким образом можно сократить количество строк в коде. Например функцию можно использовать в таком куске кода:
:if ($lenPass = 8) do={:log warning "WiFi password s random.org: $newPassword"; $myFunc} 
Он выполнит запись в лог, а потом все команды которые записаны в функции $myFunc.

Еще пример с вики:
:global myFunc do={ :return ($a + $b)}
:put [$myFunc a=6 b=2]
output:
8
Так же можно передать существующий скрипт в функцию:

#add script
 /system script add name=myScript source=":put \"Hello $myVar !\"" 

:global myFunc [:parse [/system script get myScript source]]
$myFunc myVar=world
output:
Hello world !

Обработчик ошибок.

Есть такой скрипт:
/tool fetch url="https://www.random.org/passwords/\?num=1&len=8&format=plain&rnd=new" keep-result=yes dst-path="pass.txt";
log info 1;
Если по какой-то причине  www.random.org будет недоступен, то скрипт не продолжит работу, а завершится с ошибкой. Что-бы он продолжил работу нужно добавить обработчик:
:do {/tool fetch url="https://www.random.org/passwords/\?num=1&len=8&format=plain&rnd=new" keep-result=yes dst-path="pass.txt"} on-error={:log warning "random.org not generator"};
log info 1;
В таком случае скрипт продолжит работу.
Еще пример с вики:
:do {
      :put [:resolve www.example.com];
} on-error={ :put "resolver failed"};
:put "lala"
output:
resolver failed
lala 
http://wiki.mikrotik.com/wiki/Manual:Scripting 

вторник, 15 сентября 2015 г.

Удаляем с DHCP-сервера клиентов у которых поле host-name пустое.

foreach i in=[/ip dhcp-server lease find] do={
   :if ([:len [/ip dhcp-server lease get $i host-name]] = 0) do={
      /ip dhcp-server lease remove $i;
   }
}

Генерируем пароли через сервис random.org.

Предыдущий генератор не совершенен. А генерации случайных чисел в Mikrotik пока нет, но можно использовать сторонний сервис: random.org.
:global RandomOrg "";
/tool fetch url="https://www.random.org/passwords/\?num=1&len=8&format=plain&rnd=new" keep-result=yes dst-path="pass.txt";
delay 3;
:global RandomOrg [/file get pass.txt contents];
/file remove pass.txt;
Данный скрипт записывает сгенерированный пароль и 8 символов в переменную, если сервис не доступен - переменная будет пустая. 

воскресенье, 13 сентября 2015 г.

Отправка сведений об устройстве на почту.

  Скрипт отправляет информацию об устройстве на почту:
:local firmware [ /system routerboard get current-firmware ];
:local routeros [ /system resource get version ];
:local routername [ /system identity get name ];
:local licenselevel [ /system license get nlevel ];
:local architecture [ /system resource get architecture-name ];
:local boardname [ /system resource get board-name ];
/tool e-mail send to=email@here subject="Current RouterOs" body=("Router name: $routername\nFirmware: $firmware\nRouterOS: $routeros\nLicence level: $licenselevel\nBoard name: $boardname\nArchitecture: $architecture\n\n " );

Передаем динамический IP резервного интернета с одного Mikrotik на другой.

   Есть два офиса. На втором офисе 2 интернета, основной и резервный. Основной с реальным IP, резервный с динамическим (usb-модем). При переключении на резервный канал на втором офисе, на главном офисе должны знать какой IP сейчас на втором офисе. Для этого на второстепенном офисе каждые 10 минут отрабатывает скрипт, который извлекает внешний IP с PPP-интерфейса и передает на основной офис, в глобальную переменную Mikrotik.
:global inter;
/interface ppp-client monitor ppp-intertelekom once do={:set inter $"local-address"};
/file remove [find name=inter.txt];
delay 2;
/file print file=inter.txt;
delay 2;
/file set inter.txt contents=":global interNaVYB $inter";
delay 1;
/tool fetch mode=ftp upload=yes address=1.1.1.1 port=30 user=admin password=admin ascii=no src-path=inter.txt dst-path=inter.auto.rsc

Создание папки.

Напрямую папку создать нельзя. Делаем небольшую уловку:
/tool fetch address=127.0.0.1 src-path=someDummyFile user=admin password=admin mode=ftp dst-path=newDir/newFileName;
Для того что-бы это работало нужно что б сервис ftp работал, если в скрипте не указывать порт, то он должен быть стандартным. Пользователь должен иметь доступ к ftp. newDir - название новой пустой диретории.

Отрезать маску IP-адреса.

:local $ip "1.1.1.1/32"
 :for i from=([:len $ip] - 1) to=0 do={
     :if ([:pick $ip $i] = "/" ) do={
         :set ip [:pick $ip 0 $i]
         }
     }
и покороче
:local s "1.1.1.1/24";
:put [:pick $s 0 [:find $s "/"]] 

вторник, 8 сентября 2015 г.

Проверить выполняется ли скрипт в данный момент или нет.

:if ([:len [system script job find script ="script23"]] > 1) do={} else={log info svoboden}
Этот скрипт называется  "script23". При запуске он проверяет выполняется ли он в данный момент(проверяет по своему имени). Если выполняется-то он ничего не делает и завершается, если не выполняется, то выполняет действие "log info svoboden". Этот оборот используется например в данном скрипте.  Для чего это нужно. Например скрипт может входить в бесконечный цикл(например пока не подключится к нужной сети wifi), но запускается он по шедуллеру, что б не было дубликатов нужна такая проверка. В таком случае ставим время повторения в шедуллере 1 минута, и пока не завершится скрипт, он заново не стартанет.

Автоматическое подключение одной из двух доступных WIFI-сетей.

Есть две wifi сети. Одна открытая ssid 52, другая запаролена ssid 3G. Изначально наш роутер подключен к открытой сети. Эта сеть всегда онлайн, но бывают перебои - или ее нет, или на ней нет интернета. Есть вторая сеть - 3G, она включается с мобильного телефона. Задача, при пропадании первой сети, и появлении второй(включили на телефоне функцию "точка доступа") подключатся к сети 3G. После этого раз в час пробовать подключатся к сети 52, если она активна переходить на нее. В случае если нет ни одной сети периодически пытаться подключится в любой из этих двух бесконечно долго. Скрипт адаптирован к двум зашифрованным сетям. Скрипт выполняется только тогда, когда он закончил свою работу. Скрипт предусматривает что вы получаете адрес по dhcp и в одной и во второй сети. При проверке главного интерфейса роутер отключается от рабочего резервного, т.к. в микротике один радиомодуль. Ну и непонятно по какой причине микротик до сих пор не умеет выводит значения поиска беспроводных сетей в переменные.
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#   23q RouterOS v.6.18-6.28
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# 0) kidaem v sheduller na 1 minutu
# 1) proverit' nazvanie scripta "wifi_connect"
# 2) proverit' vremja dozvona na glavnuy tochku "TimeProverkaGlav" 3600
# 3) proverit' nazvanie wlan interfeisa - "wlan1"
# 4) proverit' nastroiki wlan i schifrovaniya
# 5) proverit' nastroiki dhcp-client na wlan
:if ([:len [system script job find script ="wifi_connect"]] > 1) do={} else={
# SSID glavnogo ineta
:local SSIDglav 52;
# Pass glavnogo ineta
#:local SSIDglavpass 2323wifi;
# SSID rezervnogo ineta
:local SSIDrezerv 3G;
# Pass rezervnogo ineta
:local SSIDrezervpass 12345678;
# Zaderchka mechdu popitkami pereklucheniya na glavniy inet
:local TimeProverkaGlav 3600;
:local SSID [/interface wireless get value-name=ssid number=0];
:local PingCount 3;
# YandexDNS
:local PingTarget1 77.88.8.8;
# OpenDNS
:local PingTarget2 208.67.222.222;
# GoogleDNS
:local PingTarget3 8.8.8.8;
:if ($SSID=$SSIDglav) do={
:local PingResult1 [/ping $PingTarget1 count=$PingCount];
:local PingResult2 [/ping $PingTarget2 count=$PingCount];
:local PingResult3 [/ping $PingTarget3 count=$PingCount];
:if (($PingResult1 + $PingResult2 + $PingResult3) >= (2 * $PingCount)) do={} else={
/interface wireless set [ find default-name=wlan1 ] band=2ghz-b/g/n disabled=no distance=indoors l2mtu=2290 ssid=$SSIDrezerv wireless-protocol=802.11;
/interface wireless security-profiles set [ find default=yes ] authentication-types=wpa2-psk eap-methods="" mode=dynamic-keys supplicant-identity=MikroTik wpa-pre-shared-key=$SSIDrezervpass wpa2-pre-shared-key=$SSIDrezervpass; :delay 7;
/ip dhcp-client disable [find interface=wlan1];
:delay 3;
/ip dhcp-client enable [find interface=wlan1];
:delay 10;
:local PingResult11 [/ping $PingTarget1 count=$PingCount];
:local PingResult21 [/ping $PingTarget2 count=$PingCount];
:local PingResult31 [/ping $PingTarget3 count=$PingCount];
:if (($PingResult11 + $PingResult21 + $PingResult31) >= (2 * $PingCount)) do={:log info "WiFi $SSIDrezerv active"} else={
:local GLAVworking false;
:local REZERVworking false;
:while ($GLAVworking!=true and $REZERVworking!=true) do={
/interface wireless set [ find default-name=wlan1 ] band=2ghz-b/g/n disabled=no distance=indoors frequency=2462 l2mtu=2290 ssid=$SSIDglav wireless-protocol=802.11;
/interface wireless security-profiles set [ find default=yes ] mode=none;
:delay 7;
/ip dhcp-client disable [find interface=wlan1];
:delay 3;
/ip dhcp-client enable [find interface=wlan1];
:delay 10;
:local PingResultzikl1 [/ping $PingTarget1 count=$PingCount];
:local PingResultzikl2 [/ping $PingTarget2 count=$PingCount];
:local PingResultzikl3 [/ping $PingTarget3 count=$PingCount];
:if (($PingResultzikl1 + $PingResultzikl2 + $PingResultzikl3) >= 6) do={:set GLAVworking true};
/interface wireless set [ find default-name=wlan1 ] band=2ghz-b/g/n disabled=no distance=indoors l2mtu=2290 ssid=$SSIDrezerv wireless-protocol=802.11;
/interface wireless security-profiles set [ find default=yes ] authentication-types=wpa2-psk eap-methods="" mode=dynamic-keys supplicant-identity=MikroTik wpa-pre-shared-key=$SSIDrezervpass wpa2-pre-shared-key=$SSIDrezervpass;
:delay 7;
/ip dhcp-client disable [find interface=wlan1];
:delay 3;
/ip dhcp-client enable [find interface=wlan1];
:delay 10;
:local PingResultzikl11 [/ping $PingTarget1 count=$PingCount];
:local PingResultzikl22 [/ping $PingTarget2 count=$PingCount];
:local PingResultzikl33 [/ping $PingTarget3 count=$PingCount];
:if (($PingResultzikl11 + $PingResultzikl22 + $PingResultzikl33) >= 6) do={:set REZERVworking true}};
if ($GLAVworking=true) do={
/interface wireless set [ find default-name=wlan1 ] band=2ghz-b/g/n disabled=no distance=indoors frequency=2462 l2mtu=2290 ssid=$SSIDglav wireless-protocol=802.11;
/interface wireless security-profiles set [ find default=yes ] mode=none;
:delay 7;
/ip dhcp-client disable [find interface=wlan1];
:delay 3;
/ip dhcp-client enable [find interface=wlan1]} else={:log info "WiFi $SSIDrezerv active"}}}} else={:delay $TimeProverkaGlav;
/interface wireless set [ find default-name=wlan1 ] band=2ghz-b/g/n disabled=no distance=indoors frequency=2462 l2mtu=2290 ssid=$SSIDglav wireless-protocol=802.11;
/interface wireless security-profiles set [ find default=yes ] mode=none;
:delay 7;
/ip dhcp-client disable [find interface=wlan1];
:delay 3;
/ip dhcp-client enable [find interface=wlan1];
:delay 10;
:local PingResultzikl21 [/ping $PingTarget1 count=$PingCount];
:local PingResultzikl22 [/ping $PingTarget2 count=$PingCount];
:local PingResultzikl23 [/ping $PingTarget3 count=$PingCount];
:if (($PingResultzikl21 + $PingResultzikl22 + $PingResultzikl23) >= 6) do={:log info "WiFi $SSIDglav active"} else={ /interface wireless set [ find default-name=wlan1 ] band=2ghz-b/g/n disabled=no distance=indoors l2mtu=2290 ssid=$SSIDrezerv wireless-protocol=802.11;
/interface wireless security-profiles set [ find default=yes ] authentication-types=wpa2-psk eap-methods="" mode=dynamic-keys supplicant-identity=MikroTik wpa-pre-shared-key=$SSIDrezervpass wpa2-pre-shared-key=$SSIDrezervpass;
:delay 7;
/ip dhcp-client disable [find interface=wlan1];
:delay 3;
/ip dhcp-client enable [find interface=wlan1]}}}

Определяем последний день текущего месяца.

  Иногда, например для отчетов с Mikrotik, нужно знать последний день текущего месяца -30, 31 или 28, 29( в феврале). Для этого нам поможет скрипт:
:global date
:global day
:global month
:global year
:global yeardiv
:global yearmult
:global leapyear
:global lastday
:global found
 
 :set date [system clock get date]
 :set month [:pick $date 0 3]
 :set day [:pick $date 4 6]
 :set year [:pick $date 7 11]

 :set yeardiv ($year / 4)
 :set yearmult ($yeardiv * 4)

 :if ([$yearmult] = $year) do={ :set leapyear true } else={ :set leapyear false }
 :if ([$month] = "jan") do={ :set lastday 31 }
 :if ([$month] = "feb") do={
        :if ($leapyear = true) do={ :set lastday 29 }
        :if ($leapyear = false) do={ :set lastday 28 } }
 :if ([$month] = "mar") do={ :set lastday 31 }
 :if ([$month] = "apr") do={ :set lastday 30 }
 :if ([$month] = "may") do={ :set lastday 31 }
 :if ([$month] = "jun") do={ :set lastday 30 }
 :if ([$month] = "jul") do={ :set lastday 31 }
 :if ([$month] = "aug") do={ :set lastday 31 }
 :if ([$month] = "sep") do={ :set lastday 30 }
 :if ([$month] = "oct") do={ :set lastday 31 }
 :if ([$month] = "nov") do={ :set lastday 30 }
 :if ([$month] = "dec") do={ :set lastday 31 }
 :if ([$lastday] = $day) do={log info 1} else={log info 2}
Скрипт выполняется каждый день. Если сегодня последний день месяца пишем в лог "1", если нет - пишем в лог "2". Естественно тут можно выполнять нужные именно вам команды. Так же глобальные переменные в начале можно заменить на локальные.